org.pentaho.platform.dataaccess.datasource.api.AnalysisService.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.platform.dataaccess.datasource.api.AnalysisService.java

Source

/*!
 * 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-2015 Pentaho Corporation..  All rights reserved.
 */

package org.pentaho.platform.dataaccess.datasource.api;

import com.sun.jersey.core.header.FormDataContentDisposition;
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.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.engine.PentahoAccessControlException;
import org.pentaho.platform.api.repository2.unified.IPlatformImportBundle;
import org.pentaho.platform.api.repository2.unified.IUnifiedRepository;
import org.pentaho.platform.api.repository2.unified.RepositoryFileAcl;
import org.pentaho.platform.dataaccess.datasource.wizard.service.ConnectionServiceException;
import org.pentaho.platform.engine.core.system.PentahoSessionHolder;
import org.pentaho.platform.engine.core.system.PentahoSystem;
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.services.importer.IPlatformImporter;
import org.pentaho.platform.plugin.services.importer.PlatformImportException;
import org.pentaho.platform.plugin.services.importer.RepositoryFileImportBundle;
import org.pentaho.platform.plugin.services.importexport.legacy.MondrianCatalogRepositoryHelper;
import org.pentaho.platform.repository2.unified.webservices.RepositoryFileAclDto;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class AnalysisService extends DatasourceService {

    public static final String METADATA_EXT = ".xmi";
    private static final String OVERWRITE_IN_REPOS = "overwrite";
    private static final String DATASOURCE_NAME = "datasourceName";
    private static final String ENABLE_XMLA = "EnableXmla";
    private static final String PARAMETERS = "parameters";
    private static final String DOMAIN_ID = "domain-id";
    private static final String MONDRIAN_MIME_TYPE = "application/vnd.pentaho.mondrian+xml";
    private static final String CATALOG_NAME = "catalogName";
    private static final String UTF_8 = "UTF-8";
    private static final Log logger = LogFactory.getLog(AnalysisService.class);

    /*
     * register the handler in the PentahoSpringObjects.xml for MondrianImportHandler
     */
    protected IPlatformImporter importer;
    protected IAclAwareMondrianCatalogService aclAwareMondrianCatalogService;

    public AnalysisService() {
        importer = PentahoSystem.get(IPlatformImporter.class);
        if (mondrianCatalogService instanceof IAclAwareMondrianCatalogService) {
            aclAwareMondrianCatalogService = (IAclAwareMondrianCatalogService) mondrianCatalogService;
        }
    }

    public Map<String, InputStream> doGetAnalysisFilesAsDownload(String analysisId)
            throws PentahoAccessControlException {
        if (!canManageACL()) {
            throw new PentahoAccessControlException();
        }

        MondrianCatalogRepositoryHelper helper = createNewMondrianCatalogRepositoryHelper();

        Map<String, InputStream> fileData = helper.getModrianSchemaFiles(analysisId);
        super.parseMondrianSchemaName(analysisId, fileData);

        return fileData;
    }

    public void removeAnalysis(String analysisId) throws PentahoAccessControlException {
        try {
            ensureDataAccessPermissionCheck();
        } catch (ConnectionServiceException e) {
            throw new PentahoAccessControlException();
        }
        mondrianCatalogService.removeCatalog(fixEncodedSlashParam(analysisId), getSession());
    }

    public List<String> getAnalysisDatasourceIds() {
        List<String> analysisIds = new ArrayList<String>();
        List<MondrianCatalog> mockMondrianCatalogList = mondrianCatalogService.listCatalogs(getSession(), false);
        Set<String> ids = metadataDomainRepository.getDomainIds();
        for (MondrianCatalog mondrianCatalog : mockMondrianCatalogList) {
            String domainId = mondrianCatalog.getName() + METADATA_EXT;
            if (!ids.contains(domainId)) {
                analysisIds.add(mondrianCatalog.getName());
            }
        }
        return analysisIds;

    }

    public void putMondrianSchema(InputStream dataInputStream, FormDataContentDisposition schemaFileInfo,
            String catalogName, // Optional
            String origCatalogName, // Optional
            String datasourceName, // Optional
            boolean overwrite, boolean xmlaEnabledFlag, String parameters, RepositoryFileAclDto acl)
            throws PentahoAccessControlException, PlatformImportException, Exception {

        accessValidation();
        String fileName = schemaFileInfo.getFileName();
        processMondrianImport(dataInputStream, catalogName, origCatalogName, overwrite, xmlaEnabledFlag, parameters,
                fileName, acl);
    }

    public RepositoryFileAclDto getAnalysisDatasourceAcl(String analysisId)
            throws PentahoAccessControlException, FileNotFoundException {
        checkAnalysisExists(analysisId);

        if (aclAwareMondrianCatalogService != null) {
            final RepositoryFileAcl acl = aclAwareMondrianCatalogService.getAclFor(analysisId);
            return acl == null ? null : repositoryFileAclAdapter.marshal(acl);
        }
        return null;
    }

    public void setAnalysisDatasourceAcl(String analysisId, RepositoryFileAclDto aclDto)
            throws PentahoAccessControlException, FileNotFoundException {
        checkAnalysisExists(analysisId);

        final RepositoryFileAcl acl = aclDto == null ? null : repositoryFileAclAdapter.unmarshal(aclDto);
        if (aclAwareMondrianCatalogService != null) {
            aclAwareMondrianCatalogService.setAclFor(analysisId, acl);
        }
        flushDataSources();
    }

    private void checkAnalysisExists(String analysisId)
            throws FileNotFoundException, PentahoAccessControlException {
        if (!canManageACL()) {
            throw new PentahoAccessControlException();
        }
        if (mondrianCatalogService.getCatalog(analysisId, PentahoSessionHolder.getSession()) == null) {
            throw new FileNotFoundException(analysisId + " doesn't exist");
        }
    }

    /**
     * This is the main method that handles the actual Import Handler to persist to PUR
     *
     * @param dataInputStream
     * @param catalogName
     * @param overwrite
     * @param xmlaEnabledFlag
     * @param parameters
     * @param fileName
     * @param acl acl information for the data source. This parameter is optional.
     * @throws PlatformImportException
     */
    protected void processMondrianImport(InputStream dataInputStream, String catalogName, String origCatalogName,
            boolean overwrite, boolean xmlaEnabledFlag, String parameters, String fileName,
            RepositoryFileAclDto acl) throws PlatformImportException {
        boolean overWriteInRepository = determineOverwriteFlag(parameters, overwrite);
        IPlatformImportBundle bundle = createPlatformBundle(parameters, dataInputStream, catalogName,
                overWriteInRepository, fileName, xmlaEnabledFlag, acl);
        if (isChangeCatalogName(origCatalogName, bundle)) {
            IMondrianCatalogService catalogService = PentahoSystem.get(IMondrianCatalogService.class,
                    PentahoSessionHolder.getSession());
            catalogService.removeCatalog(origCatalogName, PentahoSessionHolder.getSession());
        }
        if (isOverwriteAnnotations(parameters, overWriteInRepository)) {
            IMondrianCatalogService catalogService = PentahoSystem.get(IMondrianCatalogService.class,
                    PentahoSessionHolder.getSession());
            List<MondrianCatalog> catalogs = catalogService.listCatalogs(PentahoSessionHolder.getSession(), false);
            for (MondrianCatalog catalog : catalogs) {
                if (catalog.getName().equals(bundle.getName())) {
                    catalogService.removeCatalog(bundle.getName(), PentahoSessionHolder.getSession());
                    break;
                }
            }
        }
        importer.importFile(bundle);
    }

    private boolean isChangeCatalogName(final String origCatalogName, final IPlatformImportBundle bundle) {
        // MONDRIAN-1731
        // we are importing a mondrian catalog with a new schema (during edit), remove the old catalog first
        // processing the bundle without doing this will result in a new catalog, giving the effect of adding
        // a catalog rather than editing
        return !StringUtils.isEmpty(origCatalogName) && !bundle.getName().equals(origCatalogName);
    }

    private boolean isOverwriteAnnotations(final String parameters, final boolean overWriteInRepository) {
        return overWriteInRepository && !"true".equalsIgnoreCase(getValue(parameters, "retainInlineAnnotations"));
    }

    /**
     * helper method to calculate the overwrite in repos flag from parameters or passed value
     *
     * @param parameters
     * @param overWriteInRepository
     * @return boolean if overwrite is allowed
     */
    private boolean determineOverwriteFlag(String parameters, boolean overWriteInRepository) {
        String overwriteStr = getValue(parameters, OVERWRITE_IN_REPOS);
        if (overwriteStr != null) {
            overWriteInRepository = "True".equalsIgnoreCase(overwriteStr) ? true : false;
        } // if there is a conflict - parameters win?
        return overWriteInRepository;
    }

    /**
     * helper method to create the platform bundle used by the Jcr repository
     *
     * @param parameters
     * @param dataInputStream
     * @param catalogName
     * @param overWriteInRepository
     * @param fileName
     * @param xmlaEnabled
     * @param acl acl information for the data source. This parameter is optional.
     * @return IPlatformImportBundle
     */
    private IPlatformImportBundle createPlatformBundle(String parameters, InputStream dataInputStream,
            String catalogName, boolean overWriteInRepository, String fileName, boolean xmlaEnabled,
            RepositoryFileAclDto acl) {

        byte[] bytes = null;
        try {
            bytes = IOUtils.toByteArray(dataInputStream);
            if (bytes.length == 0 && catalogName != null) {
                MondrianCatalogRepositoryHelper helper = new MondrianCatalogRepositoryHelper(
                        PentahoSystem.get(IUnifiedRepository.class));
                Map<String, InputStream> fileData = helper.getModrianSchemaFiles(catalogName);
                dataInputStream = fileData.get("schema.xml");
                bytes = IOUtils.toByteArray(dataInputStream);
            }
        } catch (IOException e) {
            logger.error(e);
        }

        String datasource = getValue(parameters, "Datasource");
        String domainId = this.determineDomainCatalogName(parameters, catalogName, fileName,
                new ByteArrayInputStream(bytes));
        String sep = ";";
        if (StringUtils.isEmpty(parameters)) {
            parameters = "Provider=mondrian";
            parameters += sep + DATASOURCE_NAME + "=" + datasource;
            parameters += sep + ENABLE_XMLA + "=" + xmlaEnabled;
        }

        RepositoryFileImportBundle.Builder bundleBuilder = new RepositoryFileImportBundle.Builder()
                .input(new ByteArrayInputStream(bytes)).charSet(UTF_8).hidden(false).name(domainId)
                .overwriteFile(overWriteInRepository).mime(MONDRIAN_MIME_TYPE).withParam(PARAMETERS, parameters)
                .withParam(DOMAIN_ID, domainId);
        if (acl != null) {
            bundleBuilder.acl(repositoryFileAclAdapter.unmarshal(acl)).applyAclSettings(true);
        }
        bundleBuilder.withParam(ENABLE_XMLA, Boolean.toString(xmlaEnabled));

        IPlatformImportBundle bundle = bundleBuilder.build();
        return bundle;
    }

    /**
     * convert string to property to do a lookup "Provider=Mondrian;DataSource=Pentaho"
     *
     * @param parameters
     * @param key
     * @return
     */
    private String getValue(String parameters, String key) {
        mondrian.olap.Util.PropertyList propertyList = mondrian.olap.Util.parseConnectString(parameters);
        return propertyList.get(key);
    }

    private String getSchemaName(String encoding, InputStream inputStream) throws XMLStreamException, IOException {
        String domainId = null;
        XMLStreamReader reader = null;
        try {
            XMLInputFactory factory = XMLInputFactory.newInstance();
            factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
            if (StringUtils.isEmpty(encoding)) {
                reader = factory.createXMLStreamReader(inputStream);
            } else {
                reader = factory.createXMLStreamReader(inputStream, encoding);
            }

            while (reader.next() != XMLStreamReader.END_DOCUMENT) {
                if (reader.getEventType() == XMLStreamReader.START_ELEMENT
                        && reader.getLocalName().equalsIgnoreCase("Schema")) {
                    domainId = reader.getAttributeValue("", "name");
                    return domainId;
                }
            }
        } finally {
            if (reader != null) {
                reader.close();
            }
            inputStream.reset();
        }

        return domainId;
    }

    /**
     * helper method to calculate the domain id from the parameters, file name, or pass catalog
     *
     * @param parameters
     * @param catalogName
     * @param fileName
     * @return Look up name from parameters or file name or passed in catalog name
     */
    private String determineDomainCatalogName(String parameters, String catalogName, String fileName,
            InputStream inputStream) {
        /*
         * Try to resolve the domainId out of the mondrian schema name. If not present then use the catalog name parameter
         * or finally the file name.
         */
        String domainId = null;
        try {
            domainId = getSchemaName(null, inputStream);
        } catch (Exception e) {
            try {
                domainId = getSchemaName(UTF_8, inputStream);
            } catch (Exception e1) {
                logger.error(e1);
            }
        }
        if (!StringUtils.isEmpty(domainId)) {
            return domainId;
        }

        domainId = (getValue(parameters, CATALOG_NAME) == null) ? catalogName : getValue(parameters, CATALOG_NAME);
        if (domainId == null || "".equals(domainId)) {
            if (fileName.contains(".")) {
                domainId = fileName.substring(0, fileName.indexOf("."));
            } else {
                domainId = fileName;
            }
        } else {
            if (domainId.contains(".")) {
                domainId = domainId.substring(0, domainId.indexOf("."));
            }
        }
        return domainId;
    }

    protected MondrianCatalogRepositoryHelper createNewMondrianCatalogRepositoryHelper() {
        return new MondrianCatalogRepositoryHelper(PentahoSystem.get(IUnifiedRepository.class));
    }

    protected boolean canAdministerCheck() {
        return super.canAdminister();
    }

    protected void ensureDataAccessPermissionCheck() throws ConnectionServiceException {
        super.ensureDataAccessPermission();
    }

    protected void accessValidation() throws PentahoAccessControlException {
        super.validateAccess();
    }

    protected IPentahoSession getSession() {
        return PentahoSessionHolder.getSession();
    }
}