KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > cmp > jdbc > JDBCQueryManager


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.ejb.plugins.cmp.jdbc;
23
24 import java.lang.reflect.Method JavaDoc;
25 import java.lang.reflect.Constructor JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.Map JavaDoc;
29 import javax.ejb.FinderException JavaDoc;
30
31 import org.jboss.deployment.DeploymentException;
32 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCEntityBridge;
33 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCAutomaticQueryMetaData;
34 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCQueryMetaData;
35 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCDeclaredQueryMetaData;
36 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCDynamicQLQueryMetaData;
37 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCJBossQLQueryMetaData;
38 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCQlQueryMetaData;
39 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCReadAheadMetaData;
40 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCEntityMetaData;
41 import org.jboss.ejb.plugins.cmp.ejbql.Catalog;
42 import org.jboss.logging.Logger;
43 import org.jboss.metadata.MetaData;
44 import org.w3c.dom.Element JavaDoc;
45
46 /**
47  * Maintains a map from a query method to query command.
48  *
49  * @author <a HREF="mailto:dain@daingroup.com">Dain Sundstrom</a>
50  * @author <a HREF="mailto:rickard.oberg@telkel.com">Rickard ´┐Żberg</a>
51  * @author <a HREF="mailto:marc.fleury@telkel.com">Marc Fleury</a>
52  * @author <a HREF="mailto:shevlandj@kpi.com.au">Joe Shevland</a>
53  * @author <a HREF="mailto:justin@j-m-f.demon.co.uk">Justin Forder</a>
54  * @author <a HREF="mailto:alex@jboss.org">Alex Loubyansky</a>
55  * @version $Revision: 43506 $
56  */

