KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas_ejb > container > jorm > JormFactory


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999-2005 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: JormFactory.java,v 1.41 2005/06/06 13:41:09 benoitf Exp $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.jonas_ejb.container.jorm;
27
28 import org.objectweb.jonas_ejb.container.JContainer;
29 import org.objectweb.jonas_ejb.container.JEntityFactory;
30 import org.objectweb.jonas_ejb.container.JEntitySwitch;
31 import org.objectweb.jonas_ejb.container.TraceEjb;
32 import org.objectweb.jonas_ejb.deployment.api.EjbRelationshipRoleDesc;
33 import org.objectweb.jonas_ejb.deployment.api.EntityCmp2Desc;
34 import org.objectweb.jonas_ejb.deployment.api.EntityDesc;
35 import org.objectweb.jonas_ejb.lib.JormType;
36 import org.objectweb.jorm.api.PBinding;
37 import org.objectweb.jorm.api.PClassMapping;
38 import org.objectweb.jorm.api.PClassMappingCtrl;
39 import org.objectweb.jorm.api.PException;
40 import org.objectweb.jorm.api.PMapCluster;
41 import org.objectweb.jorm.api.PMapper;
42 import org.objectweb.jorm.api.PMappingCallback;
43 import org.objectweb.jorm.facility.naming.basidir.BasidBinder;
44 import org.objectweb.jorm.naming.api.PBinder;
45 import org.objectweb.jorm.naming.api.PExceptionNaming;
46 import org.objectweb.jorm.naming.api.PName;
47 import org.objectweb.jorm.naming.api.PNameCoder;
48 import org.objectweb.jorm.naming.api.PNamingContext;
49 import org.objectweb.util.monolog.api.BasicLevel;
50
51 import javax.ejb.EJBException JavaDoc;
52 import javax.ejb.EntityBean JavaDoc;
53
54 import java.io.Serializable JavaDoc;
55 import java.util.Iterator JavaDoc;
56
57 /**
58  * This class is an extension of the JEntityFactory class. It initializes the
59  * persitant class (the bean) in the jorm mapper. This class is abstract in
60  * order to be extended by the PClassMapping generated for the Bean.
61  *
62  * @author Sebastien Chassande-Barrioz
63  */

