Package pt.webdetails.cdf.dd

Source Code of pt.webdetails.cdf.dd.DashboardDesignerContentGenerator

/*!
* Copyright 2002 - 2014 Webdetails, a Pentaho company.  All rights reserved.
*
* This software was developed by Webdetails and is provided under the terms
* of the Mozilla Public License, Version 2.0, or any later version. You may not use
* this file except in compliance with the license. If you need a copy of the license,
* please go to  http://mozilla.org/MPL/2.0/. The Initial Developer is Webdetails.
*
* Software distributed under the Mozilla Public License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or  implied. Please refer to
* the license for the specific language governing your rights and limitations.
*/

package pt.webdetails.cdf.dd;

import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.json.JSONException;

import org.json.JSONObject;
import org.pentaho.platform.api.engine.IParameterProvider;
import org.pentaho.platform.api.engine.IPluginResourceLoader;
import org.pentaho.platform.api.engine.PentahoAccessControlException;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.engine.security.SecurityParameterProvider;

import pt.webdetails.cdf.dd.cdf.CdfStyles;
import pt.webdetails.cdf.dd.cdf.CdfTemplates;
import pt.webdetails.cdf.dd.datasources.CdaDataSourceReader;
import pt.webdetails.cdf.dd.editor.DashboardEditor;
import pt.webdetails.cdf.dd.localization.MessageBundlesHelper;
import pt.webdetails.cdf.dd.model.core.writer.ThingWriteException;
import pt.webdetails.cdf.dd.model.inst.writer.cdfrunjs.dashboard.CdfRunJsDashboardWriteOptions;
import pt.webdetails.cdf.dd.model.inst.writer.cdfrunjs.dashboard.CdfRunJsDashboardWriteResult;
import pt.webdetails.cdf.dd.structure.DashboardStructure;
import pt.webdetails.cdf.dd.structure.DashboardStructureException;
import pt.webdetails.cdf.dd.structure.DashboardWcdfDescriptor;
import pt.webdetails.cdf.dd.util.CdeEnvironment;
import pt.webdetails.cdf.dd.util.GenericBasicFileFilter;
import pt.webdetails.cdf.dd.util.GenericFileAndDirectoryFilter;
import pt.webdetails.cdf.dd.util.JsonUtils;
import pt.webdetails.cdf.dd.util.Utils;
import pt.webdetails.cpf.InterPluginCall;
import pt.webdetails.cpf.SimpleContentGenerator;
import pt.webdetails.cpf.VersionChecker;
import pt.webdetails.cpf.annotations.AccessLevel;
import pt.webdetails.cpf.annotations.Audited;
import pt.webdetails.cpf.annotations.Exposed;
import pt.webdetails.cpf.olap.OlapUtils;
import pt.webdetails.cpf.repository.api.FileAccess;
import pt.webdetails.cpf.repository.api.IBasicFile;
import pt.webdetails.cpf.repository.api.IReadAccess;
import pt.webdetails.cpf.repository.api.IUserContentAccess;
import pt.webdetails.cpf.repository.util.RepositoryHelper;
import pt.webdetails.cpf.utils.MimeTypes;

public class DashboardDesignerContentGenerator extends SimpleContentGenerator {

  private static final Log logger = LogFactory.getLog( DashboardDesignerContentGenerator.class );

  private static final long serialVersionUID = 1L;

  private static final String MIME_TYPE = "text/html";

  private static final String CSS_TYPE = "text/css";

  private static final String JAVASCRIPT_TYPE = "text/javascript";

  /**
   * 1 week cache
   */
  private static final int RESOURCE_CACHE_DURATION = 3600 * 24 * 8; // 1 week
  // cache

  private static final int NO_CACHE_DURATION = 0;

  private static final String EXTERNAL_EDITOR_PAGE = "resources/ext-editor.html";

  private static final String COMPONENT_EDITOR_PAGE = "resources/cdf-dd-component-editor.html";

  private static final String OPERATION_LOAD = "load";
  private static final String OPERATION_DELETE = "delete";
  private static final String OPERATION_SAVE = "save";
  private static final String OPERATION_SAVE_AS = "saveas";
  private static final String OPERATION_NEW_FILE = "newfile";
  private static final String OPERATION_SAVE_SETTINGS = "savesettings";

  private static final String REQUEST_PARAM_FILE = "file";
  private static final String REQUEST_PARAM_PATH = "path";
  private static final String REQUEST_PARAM_OPERATION = "operation";
  private static final String REQUEST_PARAM_CDFSTRUCTURE = "cdfstructure";
  private static final String REQUEST_PARAM_TITLE = "title";
  private static final String REQUEST_PARAM_DESCRIPTION = "description";

  private static final String GET_RESOURCE = "getResource?resource=";

  public static final String UNSAVED_FILE_PATH = "/null/null/null";


