/* * 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 2009-2010 Pentaho Corporation. All rights reserved. * * Created Sep, 2010 * @author jdixon */ package org.pentaho.platform.dataaccess.datasource.wizard.service.impl; import java.io.File; import java.util.ArrayList; import java.util.Locale; import mondrian.xmla.DataSourcesConfig.DataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.pentaho.agilebi.modeler.IModelerSource; import org.pentaho.agilebi.modeler.ModelerMessagesHolder; import org.pentaho.agilebi.modeler.ModelerWorkspace; import org.pentaho.agilebi.modeler.gwt.BogoPojo; import org.pentaho.agilebi.modeler.gwt.GwtModelerWorkspaceHelper; import org.pentaho.agilebi.modeler.services.IModelerService; import org.pentaho.agilebi.modeler.util.SpoonModelerMessages; import org.pentaho.agilebi.modeler.util.TableModelerSource; import org.pentaho.di.core.Props; import org.pentaho.di.core.database.DatabaseMeta; import org.pentaho.di.core.exception.KettleException; import org.pentaho.metadata.model.Domain; import org.pentaho.metadata.model.LogicalModel; import org.pentaho.metadata.model.SqlPhysicalModel; import org.pentaho.metadata.repository.IMetadataDomainRepository; import org.pentaho.metadata.util.MondrianModelExporter; import org.pentaho.metadata.util.XmiParser; import org.pentaho.platform.api.engine.IApplicationContext; import org.pentaho.platform.api.engine.IPentahoObjectFactory; import org.pentaho.platform.api.engine.IPentahoSession; import org.pentaho.platform.api.repository.ISolutionRepository; import org.pentaho.platform.dataaccess.datasource.wizard.service.agile.AgileHelper; import org.pentaho.platform.dataaccess.datasource.wizard.service.impl.utils.InlineSqlModelerSource; import org.pentaho.platform.engine.core.solution.ActionInfo; import org.pentaho.platform.engine.core.system.PentahoBase; import org.pentaho.platform.engine.core.system.PentahoSessionHolder; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.engine.services.metadata.MetadataPublisher; import org.pentaho.platform.plugin.action.kettle.KettleSystemListener; 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.MondrianCube; import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianDataSource; import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianSchema; /** * User: nbaker * Date: Jul 16, 2010 */ public class ModelerService extends PentahoBase implements IModelerService { private static final Log logger = LogFactory.getLog(ModelerService.class); public static final String TMP_FILE_PATH = File.separatorChar + "system" + File.separatorChar + File.separatorChar + "tmp" + File.separatorChar; public Log getLogger() { return logger; } static { try { // try to set the modelermessages. at this point, just give it the spoon messages. no need to give it // GWT messages, this is a server-side function. ModelerMessagesHolder.setMessages(new SpoonModelerMessages()); } catch (IllegalStateException e) { logger.debug(e.getMessage(), e); } } protected void initKettle(){ try { KettleSystemListener.environmentInit(PentahoSessionHolder.getSession()); if(Props.isInitialized() == false){ Props.init(Props.TYPE_PROPERTIES_EMPTY); } } catch (KettleException e) { logger.error(e); throw new IllegalStateException("Failed to initialize Kettle system"); //$NON-NLS-1$ } } //TODO: remove this method in favor so specific calls @Deprecated public Domain generateDomain(String connectionName, String tableName, String dbType, String query, String datasourceName) throws Exception { initKettle(); try{ DatabaseMeta database = AgileHelper.getDatabaseMeta(); IModelerSource source; if(tableName != null){ source = new TableModelerSource(database, tableName, null, datasourceName); } else { source = new InlineSqlModelerSource(connectionName, dbType, query, datasourceName); } return source.generateDomain(); } catch(Exception e){ logger.error(e); throw new Exception(e.getLocalizedMessage()); } } public Domain generateCSVDomain(String tableName, String datasourceName) throws Exception { initKettle(); try{ DatabaseMeta database = AgileHelper.getDatabaseMeta(); IModelerSource source = new TableModelerSource(database, tableName, null, datasourceName); return source.generateDomain(); } catch(Exception e){ logger.error(e); throw new Exception(e.getLocalizedMessage()); } } public BogoPojo gwtWorkaround ( BogoPojo pojo){ return new BogoPojo(); } public String serializeModels(Domain domain, String name) throws Exception { return serializeModels(domain, name, true); } public String serializeModels(Domain domain, String name, boolean doOlap) throws Exception { String domainId = null; initKettle(); try { ModelerWorkspace model = new ModelerWorkspace(new GwtModelerWorkspaceHelper()); model.setModelName(name); model.setDomain(domain); String solutionStorage = AgileHelper.getDatasourceSolutionStorage(); String metadataLocation = "resources" + ISolutionRepository.SEPARATOR + "metadata"; //$NON-NLS-1$ //$NON-NLS-2$ String path = solutionStorage + ISolutionRepository.SEPARATOR + metadataLocation + ISolutionRepository.SEPARATOR; domainId = path + name + ".xmi"; //$NON-NLS-1$ domain.setId(domainId); IApplicationContext appContext = PentahoSystem.getApplicationContext(); if (appContext != null) { path = PentahoSystem.getApplicationContext().getSolutionPath(path); } File pathDir = new File(path); if (!pathDir.exists()) { pathDir.mkdirs(); } IPentahoObjectFactory pentahoObjectFactory = PentahoSystem.getObjectFactory(); IPentahoSession session = pentahoObjectFactory.get(IPentahoSession.class, "systemStartupSession", null); //$NON-NLS-1$ ISolutionRepository repository = PentahoSystem.get(ISolutionRepository.class, session); LogicalModel lModel = domain.getLogicalModels().get(0); String catName = lModel.getName(Locale.getDefault().toString()); cleanseExistingCatalog(catName, session); if(doOlap){ lModel.setProperty("MondrianCatalogRef", catName); //$NON-NLS-1$ } XmiParser parser = new XmiParser(); String reportXML = parser.generateXmi(model.getDomain()); // Serialize domain to xmi. String base = PentahoSystem.getApplicationContext().getSolutionRootPath(); String parentPath = ActionInfo.buildSolutionPath(solutionStorage, metadataLocation, ""); //$NON-NLS-1$ int status = repository.publish(base, '/' + parentPath, name + ".xmi", reportXML.getBytes("UTF-8"), true); //$NON-NLS-1$ //$NON-NLS-2$ if (status != ISolutionRepository.FILE_ADD_SUCCESSFUL) { throw new RuntimeException("Unable to save to repository. Status: " + status); //$NON-NLS-1$ } // Serialize domain to olap schema. if(doOlap){ MondrianModelExporter exporter = new MondrianModelExporter(lModel, Locale.getDefault().toString()); String mondrianSchema = exporter.createMondrianModelXML(); Document schemaDoc = DocumentHelper.parseText(mondrianSchema); byte[] schemaBytes = schemaDoc.asXML().getBytes("UTF-8"); //$NON-NLS-1$ status = repository.publish(base, '/' + parentPath, name + ".mondrian.xml", schemaBytes, true); //$NON-NLS-1$ if (status != ISolutionRepository.FILE_ADD_SUCCESSFUL) { throw new RuntimeException("Unable to save to repository. Status: " + status); //$NON-NLS-1$ } // Refresh Metadata PentahoSystem.publish(session, MetadataPublisher.class.getName()); // Write this catalog to the default Pentaho DataSource and refresh the cache. File file = new File(path + name + ".mondrian.xml"); //$NON-NLS-1$ // Need to find a better way to get the connection name instead of using the Id. String catConnectStr = "Provider=mondrian;DataSource=" + ((SqlPhysicalModel) domain.getPhysicalModels().get(0)).getId(); //$NON-NLS-1$ String catDef = "solution:" + solutionStorage + ISolutionRepository.SEPARATOR //$NON-NLS-1$ + "resources" + ISolutionRepository.SEPARATOR + "metadata" + ISolutionRepository.SEPARATOR + file.getName(); //$NON-NLS-1$//$NON-NLS-2$ addCatalog(catName, catConnectStr, catDef, session); } } catch (Exception e) { logger.error(e); throw e; } return domainId; } private void cleanseExistingCatalog(String catName, IPentahoSession session) { // If mondrian catalog exists delete it to avoid duplicates and orphan entries in the datasources.xml registry. //IPentahoSession session = PentahoSessionHolder.getSession(); if(session != null) { IMondrianCatalogService service = PentahoSystem.get(IMondrianCatalogService.class, null); MondrianCatalog catalog = service.getCatalog(catName, session); if(catalog != null) { service.removeCatalog(catName, session); } } } private void addCatalog(String catName, String catConnectStr, String catDef, IPentahoSession session) { IMondrianCatalogService mondrianCatalogService = PentahoSystem.get(IMondrianCatalogService.class, "IMondrianCatalogService", session); //$NON-NLS-1$ String dsUrl = PentahoSystem.getApplicationContext().getBaseUrl(); if (!dsUrl.endsWith("/")) { //$NON-NLS-1$ dsUrl += "/"; //$NON-NLS-1$ } dsUrl += "Xmla"; //$NON-NLS-1$ MondrianDataSource ds = new MondrianDataSource( "Provider=Mondrian;DataSource=Pentaho", //$NON-NLS-1$ "Pentaho BI Platform Datasources", //$NON-NLS-1$ dsUrl, "Provider=Mondrian", // no default jndi datasource should be specified //$NON-NLS-1$ "PentahoXMLA", //$NON-NLS-1$ DataSource.PROVIDER_TYPE_MDP, DataSource.AUTH_MODE_UNAUTHENTICATED, null ); MondrianCatalog cat = new MondrianCatalog( catName, catConnectStr, catDef, ds, new MondrianSchema(catName, new ArrayList<MondrianCube>()) ); mondrianCatalogService.addCatalog(cat, true, session); } public Domain loadDomain(String id) throws Exception { IMetadataDomainRepository repo = PentahoSystem.get(IMetadataDomainRepository.class); return repo.getDomain(id); } }