View Javadoc
1   package org.synchronoss.cpo.jdbc;
2   
3   /*-
4    * [[
5    * jdbc
6    * ==
7    * Copyright (C) 2003 - 2026 Exaxis LLC, Synchronoss Technologies Inc
8    * ==
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ]]
23   */
24  
25  import java.sql.CallableStatement;
26  import java.sql.Connection;
27  import java.sql.SQLException;
28  import java.util.ArrayList;
29  import java.util.List;
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  import org.synchronoss.cpo.core.CpoData;
33  import org.synchronoss.cpo.core.CpoException;
34  import org.synchronoss.cpo.core.CpoReleasable;
35  import org.synchronoss.cpo.core.meta.domain.CpoArgument;
36  import org.synchronoss.cpo.core.meta.domain.CpoClass;
37  import org.synchronoss.cpo.core.meta.domain.CpoFunction;
38  
39  /**
40   * JdbcCallableStatementFactory is the object that encapsulates the creation of the actual
41   * CallableStatement for the JDBC driver.
42   *
43   * @author david berry
44   */
45  public final class JdbcCallableStatementFactory implements CpoReleasable {
46  
47    private static final Logger logger = LoggerFactory.getLogger(JdbcCallableStatementFactory.class);
48    private CallableStatement cs_ = null;
49  
50    private JdbcCallableStatementFactory() {}
51  
52    private List<CpoReleasable> releasables = new ArrayList<>();
53    private List<CpoArgument> outArguments = new ArrayList<>();
54  
55    /**
56     * Used to build the CallableStatement that is used by CPO to create the actual JDBC
57     * CallableStatement. The constructor is called by the internal CPO framework. This is not to be
58     * used by users of CPO. Programmers that build Transforms may need to use this object to get
59     * access to the actual connection.
60     *
61     * @param conn The actual jdbc connection that will be used to create the callable statement.
62     * @param jca The JdbcCpoAdapter that is controlling this transaction
63     * @param function The CpoFunction that is being executed
64     * @param criteria The bean that is being acted upon
65     * @param resultClass An instance of the result class
66     * @throws CpoException if a CPO error occurs
67     */
68    public JdbcCallableStatementFactory(
69        Connection conn,
70        JdbcCpoAdapter jca,
71        CpoFunction function,
72        Object criteria,
73        CpoClass resultClass)
74        throws CpoException {
75      CallableStatement cstmt;
76      JdbcCpoAttribute attribute;
77      Logger localLogger = criteria == null ? logger : LoggerFactory.getLogger(criteria.getClass());
78  
79      try {
80        outArguments = function.getArguments();
81  
82        localLogger.debug("SQL = <" + function.getExpression() + ">");
83  
84        // prepare the Callable Statement
85        cstmt = conn.prepareCall(function.getExpression());
86        setCallableStatement(cstmt);
87  
88        int j = 1;
89        for (CpoArgument argument : outArguments) {
90          JdbcCpoArgument jdbcArgument = (JdbcCpoArgument) argument;
91          attribute = (JdbcCpoAttribute) argument.getAttribute();
92  
93          if (jdbcArgument.isInParameter()) {
94            CpoData cpoData = new CallableStatementCpoData(this, attribute, j);
95            cpoData.invokeSetter(criteria);
96          }
97  
98          if (jdbcArgument.isOutParameter()) {
99            // The function will not know the type of the attribute on the result object, so look it
100           // up now
101           if (attribute == null) {
102             attribute = (JdbcCpoAttribute) resultClass.getAttributeJava(argument.getName());
103             if (attribute == null) {
104               throw new CpoException(
105                   "Attribute <"
106                       + argument.getName()
107                       + "> does not exist on class <"
108                       + resultClass.getName()
109                       + ">");
110             }
111           }
112           localLogger.debug(
113               "Setting OUT parameter " + j + " as Type " + attribute.getDataTypeInt());
114           if (jdbcArgument.getTypeInfo() != null)
115             cstmt.registerOutParameter(j, attribute.getDataTypeInt(), jdbcArgument.getTypeInfo());
116           else cstmt.registerOutParameter(j, attribute.getDataTypeInt());
117         }
118         j++;
119       }
120 
121     } catch (SQLException e) {
122       throw new CpoException("Error Instantiating JdbcCallableStatementFactory", e);
123     }
124   }
125 
126   /**
127    * returns the jdbc callable statment associated with this object
128    *
129    * @return The CallableStatement
130    */
131   public CallableStatement getCallableStatement() {
132     return cs_;
133   }
134 
135   /**
136    * Set the callable statement for this factory.
137    *
138    * @param cs the callable statement
139    */
140   protected void setCallableStatement(CallableStatement cs) {
141     cs_ = cs;
142   }
143 
144   /**
145    * returns the Out parameters from the callable statement
146    *
147    * @return The out arguments from the Callable Statement
148    */
149   public List<CpoArgument> getOutArguments() {
150     return outArguments;
151   }
152 
153   /**
154    * Adds a releasable object to this object. The release method on the releasable will be called
155    * when the callableStatement is executed.
156    *
157    * @param releasable - A CpoReleasable object. An Object whose lifetime is associated with the
158    *     lifetime of the Callable statement
159    */
160   public void AddReleasable(CpoReleasable releasable) {
161     if (releasable != null) {
162       releasables.add(releasable);
163     }
164   }
165 
166   /**
167    * Called by the CPO framework. This method calls the {@code release} on all the CpoReleasable
168    * associated with this object
169    */
170   @Override
171   public void release() throws CpoException {
172     for (CpoReleasable releasable : releasables) {
173       try {
174         releasable.release();
175       } catch (CpoException ce) {
176         logger.error("Error Releasing Callable Statement Transform Object", ce);
177         throw ce;
178       }
179     }
180   }
181 }