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 class JdbcCallableStatementFactory implements CpoReleasable {
46  
47    private static final Logger logger = LoggerFactory.getLogger(JdbcCallableStatementFactory.class);
48    private CallableStatement cs_ = null;
49  
50    @SuppressWarnings("unused")
51    private JdbcCallableStatementFactory() {}
52  
53    private List<CpoReleasable> releasables = new ArrayList<>();
54    private List<CpoArgument> outArguments = new ArrayList<>();
55  
56    /**
57     * Used to build the CallableStatement that is used by CPO to create the actual JDBC
58     * CallableStatement. The constructor is called by the internal CPO framework. This is not to be
59     * used by users of CPO. Programmers that build Transforms may need to use this object to get
60     * access to the actual connection.
61     *
62     * @param conn The actual jdbc connection that will be used to create the callable statement.
63     * @param jca The JdbcCpoAdapter that is controlling this transaction
64     * @param function The CpoFunction that is being executed
65     * @param criteria The bean that is being acted upon
66     * @param resultClass An instance of the result class
67     * @throws CpoException if a CPO error occurs
68     */
69    public JdbcCallableStatementFactory(
70        Connection conn,
71        JdbcCpoAdapter jca,
72        CpoFunction function,
73        Object criteria,
74        CpoClass resultClass)
75        throws CpoException {
76      CallableStatement cstmt;
77      JdbcCpoAttribute attribute;
78      Logger localLogger = criteria == null ? logger : LoggerFactory.getLogger(criteria.getClass());
79  
80      try {
81        outArguments = function.getArguments();
82  
83        localLogger.debug("SQL = <" + function.getExpression() + ">");
84  
85        // prepare the Callable Statement
86        cstmt = conn.prepareCall(function.getExpression());
87        setCallableStatement(cstmt);
88  
89        int j = 1;
90        for (CpoArgument argument : outArguments) {
91          JdbcCpoArgument jdbcArgument = (JdbcCpoArgument) argument;
92          attribute = (JdbcCpoAttribute) argument.getAttribute();
93  
94          if (jdbcArgument.isInParameter()) {
95            CpoData cpoData = new CallableStatementCpoData(this, attribute, j);
96            cpoData.invokeSetter(criteria);
97          }
98  
99          if (jdbcArgument.isOutParameter()) {
100           // The function will not know the type of the attribute on the result object, so look it
101           // up now
102           if (attribute == null) {
103             attribute = (JdbcCpoAttribute) resultClass.getAttributeJava(argument.getName());
104             if (attribute == null) {
105               throw new CpoException(
106                   "Attribute <"
107                       + argument.getName()
108                       + "> does not exist on class <"
109                       + resultClass.getName()
110                       + ">");
111             }
112           }
113           localLogger.debug(
114               "Setting OUT parameter " + j + " as Type " + attribute.getDataTypeInt());
115           if (jdbcArgument.getTypeInfo() != null)
116             cstmt.registerOutParameter(j, attribute.getDataTypeInt(), jdbcArgument.getTypeInfo());
117           else cstmt.registerOutParameter(j, attribute.getDataTypeInt());
118         }
119         j++;
120       }
121 
122     } catch (SQLException e) {
123       throw new CpoException("Error Instantiating JdbcCallableStatementFactory", e);
124     }
125   }
126 
127   /**
128    * returns the jdbc callable statment associated with this object
129    *
130    * @return The CallableStatement
131    */
132   public CallableStatement getCallableStatement() {
133     return cs_;
134   }
135 
136   /**
137    * Set the callable statement for this factory.
138    *
139    * @param cs the callable statement
140    */
141   protected void setCallableStatement(CallableStatement cs) {
142     cs_ = cs;
143   }
144 
145   /**
146    * returns the Out parameters from the callable statement
147    *
148    * @return The out arguments from the Callable Statement
149    */
150   public List<CpoArgument> getOutArguments() {
151     return outArguments;
152   }
153 
154   /**
155    * Adds a releasable object to this object. The release method on the releasable will be called
156    * when the callableStatement is executed.
157    *
158    * @param releasable - A CpoReleasable object. An Object whose lifetime is associated with the
159    *     lifetime of the Callable statement
160    */
161   public void AddReleasable(CpoReleasable releasable) {
162     if (releasable != null) {
163       releasables.add(releasable);
164     }
165   }
166 
167   /**
168    * Called by the CPO framework. This method calls the {@code release} on all the CpoReleasable
169    * associated with this object
170    */
171   @Override
172   public void release() throws CpoException {
173     for (CpoReleasable releasable : releasables) {
174       try {
175         releasable.release();
176       } catch (CpoException ce) {
177         logger.error("Error Releasing Callable Statement Transform Object", ce);
178         throw ce;
179       }
180     }
181   }
182 }