  /**
   * Parameters received by content generator
   */
  protected static class MethodParams {
    public static final String DEBUG = "debug";

    public static final String ROOT = "root";

    public static final String SOLUTION = "solution";

    public static final String PATH = "path";

    public static final String FILE = "file";

    public static final String RESOURCE = "resource";

    /**
     * JSON structure
     */

    public static final String DATA = "data";
  }

  /*
   * This block initializes exposed methods
   */
  private static Map<String, Method> exposedMethods = new HashMap<String, Method>();

  static {
    // to keep case-insensitive methods
    logger.info( "loading exposed methods" );
    exposedMethods = getExposedMethods(
      DashboardDesignerContentGenerator.class, true );
  }

  @Override
  protected Method getMethod( String methodName ) throws NoSuchMethodException {
    Method method = exposedMethods.get( StringUtils.lowerCase( methodName ) );
    if ( method == null ) {
      throw new NoSuchMethodException();
    }
    return method;
  }

  public DashboardDesignerContentGenerator() {
  }

  @Override
  public String getPluginName() {
    return CdeEnvironment.getPluginId();
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void syncronize( final OutputStream out ) throws Exception {
    String title = null;
    String description = null;
    String operation = null;
    String path = null;
    String cdfStructure = null;
    if ( getRequest().getContentType().startsWith( "multipart/form-data" ) ) {
      FileItemFactory factory = new DiskFileItemFactory();
      ServletFileUpload upload = new ServletFileUpload( factory );
      List items = null;
      try {
        items = upload.parseRequest( getRequest() );
      } catch ( FileUploadBase.InvalidContentTypeException e ) {
        logger.debug( "Syncronize - content type not multipart/form-data" );
      }
      if ( items != null ) {
        for ( int i = 0; i < items.size(); i++ ) {
          FileItem fi = (FileItem) items.get( i );

          if ( "operation".equals( fi.getFieldName() ) ) {
            operation = fi.getString();
          }
          if ( "file".equals( fi.getFieldName() ) ) {
            path = fi.getString();
          }
          if ( "cdfstructure".equals( fi.getFieldName() ) ) {
            cdfStructure = fi.getString( "UTF-8" );
          }
          if ( "title".equals( fi.getFieldName() ) ) {
            title = fi.getString();
          }
          if ( "description".equals( fi.getFieldName() ) ) {
            description = fi.getString();
          }
        }
        if ( StringUtils.isEmpty( title ) ) {
          title = FilenameUtils.getBaseName( path );
        }
        if ( StringUtils.isEmpty( description ) ) {
          description = FilenameUtils.getBaseName( path );
        }
        boolean saveAsAccessGranted = false;
        if ( operation.equals( OPERATION_SAVE_AS ) ) {
          saveAsAccessGranted =
            CdeEnvironment.getUserContentAccess().hasAccess( FilenameUtils.getPath( path ), FileAccess.EXECUTE );
        }
        if ( !saveAsAccessGranted && ( path != null ) && ( !path.endsWith( "_tmp.cdfde" ) )
          && ( !CdeEnvironment.getUserContentAccess().hasAccess( path, FileAccess.EXECUTE ) ) ) {
          getResponse().setStatus( 403 );
          logger.warn( "Access denied for the syncronize method: " + path );
          return;
        }
      }
    } else {

      path = ( (String) getRequestParameters().getParameter( REQUEST_PARAM_FILE ) ).replaceAll( "cdfde", "wcdf" );

      // Check security. Caveat: if no path is supplied, then we're in the new parameter
      if ( getRequestParameters().hasParameter( REQUEST_PARAM_PATH ) && !CdeEnvironment.getUserContentAccess()
        .hasAccess( path, FileAccess.EXECUTE ) ) {
        getResponse().setStatus( HttpServletResponse.SC_FORBIDDEN );
        logger.warn( "Access denied for the syncronize method: " + path );
        return;
      }
      cdfStructure = (String) getRequestParameters().getStringParameter( REQUEST_PARAM_CDFSTRUCTURE, null );

      path = getRequestParameters().getStringParameter( REQUEST_PARAM_FILE, null );
      title = StringUtils.defaultIfEmpty( ( (String) getRequestParameters().getParameter( REQUEST_PARAM_TITLE ) ),
        FilenameUtils.getBaseName( path ) );
      description =
        StringUtils.defaultIfEmpty( (String) getRequestParameters().getParameter( REQUEST_PARAM_DESCRIPTION ), "" );
      operation = getRequestParameters().getStringParameter( REQUEST_PARAM_OPERATION, "" ).toLowerCase();

      // file path must exist
      if ( getRequestParameters() == null || getRequestParameters().getParameter( REQUEST_PARAM_FILE ) == null ) {
        throw new Exception(
          Messages.getString( "SyncronizeCdfStructure.ERROR_002_INVALID_FILE_PARAMETER_EXCEPTION" ) );
      }
    }

    try {

      final DashboardStructure dashboardStructure = new DashboardStructure();
      Object result = null;

      if ( OPERATION_LOAD.equalsIgnoreCase( operation ) ) {
        String file = getRequestParameters().getStringParameter( "file", null );
        JsonUtils.buildJsonResult( getResponse().getOutputStream(), true, dashboardStructure.load( file ) );
        return;
      } else if ( OPERATION_DELETE.equalsIgnoreCase( operation ) ) {
        dashboardStructure.delete( toHashMap( getRequestParameters() ) );

      } else if ( OPERATION_SAVE.equalsIgnoreCase( operation ) ) {
        result = dashboardStructure.save( path, cdfStructure );
      } else if ( OPERATION_SAVE_AS.equalsIgnoreCase( operation ) ) {
        boolean isPreview = ( path.indexOf( "_tmp.cdfde" ) > -1 || path.indexOf( "_tmp.wcdf" ) > -1 );
        dashboardStructure.saveAs( path, title, description, cdfStructure, isPreview );

      } else if ( OPERATION_NEW_FILE.equalsIgnoreCase( operation ) ) {
        dashboardStructure.newfile( toHashMap( getRequestParameters() ) );

      } else if ( OPERATION_SAVE_SETTINGS.equalsIgnoreCase( operation ) ) {
        // check if user is attempting to save settings over a new (non yet saved) dashboard/widget/template
        String file = getRequestParameters().getStringParameter( "file", null );
        if ( StringUtils.isEmpty( file ) || UNSAVED_FILE_PATH.equals( file ) ) {
          String msg = Messages.getString( "CdfTemplates.ERROR_003_SAVE_DASHBOARD_FIRST" );
          logger.warn( msg );
          JsonUtils.buildJsonResult( getResponse().getOutputStream(), false, msg );
          return;
        }
        dashboardStructure.savesettings( toHashMap( getRequestParameters() ) );

      } else {
        logger.error( "Unknown operation: " + operation );
      }

      JsonUtils.buildJsonResult( getResponse().getOutputStream(), true, result );

    } catch ( Exception e ) {
      if ( e.getCause() != null ) {
        if ( e.getCause() instanceof DashboardStructureException ) {
          JsonUtils.buildJsonResult( getResponse().getOutputStream(), false, e.getCause().getMessage() );
        } else if ( e instanceof InvocationTargetException ) {
          throw (Exception) e.getCause();
        }
      }
      throw e;
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  @Audited( action = "edit" )
  public void newDashboard( final OutputStream out ) throws Exception {
    this.edit( out );
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC, outputType = MimeType.JAVASCRIPT )
  public void getComponentDefinitions( OutputStream out ) throws Exception {
    // Get and output the definitions
    try {
      String definition = MetaModelManager.getInstance().getJsDefinition();
      out.write( definition.getBytes() );
    } catch ( Exception ex ) {
      String msg = "Could not get component definitions: " + ex.getMessage();
      logger.error( msg );
      throw ex;
    }
  }

  /**
   * Re-initializes the designer back-end.
   *
   * @author pdpi
   */
  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void refresh( final OutputStream out ) throws Exception {
    String msg = "Refreshed CDE Successfully";

    try {
      DashboardManager.getInstance().refreshAll();
    } catch ( Exception re ) {
      msg = "Method refresh failed while trying to execute.";

      logger.error( msg, re );
      writeOut( out, msg );
      return;
    }

    writeOut( out, msg );
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void getContent( OutputStream out ) throws Exception {
    CdfRunJsDashboardWriteResult dashboardWrite = this.loadDashboard();
    writeOut( out, dashboardWrite.getContent() );
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void getHeaders( final OutputStream out ) throws Exception {
    CdfRunJsDashboardWriteResult dashboardWrite = this.loadDashboard();
    writeOut( out, dashboardWrite.getHeader() );
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  @Audited( action = "render" )
  public void render( final OutputStream out ) throws IOException {
    String relativePath = getWcdfRelativePath( getRequestParameters() );

    // Check security
    if ( !CdeEnvironment.getUserContentAccess().hasAccess( relativePath, FileAccess.EXECUTE ) ) {
      writeOut( out, "Access Denied or File Not Found." );
      return;
    }

    // Response
    try {
      setResponseHeaders( MIME_TYPE, 0, null );
    } catch ( Exception e ) {
      logger.warn( e.toString() );
    }

    try {
      long start = System.currentTimeMillis();
      logger.info( "[Timing] CDE Starting Dashboard Rendering" );

      String result = this.loadDashboard().render( getCdfContext() );

      //i18n token replacement
      if ( !StringUtils.isEmpty( result ) ) {
        String msgDir = FilenameUtils.getPath( FilenameUtils.separatorsToUnix( relativePath ) );
        result = new MessageBundlesHelper( msgDir, null ).replaceParameters( result, null );
      }

      writeOut( out, result );
      logger.info( "[Timing] CDE Finished Dashboard Rendering: "
        + Utils.ellapsedSeconds( start ) + "s" );
    } catch ( FileNotFoundException ex ) { // could not open cdfe
      String msg = "File not found: " + ex.getLocalizedMessage();
      logger.error( msg, ex );
      writeOut( out, msg );
    } catch ( Exception ex ) {
      String msg = "Could not load dashboard: " + ex.getMessage();
      logger.error( msg, ex );
      writeOut( out, msg );
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC, outputType = MimeType.CSS )
  public void getCssResource( final OutputStream out ) throws Exception {
    setResponseHeaders( CSS_TYPE, RESOURCE_CACHE_DURATION, null );
    getResource( out );
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC, outputType = MimeType.JAVASCRIPT )
  public void getJsResource( final OutputStream out ) throws Exception {
    setResponseHeaders( JAVASCRIPT_TYPE, RESOURCE_CACHE_DURATION, null );
    final HttpServletResponse response = getResponse();
    // Set cache for 1 year, give or take.
    response.setHeader( "Cache-Control", "max-age=" + 60 * 60 * 24 * 365 );
    try {
      getResource( out );
    } catch ( SecurityException e ) {
      response.sendError( HttpServletResponse.SC_FORBIDDEN );
    } catch ( FileNotFoundException e ) {
      response.sendError( HttpServletResponse.SC_NOT_FOUND );
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void getUntypedResource( final OutputStream out ) throws IOException {
    final HttpServletResponse response = getResponse();
    response.setHeader( "Content-Type", "text/plain" );
    response.setHeader( "content-disposition", "inline" );

    getResource( out );
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void getImg( final OutputStream out ) throws Exception {
    String pathString = getPathParameters().getStringParameter(
      MethodParams.PATH, "" );
    String resource;
    if ( pathString.split( "/" ).length > 2 ) {
      resource = pathString.replaceAll( "^/.*?/", "" );
    } else {
      resource = getRequestParameters().getStringParameter(
        MethodParams.PATH, "" );
    }

    resource = resource.startsWith( "/" ) ? resource : "/" + resource;

    String[] path = resource.split( "/" );
    String fileName = path[ path.length - 1 ];
    setResponseHeaders( MimeTypes.getMimeType( fileName ),
      RESOURCE_CACHE_DURATION, null );
    final HttpServletResponse response = getResponse();
    // Set cache for 1 year, give or take.
    response.setHeader( "Cache-Control", "max-age=" + 60 * 60 * 24 * 365 );
    try {
      getResource( out );
    } catch ( SecurityException e ) {
      response.sendError( HttpServletResponse.SC_FORBIDDEN );
    } catch ( FileNotFoundException e ) {
      response.sendError( HttpServletResponse.SC_NOT_FOUND );
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void res( final OutputStream out ) throws Exception {
    String pathString = getPathParameters().getStringParameter( MethodParams.PATH, "" );
    String resource;
    if ( pathString.split( "/" ).length > 2 ) {
      resource = pathString.replaceAll( "^/.*?/", "" );
    } else {
      resource = getRequestParameters().getStringParameter( MethodParams.PATH, "" );
    }

    final HttpServletResponse response = getResponse();

    if ( StringUtils.isEmpty( resource ) ) {
      response.sendError( HttpServletResponse.SC_NOT_FOUND );
      return;
    }

    resource = StringUtils.strip( resource, "/" );

    String[] path = resource.split( "/" );
    String[] fileName = path[ path.length - 1 ].split( "\\." );

    String mimeType;
    try {
      final MimeTypes.FileType fileType = MimeTypes.FileType.valueOf( fileName[ fileName.length - 1 ].toUpperCase() );
      mimeType = MimeTypes.getMimeType( fileType );
    } catch ( java.lang.IllegalArgumentException ex ) {
      mimeType = "";
    } catch ( EnumConstantNotPresentException ex ) {
      mimeType = "";
    }

    setResponseHeaders( mimeType, RESOURCE_CACHE_DURATION, null );

    // Set cache for 1 year, give or take.
    response.setHeader( "Cache-Control", "max-age=" + 60 * 60 * 24 * 365 );
    response.setHeader( "content-disposition", "inline; filename=\"" + path[ path.length - 1 ] + "\"" );
    InputStream resInput = null;
    try {
      IBasicFile file = Utils.getFileViaAppropriateReadAccess( resource );
      if ( file == null ) {
        logger.error( "resource not found:" + resource );
        response.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
        return;
      }
      resInput = file.getContents();
      IOUtils.copy( resInput, out );
      setCacheControl();
    } catch ( SecurityException e ) {
      response.sendError( HttpServletResponse.SC_FORBIDDEN );
    } catch ( IOException e ) {
      logger.error( "Erro reading resource " + resource, e );
    } finally {
      IOUtils.closeQuietly( resInput );
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void getResource( final OutputStream out ) throws IOException {

    String pathString = getPathParameters().getStringParameter( MethodParams.PATH, null );
    String resource;
    if ( pathString.split( "/" ).length > 2 ) {
      resource = pathString.replaceAll( "^/.*?/", "" );
    } else {
      resource = getRequestParameters().getStringParameter( MethodParams.RESOURCE, null );
    }

    final HttpServletResponse response = getResponse();

    if ( StringUtils.isEmpty( resource ) ) {
      response.sendError( HttpServletResponse.SC_NOT_FOUND );
      return;
    }

    resource = StringUtils.strip( resource, "/" );

    String[] path = resource.split( "/" );
    String[] fileName = path[ path.length - 1 ].split( "\\." );

    String mimeType;
    try {
      final MimeTypes.FileType fileType = MimeTypes.FileType.valueOf( fileName[ fileName.length - 1 ].toUpperCase() );
      mimeType = MimeTypes.getMimeType( fileType );
    } catch ( java.lang.IllegalArgumentException ex ) {
      mimeType = "";
    } catch ( EnumConstantNotPresentException ex ) {
      mimeType = "";
    }

    try {
      setResponseHeaders( mimeType, RESOURCE_CACHE_DURATION, null );

      // Set cache for 1 year, give or take.
      response.setHeader( "Cache-Control", "max-age=" + 60 * 60 * 24 * 365 );
      response.setHeader( "content-disposition", "inline; filename=\"" + path[ path.length - 1 ] + "\"" );

      IBasicFile file = Utils.getFileViaAppropriateReadAccess( resource );
      if ( file == null ) {
        logger.error( "resource not found:" + resource );
        response.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
        return;
      }

      IOUtils.copy( file.getContents(), out );
      setCacheControl();
    } catch ( SecurityException e ) {
      response.sendError( HttpServletResponse.SC_FORBIDDEN );
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  @Audited( action = "edit" )
  public void edit( final OutputStream out ) throws Exception {
    // 0 - Check security. Caveat: if no path is supplied, then we're in the new parameter
    IParameterProvider requestParams = getRequestParameters();
    IParameterProvider pathParams = getPathParameters();

    boolean debugMode = requestParams.hasParameter( MethodParams.DEBUG )
      && requestParams.getParameter( MethodParams.DEBUG ).toString().equals( "true" );

    String wcdfPath = getWcdfRelativePath( requestParams );

    if ( requestParams.hasParameter( CdeConstants.MethodParams.PATH )
      && !CdeEnvironment.getUserContentAccess().hasAccess( wcdfPath, FileAccess.WRITE ) ) {
      writeOut( out, "Access Denied" );
    }

    String result = DashboardEditor.getEditor( wcdfPath, debugMode, getScheme( pathParams ), false );

    //i18n token replacement
    if ( !StringUtils.isEmpty( result ) ) {
      String msgDir = FilenameUtils.getPath( FilenameUtils.separatorsToUnix( wcdfPath ) );
      result = new MessageBundlesHelper( msgDir, null ).replaceParameters( result, null );
    }

    writeOut( out, result );
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void syncTemplates( final OutputStream out ) throws Exception {
    IParameterProvider requestParams = getRequestParameters();
    String method = requestParams.getStringParameter( REQUEST_PARAM_OPERATION, null );

    final CdfTemplates cdfTemplates = new CdfTemplates( GET_RESOURCE );

    if ( method.equals( OPERATION_LOAD ) ) {
      Object result = cdfTemplates.load();
      JsonUtils.buildJsonResult( out, true, result );
    } else if ( method.equals( OPERATION_SAVE ) ) {
      String file = requestParams.getStringParameter( REQUEST_PARAM_FILE, null ),
        structure = requestParams.getStringParameter( CdeConstants.MethodParams.CDF_STRUCTURE, null );
      cdfTemplates.save( file, structure );
      JsonUtils.buildJsonResult( out, true, null );
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void syncStyles( final OutputStream out ) throws Exception {
    final CdfStyles cdfStyles = new CdfStyles();

    Object result = cdfStyles.liststyles();
    JsonUtils.buildJsonResult( out, true, result );
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void listRenderers( final OutputStream out ) throws Exception {
    writeOut( out, "{\"result\": [\""
      + DashboardWcdfDescriptor.DashboardRendererType.MOBILE.getType()
      + "\",\""
      + DashboardWcdfDescriptor.DashboardRendererType.BLUEPRINT.getType()
      + "\",\""
      + DashboardWcdfDescriptor.DashboardRendererType.BOOTSTRAP.getType()

      + "\"]}" );
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void olapUtils( final OutputStream out ) throws JSONException {
    OlapUtils olapUtils = new OlapUtils();
    Object result = null;

    try {
      String operation = getRequestParameters().getStringParameter( "operation", "-" );

      if ( operation.equals( "GetOlapCubes" ) ) {

        result = olapUtils.getOlapCubes();

      } else if ( operation.equals( "GetCubeStructure" ) ) {

        String catalog = getRequestParameters().getStringParameter( "catalog", null );
        String cube = getRequestParameters().getStringParameter( "cube", null );
        String jndi = getRequestParameters().getStringParameter( "jndi", null );

        result = olapUtils.getCubeStructure( catalog, cube, jndi );

      } else if ( operation.equals( "GetLevelMembersStructure" ) ) {

        String catalog = getRequestParameters().getStringParameter( "catalog", null );
        String cube = getRequestParameters().getStringParameter( "cube", null );
        String member = getRequestParameters().getStringParameter( "member", null );
        String direction = getRequestParameters().getStringParameter( "direction", null );

        result = olapUtils.getLevelMembersStructure( catalog, cube, member, direction );

      } else if ( operation.equals( "GetPaginatedLevelMembers" ) ) {

        String catalog = getRequestParameters().getStringParameter( "catalog", null );
        String cube = getRequestParameters().getStringParameter( "cube", null );
        String startMember = getRequestParameters().getStringParameter( "startMember", null );
        String level = getRequestParameters().getStringParameter( "level", null );
        String context = getRequestParameters().getStringParameter( "context", null );
        String searchTerm = getRequestParameters().getStringParameter( "searchTerm", null );
        long pageSize = getRequestParameters().getLongParameter( "pageSize", 0 );
        long pageStart = getRequestParameters().getLongParameter( "pageStart", 0 );

        result = olapUtils
          .getPaginatedLevelMembers( catalog, cube, level, startMember, context, searchTerm, pageSize, pageStart );

      }
      buildJsonResult( out, result != null, result );
    } catch ( Exception ex ) {
      logger.fatal( ex );
      buildJsonResult( out, false, "Exception found: " + ex.getClass().getName() + " - " + ex.getMessage() );
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void exploreFolder( final OutputStream out ) throws IOException, JSONException {

    IParameterProvider requestParams = getRequestParameters();
    final String folder = requestParams.getStringParameter( "dir", null );
    final String fileExtensions = requestParams.getStringParameter( "fileExtensions", null );
    final String permission = requestParams.getStringParameter( "access", null );
    final String outputType = requestParams.getStringParameter( "outputType", null );

    if ( outputType != null && outputType.equals( "json" ) ) {
      try {
        writeOut( out, RepositoryHelper.toJSON( folder, getFileList( folder, fileExtensions, permission ) ) );
      } catch ( JSONException e ) {
        logger.error( "exploreFolder" + folder, e );
        writeOut( out, "error getting files in folder " + folder );
      }
    } else {
      writeOut( out, RepositoryHelper.toJQueryFileTree( folder, getFileList( folder, fileExtensions, permission ) ) );
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void getCDEplugins( final OutputStream out ) throws IOException {
    CdePlugins plugins = new CdePlugins();
    writeOut( out, plugins.getCdePlugins() );
  }

  /**
   * List CDA datasources for given dashboard.
   */
  @Deprecated
  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void listCdaSources( final OutputStream out ) throws IOException {

    String dashboard = getRequestParameters().getStringParameter( "dashboard", null );
    dashboard = DashboardWcdfDescriptor.toStructurePath( dashboard );

    List<CdaDataSourceReader.CdaDataSource> dataSourcesList = getCdaSources( dashboard );
    CdaDataSourceReader.CdaDataSource[] dataSources =
      dataSourcesList.toArray( new CdaDataSourceReader.CdaDataSource[ dataSourcesList.size() ] );
    String result = "[" + StringUtils.join( dataSources, "," ) + "]";
    writeOut( out, result );
  }

  protected List<CdaDataSourceReader.CdaDataSource> getCdaSources( String dashboard ) {
    return CdaDataSourceReader.getCdaDataSources( dashboard );
  }


  // External Editor v
  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void getFile( final OutputStream out ) throws IOException {

    String path = getRequestParameters().getStringParameter( MethodParams.PATH, "" );
    IUserContentAccess access = CdeEnvironment.getUserContentAccess();

    if ( access.fileExists( path ) ) {
      setResponseHeaders( "text/plain", NO_CACHE_DURATION, null );
      writeOut( out, IOUtils.toString( access.getFileInputStream( path ) ) );
    } else {
      writeOut( out, "No file found in given path " + path );
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void createFolder( OutputStream out ) throws PentahoAccessControlException, IOException {

    String path = getRequestParameters().getStringParameter( MethodParams.PATH, null );
    IUserContentAccess access = CdeEnvironment.getUserContentAccess();

    if ( access.fileExists( path ) ) {
      writeOut( out, "already exists: " + path );
    } else {
      if ( access.createFolder( path ) ) {
        writeOut( out, path + "created ok" );
      } else {
        writeOut( out, "error creating folder " + path );
      }
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void deleteFile( OutputStream out ) throws PentahoAccessControlException, IOException {

    String path = getRequestParameters().getStringParameter( MethodParams.PATH, null );

    IUserContentAccess access = CdeEnvironment.getUserContentAccess();
    if ( access.hasAccess( path, FileAccess.DELETE ) && access.deleteFile( path ) ) {
      writeOut( out, "file  " + path + " removed ok" );
    } else {
      writeOut( out, "Error removing " + path );
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void writeFile( OutputStream out ) throws PentahoAccessControlException, IOException {

    IParameterProvider requestParams = getRequestParameters();
    String path = requestParams.getStringParameter( MethodParams.PATH, null );
    String contents = requestParams.getStringParameter( MethodParams.DATA, null );
    boolean createNew = requestParams.hasParameter( "createNew" );

    IUserContentAccess access = CdeEnvironment.getUserContentAccess();

    if ( access.hasAccess( path, FileAccess.WRITE )
      || ( createNew && access.hasAccess( FilenameUtils.getFullPath( path ), FileAccess.WRITE ) ) ) {

      if ( access.saveFile( path, new ByteArrayInputStream( contents.getBytes( ENCODING ) ) ) ) {
        // saved ok
        writeOut( out, "file '" + path + "' saved ok" );
      } else {
        // error
        logger.error( "writeFile: failed saving " + path );
        writeOut( out, "error saving file " + path );
      }

    } else {
      logger.error( "writeFile: no permissions to write file " + path );
      writeOut( out, "no permissions to write file " + path );
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void canEdit( OutputStream out ) throws IOException {

    String path = getRequestParameters().getStringParameter( MethodParams.PATH, null );

    writeOut( out, String.valueOf( CdeEnvironment.getUserContentAccess().hasAccess( path, FileAccess.WRITE ) ) );
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void extEditor( final OutputStream out ) throws IOException {

    IReadAccess access = CdeEnvironment.getPluginSystemReader();

    if ( access.fileExists( EXTERNAL_EDITOR_PAGE ) ) {
      writeOut( out, IOUtils.toString( access.getFileInputStream( EXTERNAL_EDITOR_PAGE ) ) );
    } else {
      writeOut( out, "no external editor found in " + Utils.joinPath( getPluginDir(), EXTERNAL_EDITOR_PAGE ) );
    }
  }

  // External Editor ^
  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void componentEditor( final OutputStream out ) throws IOException {

    IReadAccess access = CdeEnvironment.getPluginSystemReader();

    if ( access.fileExists( COMPONENT_EDITOR_PAGE ) ) {
      writeOut( out, IOUtils.toString( access.getFileInputStream( COMPONENT_EDITOR_PAGE ) ) );
    } else {
      writeOut( out, "no external editor found in " + Utils.joinPath( getPluginDir(), COMPONENT_EDITOR_PAGE ) );
    }
  }

  private String getWcdfRelativePath( final IParameterProvider pathParams ) {
    final String path = "/"
      + pathParams.getStringParameter( MethodParams.SOLUTION, null )
      + "/" + pathParams.getStringParameter( MethodParams.PATH, null )
      + "/" + pathParams.getStringParameter( MethodParams.FILE, null );

    return path.replaceAll( "//+", "/" );
  }

  private void setCacheControl() {
    final IPluginResourceLoader resLoader = PentahoSystem.get( IPluginResourceLoader.class, null );
    final String maxAge = resLoader.getPluginSetting( this.getClass(), "max-age" );
    final HttpServletResponse response = getResponse();
    if ( maxAge != null && response != null ) {
      response.setHeader( "Cache-Control", "max-age=" + maxAge );
    }
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void checkVersion( OutputStream out ) throws IOException,
    JSONException {
    VersionChecker versionChecker = new CdeVersionChecker(
      CdeSettings.getSettings() );
    writeOut( out, versionChecker.checkVersion() );
  }

  @Exposed( accessLevel = AccessLevel.PUBLIC )
  public void getVersion( OutputStream out ) throws IOException, JSONException {
    VersionChecker versionChecker = new CdeVersionChecker(
      CdeSettings.getSettings() );
    writeOut( out, versionChecker.getVersion() );
  }

  private String getScheme( IParameterProvider pathParams ) {
    try {
      ServletRequest req = (ServletRequest) ( pathParams
        .getParameter( "httprequest" ) );
      return req.getScheme();
    } catch ( Exception e ) {
      return "http";
    }
  }

  private CdfRunJsDashboardWriteResult loadDashboard()
    throws ThingWriteException {
    IParameterProvider pathParams = parameterProviders.get( "path" );
    IParameterProvider requestParams = parameterProviders.get( "request" );

    String scheme = ( requestParams.hasParameter( "inferScheme" ) && requestParams
      .getParameter( "inferScheme" ).equals( "false" ) ) ? ""
      : getScheme( pathParams );

    String absRoot = requestParams.getStringParameter( "root", "" );

    boolean absolute = requestParams.hasParameter( "absolute" )
      && requestParams.getParameter( "absolute" ).equals( "true" );

    boolean bypassCacheRead = requestParams.hasParameter( "bypassCache" )
      && requestParams.getParameter( "bypassCache" ).equals( "true" );

    boolean debug = requestParams.hasParameter( "debug" )
      && requestParams.getParameter( "debug" ).equals( "true" );

    String wcdfFilePath = getWcdfRelativePath( requestParams );

    String style = requestParams.getStringParameter( "style", "" );

    CdfRunJsDashboardWriteOptions options = new CdfRunJsDashboardWriteOptions(
      absolute, debug, absRoot, scheme );

    return DashboardManager.getInstance().getDashboardCdfRunJs(
      wcdfFilePath, options, bypassCacheRead, style );
  }

  private String getCdfContext() {
    InterPluginCall cdfContext = new InterPluginCall( InterPluginCall.CDF,
      "Context" );
    cdfContext.setRequest( getRequest() );
    cdfContext.setRequestParameters( getRequestParameters() );
    return cdfContext.callInPluginClassLoader();
  }

  public IBasicFile[] getFileList( String dir, final String fileExtensions, String permission ) {

    ArrayList<String> extensionsList = new ArrayList<String>();
    String[] extensions = StringUtils.split( fileExtensions, "." );
    if ( extensions != null ) {
      for ( String extension : extensions ) {
        // For some reason, in 4.5 filebased rep started to report a leading dot in extensions
        // Adding both just to be sure we don't break stuff
        extensionsList.add( "." + extension );
        extensionsList.add( extension );
      }
    }

    FileAccess fileAccess = FileAccess.parse( permission );
    if ( fileAccess == null ) {
      fileAccess = FileAccess.READ;
    }

    GenericBasicFileFilter fileFilter =
      new GenericBasicFileFilter( null, extensionsList.toArray( new String[ extensionsList.size() ] ), true );

    GenericFileAndDirectoryFilter fileAndDirFilter = new GenericFileAndDirectoryFilter( fileFilter );

    // folder filtering ( see settings.xml ) will only occur for non-admin users
    if ( !isAdministrator() ) {
      fileAndDirFilter.setDirectories( CdeSettings.getFilePickerHiddenFolderPaths( CdeSettings.FolderType.REPO ) );
      fileAndDirFilter.setFilterType( GenericFileAndDirectoryFilter.FilterType.FILTER_OUT ); // act as a black-list
    }

    List<IBasicFile> fileList =
      CdeEnvironment.getContentAccessFactory().getUserContentAccess( "/" ).listFiles( dir, fileAndDirFilter, 1, true );

    if ( fileList != null && fileList.size() > 0 ) {
      return fileList.toArray( new IBasicFile[ fileList.size() ] );
    }

    return new IBasicFile[] { };
  }

  private static HashMap<String, Object> toHashMap( IParameterProvider parameterProvider ) {

    HashMap<String, Object> map = new HashMap<String, Object>();

    if ( parameterProvider == null ) {
      return map;
    }

    Iterator<String> names = parameterProvider.getParameterNames();

    while ( names.hasNext() ) {
      String name = names.next();
      Object value = parameterProvider.getParameter( name );
      map.put( name, value );
    }

    return map;
  }

  public static String getPluginDir() {
    return CdeEnvironment.getSystemDir() + "/" + CdeEnvironment.getPluginId() + "/";
  }

  // this should be in JsonUtils, when the custom json lib gets removed
  private void buildJsonResult( OutputStream out, Boolean sucess, Object result ) throws JSONException {
    JSONObject jsonResult = new JSONObject();

    jsonResult.put( "status", sucess.toString() );
    if ( result != null ) {
      jsonResult.put( "result", result );
    }
    PrintWriter pw = null;
    try {
      pw = new PrintWriter( out );
      pw.print( jsonResult.toString( 2 ) );
      pw.flush();
    } finally {
      IOUtils.closeQuietly( pw );
    }

  }

  /**
   * checks is the current user is administrator
   *
   * @return true if the current user is administrator, false otherwise
   */
  protected boolean isAdministrator() {
    SecurityParameterProvider securityParams = new SecurityParameterProvider( userSession );
    return Boolean.valueOf( (String) securityParams.getParameter( "principalAdministrator" ) );
  }

}
TOP

Related Classes of pt.webdetails.cdf.dd.DashboardDesignerContentGenerator

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.