/*! * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * Copyright (c) 2002-2016 Pentaho Corporation.. All rights reserved. */ package org.pentaho.platform.plugin.services.importer; /** * Used by REST Services to handle mulit part form upload from Schema WorkBench * * @author tband * @date 6/27/12 * */ import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.xml.parsers.ParserConfigurationException; import mondrian.util.Pair; import org.apache.commons.lang.StringEscapeUtils; import org.pentaho.metadata.repository.DomainAlreadyExistsException; import org.pentaho.metadata.repository.DomainIdNullException; import org.pentaho.metadata.repository.DomainStorageException; import org.pentaho.platform.api.engine.IPentahoSession; import org.pentaho.platform.api.mimetype.IMimeType; import org.pentaho.platform.api.repository2.unified.IPlatformImportBundle; import org.pentaho.platform.api.repository2.unified.RepositoryFile; import org.pentaho.platform.api.repository2.unified.RepositoryFileAcl; import org.pentaho.platform.engine.core.system.PentahoSessionHolder; import org.pentaho.platform.plugin.action.mondrian.catalog.IAclAwareMondrianCatalogService; import org.pentaho.platform.plugin.action.mondrian.catalog.IMondrianCatalogService; import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianCatalog; import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianCatalogServiceException; import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianCatalogServiceException.Reason; import org.xml.sax.SAXException; public class MondrianImportHandler implements IPlatformImportHandler { protected static final String PARAMETERS = "parameters"; protected static final String ENABLE_XMLA = "EnableXmla"; protected static final String DOMAIN_ID = "domain-id"; protected static final String DATA_SOURCE = "DataSource"; protected static final String PROVIDER = "Provider"; protected static final String DEFAULT_PROVIDER = "mondrian"; private List<IMimeType> mimeTypes; IMondrianCatalogService mondrianRepositoryImporter; public MondrianImportHandler( List<IMimeType> mimeTypes, final IMondrianCatalogService mondrianImporter ) { if ( mondrianImporter == null ) { throw new IllegalArgumentException(); } this.mimeTypes = mimeTypes; this.mondrianRepositoryImporter = mondrianImporter; } /** * **************************************** Main entry point from the Spring Interface * * @param IPlatformImportBundle * @throws IOException * @throws DomainStorageException * @throws DomainAlreadyExistsException * @throws DomainIdNullException * @throws PlatformImportException * @throws SAXException * @throws ParserConfigurationException */ public void importFile( IPlatformImportBundle bundle ) throws PlatformImportException, DomainIdNullException, DomainAlreadyExistsException, DomainStorageException, IOException { boolean overwriteInRepossitory = bundle.overwriteInRepository(); boolean xmla = "false".equalsIgnoreCase( findParameterPropertyValue( bundle, ENABLE_XMLA ) ) ? false : true; final String domainId = (String) bundle.getProperty( DOMAIN_ID ); if ( domainId == null ) { throw new PlatformImportException( "Bundle missing required domain-id property" ); } try { InputStream is = bundle.getInputStream(); MondrianCatalog catalog = this.createCatalogObject( domainId, xmla, bundle ); IPentahoSession session = PentahoSessionHolder.getSession(); if ( mondrianRepositoryImporter instanceof IAclAwareMondrianCatalogService ) { RepositoryFileAcl acl = bundle.isApplyAclSettings() ? bundle.getAcl() : null; IAclAwareMondrianCatalogService aware = (IAclAwareMondrianCatalogService) mondrianRepositoryImporter; aware.addCatalog( is, catalog, overwriteInRepossitory, acl, session ); } else { mondrianRepositoryImporter.addCatalog( is, catalog, overwriteInRepossitory, session ); } } catch ( MondrianCatalogServiceException mse ) { int statusCode = convertExceptionToStatus( mse ); throw new PlatformImportException( mse.getMessage(), statusCode ); } catch ( Exception e ) { throw new PlatformImportException( e.getMessage(), PlatformImportException.PUBLISH_GENERAL_ERROR ); } } /** * helper method to find the value in the bundle from either the property or parameter list * * @param bundle * @param key * @return */ private String findParameterPropertyValue( IPlatformImportBundle bundle, String key ) { String value = (String) bundle.getProperty( key ); if ( value == null ) { mondrian.olap.Util.PropertyList propertyList = mondrian.olap.Util.parseConnectString( (String) bundle.getProperty( PARAMETERS ) ); value = propertyList.get( key ); } return value; } private Map<String, String> findParameters( IPlatformImportBundle bundle ) { mondrian.olap.Util.PropertyList propertyList = mondrian.olap.Util.parseConnectString( (String) bundle.getProperty( PARAMETERS ) ); final Map<String, String> parameters = new HashMap<String, String>(); for ( Pair<String, String> prop : propertyList ) { parameters.put( prop.left, prop.right ); } return parameters; } /** * convert the catalog service exception to a platform exception and get the proper status code * * @param mse * @return */ private int convertExceptionToStatus( MondrianCatalogServiceException mse ) { int statusCode = PlatformImportException.PUBLISH_TO_SERVER_FAILED; if ( mse.getReason().equals( Reason.GENERAL ) ) { statusCode = PlatformImportException.PUBLISH_GENERAL_ERROR; } else { if ( mse.getReason().equals( Reason.ACCESS_DENIED ) ) { statusCode = PlatformImportException.PUBLISH_TO_SERVER_FAILED; } else { if ( mse.getReason().equals( Reason.ALREADY_EXISTS ) ) { statusCode = PlatformImportException.PUBLISH_SCHEMA_EXISTS_ERROR; } else { if ( mse.getReason().equals( Reason.XMLA_SCHEMA_NAME_EXISTS ) ) { statusCode = PlatformImportException.PUBLISH_XMLA_CATALOG_EXISTS; } } } } return statusCode; } /** * Helper method to create a catalog object */ protected MondrianCatalog createCatalogObject( String catName, boolean xmlaEnabled, IPlatformImportBundle bundle ) throws ParserConfigurationException, SAXException, IOException, PlatformImportException { final Map<String, String> parameters = findParameters( bundle ); final String dsName = findParameterPropertyValue( bundle, DATA_SOURCE ); final String provider; if ( parameters.containsKey( PROVIDER ) ) { provider = findParameterPropertyValue( bundle, PROVIDER ); } else { // Defaults to 'mondrian' provider = DEFAULT_PROVIDER; } StringBuilder sb = new StringBuilder(); if ( dsName != null ) { sb.append( "DataSource=\"" ) .append( StringEscapeUtils.escapeXml( dsName.replaceAll( """, "\"" ) ) ) .append( "\";" ); } if ( !parameters.containsKey( "EnableXmla" ) ) { sb.append( "EnableXmla=" ) .append( xmlaEnabled ) .append( ";" ); } sb.append( "Provider=\"" ) .append( StringEscapeUtils.escapeXml( provider.replaceAll( """, "\"" ) ) ) .append( "\"" ); // Build a list of the remaining properties for ( Entry<String, String> parameter : parameters.entrySet() ) { if ( !parameter.getKey().equals( DATA_SOURCE ) && !parameter.getKey().equals( PROVIDER ) ) { //value contains custom-escaped quotes. //It needs custom unescape and standard escapeXml for following mondrian parsing String parseSafeValue = StringEscapeUtils.escapeXml( parameter.getValue().replaceAll( """, "\"" ) ); sb.append( ";" ); sb.append( parameter.getKey() ); sb.append( "=\"" ); sb.append( parseSafeValue ); sb.append( "\"" ); } } MondrianCatalog catalog = new MondrianCatalog( catName, sb.toString(), provider + ":" + RepositoryFile.SEPARATOR + catName, null, null ); return catalog; } @Override public List<IMimeType> getMimeTypes() { return mimeTypes; } }