/*
* 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;
}
}