| /* |
| * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0, which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, |
| * version 2 with the GNU Classpath Exception, which is available at |
| * https://www.gnu.org/software/classpath/license.html. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| */ |
| |
| package com.sun.connector.cciblackbox; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.sql.CallableStatement; |
| import java.sql.DatabaseMetaData; |
| import java.sql.ResultSet; |
| import java.sql.SQLException; |
| import java.sql.SQLWarning; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import jakarta.resource.ResourceException; |
| import jakarta.resource.cci.IndexedRecord; |
| import jakarta.resource.cci.Interaction; |
| import jakarta.resource.cci.InteractionSpec; |
| import jakarta.resource.cci.Record; |
| import jakarta.resource.cci.ResourceWarning; |
| |
| /** |
| * This implementation class enables a component to execute EIS functions. |
| * @author Sheetal Vartak |
| */ |
| public class CciInteraction implements Interaction { |
| |
| protected jakarta.resource.cci.Connection connection; |
| |
| protected CallableStatement csmt; |
| |
| public CciInteraction(jakarta.resource.cci.Connection con) { |
| connection = con; |
| } |
| |
| public jakarta.resource.cci.Connection getConnection() { |
| return connection; |
| } |
| |
| public void close() throws ResourceException { |
| connection = null; |
| |
| } |
| |
| public boolean execute(InteractionSpec ispec, jakarta.resource.cci.Record input, jakarta.resource.cci.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 |
| */ |
| jakarta.resource.cci.Record exec(String procName, String schema, String catalog, jakarta.resource.cci.Record input, jakarta.resource.cci.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 jakarta.resource.cci.Record execute(InteractionSpec ispec, jakarta.resource.cci.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()); |
| } |
| } |
| |
| } |