64 public abstract class JormFactory extends JEntityFactory implements PClassMapping, PClassMappingCtrl {
65
66     protected int relNonInit;
67     protected boolean mapped;
68     protected PMapper mapper = null;
69     protected EntityCmp2Desc ecd = null;
70
71     /**
72      * Class used for EntitySwitch (binding class)
73     */

74     private Class JavaDoc bindingClass = null;
75
76
77
78     /**
79      * constructor
80      */

81     public JormFactory() {
82         super();
83     }
84
85     protected abstract void setMapper(String JavaDoc mapperName) throws PException;
86     public abstract Object JavaDoc getConnection(Object JavaDoc hints) throws PException;
87     public abstract void releaseConnection(Object JavaDoc conn) throws PException;
88
89     /**
90      * Initialization of the factory. This is called just after the newInstance()
91      * from the JContainer (addBean method)
92      */

93     public void init(EntityDesc ed, JContainer c, String JavaDoc mapperName) {
94         if (TraceEjb.isDebugFactory()) {
95             TraceEjb.factory.log(BasicLevel.DEBUG, ed.getEjbName());
96         }
97
98         // First, call the super in order to have the access to the datasource
99
// and the beanNaming
100
super.init(ed, c);
101         ecd = (EntityCmp2Desc) ed;
102         try {
103             setMapper(mapperName);
104         } catch (PException e) {
105             throw new EJBException JavaDoc("JormFactory cannot create the mapper", e);
106         }
107
108         //----------------------- JORM INITIALIZATION -----------------------//
109
if (TraceEjb.isDebugFactory()) {
110             TraceEjb.factory.log(BasicLevel.DEBUG, "Jorm initialisation");
111         }
112         PBinder binder = null;
113         Class JavaDoc binderClass = null;
114         int binderCT = 0;
115         try {
116             // Instanciate the binder
117
binderClass = c.getClassLoader().loadClass(ecd.getJormBinderClassName());
118             binder = (PBinder) binderClass.newInstance();
119             if (ecd.hasPrimaryKeyField()) {
120                 binderCT = JormType.getCodingType(ecd.getCmpFieldDesc(ecd.getPrimaryKeyFieldName()).getFieldType(), true);
121                 ((BasidBinder) binder).setCodingType(binderCT);
122             } else {
123                 // TODO:
124
// - take the initial values of the primary key
125
// - put them into the generated binder (use a PNG)
126
}
127             if (TraceEjb.isDebugFactory()) {
128                 TraceEjb.factory.log(BasicLevel.DEBUG, "binder " + ecd.getJormBinderClassName() + "instanciated");
129             }
130
131             // Link the binder and the PClassMapping
132
binder.setPClassMapping(this);
133             setPBinder(binder);
134             setClassPNameCoder(binder);
135             if (TraceEjb.isDebugFactory()) {
136                 TraceEjb.factory.log(BasicLevel.DEBUG, "binder linked to the mapping");
137             }
138
139         } catch (Exception JavaDoc e) {
140             TraceEjb.factory.log(BasicLevel.ERROR, "Impossible to create the binder", e);
141             throw new EJBException JavaDoc("Impossible to create the binder: bean:" + ecd.getEjbName(), e);
142         }
143
144         // for each reference assignes the PNamingcontext if it is possible.
145
relNonInit = 0;
146         try {
147             for (Iterator JavaDoc it = ecd.getEjbRelationshipRoleDescIterator(); it.hasNext();) {
148                 EjbRelationshipRoleDesc rsr = (EjbRelationshipRoleDesc) it.next();
149                 String JavaDoc source = rsr.getSourceBean().getEjbName();
150                 String JavaDoc target = rsr.getTargetBean().getEjbName();
151                 JormFactory pcm2 = source.equals(target) ? this : (JormFactory) c.getBeanFactory(target);
152                 if (TraceEjb.isDebugFactory()) {
153                     TraceEjb.factory.log(BasicLevel.DEBUG,
154                             "treatement of the relation " + rsr.getRelation().getName()
155                             + ": current-bean=" + ecd.getEjbName()
156                             + ", source-bean=" + source
157                             + ", dest-bean=" + target
158                             + ", cmr-field=" + rsr.getCmrFieldName());
159                 }
160                 if (rsr.hasCmrField()) {
161                     PClassMapping gcm = null;
162                     //Multivalued relation
163
if (rsr.isTargetMultiple()) {
164                         // Instanciate a GenClassMapping and link it
165
gcm = newGCMInstance(mapperName);
166                         gcm.init((PMappingCallback) mapper, null);
167                         setGenClassMapping(rsr.getCmrFieldName(), gcm);
168                         if (TraceEjb.isDebugFactory()) {
169                             TraceEjb.factory.log(BasicLevel.DEBUG,
170                                     "assign a GenClassMapping for the CMR "
171                                     + rsr.getCmrFieldName() + " / gcm=" + gcm);
172                         }
173
174                         PBinder gcmBinder = null;
175                         try {
176                             gcmBinder = (PBinder) binderClass.newInstance();
177                         } catch (Exception JavaDoc e) {
178                             TraceEjb.factory.log(BasicLevel.ERROR,
179                                                 "Impossible to create the binder of the GCM bean: "
180                                                 + ecd.getEjbName() + " / CMR: "
181                                                 + rsr.getCmrFieldName(), e);
182                             throw new EJBException JavaDoc(
183                                                    "Impossible to create the binder of the GCM bean: "
184                                                    + ecd.getEjbName() + " / CMR: "
185                                                    + rsr.getCmrFieldName(), e);
186                         }
187                         if (ecd.hasPrimaryKeyField()) {
188                             ((BasidBinder) gcmBinder).setCodingType(binderCT);
189                         } else {
190                             // TODO: (not so important)
191
// - take the initial values of the primary key
192
// - put them into the generated binder (use a PNG)
193
}
194                         gcm.setPBinder(gcmBinder);
195                         gcmBinder.setPClassMapping(gcm);
196                         setPNameCoder(rsr.getCmrFieldName(), (PNameCoder) gcmBinder);
197                     }
198
199                     // As the bean with which the current bean is in relation
200
// may be not load, the test of pcm2!=null is needed
201
if (pcm2 != null) {
202                         if (TraceEjb.isDebugFactory()) {
203                             TraceEjb.factory.log(BasicLevel.DEBUG, "Pnc Assignement");
204                         }
205                         if (rsr.isTargetMultiple()) {
206                             ((PClassMappingCtrl)gcm).setPNameCoder((PNameCoder) pcm2.getPBinder());
207                         } else {
208                             setPNameCoder(rsr.getCmrFieldName(), (PNameCoder) pcm2.getPBinder());
209                         }
210                         if (pcm2.isPrefetch()) {
211                             initGenClassPrefetch(gcm, pcm2);
212                         }
213                     } else {
214                         relNonInit++;
215                         if (TraceEjb.isDebugFactory()) {
216                             TraceEjb.factory.log(BasicLevel.DEBUG, "the Pnc is not reachable currently. relNonInit=" + relNonInit);
217                         }
218                         // The PNamingContext has not been set.
219
}
220                 }
221                 EjbRelationshipRoleDesc rsr2 = rsr.getOppositeRelationshipRole();
222                 if (pcm2 != null && rsr2.hasCmrField() && pcm2 != this) {
223                     // This case appears when the scheduling of the bean adding
224
// in the container is bad (or cyclic relation): A bean has
225
// been load and have a relation to current bean. We must
226
// therfore set the naming context on the PClassMapping of
227
// the first bean for the opposite CMR field
228
if (TraceEjb.isDebugFactory()) {
229                         TraceEjb.factory.log(BasicLevel.DEBUG,
230                                 "later Pnc assignement of the opposite CMR field: "
231                                 + rsr2.getCmrFieldName());
232                     }
233                     pcm2.configurePnc(rsr2.getCmrFieldName(), (PNamingContext) getPBinder(), this, rsr2.isTargetMultiple());
234                 }
235             }
236         } catch (EJBException JavaDoc e) {
237             throw e;
238         } catch (Exception JavaDoc e) {
239             TraceEjb.factory.log(BasicLevel.ERROR,
240                                 "Impossible to assign the naming context to the PClassMapping", e);
241             throw new EJBException JavaDoc("Impossible to assign the naming context to the PClassMapping", e);
242         }
243         mapped = false;
244         if (relNonInit == 0) {
245             mapClass();
246         }
247
248         // load the binding class
249
String JavaDoc cn = ((EntityCmp2Desc) dd).getJormBindingClassName();
250         try {
251             bindingClass = getContainer().getClassLoader().loadClass(cn);
252         } catch (ClassNotFoundException JavaDoc e) {
253             String JavaDoc err = "Impossible to load binding class '" + cn + "'.";
254             TraceEjb.factory.log(BasicLevel.ERROR, err, e);
255             throw new EJBException JavaDoc(err, e);
256         }
257
258     }
259
260     /**
261      * @return mapper
262      */

263     public PMapper getMapper() {
264         return mapper;
265     }
266
267     /**
268      * It assignes the PNamingContext which manages a relation.
269      * @param n
270      * @param pnc
271      * @param isMultiple
272      */

273     public void configurePnc(String JavaDoc n, PNamingContext pnc, JormFactory target, boolean isMultiple) throws PException {
274         if (isMultiple) {
275             PClassMappingCtrl gcm = (PClassMappingCtrl) getGenClassMapping(n);
276             gcm.setPNameCoder(pnc);
277             if (target.isPrefetch()) {
278                 //Initializes the genclass prefetching too
279
initGenClassPrefetch((PClassMapping) gcm, target);
280             }
281
282         } else {
283             setPNameCoder(n, pnc);
284         }
285         relNonInit--;
286         if (TraceEjb.isDebugFactory()) {
287             TraceEjb.factory.log(BasicLevel.DEBUG, "PNamingContext assigned, relNonInit=" + relNonInit);
288         }
289         if (relNonInit == 0) {
290             mapClass();
291         }
292     }
293
294     private void mapClass() {
295         if (mapped) {
296             throw new EJBException JavaDoc("The class is already mapped");
297         }
298
299         try {
300             // Map the user class into the mapper
301
mapper.map(this);
302             // Drop or Create tables, depending on what is in the DD
303
PMapCluster pmapclust = mapper.getPMapCluster(getClassName());
304             if (pmapclust.isDefined()) {
305                 switch (ecd.getCleanupPolicy()) {
306                 case EntityDesc.CLEANUP_REMOVEDATA:
307                     pmapclust.createMappingStructures(false);
308                     pmapclust.deleteData();
309                     break;
310                 case EntityDesc.CLEANUP_REMOVEALL:
311                     pmapclust.deleteMappingStructures();
312                     pmapclust.createMappingStructures(true);
313                     break;
314                 case EntityDesc.CLEANUP_NONE:
315                     break;
316                 case EntityDesc.CLEANUP_CREATE:
317                     pmapclust.createMappingStructures(false);
318                     break;
319                 default:
320                     throw new EJBException JavaDoc("Unknown cleanup policy: " + ecd.getCleanupPolicy());
321                 }
322             } else {
323                 // nothing in the JOnAS case because that means several beans have
324
// common structure due to the CMR. Then the last element of the
325
// PMapCluster should really apply your data action.
326
}
327             mapped = true;
328             if (TraceEjb.isDebugFactory()) {
329                 TraceEjb.factory.log(BasicLevel.DEBUG, getClassName() + " is mapped");
330             }
331         } catch (PException pe) {
332             Exception JavaDoc e = pe;
333             while ((e instanceof PException) && ((PException) e).getNestedException() != null) {
334                 e = ((PException) e).getNestedException();
335             }
336             TraceEjb.factory.log(BasicLevel.ERROR, "Impossible to map the class on the rdb mapper", e);
337             throw new EJBException JavaDoc("Impossible to map the class on the rdb mapper", e);
338         }
339     }
340
341     public void stop() {
342         super.stop();
343         try {
344             mapper.unmap(getClassName());
345             mapped = false;
346         } catch (PException e) {
347             TraceEjb.factory.log(BasicLevel.ERROR,
348                                 "Impossible to unmap the class " + getClassName(), e);
349         }
350     }
351
352     /**
353      * This method is overrided in order to specify the JEntityContext class
354      * which must be instanciated.
355      * Create a new instance of the bean and its EntityContext
356      * In case of CMP, the bean class is derived to manage entity persistence.
357      */

358     protected org.objectweb.jonas_ejb.container.JEntityContext createNewContext(EntityBean JavaDoc bean) {
359         return new org.objectweb.jonas_ejb.container.jorm.JEntityContext(this, bean);
360     }
361
362     public JEntitySwitch getJEntitySwitch() {
363         Object JavaDoc result = null;
364         try {
365             result = bindingClass.newInstance();
366         } catch (Exception JavaDoc e) {
367             TraceEjb.factory.log(BasicLevel.ERROR, "Impossible to create a new JEntitySwitch as specified in BeanNaming: " + bindingClass.getName(), e);
368             return super.getJEntitySwitch();
369         }
370         try {
371             ((PBinding) result).init(this);
372         } catch (PException e) {
373             TraceEjb.factory.log(BasicLevel.ERROR, "Impossible to initialized the new JEntitySwitch as specified in BeanNaming: " + bindingClass.getName(), e);
374         }
375         return (JEntitySwitch) result;
376     }
377
378     /**
379      * Create a GenClassMapping
380      * @param mapperName name of the mapper
381      */

382     protected PClassMapping newGCMInstance(String JavaDoc mapperName) throws Exception JavaDoc {
383         int idx = mapperName.indexOf(".");
384         String JavaDoc mn = (idx != -1) ? mapperName.substring(0, idx) : mapperName;
385         return (PClassMapping) Class.forName("org.objectweb.jorm.mapper." + mn + ".genclass."
386                                              + Character.toUpperCase(mn.charAt(0))
387                                              + mn.substring(1, mn.length()) + "GenClassMapping"
388                                              ).newInstance();
389     }
390
391     /**
392      * Encode PK in case of CMP2
393      * @return String representation of the PName
394      */

395     public Serializable JavaDoc encodePK(Serializable JavaDoc pk) {
396         try {
397             return (Serializable JavaDoc) ((PName) pk).encodeString();
398         } catch (PExceptionNaming e) {
399             TraceEjb.factory.log(BasicLevel.ERROR, "impossible to serialize PK" + e);
400             return pk;
401         }
402     }
403
404     /**
405      * Decode String to a PName
406      * @return PName matching the String
407      */

408     public Serializable JavaDoc decodePK(Serializable JavaDoc strpk) {
409         try {
410             return getPBinder().decodeString((String JavaDoc) strpk);
411         } catch (PExceptionNaming e) {
412             TraceEjb.factory.log(BasicLevel.ERROR, "impossible to deserialize PK" + e);
413             return strpk;
414         }
415     }
416
417     /**
418      * It initializes the prefetching of a genclassMapping with the
419      * PClassMapping of the target class of the multivalued CMR.
420      * @param gcm is the GenClassMapping to initialized
421      * @param targetPCM is the PClassMapping of the target class
422      */

423     protected abstract void initGenClassPrefetch(PClassMapping gcm, PClassMapping targetPCM);
424 }
425
Popular Tags