KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > cmp > jdbc2 > JDBCStoreManager2


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.jdbc2;
23
24 import org.jboss.ejb.EntityEnterpriseContext;
25 import org.jboss.ejb.Container;
26 import org.jboss.ejb.EntityContainer;
27 import org.jboss.ejb.EjbModule;
28 import org.jboss.ejb.GenericEntityObjectFactory;
29 import org.jboss.ejb.plugins.cmp.jdbc.JDBCTypeFactory;
30 import org.jboss.ejb.plugins.cmp.jdbc.JDBCEntityPersistenceStore;
31 import org.jboss.ejb.plugins.cmp.jdbc.JDBCStartCommand;
32 import org.jboss.ejb.plugins.cmp.jdbc.JDBCStopCommand;
33 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCAbstractEntityBridge;
34 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCEntityMetaData;
35 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCApplicationMetaData;
36 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCXmlFileLoader;
37 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCEntityCommandMetaData;
38 import org.jboss.ejb.plugins.cmp.ejbql.Catalog;
39 import org.jboss.ejb.plugins.cmp.jdbc2.bridge.JDBCEntityBridge2;
40 import org.jboss.ejb.plugins.cmp.jdbc2.schema.Schema;
41 import org.jboss.ejb.plugins.cmp.jdbc2.schema.EntityTable;
42 import org.jboss.logging.Logger;
43 import org.jboss.deployment.DeploymentException;
44 import org.jboss.metadata.ApplicationMetaData;
45 import org.jboss.tm.TransactionLocal;
46
47 import javax.ejb.DuplicateKeyException JavaDoc;
48 import javax.ejb.FinderException JavaDoc;
49 import javax.ejb.EJBException JavaDoc;
50 import javax.ejb.CreateException JavaDoc;
51 import javax.ejb.RemoveException JavaDoc;
52 import java.lang.reflect.Method JavaDoc;
53 import java.util.Collection JavaDoc;
54 import java.util.HashMap JavaDoc;
55 import java.util.ArrayList JavaDoc;
56 import java.util.List JavaDoc;
57 import java.util.Map JavaDoc;
58 import java.util.Iterator JavaDoc;
59 import java.sql.SQLException JavaDoc;
60
61
62 /**
63  * @author <a HREF="mailto:alex@jboss.org">Alexey Loubyansky</a>
64  * @version <tt>$Revision: 58204 $</tt>
65  */

