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.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.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 javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.io.DOMReader;
import org.pentaho.platform.api.engine.ICacheManager;
import org.pentaho.platform.api.engine.IPentahoAclEntry;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.engine.ISolutionFile;
import org.pentaho.platform.api.repository.ISolutionRepository;
import org.pentaho.platform.api.repository.ISolutionRepositoryService;
import org.pentaho.platform.engine.core.solution.ActionInfo;
import org.pentaho.platform.engine.core.system.PentahoSessionHolder;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.engine.security.SecurityHelper;
import org.saiku.plugin.util.PluginConfig;
import org.saiku.repository.AclMethod;
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.stereotype.Component;

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/{username}/repository")
@XmlAccessorType(XmlAccessType.NONE)
public class PentahoRepositoryResource2 implements ISaikuRepository {

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

  private static final String CACHE_REPOSITORY_DOCUMENT = "CDF_REPOSITORY_DOCUMENT";
  IPentahoSession userSession;
  ICacheManager cacheManager;

  boolean cachingAvailable;

  private ISolutionRepository repository;

  public PentahoRepositoryResource2() {
   
    cacheManager = PentahoSystem.getCacheManager(userSession);
    cachingAvailable = cacheManager != null && cacheManager.cacheEnabled();
    userSession = PentahoSessionHolder.getSession();
    repository = PentahoSystem.get(ISolutionRepository.class, userSession);

  }

  private Document getRepositoryDocument(final IPentahoSession userSession) throws ParserConfigurationException
  {      //
    Document repositoryDocument;
    if (cachingAvailable && (repositoryDocument = (Document) cacheManager.getFromSessionCache(userSession, CACHE_REPOSITORY_DOCUMENT)) != null)
    {
      log.debug("Repository Document found in cache");
      return repositoryDocument;
    }
    else
    {
      //System.out.println(Calendar.getInstance().getTime() + ": Getting repository Document");
      final DOMReader reader = new DOMReader();
      repositoryDocument = reader.read(PentahoSystem.get(ISolutionRepositoryService.class, userSession).getSolutionRepositoryDoc(userSession, new String[0]));
      //repositoryDocument = reader.read(new SolutionRepositoryService().getSolutionRepositoryDoc(userSession, new String[0]));
      cacheManager.putInSessionCache(userSession, CACHE_REPOSITORY_DOCUMENT, repositoryDocument);
      //System.out.println(Calendar.getInstance().getTime() + ": Repository Document Returned");
    }
    return repositoryDocument;
 


  /**
   * Get Saved Queries.
   * @return A list of SavedQuery Objects.
   */
  @GET
  @Produces({"application/json" })
  public List<IRepositoryObject> getRepository (
      @QueryParam("path") String path,
      @QueryParam("type") String type)
      {
    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);
      }
      userSession = PentahoSessionHolder.getSession();
      repository = PentahoSystem.get(ISolutionRepository.class, userSession);
     
      if (StringUtils.isNotBlank(path)) {
        ISolutionFile sf = repository.getSolutionFile(path, ISolutionRepository.ACTION_EXECUTE);
        if (sf != null && !sf.isDirectory() && (StringUtils.isBlank(type) || sf.getExtension().endsWith(type.toLowerCase())))  {
          List<AclMethod> acls = getAcl(path, false);
                  String localizedName = repository.getLocalizedFileProperty(sf, "title", ISolutionRepository.ACTION_EXECUTE); //$NON-NLS-1$
          objects.add(new RepositoryFileObject(localizedName, "#" + path, type, path, acls));
          return objects;
        }
      }
      Document navDoc = getRepositoryDocument(PentahoSessionHolder.getSession());
      Node tree = navDoc.getRootElement();
     
