/* * 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 2005 - 2009 Pentaho Corporation. All rights reserved. * * * Created Sep 12, 2005 * @author wseyler */ package org.pentaho.platform.plugin.services.connections.mondrian; import java.util.Enumeration; import java.util.List; import java.util.Properties; import javax.sql.DataSource; import mondrian.olap.Connection; import mondrian.olap.DriverManager; import mondrian.olap.Query; import mondrian.olap.Result; import mondrian.olap.Util; import mondrian.rolap.RolapConnectionProperties; import org.pentaho.commons.connection.IPentahoConnection; import org.pentaho.commons.connection.IPentahoResultSet; import org.pentaho.metadata.messages.LocaleHelper; import org.pentaho.platform.api.data.IDatasourceService; import org.pentaho.platform.api.engine.IConnectionUserRoleMapper; import org.pentaho.platform.api.engine.ILogger; import org.pentaho.platform.api.engine.PentahoAccessControlException; import org.pentaho.platform.engine.core.system.IPentahoLoggingConnection; import org.pentaho.platform.engine.core.system.PentahoSessionHolder; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.plugin.services.messages.Messages; import org.pentaho.platform.util.logging.Logger; /** * @author wseyler * * TODO To change the template for this generated type comment go to Window - * Preferences - Java - Code Style - Code Templates */ public class MDXConnection implements IPentahoLoggingConnection { /** * Defines the XML element in the component-definition that holds the * mondrian-specific MDX Connection string. */ public static final String CONNECTION_STRING_KEY = "mdx-connection-string"; //$NON-NLS-1$ public static final String MDX_CONNECTION_MAPPER_KEY = "Mondrian-UserRoleMapper"; //$NON-NLS-1$ Connection nativeConnection = null; String lastQuery = null; IPentahoResultSet resultSet = null; ILogger logger = null; private boolean useExtendedColumnNames = false; public MDXConnection() { super(); } public void setLogger(final ILogger logger) { this.logger = logger; } public void setProperties(final Properties props) { // TODO: consolidate this in the init String connectStr = props.getProperty(IPentahoConnection.JNDI_NAME_KEY); if (connectStr != null) { init(connectStr); } else { final String connection = props.getProperty(IPentahoConnection.CONNECTION); final String provider = props.getProperty(IPentahoConnection.PROVIDER); final String userName = props.getProperty(IPentahoConnection.USERNAME_KEY); final String password = props.getProperty(IPentahoConnection.PASSWORD_KEY); if (connection != null && provider != null) { init(connection, provider, userName, password); } else { init(props); } } } /** * @param driver - The name of the driver or the connection string * @param provider - the provider for MDX usally "mondrian" * @param userName - User to connect to the datasource with * @param password - Password for the user * * @deprecated * @see MDXConnection(Properties props, ILogger logger) */ @Deprecated public MDXConnection(final String driver, final String provider, final String userName, final String password) { super(); init(driver, provider, userName, password); } public MDXConnection(final String connectStr, final ILogger logger) { super(); this.logger = logger; init(connectStr); } protected void init(final String connectStr) { Util.PropertyList properties = Util.parseConnectString(connectStr); init(properties); } @SuppressWarnings( "unchecked" ) protected void init(final Properties properties) { Util.PropertyList pl = new Util.PropertyList(); Enumeration enum1 = properties.keys(); while (enum1.hasMoreElements()) { Object key = enum1.nextElement(); Object value = properties.get(key); pl.put(key.toString(), value.toString()); } init(pl); } protected void init(final String driver, final String provider, final String userName, final String password) { StringBuffer buffer = new StringBuffer(); buffer.append("provider=" + provider); //$NON-NLS-1$ // // MB - This is a hack. Should instead have either a flag or a // different method for specifying a datasource instead of this. // // TODO: Fix for post 1.2 RC 2 // // // WES - This hack was fixed up to maintain backward capability. // In addition methods were added so that connection info can be passed // in via a properties map. if (driver.indexOf("dataSource=") >= 0) { //$NON-NLS-1$ buffer.append("; ").append(driver); //$NON-NLS-1$ } else { buffer.append("; Jdbc=" + driver); //$NON-NLS-1$ } if (userName != null) { buffer.append("; JdbcUser=" + userName); //$NON-NLS-1$ } if (password != null) { buffer.append("; JdbcPassword=" + password); //$NON-NLS-1$ } init(buffer.toString()); } protected void mapPlatformRolesToMondrianRoles(Util.PropertyList properties) throws PentahoAccessControlException { if (properties.get(RolapConnectionProperties.Role.name(), null) == null) { // Only if the action sequence/requester hasn't already injected a role in here do this. IConnectionUserRoleMapper mondrianUserRoleMapper = PentahoSystem.get(IConnectionUserRoleMapper.class, MDXConnection.MDX_CONNECTION_MAPPER_KEY, null); if (mondrianUserRoleMapper != null) { // Do role mapping String[] validMondrianRolesForUser = mondrianUserRoleMapper.mapConnectionRoles(PentahoSessionHolder.getSession(), properties.get(RolapConnectionProperties.Catalog.name())); if ( (validMondrianRolesForUser != null) && (validMondrianRolesForUser.length>0) ) { StringBuffer buff = new StringBuffer(); String aRole = null; for (int i=0; i<validMondrianRolesForUser.length; i++) { aRole = validMondrianRolesForUser[i]; // According to http://mondrian.pentaho.org/documentation/configuration.php // double-comma escapes a comma if (i>0) { buff.append(","); } buff.append(aRole.replaceAll(",", ",,")); } properties.put(RolapConnectionProperties.Role.name(), buff.toString()); } } } } protected void init(Util.PropertyList properties) { try { if (nativeConnection != null) { // Assume we're open close(); } // default behavior in the platform is to have I18N support for MDX Connection if (properties.get(RolapConnectionProperties.DynamicSchemaProcessor.name()) == null) { properties.put(RolapConnectionProperties.DynamicSchemaProcessor.name(), "mondrian.i18n.LocalizingDynamicSchemaProcessor"); //$NON-NLS-1$ properties.put(RolapConnectionProperties.Locale.name(), LocaleHelper.getLocale().toString()); } String dataSourceName = properties.get(RolapConnectionProperties.DataSource.name()); mapPlatformRolesToMondrianRoles(properties); if (dataSourceName != null) { IDatasourceService datasourceService = PentahoSystem.getObjectFactory().get(IDatasourceService.class ,null); DataSource dataSourceImpl = datasourceService.getDataSource(dataSourceName); if (dataSourceImpl != null) { properties.remove(RolapConnectionProperties.DataSource.name()); nativeConnection = DriverManager.getConnection(properties, null, dataSourceImpl); } else { nativeConnection = DriverManager.getConnection(properties, null); } } else { nativeConnection = DriverManager.getConnection(properties, null); } if (nativeConnection == null) { logger.error(Messages.getInstance().getErrorString( "MDXConnection.ERROR_0002_INVALID_CONNECTION", properties != null ? properties.toString() : "null")); //$NON-NLS-1$ //$NON-NLS-2$ } } catch (Throwable t) { if (logger != null) { logger.error(Messages.getInstance().getErrorString( "MDXConnection.ERROR_0002_INVALID_CONNECTION", properties != null ? properties.toString() : "null"), t); //$NON-NLS-1$ //$NON-NLS-2$ } else { Logger.error(this.getClass().getName(), Messages.getInstance().getErrorString( "MDXConnection.ERROR_0002_INVALID_CONNECTION", properties != null ? properties.toString() : "null"), t); //$NON-NLS-1$ //$NON-NLS-2$ } } } public boolean initialized() { return nativeConnection != null; } @SuppressWarnings( "unchecked" ) public IPentahoResultSet prepareAndExecuteQuery(final String query, final List parameters) throws Exception { throw new UnsupportedOperationException(); } public boolean preparedQueriesSupported() { return false; } /* * (non-Javadoc) * * @see org.pentaho.connection.IPentahoConnection#close() */ public void close() { if (nativeConnection != null) { nativeConnection.close(); } } /* * (non-Javadoc) * * @see org.pentaho.connection.IPentahoConnection#getLastQuery() */ public String getLastQuery() { return lastQuery; } /* * (non-Javadoc) * * @see org.pentaho.connection.IPentahoConnection#executeQuery(java.lang.String) */ public IPentahoResultSet executeQuery(final String query) { Query mdxQuery = nativeConnection.parseQuery(query); Result result = nativeConnection.execute(mdxQuery); resultSet = new MDXResultSet(result, nativeConnection, useExtendedColumnNames); return resultSet; } /* * (non-Javadoc) * * @see org.pentaho.connection.IPentahoConnection#isClosed() */ public boolean isClosed() { return false; } /* * (non-Javadoc) * * @see org.pentaho.connection.IPentahoConnection#isReadOnly() */ public boolean isReadOnly() { return true; } /* * (non-Javadoc) * * @see org.pentaho.connection.IPentahoConnection#clearWarnings() */ public void clearWarnings() { // TODO Auto-generated method stub } public IPentahoResultSet getResultSet() { return resultSet; } public boolean connect(final Properties props) { if (nativeConnection != null) { // Assume we're open close(); } init(props); String query = props.getProperty(IPentahoConnection.QUERY_KEY); if ((query != null) && (query.length() > 0) && (nativeConnection != null)) { executeQuery(query); } return nativeConnection != null; } /* * (non-Javadoc) * * @see org.pentaho.connection.IPentahoConnection#setMaxRows(int) */ public void setMaxRows(final int maxRows) { // TODO Auto-generated method stub throw new UnsupportedOperationException(); } /* * (non-Javadoc) * * @see org.pentaho.connection.IPentahoConnection#setFetchSize(int) */ public void setFetchSize(final int fetchSize) { // TODO Auto-generated method stub throw new UnsupportedOperationException(); } public Connection getConnection() { return nativeConnection; } /** * return datasource type MDX * @return datasource type */ public String getDatasourceType() { return IPentahoConnection.MDX_DATASOURCE; } public void setUseExtendedColumnNames(boolean useExtendedColumnNames) { this.useExtendedColumnNames = useExtendedColumnNames; } }