/*
* Use of this J2EE Connectors Sample Source Code file is governed by
* the following modified BSD license:
*
* Copyright 2002 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* -Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* -Redistribution in binary form must reproduct the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND
* ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES OR LIABILITIES
* SUFFERED BY LICENSEE AS A RESULT OF OR RELATING TO USE, MODIFICATION
* OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
* OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
* PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
* LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that Software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
package com.sun.connector.cciblackbox;
import java.sql.*;
import java.util.*;
import javax.resource.ResourceException;
import javax.resource.spi.ConnectionEvent;
import javax.resource.spi.IllegalStateException;
import javax.resource.cci.*;
import java.lang.reflect.*;
import java.lang.*;
import java.sql.ResultSet;
/**
* This implementation class enables a component to execute EIS functions.
* @author Sheetal Vartak
*/
public class CciInteraction implements Interaction {
private javax.resource.cci.Connection connection;
private CallableStatement csmt;
public CciInteraction(javax.resource.cci.Connection con) {
connection = con;
}
public javax.resource.cci.Connection getConnection() {
return connection;
}
public void close() throws ResourceException {
connection = null;
}
public boolean execute (InteractionSpec ispec, Record input, Record output)
throws ResourceException {
if (ispec == null ||
(!(ispec instanceof CciInteractionSpec))) {
throw new ResourceException("Invalid interaction spec");
}
String procName = ((CciInteractionSpec)ispec).getFunctionName();
String schema = ((CciInteractionSpec)ispec).getSchema();
String catalog = ((CciInteractionSpec)ispec).getCatalog();
output = exec(procName,schema,catalog,input,output);
if (output != null) {
return true;
} else {
return false;
}
}
/**
* This method does the following:
* 1> using the DatabaseMetadata class, gets the parameters that are IN,OUT
* or INOUT for the stored procedure.
* 2>create the callablestatement withthe right JDBC syntax
* e.g. {? = call proc_name(?,?)}
* {call proc_name(?)}
* {? = call proc_name()}
* 3> execute the statement and return the output in an IndexedRecord object
*/
Record exec(String procName, String schema, String catalog,
Record input,Record output) throws ResourceException {
try{
java.sql.Connection conn =
((CciConnection)connection).getManagedConnection().getJdbcConnection();
DatabaseMetaData metadata =conn.getMetaData();
if (!metadata.supportsCatalogsInProcedureCalls()) {
catalog = "";
}
if (!metadata.supportsSchemasInProcedureCalls()) {
schema = "";
}
ResultSet procNames =
metadata.getProcedures(catalog, schema, procName);
int procFound = 0;
while (procNames.next()) {
procFound++;
}
procNames.close();
if (procFound == 0) {
throw new ResourceException("Cannot find procedure " +
procName +
". Please check catalog, schema and function name.");
}
ResultSet rs =
metadata.getProcedureColumns(catalog,schema,procName,null);
List parameterList = new ArrayList();
boolean function=false;
while(rs.next()) {
if((rs.getShort(5)==DatabaseMetaData.procedureColumnReturn)
&& (!((rs.getString(7)).equals("void")))) {
function= true;
}
if (rs.getString(7).equals("void")) {
continue; // skip extra info from Cloudscape
}
parameterList.add(new Parameter( rs.getString(1),
rs.getString(2),
rs.getString(3),
rs.getString(4),
rs.getShort(5),
rs.getShort(6),
rs.getShort(10)));
}
rs.close();
int paramCount = parameterList.size();
if (function) {
paramCount -= 1;
}
//if the procedure is parameterless, paramCount = 0
procName += "(";
for(int i=0;i<paramCount;i++) {
if (i == 0) {
procName += "?";
} else {
procName += ",?";
}
}
procName += ")";
String schemaAddOn = "";
if (schema != null && !schema.equals("")) {
schemaAddOn = schema + ".";
}
if (function) {
procName = "? = call " + schemaAddOn + procName;
} else {
procName = "call " + schemaAddOn + procName;
}
//System.out.println("procName.."+procName);
CallableStatement cstmt =
conn.prepareCall("{"+ procName +"}");
//get all IN parameters and register all OUT parameters
int count = parameterList.size();
int recCount = 0;
IndexedRecord iRec = null;
for (int i=0; i<count; i++) {
Parameter parameter = (Parameter) parameterList.get(i);
if (parameter.isInputColumn()) {
if (iRec == null) {
if (input instanceof IndexedRecord) {
iRec = (IndexedRecord) input;
} else {
throw new ResourceException("Invalid input record");
}
}
//get value from input record
cstmt.setObject(i+1, iRec.get(recCount));
recCount++;
}
}
IndexedRecord oRec = null;
for (int i=0; i<count; i++) {
Parameter parameter = (Parameter) parameterList.get(i);
if (parameter.isOutputColumn()) {
if (oRec == null) {
if (output instanceof IndexedRecord) {
oRec = (IndexedRecord) output;
} else {
throw new ResourceException("Invalid output record");
}
}
if (parameter.isDecimalNumeric()) {
cstmt.registerOutParameter
(i+1, parameter.getDataType(),
parameter.getScale());
} else {
cstmt.registerOutParameter
(i+1, parameter.getDataType());
}
}
}
cstmt.execute();
Class[] parameters = new Class[] {int.class};
//get the right getXXX() from Mapping.java for the output
Mapping map = new Mapping();
for(int i=0; i<count; i++) {
Parameter parameter = (Parameter) parameterList.get(i);
if(parameter.isOutputColumn()) {
String ans =(String)
map.get(new Integer(parameter.getDataType()));
Method method =
cstmt.getClass().getMethod(ans,parameters);
Object[] obj = new Object[] {new Integer(i+1)};
Object o=method.invoke(cstmt,obj);
if(output instanceof IndexedRecord) {
oRec = (IndexedRecord)output;
oRec.add(o);
//System.out.println("output..."+o.toString());
}
}
}
cstmt.close();
return oRec;
// conn.close();
} catch(SQLException ex) {
throw new ResourceException(ex.getMessage());
} catch (NoSuchMethodException ex) {
throw new ResourceException(ex.getMessage());
} catch (IllegalAccessException ex) {
throw new ResourceException(ex.getMessage());
} catch (InvocationTargetException ex) {
throw new ResourceException(ex.getMessage());
}
}
public Record execute (InteractionSpec ispec, Record input)
throws ResourceException {
if (ispec == null ||
(!(ispec instanceof CciInteractionSpec))) {
throw new ResourceException("Invalid interaction spec");
}
String procName = ((CciInteractionSpec)ispec).getFunctionName();
String schema = ((CciInteractionSpec)ispec).getSchema();
String catalog = ((CciInteractionSpec)ispec).getCatalog();
IndexedRecord output = new CciIndexedRecord();
return exec(procName,schema,catalog,input,output);
}
public ResourceWarning getWarnings() throws ResourceException {
ResourceWarning resWarning=null;
try {
java.sql.Connection con =
((CciConnection)connection).getManagedConnection().getJdbcConnection();
SQLWarning sql = con.getWarnings();
resWarning = new ResourceWarning(sql.getMessage());
}catch(SQLException e) {
throw new ResourceException(e.getMessage());
}
return resWarning;
}
public void clearWarnings() throws ResourceException {
try {
java.sql.Connection con =
((CciConnection)connection).getManagedConnection().getJdbcConnection();
con.clearWarnings();
}catch(SQLException e) {
throw new ResourceException(e.getMessage());
}
}
}