57 public final class JDBCQueryManager
58 {
59    private static final String JavaDoc FIND_BY_PK = "findByPrimaryKey";
60    private static final String JavaDoc EJB_FIND = "ejbFind";
61    private static final String JavaDoc FIND_ALL = "findAll";
62    private static final String JavaDoc FIND_BY = "findBy";
63
64    private final Map JavaDoc knownQueries = new HashMap JavaDoc();
65    private final JDBCStoreManager manager;
66
67    public JDBCQueryManager(JDBCStoreManager manager)
68    {
69       this.manager = manager;
70    }
71
72    public static final Class JavaDoc getQLCompiler(Element JavaDoc query, JDBCEntityMetaData entity)
73       throws DeploymentException
74    {
75       String JavaDoc compiler = MetaData.getOptionalChildContent(query, "ql-compiler");
76       Class JavaDoc impl;
77
78       if(compiler == null || compiler.trim().length() == 0)
79       {
80          impl = entity.getQLCompiler();
81       }
82       else
83       {
84          try
85          {
86             impl = TCLAction.UTIL.getContextClassLoader().loadClass(compiler);
87          }
88          catch(ClassNotFoundException JavaDoc e)
89          {
90             throw new DeploymentException("Failed to load compiler implementation: " + compiler);
91          }
92       }
93       return impl;
94    }
95
96    public static final QLCompiler getInstance(Class JavaDoc impl, Catalog catalog)
97       throws DeploymentException
98    {
99       if(impl == null)
100       {
101          throw new DeploymentException("ql-compiler is not specified.");
102       }
103
104       final Constructor JavaDoc constructor;
105       try
106       {
107          constructor = impl.getConstructor(new Class JavaDoc[]{Catalog.class});
108       }
109       catch(NoSuchMethodException JavaDoc e)
110       {
111          throw new DeploymentException("Compiler class does not have a constructor which takes " + Catalog.class.getName());
112       }
113
114       try
115       {
116          return (QLCompiler)constructor.newInstance(new Object JavaDoc[]{catalog});
117       }
118       catch(Exception JavaDoc e)
119       {
120          throw new DeploymentException("Failed to create an instance of " + impl.getName() + ": " + e.getMessage(), e);
121       }
122    }
123
124    public JDBCQueryCommand getQueryCommand(Method JavaDoc queryMethod)
125    throws FinderException JavaDoc
126    {
127       JDBCQueryCommand queryCommand = (JDBCQueryCommand)knownQueries.get(queryMethod);
128       
129       if(queryCommand == null)
130       {
131          throw new FinderException JavaDoc("Unknown query: " + queryMethod);
132       }
133       return queryCommand;
134    }
135    
136    public void start() throws DeploymentException
137    {
138       Logger log = Logger.getLogger(
139             this.getClass().getName() +
140             "." +
141             manager.getMetaData().getName());
142
143       JDBCCommandFactory factory = manager.getCommandFactory();
144
145       Class JavaDoc homeClass = manager.getContainer().getHomeClass();
146       Class JavaDoc localHomeClass = manager.getContainer().getLocalHomeClass();
147
148       //
149
// findByPrimaryKey
150
//
151
JDBCEntityBridge entity = (JDBCEntityBridge) manager.getEntityBridge();
152       if(homeClass != null)
153       {
154          try
155          {
156             // try to get the finder method on the home interface
157
Method JavaDoc method = homeClass.getMethod(FIND_BY_PK, new Class JavaDoc[]{entity.getPrimaryKeyClass()});
158
159             JDBCQueryMetaData findByPKMD = manager.getMetaData().getQueryMetaDataForMethod(method);
160             JDBCReadAheadMetaData readAhead = (findByPKMD == null ?
161                entity.getMetaData().getReadAhead() : findByPKMD.getReadAhead());
162
163             // got it add it to known finders
164
JDBCQueryMetaData q = new JDBCAutomaticQueryMetaData(
165                   method,
166                   readAhead,
167                entity.getMetaData().getQLCompiler(),
168                false
169             );
170             knownQueries.put(method, factory.createFindByPrimaryKeyQuery(q));
171
172             if(log.isDebugEnabled())
173                log.debug("Added findByPrimaryKey query command for home interface");
174          } catch(NoSuchMethodException JavaDoc e)
175          {
176             throw new DeploymentException("Home interface does not have a findByPrimaryKey method");
177          }
178       }
179
180       if(localHomeClass != null)
181       {
182
183          Method JavaDoc method;
184          try
185          {
186             // try to get the finder method on the local home interface
187
method = localHomeClass.getMethod(FIND_BY_PK, new Class JavaDoc[] { entity.getPrimaryKeyClass() });
188          } catch(NoSuchMethodException JavaDoc e)
189          {
190             throw new DeploymentException("Local home interface does " +
191                   "not have the method findByPrimaryKey(" +
192                   entity.getPrimaryKeyClass().getName() + ")");
193          }
194
195          // got it add it to known finders
196
JDBCQueryMetaData findByPKMD = manager.getMetaData().getQueryMetaDataForMethod(method);
197          JDBCReadAheadMetaData readAhead = (findByPKMD == null ?
198             entity.getMetaData().getReadAhead() : findByPKMD.getReadAhead());
199          JDBCQueryMetaData q = new JDBCAutomaticQueryMetaData(method, readAhead, entity.getMetaData().getQLCompiler(), false);
200          knownQueries.put(method, factory.createFindByPrimaryKeyQuery(q));
201
202          if(log.isDebugEnabled())
203             log.debug("Added findByPrimaryKey query command for local home interface");
204       }
205
206       //
207
// Custom finders - Overrides defined and automatic finders.
208
//
209
Class JavaDoc ejbClass = manager.getMetaData().getEntityClass();
210
211       Method JavaDoc[] customMethods = ejbClass.getMethods();
212       for (int i = 0; i < customMethods.length; i++)
213       {
214          Method JavaDoc m = customMethods[i];
215          String JavaDoc methodName = m.getName();
216          if(methodName.startsWith(EJB_FIND))
217          {
218             String JavaDoc interfaceName = 'f' + methodName.substring(4);
219
220             if(homeClass != null)
221             {
222                try
223                {
224                   // try to get the finder method on the home interface
225
Method JavaDoc interfaceMethod = homeClass.getMethod(
226                         interfaceName,
227                         m.getParameterTypes());
228
229                   // got it add it to known finders
230
knownQueries.put(interfaceMethod, new JDBCCustomFinderQuery(manager, m));
231
232                   if(log.isDebugEnabled())
233                      log.debug("Added custom finder " + methodName + " on home interface");
234                } catch(NoSuchMethodException JavaDoc e)
235                {
236                   // this is ok method may not be defined on this interface
237
}
238             }
239
240             if(localHomeClass != null)
241             {
242                try
243                {
244                   // try to get the finder method on the local home interface
245
Method JavaDoc interfaceMethod = localHomeClass.getMethod(
246                         interfaceName,
247                         m.getParameterTypes());
248
249                   // got it add it to known finders
250
knownQueries.put(interfaceMethod, new JDBCCustomFinderQuery(manager, m));
251
252                   if(log.isDebugEnabled())
253                      log.debug("Added custom finder " + methodName + " on local home interface");
254                } catch(NoSuchMethodException JavaDoc e)
255                {
256                   // this is ok method may not be defined on this interface
257
}
258             }
259          }
260       }
261
262       //
263
// Defined finders - Overrides automatic finders.
264
//
265
Iterator JavaDoc definedFinders = manager.getMetaData().getQueries().iterator();
266       while(definedFinders.hasNext())
267       {
268          JDBCQueryMetaData q = (JDBCQueryMetaData)definedFinders.next();
269
270          if(!knownQueries.containsKey(q.getMethod()) )
271          {
272             if(q instanceof JDBCJBossQLQueryMetaData)
273             {
274                knownQueries.put(q.getMethod(), factory.createJBossQLQuery(q));
275
276             } else if(q instanceof JDBCDynamicQLQueryMetaData)
277             {
278                knownQueries.put(q.getMethod(), factory.createDynamicQLQuery(q));
279
280             } else if(q instanceof JDBCDeclaredQueryMetaData)
281             {
282                knownQueries.put(q.getMethod(), factory.createDeclaredSQLQuery(q));
283
284             } else if(q instanceof JDBCQlQueryMetaData)
285             {
286                knownQueries.put(q.getMethod(), factory.createEJBQLQuery(q));
287             }
288          }
289       }
290
291       //
292
// Automatic finders - The last resort
293
//
294
if(homeClass != null)
295       {
296          addAutomaticFinders(manager, homeClass.getMethods(), log);
297       }
298
299       if(localHomeClass != null)
300       {
301          addAutomaticFinders(manager, localHomeClass.getMethods(), log);
302       }
303    }
304
305    public void clear()
306    {
307       this.knownQueries.clear();
308    }
309
310    private void addAutomaticFinders(
311          JDBCStoreManager manager,
312          Method JavaDoc[] homeMethods,
313          Logger log) throws DeploymentException
314    {
315
316       JDBCCommandFactory factory = manager.getCommandFactory();
317       JDBCEntityBridge entity = (JDBCEntityBridge) manager.getEntityBridge();
318       for (int i = 0; i < homeMethods.length; i++)
319       {
320          Method JavaDoc method = homeMethods[i];
321
322          if(!knownQueries.containsKey(method))
323          {
324             String JavaDoc name = method.getName();
325             if(name.equals(FIND_ALL))
326             {
327                JDBCQueryMetaData q = new JDBCAutomaticQueryMetaData(
328                      method,
329                      entity.getMetaData().getReadAhead(),
330                   entity.getMetaData().getQLCompiler(), false
331                   );
332                knownQueries.put(method, factory.createFindAllQuery(q));
333             }
334             else if(name.startsWith(FIND_BY) && !name.equals(FIND_BY_PK))
335             {
336                try
337                {
338                   JDBCQueryMetaData q = new JDBCAutomaticQueryMetaData(
339                         method,
340                         entity.getMetaData().getReadAhead(),
341                      entity.getMetaData().getQLCompiler(), false);
342                   knownQueries.put(method, factory.createFindByQuery(q));
343                } catch (IllegalArgumentException JavaDoc e)
344                {
345                   log.debug("Could not create the finder " + name +
346                         ", because no matching CMP field was found.");
347                }
348             }
349          }
350       }
351    }
352 }
353
Popular Tags