19a13ed73b70517fb9bd50099554fecb80ca86fc
[tomcat7.0] /
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 package org.apache.tomcat.jdbc.pool.interceptor;
18
19 import java.lang.reflect.Method;
20
21 import org.apache.tomcat.jdbc.pool.ConnectionPool;
22 import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
23 import org.apache.tomcat.jdbc.pool.PooledConnection;
24
25 /**
26  * Abstraction interceptor. This component intercepts all calls to create some type of SQL statement.
27  * By extending this class, one can intercept queries and update statements by overriding the {@link #createStatement(Object, Method, Object[], Object, long)}
28  * method.
29  * @author Filip Hanik
30  * @version 1.0
31  */
32 public abstract class  AbstractCreateStatementInterceptor extends JdbcInterceptor {
33     protected static final String CREATE_STATEMENT      = "createStatement";
34     protected static final int    CREATE_STATEMENT_IDX  = 0;
35     protected static final String PREPARE_STATEMENT     = "prepareStatement";
36     protected static final int    PREPARE_STATEMENT_IDX = 1;
37     protected static final String PREPARE_CALL          = "prepareCall";
38     protected static final int    PREPARE_CALL_IDX      = 2;
39
40     protected static final String[] STATEMENT_TYPES = {CREATE_STATEMENT, PREPARE_STATEMENT, PREPARE_CALL};
41     protected static final int    STATEMENT_TYPE_COUNT = STATEMENT_TYPES.length;
42     
43     protected static final String EXECUTE        = "execute";
44     protected static final String EXECUTE_QUERY  = "executeQuery";
45     protected static final String EXECUTE_UPDATE = "executeUpdate";
46     protected static final String EXECUTE_BATCH  = "executeBatch";
47
48     protected static final String[] EXECUTE_TYPES = {EXECUTE, EXECUTE_QUERY, EXECUTE_UPDATE, EXECUTE_BATCH};
49
50     public  AbstractCreateStatementInterceptor() {
51         super();
52     }
53     
54     /**
55      * {@inheritDoc}
56      */
57     @Override
58     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
59         if (compare(CLOSE_VAL,method)) {
60             closeInvoked();
61             return super.invoke(proxy, method, args);
62         } else {
63             boolean process = false;
64             process = isStatement(method, process);
65             if (process) {
66                 long start = System.currentTimeMillis();
67                 Object statement = super.invoke(proxy,method,args);
68                 long delta = System.currentTimeMillis() - start;
69                 return createStatement(proxy,method,args,statement, delta);
70             } else {
71                 return super.invoke(proxy,method,args);
72             }
73         }
74     }
75     
76     /**
77      * This method will be invoked after a successful statement creation. This method can choose to return a wrapper
78      * around the statement or return the statement itself.
79      * If this method returns a wrapper then it should return a wrapper object that implements one of the following interfaces.
80      * {@link java.sql.Statement}, {@link java.sql.PreparedStatement} or {@link java.sql.CallableStatement}
81      * @param proxy the actual proxy object
82      * @param method the method that was called. It will be one of the methods defined in {@link #STATEMENT_TYPES}
83      * @param args the arguments to the method
84      * @param statement the statement that the underlying connection created
85      * @return a {@link java.sql.Statement} object
86      */
87     public abstract Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time);
88     
89     /**
90      * Method invoked when the operation {@link java.sql.Connection#close()} is invoked. 
91      */
92     public abstract void closeInvoked();
93
94     /**
95      * Returns true if the method that is being invoked matches one of the statement types.
96      * 
97      * @param method the method being invoked on the proxy
98      * @param process boolean result used for recursion
99      * @return returns true if the method name matched
100      */
101     protected boolean isStatement(Method method, boolean process){
102         return process(STATEMENT_TYPES, method, process);
103     }
104
105     /**
106      * Returns true if the method that is being invoked matches one of the execute types.
107      * 
108      * @param method the method being invoked on the proxy
109      * @param process boolean result used for recursion
110      * @return returns true if the method name matched
111      */
112     protected boolean isExecute(Method method, boolean process){
113         return process(EXECUTE_TYPES, method, process);
114     }
115
116     /*
117      * Returns true if the method that is being invoked matches one of the method names passed in
118      * @param names list of method names that we want to intercept
119      * @param method the method being invoked on the proxy
120      * @param process boolean result used for recursion
121      * @return returns true if the method name matched
122      */
123     protected boolean process(String[] names, Method method, boolean process) {
124         final String name = method.getName();
125         for (int i=0; (!process) && i<names.length; i++) {
126             process = compare(names[i],name);
127         }
128         return process;
129     }
130     
131     /**
132      * no-op for this interceptor. no state is stored.
133      */
134     @Override
135     public void reset(ConnectionPool parent, PooledConnection con) {
136         // NOOP
137     }
138 }