Package org.saiku.plugin.resources

Source Code of org.saiku.plugin.resources.PentahoRepositoryResource2

/* 
*   Copyright 2012 OSBI Ltd
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
*/
package org.saiku.plugin.resources;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.pentaho.platform.api.engine.IAuthorizationPolicy;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.security.policy.rolebased.actions.AdministerSecurityAction;
import org.saiku.service.util.exception.SaikuServiceException;
import org.saiku.repository.AclMethod;
import org.saiku.repository.AclEntry;
import org.saiku.repository.IRepositoryObject;
import org.saiku.repository.RepositoryFileObject;
import org.saiku.repository.RepositoryFolderObject;
import org.saiku.web.rest.resources.ISaikuRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import pt.webdetails.cpf.repository.api.FileAccess;
import pt.webdetails.cpf.repository.api.IBasicFile;
import pt.webdetails.cpf.repository.api.IBasicFileFilter;
import pt.webdetails.cpf.repository.api.IContentAccessFactory;
import pt.webdetails.cpf.repository.api.IUserContentAccess;

import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;

/**
* QueryServlet contains all the methods required when manipulating an OLAP Query.
* @author Paul Stoellberger
*
*/
@Component
@Path("/saiku/api/{username}/repository")
@XmlAccessorType(XmlAccessType.NONE)
public class PentahoRepositoryResource2 implements ISaikuRepository {

  private static final Logger log = LoggerFactory.getLogger(PentahoRepositoryResource2.class);

  @Autowired
  private IContentAccessFactory contentAccessFactory;