66 public class JDBCStoreManager2
67    implements JDBCEntityPersistenceStore
68 {
69    private static final String JavaDoc CATALOG = "CATALOG";
70    private static final String JavaDoc SCHEMA = "SCHEMA";
71    private static final String JavaDoc CREATED_MANAGERS = "CREATED_JDBCStoreManagers";
72    private static final String JavaDoc CMP_JDBC = "CMP-JDBC";
73
74    private EntityContainer container;
75    private EjbModule ejbModule;
76    private Logger log;
77    private JDBCEntityMetaData metaData;
78    private JDBCEntityBridge2 entityBridge;
79    private JDBCTypeFactory typeFactory;
80    private Schema schema;
81
82    private InstanceFactory instanceFactory;
83    private QueryFactory queryFactory;
84    private CreateCommand createCmd;
85    private JDBCStartCommand startCmd;
86    private JDBCStopCommand stop;
87
88    private final TransactionLocal cascadeDeleteRegistry = new TransactionLocal()
89    {
90       protected Object JavaDoc initialValue()
91       {
92          return new HashMap JavaDoc();
93       }
94    };
95
96    // Public
97

98    public Schema getSchema()
99    {
100       schema = (Schema)getApplicationData(SCHEMA);
101       if(schema == null)
102       {
103          schema = new Schema();
104          putApplicationData(SCHEMA, schema);
105       }
106       return schema;
107    }
108
109    public Catalog getCatalog()
110    {
111       Catalog catalog = (Catalog)getApplicationData(CATALOG);
112       if(catalog == null)
113       {
114          catalog = new Catalog();
115          putApplicationData(CATALOG, catalog);
116       }
117       return catalog;
118    }
119
120    public QueryFactory getQueryFactory()
121    {
122       return queryFactory;
123    }
124
125    public boolean registerCascadeDelete(Object JavaDoc key, Object JavaDoc value)
126    {
127       Map JavaDoc map = (Map JavaDoc)cascadeDeleteRegistry.get();
128       return map.put(key, value) == null;
129    }
130
131    public boolean isCascadeDeleted(Object JavaDoc key)
132    {
133       Map JavaDoc map = (Map JavaDoc)cascadeDeleteRegistry.get();
134       return map.containsKey(key);
135    }
136
137    public void unregisterCascadeDelete(Object JavaDoc key)
138    {
139       Map JavaDoc map = (Map JavaDoc)cascadeDeleteRegistry.get();
140       map.remove(key);
141    }
142
143    // ContainerPlugin implementation
144

145    public void setContainer(Container con)
146    {
147       this.container = (EntityContainer)con;
148       if(container != null)
149       {
150          ejbModule = container.getEjbModule();
151          log = Logger.getLogger(this.getClass().getName() + "." + container.getBeanMetaData().getEjbName());
152       }
153       else
154       {
155          // undeploy
156
ejbModule = null;
157       }
158    }
159
160    // Service implementation
161

162    public void create() throws Exception JavaDoc
163    {
164       HashMap JavaDoc managersMap = (HashMap JavaDoc)getApplicationData(CREATED_MANAGERS);
165       if(managersMap == null)
166       {
167          managersMap = new HashMap JavaDoc();
168          putApplicationData(CREATED_MANAGERS, managersMap);
169       }
170       managersMap.put(container.getBeanMetaData().getEjbName(), this);
171    }
172
173    public void start() throws Exception JavaDoc
174    {
175       initStoreManager();
176
177       HashMap JavaDoc managersMap = (HashMap JavaDoc)getApplicationData(CREATED_MANAGERS);
178       Catalog catalog = getCatalog();
179       if(catalog.getEntityCount() == managersMap.size() && catalog.getEJBNames().equals(managersMap.keySet()))
180       {
181          // Make a copy of the managers (for safty)
182
List JavaDoc managers = new ArrayList JavaDoc(managersMap.values());
183
184          // Start Phase 2: resolve relationships
185
for(int i = 0; i < managers.size(); ++i)
186          {
187             JDBCStoreManager2 manager = (JDBCStoreManager2)managers.get(i);
188             manager.resolveRelationships();
189          }
190
191          // Start Phase 3: init cmr loaders
192
for(int i = 0; i < managers.size(); ++i)
193          {
194             JDBCStoreManager2 manager = (JDBCStoreManager2)managers.get(i);
195             manager.startEntity();
196          }
197
198          // Start Phase 4: create tables and compile queries
199
for(int i = 0; i < managers.size(); ++i)
200          {
201             JDBCStoreManager2 manager = (JDBCStoreManager2)managers.get(i);
202             manager.startStoreManager();
203          }
204
205          // add foreign key constraints
206
for(int i = 0; i < managers.size(); ++i)
207          {
208             JDBCStoreManager2 manager = (JDBCStoreManager2)managers.get(i);
209             manager.startCmd.addForeignKeyConstraints();
210          }
211       }
212    }
213
214    public void stop()
215    {
216       if(stop != null)
217       {
218          Map JavaDoc managersMap = (HashMap JavaDoc)getApplicationData(CREATED_MANAGERS);
219          while(!managersMap.isEmpty())
220          {
221             int stoppedInIteration = 0;
222             for(Iterator JavaDoc i = managersMap.values().iterator(); i.hasNext();)
223             {
224                JDBCStoreManager2 manager = (JDBCStoreManager2)i.next();
225                if(manager.stop.execute())
226                {
227                   i.remove();
228                   try
229                   {
230                      manager.entityBridge.stop();
231                   }
232                   catch(Exception JavaDoc e)
233                   {
234                      log.error("Failed to stop entity bridge.", e);
235                   }
236                   ++stoppedInIteration;
237                }
238             }
239
240             if(stoppedInIteration == 0)
241             {
242                break;
243             }
244          }
245       }
246    }
247
248    public void destroy()
249    {
250       //To change body of implemented methods use File | Settings | File Templates.
251
}
252
253    // JDBCEntityPersistenceStore implementation
254

255    public JDBCAbstractEntityBridge getEntityBridge()
256    {
257       return entityBridge;
258    }
259
260    public JDBCEntityMetaData getMetaData()
261    {
262       return metaData;
263    }
264
265    public JDBCTypeFactory getJDBCTypeFactory()
266    {
267       return typeFactory;
268    }
269
270    public EntityContainer getContainer()
271    {
272       return container;
273    }
274
275    public Object JavaDoc getApplicationData(Object JavaDoc key)
276    {
277       return ejbModule.getModuleData(key);
278    }
279
280    public void putApplicationData(Object JavaDoc key, Object JavaDoc value)
281    {
282       ejbModule.putModuleData(key, value);
283    }
284
285    // EntityPersistenceStore implementation
286

287    public Object JavaDoc createBeanClassInstance() throws Exception JavaDoc
288    {
289       return instanceFactory.newInstance();
290    }
291
292    public void initEntity(EntityEnterpriseContext ctx)
293    {
294       entityBridge.initPersistenceContext(ctx);
295       entityBridge.initInstance(ctx);
296    }
297
298    public Object JavaDoc createEntity(Method JavaDoc m, Object JavaDoc[] args, EntityEnterpriseContext ctx)
299       throws CreateException JavaDoc
300    {
301       /*
302       Object pk;
303       PersistentContext pctx = (PersistentContext) ctx.getPersistenceContext();
304       if(ctx.getId() == null)
305       {
306          pk = entityBridge.extractPrimaryKeyFromInstance(ctx);
307
308          if(pk == null)
309          {
310             throw new CreateException("Primary key for created instance is null.");
311          }
312
313          pctx.setPk(pk);
314       }
315       else
316       {
317          // insert-after-ejb-post-create
318          try
319          {
320             pctx.flush();
321          }
322          catch(SQLException e)
323          {
324             if("23000".equals(e.getSQLState()))
325             {
326                throw new DuplicateKeyException("Unique key violation or invalid foreign key value: pk=" + ctx.getId());
327             }
328             else
329             {
330                throw new CreateException("Failed to create instance: pk=" + ctx.getId() +
331                   ", state=" + e.getSQLState() +
332                   ", msg=" + e.getMessage());
333             }
334          }
335          pk = ctx.getId();
336       }
337       return pk;
338       */

339       return createCmd.execute(m, args, ctx);
340    }
341
342    public Object JavaDoc postCreateEntity(Method JavaDoc m, Object JavaDoc[] args, EntityEnterpriseContext ctx) throws CreateException JavaDoc
343    {
344       return null;
345    }
346
347    public Object JavaDoc findEntity(Method JavaDoc finderMethod,
348                             Object JavaDoc[] args,
349                             EntityEnterpriseContext instance,
350                             GenericEntityObjectFactory factory)
351       throws FinderException JavaDoc
352    {
353       QueryCommand query = queryFactory.getQueryCommand(finderMethod);
354       return query.fetchOne(schema, factory, args);
355    }
356
357    public Collection JavaDoc findEntities(Method JavaDoc finderMethod,
358                                   Object JavaDoc[] args,
359                                   EntityEnterpriseContext instance,
360                                   GenericEntityObjectFactory factory)
361       throws FinderException JavaDoc
362    {
363       QueryCommand query = queryFactory.getQueryCommand(finderMethod);
364       return query.fetchCollection(schema, factory, args);
365    }
366
367    public void activateEntity(EntityEnterpriseContext ctx)
368    {
369       entityBridge.initPersistenceContext(ctx);
370    }
371
372    public void loadEntity(EntityEnterpriseContext ctx)
373    {
374       try
375       {
376          EntityTable.Row row = entityBridge.getTable().loadRow(ctx.getId());
377          PersistentContext pctx = new PersistentContext(entityBridge, row);
378          ctx.setPersistenceContext(pctx);
379       }
380       catch(EJBException JavaDoc e)
381       {
382          log.error("Failed to load instance of " + entityBridge.getEntityName() + " with pk=" + ctx.getId(), e);
383          throw e;
384       }
385       catch(Exception JavaDoc e)
386       {
387          throw new EJBException JavaDoc(
388             "Failed to load instance of " + entityBridge.getEntityName() + " with pk=" + ctx.getId(), e
389          );
390       }
391    }
392
393    public boolean isStoreRequired(EntityEnterpriseContext instance)
394    {
395       return entityBridge.isStoreRequired(instance);
396    }
397
398    public boolean isModified(EntityEnterpriseContext instance) throws Exception JavaDoc
399    {
400       return entityBridge.isModified(instance);
401    }
402
403    public void storeEntity(EntityEnterpriseContext instance)
404    {
405       // scary?
406
}
407
408    public void passivateEntity(EntityEnterpriseContext ctx)
409    {
410       JDBCEntityBridge2.destroyPersistenceContext(ctx);
411    }
412
413    public void removeEntity(EntityEnterpriseContext ctx) throws RemoveException JavaDoc
414    {
415       entityBridge.remove(ctx);
416       PersistentContext pctx = (PersistentContext)ctx.getPersistenceContext();
417       pctx.remove();
418    }
419
420    // Private
421

422    protected void initStoreManager() throws Exception JavaDoc
423    {
424       if(log.isDebugEnabled())
425       {
426          log.debug("Initializing CMP plugin for " + container.getBeanMetaData().getEjbName());
427       }
428
429       metaData = loadJDBCEntityMetaData();
430
431       // setup the type factory, which is used to map java types to sql types.
432
typeFactory = new JDBCTypeFactory(metaData.getTypeMapping(),
433          metaData.getJDBCApplication().getValueClasses(),
434          metaData.getJDBCApplication().getUserTypeMappings()
435       );
436
437       entityBridge = new JDBCEntityBridge2(this, metaData);
438       entityBridge.init();
439
440       Catalog catalog = getCatalog();
441       catalog.addEntity(entityBridge);
442
443       stop = new JDBCStopCommand(this);
444    }
445
446    private void resolveRelationships() throws Exception JavaDoc
447    {
448       entityBridge.resolveRelationships();
449    }
450
451    protected void startStoreManager() throws Exception JavaDoc
452    {
453       queryFactory = new QueryFactory(entityBridge);
454       queryFactory.init();
455
456       instanceFactory = new InstanceFactory(this, entityBridge);
457
458       startCmd = new JDBCStartCommand(this);
459       startCmd.execute();
460
461       final JDBCEntityCommandMetaData entityCommand = getMetaData().getEntityCommand();
462       if(entityCommand == null || "default".equals(entityCommand.getCommandName()))
463       {
464          createCmd = new ApplicationPkCreateCommand();
465       }
466       else
467       {
468          final Class JavaDoc cmdClass = entityCommand.getCommandClass();
469          if(cmdClass == null)
470          {
471             throw new DeploymentException(
472                "entity-command class name is not specified for entity " + entityBridge.getEntityName()
473             );
474          }
475
476          try
477          {
478             createCmd = (CreateCommand)cmdClass.newInstance();
479          }
480          catch(ClassCastException JavaDoc cce)
481          {
482             throw new DeploymentException("Entity command " + cmdClass + " does not implement " + CreateCommand.class);
483          }
484       }
485
486       createCmd.init(this);
487    }
488
489    private void startEntity()
490       throws DeploymentException
491    {
492       entityBridge.start();
493    }
494
495    private JDBCEntityMetaData loadJDBCEntityMetaData()
496       throws DeploymentException
497    {
498       ApplicationMetaData amd = container.getBeanMetaData().getApplicationMetaData();
499
500       // Get JDBC MetaData
501
JDBCApplicationMetaData jamd = (JDBCApplicationMetaData)amd.getPluginData(CMP_JDBC);
502
503       if(jamd == null)
504       {
505          // we are the first cmp entity to need jbosscmp-jdbc.
506
// Load jbosscmp-jdbc.xml for the whole application
507
JDBCXmlFileLoader jfl = new JDBCXmlFileLoader(container, log);
508
509          jamd = jfl.load();
510          amd.addPluginData(CMP_JDBC, jamd);
511       }
512
513       // Get JDBC Bean MetaData
514
String JavaDoc ejbName = container.getBeanMetaData().getEjbName();
515       JDBCEntityMetaData metadata = jamd.getBeanByEjbName(ejbName);
516       if(metadata == null)
517       {
518          throw new DeploymentException("No metadata found for bean " + ejbName);
519       }
520       return metadata;
521    }
522 }
523
Popular Tags