JormFactory.java

00001 
00026 package org.objectweb.jonas_ejb.container.jorm;
00027 
00028 import org.objectweb.jonas_ejb.container.JContainer;
00029 import org.objectweb.jonas_ejb.container.JEntityFactory;
00030 import org.objectweb.jonas_ejb.container.JEntitySwitch;
00031 import org.objectweb.jonas_ejb.container.TraceEjb;
00032 import org.objectweb.jonas_ejb.deployment.api.EjbRelationshipRoleDesc;
00033 import org.objectweb.jonas_ejb.deployment.api.EntityCmp2Desc;
00034 import org.objectweb.jonas_ejb.deployment.api.EntityDesc;
00035 import org.objectweb.jonas_ejb.lib.JormType;
00036 import org.objectweb.jorm.api.PBinding;
00037 import org.objectweb.jorm.api.PClassMapping;
00038 import org.objectweb.jorm.api.PClassMappingCtrl;
00039 import org.objectweb.jorm.api.PException;
00040 import org.objectweb.jorm.api.PMapCluster;
00041 import org.objectweb.jorm.api.PMapper;
00042 import org.objectweb.jorm.api.PMappingCallback;
00043 import org.objectweb.jorm.facility.naming.basidir.BasidBinder;
00044 import org.objectweb.jorm.naming.api.PBinder;
00045 import org.objectweb.jorm.naming.api.PExceptionNaming;
00046 import org.objectweb.jorm.naming.api.PName;
00047 import org.objectweb.jorm.naming.api.PNameCoder;
00048 import org.objectweb.jorm.naming.api.PNamingContext;
00049 import org.objectweb.util.monolog.api.BasicLevel;
00050 
00051 import javax.ejb.EJBException;
00052 import javax.ejb.EntityBean;
00053 
00054 import java.io.Serializable;
00055 import java.util.Iterator;
00056 
00064 public abstract class JormFactory extends JEntityFactory implements PClassMapping, PClassMappingCtrl {
00065 
00066     protected int relNonInit;
00067     protected boolean mapped;
00068     protected PMapper mapper = null;
00069     protected EntityCmp2Desc ecd = null;
00070 
00074     public JormFactory() {
00075         super();
00076     }
00077 
00078     protected abstract void setMapper(String mapperName) throws PException;
00079     public abstract Object getConnection(Object hints) throws PException;
00080     public abstract void releaseConnection(Object conn) throws PException;
00081 
00086     public void init(EntityDesc ed, JContainer c, String mapperName) {
00087         TraceEjb.factory.log(BasicLevel.DEBUG, ed.getEjbName());
00088 
00089         // First, call the super in order to have the access to the datasource
00090         // and the beanNaming
00091         super.init(ed, c);
00092         ecd = (EntityCmp2Desc) ed;
00093         try {
00094             setMapper(mapperName);
00095         } catch (PException e) {
00096             throw new EJBException("JormFactory cannot create the mapper", e);
00097         }
00098 
00099         //----------------------- JORM INITIALIZATION -----------------------//
00100         TraceEjb.factory.log(BasicLevel.DEBUG, "Jorm initialisation");
00101         PBinder binder = null;
00102         Class binderClass = null;
00103         int binderCT = 0;
00104         try {
00105 
00106             // Instanciate the binder
00107             binderClass = c.getClassLoader().loadClass(ecd.getJormBinderClassName());
00108             binder = (PBinder) binderClass.newInstance();
00109             if (ecd.hasPrimaryKeyField()) {
00110                 binderCT = JormType.getCodingType(ecd.getCmpFieldDesc(ecd.getPrimaryKeyFieldName()).getFieldType(), true);
00111                 ((BasidBinder) binder).setCodingType(binderCT);
00112             } else {
00113                 // TODO:
00114                 // - take the initial values of the primary key
00115                 // - put them into the generated binder (use a PNG)
00116             }
00117             TraceEjb.factory.log(BasicLevel.DEBUG, "binder " + ecd.getJormBinderClassName() + "instanciated");
00118 
00119             // Link the binder and the PClassMapping
00120             binder.setPClassMapping(this);
00121             setPBinder(binder);
00122             TraceEjb.factory.log(BasicLevel.DEBUG, "binder linked to the mapping");
00123 
00124         } catch (Exception e) {
00125             TraceEjb.factory.log(BasicLevel.ERROR, "Impossible to create the binder", e);
00126             throw new EJBException("Impossible to create the binder: bean:" + ecd.getEjbName(), e);
00127         }
00128 
00129         // for each reference assignes the PNamingcontext if it is possible.
00130         relNonInit = 0;
00131         try {
00132             for (Iterator it = ecd.getEjbRelationshipRoleDescIterator(); it.hasNext();) {
00133                 EjbRelationshipRoleDesc rsr = (EjbRelationshipRoleDesc) it.next();
00134                 String source = rsr.getSourceBean().getEjbName();
00135                 String target = rsr.getTargetBean().getEjbName();
00136                 JormFactory pcm2 = source.equals(target) ? this : (JormFactory) c.getBeanFactory(target);
00137                 TraceEjb.factory.log(BasicLevel.DEBUG,
00138                                     "treatement of the relation " + rsr.getRelation().getName()
00139                                     + ": current-bean=" + ecd.getEjbName()
00140                                     + ", source-bean=" + source
00141                                     + ", dest-bean=" + target
00142                                     + ", cmr-field=" + rsr.getCmrFieldName());
00143 
00144                 if (rsr.hasCmrField()) {
00145                     PClassMapping gcm = null;
00146                     //Multivalued relation
00147                     if (rsr.isTargetMultiple()) {
00148                         // Instanciate a GenClassMapping and link it
00149                         gcm = newGCMInstance(mapperName);
00150                         gcm.init((PMappingCallback) mapper, null);
00151                         setGenClassMapping(rsr.getCmrFieldName(), gcm);
00152                         TraceEjb.factory.log(BasicLevel.DEBUG,
00153                                             "assign a GenClassMapping for the CMR "
00154                                             + rsr.getCmrFieldName() + " / gcm=" + gcm);
00155 
00156                         PBinder gcmBinder = null;
00157                         try {
00158                             gcmBinder = (PBinder) binderClass.newInstance();
00159                         } catch (Exception e) {
00160                             TraceEjb.factory.log(BasicLevel.ERROR,
00161                                                 "Impossible to create the binder of the GCM bean: "
00162                                                 + ecd.getEjbName() + " / CMR: "
00163                                                 + rsr.getCmrFieldName(), e);
00164                             throw new EJBException(
00165                                                    "Impossible to create the binder of the GCM bean: "
00166                                                    + ecd.getEjbName() + " / CMR: "
00167                                                    + rsr.getCmrFieldName(), e);
00168                         }
00169                         if (ecd.hasPrimaryKeyField()) {
00170                             ((BasidBinder) gcmBinder).setCodingType(binderCT);
00171                         } else {
00172                             // TODO: (not so important)
00173                             // - take the initial values of the primary key
00174                             // - put them into the generated binder (use a PNG)
00175                         }
00176                         gcm.setPBinder(gcmBinder);
00177                         gcmBinder.setPClassMapping(gcm);
00178                         setPNameCoder(rsr.getCmrFieldName(), (PNameCoder) gcmBinder);
00179                     }
00180 
00181                     // As the bean with which the current bean is in relation
00182                     // may be not load, the test of pcm2!=null is needed
00183                     if (pcm2 != null) {
00184                         TraceEjb.factory.log(BasicLevel.DEBUG, "Pnc Assignement");
00185                         if (rsr.isTargetMultiple()) {
00186                             ((PClassMappingCtrl)gcm).setPNameCoder((PNameCoder) pcm2.getPBinder());
00187                         } else {
00188                             setPNameCoder(rsr.getCmrFieldName(), (PNameCoder) pcm2.getPBinder());
00189                         }
00190                     } else {
00191                         relNonInit++;
00192                         TraceEjb.factory.log(BasicLevel.DEBUG, "the Pnc is not reachable currently. relNonInit=" + relNonInit);
00193                         // The PNamingContext has not been set.
00194                     }
00195                 }
00196                 EjbRelationshipRoleDesc rsr2 = rsr.getOppositeRelationshipRole();
00197                 if (pcm2 != null && rsr2.hasCmrField() && pcm2 != this) {
00198                     // This case appears when the scheduling of the bean adding
00199                     // in the container is bad (or cyclic relation): A bean has
00200                     // been load and have a relation to current bean. We must
00201                     // therfore set the naming context on the PClassMapping of
00202                     // the first bean for the opposite CMR field
00203                     TraceEjb.factory.log(BasicLevel.DEBUG,
00204                                         "later Pnc assignement of the opposite CMR field: "
00205                                         + rsr2.getCmrFieldName());
00206                     pcm2.configurePnc(rsr2.getCmrFieldName(), (PNamingContext) getPBinder(), rsr2.isTargetMultiple());
00207                 }
00208             }
00209         } catch (EJBException e) {
00210             throw e;
00211         } catch (Exception e) {
00212             TraceEjb.factory.log(BasicLevel.ERROR,
00213                                 "Impossible to assign the naming context to the PClassMapping", e);
00214             throw new EJBException("Impossible to assign the naming context to the PClassMapping", e);
00215         }
00216         mapped = false;
00217         if (relNonInit == 0) {
00218             mapClass();
00219         }
00220     }
00221 
00225     public PMapper getMapper() {
00226         return mapper;
00227     }
00228 
00235     public void configurePnc(String n, PNamingContext pnc, boolean isMultiple) throws PException {
00236         if (isMultiple) {
00237             PClassMappingCtrl gcm = (PClassMappingCtrl) getGenClassMapping(n);
00238             gcm.setPNameCoder(pnc);
00239         } else {
00240             setPNameCoder(n, pnc);
00241         }
00242         relNonInit--;
00243         TraceEjb.factory.log(BasicLevel.DEBUG, "PNamingContext assigned, relNonInit=" + relNonInit);
00244         if (relNonInit == 0) {
00245             mapClass();
00246         }
00247     }
00248 
00249     private void mapClass() {
00250         if (mapped) {
00251             throw new EJBException("The class is already mapped");
00252         }
00253 
00254         try {
00255             // Map the user class into the mapper
00256             mapper.map(this);
00257             // Drop or Create tables, depending on what is in the DD
00258             PMapCluster pmapclust = mapper.getPMapCluster(getClassName());
00259             if (pmapclust.isDefined()) {
00260                 switch (ecd.getCleanupPolicy()) {
00261                 case EntityDesc.CLEANUP_REMOVEDATA:
00262                     pmapclust.createMappingStructures(false);
00263                     pmapclust.deleteData();
00264                     break;
00265                 case EntityDesc.CLEANUP_REMOVEALL:
00266                     pmapclust.deleteMappingStructures();
00267                     pmapclust.createMappingStructures(true);
00268                     break;
00269                 case EntityDesc.CLEANUP_NONE:
00270                     break;
00271                 case EntityDesc.CLEANUP_CREATE:
00272                     pmapclust.createMappingStructures(false);
00273                     break;
00274                 default:
00275                     throw new EJBException("Unknown cleanup policy: " + ecd.getCleanupPolicy());
00276                 }
00277             } else {
00278                 // nothing in the JOnAS case because that means several beans have
00279                 // common structure due to the CMR. Then the last element of the
00280                 // PMapCluster should really apply your data action.
00281             }
00282             mapped = true;
00283             TraceEjb.factory.log(BasicLevel.DEBUG, getClassName() + " is mapped");
00284         } catch (PException pe) {
00285             Exception e = pe;
00286             while ((e instanceof PException) && ((PException) e).getNestedException() != null) {
00287                 e = ((PException) e).getNestedException();
00288             }
00289             TraceEjb.factory.log(BasicLevel.ERROR, "Impossible to map the class on the rdb mapper", e);
00290             throw new EJBException("Impossible to map the class on the rdb mapper", e);
00291         }
00292     }
00293 
00294     public void stop() {
00295         super.stop();
00296         try {
00297             mapper.unmap(getClassName());
00298             mapped = false;
00299         } catch (PException e) {
00300             TraceEjb.factory.log(BasicLevel.ERROR,
00301                                 "Impossible to unmap the class " + getClassName(), e);
00302         }
00303     }
00304 
00311     protected org.objectweb.jonas_ejb.container.JEntityContext createNewContext(EntityBean bean) {
00312         return new org.objectweb.jonas_ejb.container.jorm.JEntityContext(this, bean);
00313     }
00314 
00315     public JEntitySwitch getJEntitySwitch() {
00316         Object result = null;
00317         String cn = ((EntityCmp2Desc) dd).getJormBindingClassName();
00318         try {
00319             result = getContainer().getClassLoader().loadClass(cn).newInstance();
00320         } catch (ClassNotFoundException e1) {
00321             TraceEjb.factory.log(BasicLevel.ERROR, "Impossible to create a new JEntitySwitch as specified in BeanNaming: " + cn, e1);
00322             return null;
00323         } catch (Exception e) {
00324             TraceEjb.factory.log(BasicLevel.ERROR, "Impossible to create a new JEntitySwitch as specifief in BeanNaming: " + cn, e);
00325             return super.getJEntitySwitch();
00326         }
00327         try {
00328             ((PBinding) result).init(this);
00329         } catch (PException e) {
00330             TraceEjb.factory.log(BasicLevel.ERROR, "Impossible to initialized the new JEntitySwitch as specifief in BeanNaming: " + cn, e);
00331         }
00332         return (JEntitySwitch) result;
00333     }
00334 
00339     protected PClassMapping newGCMInstance(String mapperName) throws Exception {
00340         int idx = mapperName.indexOf(".");
00341         String mn = (idx != -1) ? mapperName.substring(0, idx) : mapperName;
00342         return (PClassMapping) Class.forName("org.objectweb.jorm.mapper." + mn + ".genclass."
00343                                              + Character.toUpperCase(mn.charAt(0))
00344                                              + mn.substring(1, mn.length()) + "GenClassMapping"
00345                                              ).newInstance();
00346     }
00347     
00352     public Serializable encodePK(Serializable pk) {
00353         try {
00354             return (Serializable) ((PName) pk).encodeString();
00355         } catch (PExceptionNaming e) {
00356             TraceEjb.factory.log(BasicLevel.ERROR, "impossible to serialize PK" + e);
00357             return pk;
00358         }
00359     }
00360     
00365     public Serializable decodePK(Serializable strpk) {
00366         try {
00367             return getPBinder().decodeString((String) strpk);
00368         } catch (PExceptionNaming e) {
00369             TraceEjb.factory.log(BasicLevel.ERROR, "impossible to deserialize PK" + e);
00370             return strpk;
00371         }
00372     }
00373 }

Generated on Tue Feb 15 15:05:39 2005 for JOnAS by  doxygen 1.3.9.1