  public List<IRepositoryObject> getRepository (
      final @QueryParam("path") String path,
      final @QueryParam("type") String type) {
    return getRepository(path, type, false);
  }
  /**
   * Get Saved Queries.
   * @return A list of SavedQuery Objects.
   */
  @GET
  @Produces({"application/json" })
  public List<IRepositoryObject> getRepository (
      final @QueryParam("path") String path,
      final @QueryParam("type") String type,
      final @QueryParam("showHidden") @DefaultValue("false") Boolean hidden
  {
    List<IRepositoryObject> objects = new ArrayList<IRepositoryObject>();
    try {
//      if (path != null && (path.startsWith("/") || path.startsWith("."))) {
//        throw new IllegalArgumentException("Path cannot be null or start with \"/\" or \".\" - Illegal Path: " + path);
//      }
     
      IUserContentAccess access = contentAccessFactory.getUserContentAccess("/");
      String root = (StringUtils.isBlank(path)) ? "/" : path;
      return getRepositoryObjects(access, root, type, hidden);
    } catch (Exception e) {
      log.error(this.getClass().getName(),e);
      e.printStackTrace();
    }
    return objects;
  }



  /**
   * Load a resource.
   * @param file - The name of the repository file to load.
   * @param path - The path of the given file to load.
   * @return A Repository File Object.
   */
  @GET
  @Produces({"text/plain" })
  @Path("/resource")
  public Response getResource (@QueryParam("file") String file)
  {
    try {
      if (StringUtils.isBlank(file)) {
        throw new IllegalArgumentException("Path cannot be null  - Illegal Path: " + file);
      }
            file = file.replaceAll(":", "/");

      log.debug("Get repository file: " + file);

      IUserContentAccess access = contentAccessFactory.getUserContentAccess(null);

      if( !access.fileExists(file) && access.hasAccess(file, FileAccess.READ)) {
        log.error("Access to Repository has failed File does not exist: " + file);
        throw new NullPointerException("Access to Repository has failed");
      }
      IBasicFile bf = access.fetchFile(file);

      String doc = IOUtils.toString(bf.getContents());
      if (doc == null) {
        throw new SaikuServiceException("Error retrieving saiku document from solution repository: " + file);
      }
      return Response.ok(doc.getBytes("UTF-8"), MediaType.TEXT_PLAIN).header(
          "content-length",doc.getBytes("UTF-8").length).build();

    }
    catch(Exception e){
      log.error("Cannot load file from repository (" + file + ")",e);
      return Response.serverError().entity(e.getMessage()).status(Status.INTERNAL_SERVER_ERROR).build();
    }
  }

  /**
   * Save a resource.
   * @param file - The name of the repository file to load.
   * @param path - The path of the given file to load.
   * @param content - The content to save.
   * @return Status
   */
  @POST
  @Path("/resource")
  public Response saveResource (
      @FormParam("file") String file,
      @FormParam("content") String content)
  {
    try {
      if (StringUtils.isBlank(file)) {
        throw new IllegalArgumentException("Path cannot be null  - Illegal Path: " + file);
      }
      if (StringUtils.isBlank(content)) {
        throw new IllegalArgumentException("Cannot save empty file to: " + file);

      }
      log.debug("Save repository file: " + file);

      IUserContentAccess access = contentAccessFactory.getUserContentAccess(null);

      boolean ok = access.saveFile(file, IOUtils.toInputStream(content));
      if (!ok) {
        throw new SaikuServiceException("Failed to write file: " + file);
      }
      return Response.ok().build();
    }
    catch(Exception e){
      log.error("Cannot save file (" + file + ")",e);
      return Response.serverError().entity(e.getMessage()).status(Status.INTERNAL_SERVER_ERROR).build();
    }

  }

  /**
   * Delete a resource.
   * @param file - The name of the repository file to load.
   * @param path - The path of the given file to load.
   * @return Status
   */
  @DELETE
  @Path("/resource")
  public Response deleteResource (@QueryParam("file") String file) {
    try {
      if (StringUtils.isBlank(file)) {
        throw new IllegalArgumentException("Path cannot be null  - Illegal Path: " + file);
      }

      log.debug("Delete repository file: " + file);

      IUserContentAccess access = contentAccessFactory.getUserContentAccess(null);

      if( !access.fileExists(file) && access.hasAccess(file, FileAccess.DELETE)) {
        throw new SaikuServiceException("Access to Repository has failed File does not exist or no delete right: " + file);
      }
      boolean ok = access.deleteFile(file);
      if (!ok) {
        throw new SaikuServiceException("Failed to write file: " + file);
      }
      return Response.ok().build();
    }
    catch(Exception e){
      log.error("Cannot load file from repository (" + file + ")",e);
    }
    return Response.serverError().build();
 

  @GET
  @Path("/zip")
  public Response getResourcesAsZip (
      @QueryParam("directory") String directory,
      @QueryParam("files") String files,
      @QueryParam("type") String type)
  {
    try {
      if (StringUtils.isBlank(directory))
        return Response.ok().build();

      final String fileType = type;
      IUserContentAccess access = contentAccessFactory.getUserContentAccess(null);
     
      if( !access.fileExists(directory) && access.hasAccess(directory, FileAccess.READ)) {
        throw new SaikuServiceException("Access to Repository has failed File does not exist or no read right: " + directory);
      }
     
      IBasicFileFilter txtFilter = StringUtils.isBlank(type) ? null : new IBasicFileFilter() {
        public boolean accept(IBasicFile file) {
          return file.isDirectory() || file.getExtension().equals(fileType);
        }
      };
     
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      ZipOutputStream zos = new ZipOutputStream(bos);

      List<IBasicFile> basicFiles = access.listFiles(directory, txtFilter);
     
      for (IBasicFile basicFile : basicFiles) {
        if (!basicFile.isDirectory()) {
          String entry = basicFile.getName();
          byte[] doc = IOUtils.toByteArray(basicFile.getContents());
          ZipEntry ze = new ZipEntry(entry);
          zos.putNextEntry(ze);
          zos.write(doc);
         
        }
      }
     
      zos.closeEntry();
      zos.close();
      byte[] zipDoc = bos.toByteArray();

      return Response.ok(zipDoc, MediaType.APPLICATION_OCTET_STREAM).header(
          "content-disposition",
          "attachment; filename = " + directory + ".zip").header(
              "content-length",zipDoc.length).build();


    } catch(Exception e){
      log.error("Cannot zip resources " + files ,e);
      String error = ExceptionUtils.getRootCauseMessage(e);
      return Response.serverError().entity(error).build();
    }

  }

  @POST
  @Path("/zipupload")
  @Consumes(MediaType.MULTIPART_FORM_DATA)
  public Response uploadArchiveZip(
      @FormDataParam("file") InputStream uploadedInputStream,
      @FormDataParam("file") FormDataContentDisposition fileDetail,
      @FormDataParam("directory") String directory)
  {
    String zipFile = fileDetail.getFileName();
    String output = "";
    try {
      if (StringUtils.isBlank(zipFile))
        throw new Exception("You must specify a zip file to upload");

      output = "Uploding file: " + zipFile + " ...\r\n";
      ZipInputStream zis = new ZipInputStream(uploadedInputStream);
      ZipEntry ze = zis.getNextEntry();
      byte[] doc = null;
      boolean isFile = false;
      if (ze == null) {
        doc = IOUtils.toByteArray(uploadedInputStream);
        isFile = true;
      }
      while (ze != null || doc != null) {
        String fileName = null;
        if (!isFile) {
          fileName = ze.getName();
          doc = IOUtils.toByteArray(zis);
        } else {
          fileName = zipFile;
        }

        output += "Saving " + fileName + "... ";
        String fullPath = (StringUtils.isNotBlank(directory)) ? directory + "/" + fileName : fileName;            

        String content = new String(doc);
        Response r = saveResource(fullPath, content);
        doc = null;

        if (Status.OK.getStatusCode() != r.getStatus()) {
          output += " ERROR: " + r.getEntity().toString() + "\r\n";
        } else {
          output += " OK\r\n";
        }
        if (!isFile)
          ze = zis.getNextEntry();
      }

      if (!isFile) {
        zis.closeEntry();
        zis.close();
      }
      uploadedInputStream.close();

      output += " SUCCESSFUL!\r\n";
      return Response.ok(output).build();

    } catch(Exception e){
      log.error("Cannot unzip resources " + zipFile ,e);
      String error = ExceptionUtils.getRootCauseMessage(e);
      return Response.serverError().entity(output + "\r\n" + error).build();
   
  }

  private List<IRepositoryObject> getRepositoryObjects(final IUserContentAccess root, String path, final String type, final Boolean hidden) throws Exception {
    List<IRepositoryObject> repoObjects = new ArrayList<IRepositoryObject>();
    IBasicFileFilter txtFilter = StringUtils.isBlank(type) ? null : new IBasicFileFilter() {
      public boolean accept(IBasicFile file) {
        return file.isDirectory() || file.getExtension().equals(type);
      }
    };
    List<IBasicFile> files = new ArrayList<IBasicFile>();
    IUserContentAccess access = contentAccessFactory.getUserContentAccess(null);
        path = path.replace(":", "/");
    if (access.fileExists(path)) {
      IBasicFile bf = access.fetchFile(path);
      if (!bf.isDirectory()) {
        files.add(bf);
        log.debug("Found file in " + path);
      } else {
        files = root.listFiles(path, txtFilter, 0, true, hidden);
        log.debug("Found files in " + path + " : " + files.size());
      }
    }

   
   
    for (IBasicFile file : files) {

      String filename = file.getName();
      // WHY IS GETPATH NULL?????
      String relativePath = file.getFullPath();
     
      // Let's not include /etc for now
//      if ("/etc".equals(relativePath)) {
//        continue;
//      }

      List<AclMethod> acls = getAcl(path, false);
      if (!file.isDirectory()) {
        String extension = file.getExtension();
        repoObjects.add(new RepositoryFileObject(filename, "#" + relativePath, extension, relativePath, acls));
      } else {
        repoObjects.add(new RepositoryFolderObject(filename, "#" + relativePath, relativePath, acls, getRepositoryObjects(root, relativePath, type, hidden)));
      }
      Collections.sort(repoObjects, new Comparator<IRepositoryObject>() {

        public int compare(IRepositoryObject o1, IRepositoryObject o2) {
          if (o1.getType().equals(IRepositoryObject.Type.FOLDER) && o2.getType().equals(IRepositoryObject.Type.FILE))
            return -1;
          if (o1.getType().equals(IRepositoryObject.Type.FILE) && o2.getType().equals(IRepositoryObject.Type.FOLDER))
            return 1;
          return o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase());

        }

      });
    }
    return repoObjects;
  }

 
  private List<AclMethod> getAcl(String file, boolean folder) {
    List<AclMethod> acls = new ArrayList<AclMethod>();
      IAuthorizationPolicy policy = PentahoSystem.get( IAuthorizationPolicy.class );
    boolean isAdmin = policy.isAllowed( AdministerSecurityAction.NAME );
    IUserContentAccess access = contentAccessFactory.getUserContentAccess(null);
    if (access.fileExists(file)) {
      acls.add(AclMethod.READ);
      if (isAdmin || access.hasAccess(file, FileAccess.WRITE)) {
        acls.add(AclMethod.WRITE);
      }
      if (isAdmin) {
        acls.add(AclMethod.GRANT);
      }
    }
    return acls;
  }


}
TOP

Related Classes of org.saiku.plugin.resources.PentahoRepositoryResource2

TOP
Copyright © 2015 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.