      String context = null;
      if (StringUtils.isNotBlank(path) && !path.startsWith("/")) {
        path = "/" + path;
        context = path;
      } else {
        context = "/";
      }
      return processTree(tree, context, type);
    } 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 (file == null || file.startsWith("/") || file.startsWith(".")) {
        throw new IllegalArgumentException("Path cannot be null or start with \"/\" or \".\" - Illegal Path: " + file);
      }
     
      String[] pathParts = file.split("/");
      String solution = pathParts.length > 1 ? pathParts[0] : "";
      String path = "";
      if (pathParts.length > 2) {
        for (int i = 1; i < pathParts.length - 1; i++) {
          path += "/" + pathParts[i];
        }
      }
      String action = pathParts[pathParts.length - 1];
     
      System.out.println("file: " + file + " solution:"+solution+" path:"+path + " action:" + action);

      String fullPath = ActionInfo.buildSolutionPath(solution, path, action);
      ISolutionRepository repository = PentahoSystem.get(ISolutionRepository.class, PentahoSessionHolder.getSession());
     
      if( repository == null ) {
        log.error("Access to Repository has failed");
        throw new NullPointerException("Access to Repository has failed");
      }

      if (repository.resourceExists(fullPath)) {
        String doc = repository.getResourceAsString(fullPath, ISolutionRepository.ACTION_EXECUTE);
        if (doc == null) {
          log.error("Error retrieving document from solution repository");
          throw new NullPointerException("Error retrieving saiku document from solution repository");
        }
        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 (" + file + ")",e);
    }
    return Response.serverError().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 (file == null || file.startsWith("/") || file.startsWith(".")) {
        throw new IllegalArgumentException("Path cannot be null or start with \"/\" or \".\" - Illegal Path: " + file);
      }
     
      String[] pathParts = file.split("/");
      String solution = pathParts.length > 1 ? pathParts[0] : "";
      String path = "";
      if (pathParts.length > 2) {
        for (int i = 1; i < pathParts.length - 1; i++) {
          path += "/" + pathParts[i];
        }
      }
      String action = pathParts[pathParts.length - 1];
     
      System.out.println("file: " + file + " solution:"+solution+" path:"+path + " action:" + action);

      String fullPath = ActionInfo.buildSolutionPath(solution, path, action);
      IPentahoSession userSession = PentahoSessionHolder.getSession();
      ISolutionRepository repository = PentahoSystem.get(ISolutionRepository.class, userSession);

      if( repository == null ) {
        log.error("Access to Repository has failed");
        throw new NullPointerException("Access to Repository has failed");
      }
      String base = PentahoSystem.getApplicationContext().getSolutionRootPath();
      String parentPath = ActionInfo.buildSolutionPath(solution, path, "");
      ISolutionFile parentFile = repository.getSolutionFile(parentPath, ISolutionRepository.ACTION_CREATE);
      String filePath = parentPath + ISolutionRepository.SEPARATOR + action;
      ISolutionFile fileToSave = repository.getSolutionFile(fullPath, ISolutionRepository.ACTION_UPDATE);



      if (fileToSave != null || (!repository.resourceExists(filePath) && parentFile != null)) {
        repository.publish(base, '/' + parentPath, action, content.getBytes() , true);
        log.debug(PluginConfig.PLUGIN_NAME + " : Published " + solution + " / " + path + " / " + action );
      } else {
        throw new Exception("Error ocurred while saving query to solution repository");
      }
      return Response.ok().build();
    }
    catch(Exception e){
      log.error("Cannot save file (" + file + ")",e);
    }
    return Response.serverError().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)
  {
    return Response.serverError().build();
  }
 
 
  @GET
  @Path("/zip")
  public Response getResourcesAsZip (
      @QueryParam("directory") String directory,
      @QueryParam("files") String files)
  {
    try {
      if (StringUtils.isBlank(directory))
        return Response.ok().build();

      IPentahoSession userSession = PentahoSessionHolder.getSession();
      ISolutionRepository repository = PentahoSystem.get(ISolutionRepository.class, userSession);
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      ZipOutputStream zos = new ZipOutputStream(bos);

      String[] fileArray = null;
      if (StringUtils.isBlank(files)) {
        ISolutionFile dir = repository.getSolutionFile(directory);
        for (ISolutionFile fo : dir.listFiles()) {
          if (!fo.isDirectory()) {
            String entry = fo.getFileName();
            if (".saiku".equals(fo.getExtension())) {
              byte[] doc = fo.getData();
              ZipEntry ze = new ZipEntry(entry);
              zos.putNextEntry(ze);
              zos.write(doc);
            }
          }
        }
      } else {
        fileArray = files.split(",");
        for (String f : fileArray) {
          String resource = directory + "/" + f;
          Response r = getResource(resource);
          if (Status.OK.equals(Status.fromStatusCode(r.getStatus()))) {
            byte[] doc = (byte[]) r.getEntity();
            ZipEntry ze = new ZipEntry(f);
            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(
      @QueryParam("test") String test,
      @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> processTree(final Node tree, final String parentPath, String fileType)
  {
    final String xPathDir = "./file[@isDirectory='true']"; //$NON-NLS-1$
    List<IRepositoryObject> repoObjects = new ArrayList<IRepositoryObject>();
    List<AclMethod> defaultAcls = new ArrayList<AclMethod>();
    defaultAcls.add(AclMethod.READ);

   
    List<IPentahoAclEntry> adminAcl = new ArrayList<IPentahoAclEntry>();
       
    try
    {
      List nodes = tree.selectNodes(xPathDir);
      final String[] parentPathArray = parentPath.split("/");
      final String solutionName = parentPathArray.length > 2 ? parentPathArray[2] : "";
      final String solutionPath = parentPathArray.length > 3 ? parentPath.substring(parentPath.indexOf(solutionName) + solutionName.length() + 1, parentPath.length()) + "/" : "";

      for (final Object node1 : nodes)
      {
        final Node node = (Node) node1;
        String name = node.valueOf("@name");
        if (parentPathArray.length > 0)
        {
          final String localizedName = node.valueOf("@localized-name");
          final boolean visible = node.valueOf("@visible").equals("true");
          final boolean isDirectory = node.valueOf("@isDirectory").equals("true");
          final String path = solutionName.length() == 0 ? "" : solutionPath + name;
          final String solution = solutionName.length() == 0 ? name : solutionName;

          final String relativePath = solution.length() > 0
                          && path != null
                          && path.length() > 0 ? solution + "/" + path : solution;

          if (visible && isDirectory)
          {
            List<IRepositoryObject> children = new ArrayList<IRepositoryObject>();
           
           
            List<Node> fileNodes;
            if (StringUtils.isBlank(fileType)) {
              fileNodes = node.selectNodes("./file[@isDirectory='false']");
            }
            else {
              fileNodes = node.selectNodes("./file[@isDirectory='false'][ends-with(string(@name),'." + fileType + "') or ends-with(string(@name),'." + fileType + "')]");
            }
            for (final Node fileNode : fileNodes)
            {
              boolean vis =  fileNode.valueOf("@visible").equals("true");
              String t =  fileNode.valueOf("@localized-name");
              String n = fileNode.valueOf("@name");
              if (vis) {
                List<AclMethod> acls = getAcl(relativePath + "/" + name, false);
                children.add(new RepositoryFileObject(t, "#" + relativePath + "/" + n, fileType, relativePath + "/" + n, acls));
              }
            }
            children.addAll(processTree(node, parentPath + "/" + name, fileType));
            List<AclMethod> acls = getAcl(relativePath, true);
            repoObjects.add(new RepositoryFolderObject(localizedName, "#" + relativePath, relativePath, acls, children));
          } else if (visible && !isDirectory) {
            if (StringUtils.isBlank(fileType) || name.endsWith(fileType)) {
              List<AclMethod> acls = getAcl(relativePath + "/" + name, false);
              repoObjects.add(new RepositoryFileObject(localizedName, "#" + relativePath + "/" + name, fileType, relativePath + "/" + name, acls));
            }
          }

        }
        else
        {
          repoObjects = processTree(tree, tree.valueOf("@path"), fileType);
        }
      }

    }
    catch (Exception e)
    {
      e.printStackTrace();
    }

    return repoObjects;
  }
 
  private List<AclMethod> getAcl(String file, boolean folder) {
    boolean isAdministrator = SecurityHelper.isPentahoAdministrator(PentahoSessionHolder.getSession());
    ISolutionFile solutionFile = repository.getSolutionFile(file, ISolutionRepository.ACTION_EXECUTE);
    List<AclMethod> acls = new ArrayList<AclMethod>();
    acls.add(AclMethod.READ);
   
    if (isAdministrator
          || repository.hasAccess(solutionFile, IPentahoAclEntry.PERM_UPDATE)
          || (folder && repository.hasAccess(solutionFile, IPentahoAclEntry.PERM_CREATE))) {
      acls.add(AclMethod.WRITE);
    }
    if (isAdministrator || repository.hasAccess(solutionFile, IPentahoAclEntry.PERM_ADMINISTRATION)) {
      acls.add(AclMethod.GRANT);
    }
    return acls;
   
  }



}
TOP

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

TOP
Copyright © 2018 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.