/*
* 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 2006 - 2009 Pentaho Corporation. All rights reserved.
*
*
* Created Dec 27, 2006
* @author mdamour
*/
package org.pentaho.platform.plugin.action.hql;
import java.io.File;
import java.util.ArrayList;
import java.util.Map;
import java.util.StringTokenizer;
import org.apache.commons.logging.Log;
import org.pentaho.actionsequence.dom.ActionInputConstant;
import org.pentaho.actionsequence.dom.IActionOutput;
import org.pentaho.actionsequence.dom.IActionResource;
import org.pentaho.actionsequence.dom.actions.HQLConnectionAction;
import org.pentaho.actionsequence.dom.actions.HQLQueryAction;
import org.pentaho.commons.connection.IPentahoConnection;
import org.pentaho.commons.connection.IPentahoResultSet;
import org.pentaho.platform.api.data.IPreparedComponent;
import org.pentaho.platform.api.engine.IActionSequenceResource;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.engine.services.connection.PentahoConnectionFactory;
import org.pentaho.platform.engine.services.runtime.MapParameterResolver;
import org.pentaho.platform.engine.services.runtime.TemplateUtil;
import org.pentaho.platform.engine.services.solution.ComponentBase;
import org.pentaho.platform.plugin.action.messages.Messages;
import org.pentaho.platform.plugin.services.connections.hql.HQLConnection;
public abstract class HQLBaseComponent extends ComponentBase implements IPreparedComponent {
private static final long serialVersionUID = 5949258346877934670L;
private IPentahoResultSet rSet;
/** reference to connection object */
private IPentahoConnection connection;
/** specifies whether component owns connection or not */
private boolean connectionOwner = true;
/** holds the query string for ipreparedcomponent functionality */
private String preparedQuery = null;
@Override
public abstract boolean validateSystemSettings();
public abstract String getResultOutputName();
@Override
public abstract Log getLogger();
public IPentahoResultSet getResultSet() {
return rSet;
}
@Override
protected boolean validateAction() {
HQLConnectionAction connAction = null;
HQLQueryAction queryAction = null;
boolean actionValidated = true;
try {
if (getActionDefinition() instanceof HQLQueryAction) {
queryAction = (HQLQueryAction) getActionDefinition();
actionValidated = isConnectionInfoSpecified(queryAction);
// Check if the query is defined.
if (actionValidated && (queryAction.getQuery() == ActionInputConstant.NULL_INPUT)) {
actionValidated = false;
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0004_QUERY_NOT_SPECIFIED", getActionName())); //$NON-NLS-1$
}
// Check if output for the query is correctly defined.
if (actionValidated && (queryAction.getOutputResultSetName() == null)
&& (queryAction.getOutputPreparedStatementName() == null)) {
actionValidated = false;
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0005_OUTPUT_NOT_SPECIFIED", getActionName())); //$NON-NLS-1$
}
} else if (getActionDefinition() instanceof HQLConnectionAction) {
connAction = (HQLConnectionAction) getActionDefinition();
actionValidated = isConnectionInfoSpecified(connAction);
} else {
actionValidated = false;
error(Messages.getInstance().getErrorString(
"ComponentBase.ERROR_0001_UNKNOWN_ACTION_TYPE", getActionDefinition().getElement().asXML())); //$NON-NLS-1$
}
} catch (Exception e) {
actionValidated = false;
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0006_VALIDATION_FAILED", getActionName()), e); //$NON-NLS-1$
}
return actionValidated;
}
private boolean isConnectionInfoSpecified(final HQLConnectionAction connAction) {
boolean value = true;
if (connAction instanceof HQLQueryAction) {
if ((((HQLQueryAction) connAction).getInputSharedConnection() == ActionInputConstant.NULL_INPUT)
&& !isBasicConnectionInfoSpecified(connAction)) {
value = false;
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0003_CONNECTION_INFO_NOT_SPECIFIED", getActionName())); //$NON-NLS-1$
}
} else {
if (!isBasicConnectionInfoSpecified(connAction)) {
value = false;
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0003_CONNECTION_INFO_NOT_SPECIFIED", getActionName())); //$NON-NLS-1$
}
}
return value;
}
private boolean isBasicConnectionInfoSpecified(final HQLConnectionAction connAction) {
boolean value = true;
if (connAction.getClassNames() == ActionInputConstant.NULL_INPUT) {
value = false;
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0001_CLASS_NAMES_INFO_NOT_SPECIFIED", getActionName())); //$NON-NLS-1$
}
if (connAction.getHibernateConfigResource() == null) {
value = false;
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0002_HIBERNATE_CONFIG_INFO_NOT_SPECIFIED", getActionName())); //$NON-NLS-1$
}
return value;
}
@Override
public void done() {
// TODO Auto-generated method stub
}
@Override
protected boolean executeAction() {
boolean returnValue = true;
try {
if (getActionDefinition() instanceof HQLQueryAction) {
HQLQueryAction queryAction = (HQLQueryAction) getActionDefinition();
String classNames[] = null;
String query = queryAction.getQuery().getStringValue();
if (queryAction.getInputSharedConnection() != ActionInputConstant.NULL_INPUT) {
connectionOwner = false;
IPreparedComponent component = (IPreparedComponent) queryAction.getInputSharedConnection().getValue();
IPentahoConnection conn = component.shareConnection();
if (IPentahoConnection.HQL_DATASOURCE.equals(conn.getDatasourceType())) {
connection = conn;
} else {
connection = null;
returnValue = false;
error(Messages.getInstance().getErrorString("IPreparedComponent.ERROR_0001_INVALID_CONNECTION_TYPE", getActionName())); //$NON-NLS-1$
}
} else {
createBasicConnection(queryAction, classNames);
}
if (connection != null) {
IActionOutput actionOutput = queryAction.getOutputPreparedStatementParam();
if (actionOutput != null) {
// prepare the query for execution, but don't execute quite yet.
prepareQuery(query);
// set the output as self, which will be used later by another component.
actionOutput.setValue(this);
} else {
return runQuery(connection, classNames, query);
}
}
} else if (getActionDefinition() instanceof HQLConnectionAction) {
HQLConnectionAction connAction = (HQLConnectionAction) getActionDefinition();
String classNames[] = null;
createBasicConnection(connAction, classNames);
if (connection != null) {
IActionOutput outputConnection = connAction.getOutputConnectionParam();
if (outputConnection != null) {
outputConnection.setValue(this);
}
}
} else {
returnValue = false;
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_00011_INVALID_HQL_COMPONENT", getActionName())); //$NON-NLS-1$
}
} catch (Exception e) {
returnValue = false;
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_00012_EXECUTE_FAILED", getActionName()), e); //$NON-NLS-1$
}
return returnValue;
}
/*
* Create the basic connection. This requires retrieving class names and catalog info.
*/
private void createBasicConnection(final HQLConnectionAction connAction, String[] classNames) {
boolean proceed = true;
String catalog = null;
if (connAction.getClassNames() != ActionInputConstant.NULL_INPUT) {
classNames = getClassNames(connAction);
} else {
proceed = false;
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0001_CLASS_NAMES_INFO_NOT_SPECIFIED", getActionName())); //$NON-NLS-1$
}
if (proceed) {
catalog = getCatalog();
if ((null == catalog) || (catalog.trim().length() <= 0)) {
proceed = false;
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_00010_CATALOG_INFO_NOT_SPECIFIED", getActionName())); //$NON-NLS-1$
}
}
if (proceed) {
connection = getConnection(new File(catalog), classNames);
if (connection == null) {
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0009_COULD_NOT_ESTABLISH_CONNECTION", getActionName())); //$NON-NLS-1$
}
}
}
/*
* Utitlity function to get the class names from the XML.
*/
private String[] getClassNames(final HQLConnectionAction connAction) {
ArrayList classNamesList = new ArrayList();
String classNames[] = null;
try {
String classes = connAction.getClassNames().getStringValue();
StringTokenizer st = new StringTokenizer(classes, ",");//getInputStringValue(CLASSNAMES), ","); //$NON-NLS-1$
while (st.hasMoreTokens()) {
String token = st.nextToken();
classNamesList.add(token.trim());
}
classNames = (String[]) classNamesList.toArray(new String[0]);
} catch (Exception e) {
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0008_COULD_NOT_RETRIEVE_CLASS_NAMES", getActionName()), e); //$NON-NLS-1$
}
return classNames;
}
/*
* Utility function to get the catalog info from hibernate config.
*/
private String getCatalog() {
IActionResource hibernateConfigRes = ((HQLConnectionAction) getActionDefinition()).getHibernateConfigResource();
String catalog = null;
String resAddress = null;
if (hibernateConfigRes != null) {
String resName = this.applyInputsToFormat(hibernateConfigRes.getName());
IActionSequenceResource resource = getResource(resName);
resAddress = resource.getAddress();
if (resAddress != null) {
catalog = this.applyInputsToFormat(resAddress);
}
if (resource.getSourceType() == IActionSequenceResource.SOLUTION_FILE_RESOURCE) {
catalog = PentahoSystem.getApplicationContext().getSolutionPath(catalog);
}
}
return catalog;
}
/**
* called when in prepared-component mode, this method populates the preparedQuery string and
* preparedParameters object.
*
* @param rawQuery
* @return
*/
protected boolean prepareQuery(final String rawQuery) {
try {
if (connection == null) {
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_00013_NO_CONNECTION")); //$NON-NLS-1$
return false;
}
if (!connection.initialized()) {
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_00013_NO_CONNECTION")); //$NON-NLS-1$
return false;
}
if (rawQuery != null) {
preparedQuery = applyInputsToFormat(rawQuery);
}
return true;
} catch (Exception e) {
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_00014_COULD_NOT_PREPARE_QUERY", getActionName()), e); //$NON-NLS-1$
}
return false;
}
/**
* executes a prepared method that returns a result set
* executePrepared looks up any "PREPARELATER" params
* in the preparedParams map.
*
* @param preparedParams a map of possible parameters.
* @return result set
*/
public IPentahoResultSet executePrepared(final Map preparedParams) {
try {
if (connection == null) {
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0009_COULD_NOT_ESTABLISH_CONNECTION")); //$NON-NLS-1$
return null;
}
if (!connection.initialized()) {
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0009_COULD_NOT_ESTABLISH_CONNECTION")); //$NON-NLS-1$
return null;
}
if (preparedQuery == null) {
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_00016_QUERY_NOT_SPECIFIED")); //$NON-NLS-1$
return null;
}
// parse preparedQuery, replacing any {PREPARELATER:NAME} with appropriate values
String query = TemplateUtil.applyTemplate(preparedQuery, getRuntimeContext(), new MapParameterResolver(
preparedParams, IPreparedComponent.PREPARE_LATER_PREFIX, getRuntimeContext()));
if (ComponentBase.debug) {
debug(Messages.getInstance().getString("HQLBaseComponent.DEBUG_RUNNING_QUERY", query)); //$NON-NLS-1$
}
// evaluate
IPentahoResultSet resultSet = connection.executeQuery(query);
rSet = resultSet;
return resultSet;
} catch (Exception e) {
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_00012_EXECUTE_FAILED", getActionName()), e); //$NON-NLS-1$
}
return null;
}
protected boolean runQuery(final IPentahoConnection conn, final String[] classNames, final String query) {
try {
if (conn == null) {
return false;
}
rSet = ((HQLConnection) conn).executeQuery(query);
IActionOutput actionOutput = ((HQLQueryAction) getActionDefinition()).getOutputResultSetParam();
if (actionOutput != null) {
actionOutput.setValue(rSet);
}
return true;
} catch (Exception e) {
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0007_QUERY_EXECUTION_FAILED", getActionName()), e); //$NON-NLS-1$
return false;
}
}
/**
* if the owner, dispose of the connection
*/
public void dispose() {
if (connectionOwner) {
if (connection != null) {
connection.close();
}
}
connection = null;
}
protected IPentahoConnection getConnection(final File hbmCfgFile, final String classNames[]) {
IPentahoConnection conn = null;
try {
conn = (HQLConnection) PentahoConnectionFactory.getConnection("HQL", getSession(), this); //$NON-NLS-1$
HQLConnection hconn = (HQLConnection) conn;
hconn.setConfigFile(hbmCfgFile);
hconn.setClassNames(classNames);
return conn;
} catch (Exception e) {
error(Messages.getInstance().getErrorString("HQLBaseComponent.ERROR_0009_COULD_NOT_ESTABLISH_CONNECTION", getActionName()), e); //$NON-NLS-1$
}
return null;
}
/**
* return this class's connection. This implements the IPreparedComponent
* interface, which may share its connection with others.
*
* @return connection object
*/
public IPentahoConnection shareConnection() {
return connection;
}
@Override
public boolean init() {
return true;
}
}