0001: /**
0002: * Copyright (C) 2001-2004 France Telecom R&D
0003: *
0004: * This library is free software; you can redistribute it and/or
0005: * modify it under the terms of the GNU Lesser General Public
0006: * License as published by the Free Software Foundation; either
0007: * version 2 of the License, or (at your option) any later version.
0008: *
0009: * This library is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0012: * Lesser General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU Lesser General Public
0015: * License along with this library; if not, write to the Free Software
0016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0017: */package org.objectweb.speedo.mapper.lib;
0018:
0019: import org.objectweb.fractal.api.control.BindingController;
0020: import org.objectweb.fractal.api.control.IllegalLifeCycleException;
0021: import org.objectweb.fractal.api.control.LifeCycleController;
0022: import org.objectweb.jorm.api.PClassMapping;
0023: import org.objectweb.jorm.api.PClassMappingCtrl;
0024: import org.objectweb.jorm.api.PException;
0025: import org.objectweb.jorm.api.PMapCluster;
0026: import org.objectweb.jorm.api.PMapper;
0027: import org.objectweb.jorm.lib.JormPathHelper;
0028: import org.objectweb.jorm.metainfo.api.Package;
0029: import org.objectweb.jorm.metainfo.lib.BasicClass;
0030: import org.objectweb.jorm.metainfo.lib.BasicCompositeName;
0031: import org.objectweb.jorm.metainfo.lib.JormManager;
0032: import org.objectweb.jorm.naming.api.PBinder;
0033: import org.objectweb.jorm.naming.api.PExceptionNaming;
0034: import org.objectweb.jorm.naming.api.PName;
0035: import org.objectweb.jorm.naming.api.PNameCoder;
0036: import org.objectweb.jorm.naming.api.PNameManager;
0037: import org.objectweb.jorm.naming.api.PNamingContext;
0038: import org.objectweb.jorm.naming.lib.KFPNCManager;
0039: import org.objectweb.jorm.type.api.PType;
0040: import org.objectweb.perseus.cache.api.CacheManager;
0041: import org.objectweb.perseus.persistence.api.ConnectionHolder;
0042: import org.objectweb.perseus.persistence.api.TransactionalPersistenceManager;
0043: import org.objectweb.speedo.api.SpeedoRuntimeException;
0044: import org.objectweb.speedo.genclass.AbstractGenClassHome;
0045: import org.objectweb.speedo.generation.lib.NamingRules;
0046: import org.objectweb.speedo.lib.Personality;
0047: import org.objectweb.speedo.mapper.api.JormFactory;
0048: import org.objectweb.speedo.mapper.api.JormFactoryAttributes;
0049: import org.objectweb.speedo.metadata.SpeedoIndex;
0050: import org.objectweb.speedo.mim.api.HomeItf;
0051: import org.objectweb.speedo.naming.api.NamingManager;
0052: import org.objectweb.speedo.naming.api.NamingManagerFactoryItf;
0053: import org.objectweb.speedo.naming.lib.NamingManagerHelper;
0054: import org.objectweb.speedo.pm.api.POManagerFactoryItf;
0055: import org.objectweb.speedo.sequence.api.SpeedoSequenceItf;
0056: import org.objectweb.util.monolog.api.BasicLevel;
0057: import org.objectweb.util.monolog.api.Logger;
0058: import org.objectweb.util.monolog.api.LoggerFactory;
0059:
0060: import java.math.BigDecimal;
0061: import java.math.BigInteger;
0062: import java.util.Date;
0063: import java.util.HashMap;
0064: import java.util.Iterator;
0065: import java.util.Map;
0066: import java.util.Properties;
0067: import java.util.Set;
0068:
0069: /**
0070: * This class manages the initialization and the naming, of persistent class.
0071: * The type of naming supported depends on the NamingManager registered into
0072: * the NamingManagerFactory
0073: *
0074: * @see org.objectweb.speedo.naming.api.NamingManager
0075: * @author S.Chassande-Barrioz
0076: */
0077: public class BasicJormFactory implements JormFactory, PNameCoder,
0078: BindingController, LifeCycleController, JormFactoryAttributes {
0079:
0080: /**
0081: * fractal binding name to the mapper
0082: */
0083: public final static String MAPPER_BINDING = "mapper";
0084: /**
0085: * fractal binding name to the cache manager
0086: */
0087: public final static String CACHE_MANAGER_BINDING = "cache-manager";
0088: public final static String TPM_BINDING = "transactional-persistence-manager";
0089: public final static String PMF_BINDING = "po-manager-factory";
0090: public final static String NMF_BINDING = "naming-manager-factory";
0091:
0092: protected TransactionalPersistenceManager tpm;
0093:
0094: protected POManagerFactoryItf pmf;
0095:
0096: /**
0097: * The mapper is used to map and find the Jorm classes.
0098: */
0099: protected PMapper mapper = null;
0100:
0101: /**
0102: * The cache to assign to the binders
0103: */
0104: protected CacheManager cache = null;
0105:
0106: /**
0107: * key = String class name
0108: * value = PBinder binder of the class
0109: */
0110: protected Map binders = null;
0111:
0112: /**
0113: * key = String class name
0114: * value = PNamingContext pnc of the class
0115: */
0116: protected Map pnamingContexts = null;
0117: /**
0118: * temporaly variable use in the recursive algorithm
0119: */
0120: protected Map cn2pcm = null;
0121:
0122: /**
0123: * The manager of NamingManager available.
0124: */
0125: private NamingManagerFactoryItf nmf;
0126:
0127: /**
0128: * The rule concerning the data structure (jorm property of the mapper)
0129: */
0130: private byte mappingStructuresRule = JormFactoryAttributes.CREATE_IF_REQUIRED;
0131:
0132: protected Logger logger = null;
0133:
0134: private KFPNCManager kfpncManager;
0135:
0136: ClassPropertiesManager cpm;
0137:
0138: Personality personality;
0139:
0140: /**
0141: * builds the BasicJormFactory
0142: * and the hosting structure for the binder list.
0143: */
0144: public BasicJormFactory() {
0145: pnamingContexts = new HashMap();
0146: binders = new HashMap();
0147: cn2pcm = new HashMap();
0148: kfpncManager = new KFPNCManager(pnamingContexts);
0149: cpm = new ClassPropertiesManager();
0150: }
0151:
0152: // IMPLEMENTATION OF THE JormFactoryAttributes INTERFACE //
0153: //-------------------------------------------------------//
0154:
0155: public byte getMappingStructureRule() {
0156: return mappingStructuresRule;
0157: }
0158:
0159: public void setMappingStructureRule(byte rule) {
0160: mappingStructuresRule = rule;
0161: }
0162:
0163: public Personality getPersonality() {
0164: return personality;
0165: }
0166:
0167: public void setPersonality(Personality p) {
0168: this .personality = p;
0169: }
0170:
0171: // IMPLEMENTATION OF THE UserBindingController INTERFACE //
0172: //-------------------------------------------------------//
0173:
0174: public String[] listFc() {
0175: return new String[] { MAPPER_BINDING, CACHE_MANAGER_BINDING,
0176: TPM_BINDING, PMF_BINDING, NMF_BINDING };
0177: }
0178:
0179: public Object lookupFc(String s) {
0180: if (MAPPER_BINDING.equals(s))
0181: return mapper;
0182: else if (CACHE_MANAGER_BINDING.equals(s))
0183: return cache;
0184: else if (TPM_BINDING.equals(s))
0185: return tpm;
0186: else if (PMF_BINDING.equals(s))
0187: return pmf;
0188: else if (NMF_BINDING.equals(s))
0189: return nmf;
0190: else
0191: return null;
0192: }
0193:
0194: public void bindFc(String s, Object o) {
0195: if ("logger".equals(s)) {
0196: logger = (Logger) o;
0197: } else if ("monolog-factory".equals(s)) {
0198: LoggerFactory lf = (LoggerFactory) o;
0199: kfpncManager.setLogger(lf.getLogger(logger.getName()
0200: + ".kfpncmanager"));
0201: cpm.logger = lf.getLogger(logger.getName()
0202: + ".class-properties");
0203: } else if (MAPPER_BINDING.equals(s)) {
0204: mapper = (PMapper) o;
0205: cpm.mapper = mapper;
0206: } else if (CACHE_MANAGER_BINDING.equals(s)) {
0207: cache = (CacheManager) o;
0208: } else if (TPM_BINDING.equals(s)) {
0209: tpm = (TransactionalPersistenceManager) o;
0210: } else if (PMF_BINDING.equals(s)) {
0211: pmf = (POManagerFactoryItf) o;
0212: } else if (NMF_BINDING.equals(s)) {
0213: nmf = (NamingManagerFactoryItf) o;
0214: }
0215: }
0216:
0217: public void unbindFc(String s) {
0218: if (MAPPER_BINDING.equals(s)) {
0219: mapper = null;
0220: } else if (CACHE_MANAGER_BINDING.equals(s)) {
0221: cache = null;
0222: } else if (TPM_BINDING.equals(s)) {
0223: tpm = null;
0224: } else if (PMF_BINDING.equals(s)) {
0225: pmf = null;
0226: } else if (NMF_BINDING.equals(s)) {
0227: nmf = null;
0228: }
0229: }
0230:
0231: private boolean started = false;
0232:
0233: public String getFcState() {
0234: return started ? STARTED : STOPPED;
0235: }
0236:
0237: public void startFc() throws IllegalLifeCycleException {
0238: if (!started) {
0239: mapper.addMapperEventListener(kfpncManager);
0240: started = true;
0241: }
0242: }
0243:
0244: public void stopFc() throws IllegalLifeCycleException {
0245: if (started) {
0246: mapper.removeMapperEventListener(kfpncManager);
0247: started = false;
0248: }
0249: }
0250:
0251: // IMPLEMENTATION OF THE JormFactory INTERFACE //
0252: //---------------------------------------------//
0253:
0254: public PBinder getPBinder(Class clazz) throws PException {
0255: String clName = clazz.getName();
0256: PClassMapping pcm = mapper.lookup(clName);
0257: if (pcm != null)
0258: return pcm.getPBinder();
0259: return getPClassMapping(clazz).getPBinder();
0260: }
0261:
0262: public PBinder getPBinder(String classname, ClassLoader cl)
0263: throws PException {
0264: PClassMapping pcm = mapper.lookup(classname);
0265: if (pcm != null)
0266: return pcm.getPBinder();
0267: return getPClassMapping(getClass(classname, cl)).getPBinder();
0268: }
0269:
0270: public ClassLoader getClassLoader(String className) {
0271: Object o = mapper.lookup(className);
0272: if (o == null) {
0273: return null;
0274: }
0275: return getClassLoader(o.getClass());
0276: }
0277:
0278: public PClassMapping getGenClassMapping(String path) {
0279: return JormPathHelper.getPClassMapping(path, mapper);
0280: }
0281:
0282: public PClassMapping getPClassMapping(Class clazz)
0283: throws PException {
0284: PClassMapping pcm = mapper.lookup(clazz.getName());
0285: if (pcm == null) {
0286: pcm = getPClassMapping(clazz.getName(), clazz
0287: .getClassLoader());
0288: }
0289: return pcm;
0290: }
0291:
0292: /**
0293: * This Method is a shortcut to the getPNamingContext(PersistentObjectItf) method.
0294: * It only does the instanciation of the classname
0295: * (Class.ForName(classsName).newInstance()) and call the
0296: * getPNamingContext(PersistentObjectItf) method with the created instance. Then if
0297: * an instance is availlable it is better to use the other method.
0298: * @param classname the Jorm class name managed by the wanted PNamingContext
0299: * @return the PNamingContext instance to use for the given jorm class name
0300: * @throws org.objectweb.jorm.api.PException
0301: */
0302: public PNamingContext getPNamingContext(String classname,
0303: ClassLoader cl) throws PException {
0304: return getPNamingContext(getClass(classname, cl));
0305: }
0306:
0307: public PNamingContext getPNamingContext(Class clazz)
0308: throws PException {
0309: PClassMapping pcm = getPClassMapping(clazz);
0310: String className = clazz.getName();
0311: String path = JormPathHelper.getPath(className);
0312: Properties classProperties = getClassProperties(clazz);
0313: String jormConf = classProperties.getProperty(path);
0314: if (jormConf != null) {
0315: return (PNamingContext) findPNameManager(className, clazz
0316: .getClassLoader(), pcm, jormConf);
0317: } else {
0318: throw new PException(
0319: "Impossible to find the PNamingContext for the class "
0320: + className);
0321: }
0322: }
0323:
0324: public Properties getSpeedoProperties() {
0325: return cpm.getProperties();
0326: }
0327:
0328: public void setSpeedoProperties(Properties p) {
0329: cpm.addProperties(p);
0330: pmf.getProperties().putAll(p);
0331: }
0332:
0333: public void setSpeedoProperty(String[] name_n_value) {
0334: cpm.addProperty(name_n_value[0], name_n_value[1]);
0335: if (name_n_value[1].length() == 0) {
0336: pmf.getProperties().remove(name_n_value[0]);
0337: } else {
0338: pmf.getProperties().setProperty(name_n_value[0],
0339: name_n_value[1]);
0340: }
0341: }
0342:
0343: public void clean() throws PException {
0344: //clear the binders
0345: binders.clear();
0346: //clear the pnaming contexts
0347: pnamingContexts.clear();
0348: //clear the map
0349: cn2pcm.clear();
0350: //clean the mapper
0351: mapper.clean();
0352: //clean the kfpnc manager
0353: kfpncManager.clean();
0354: //clean the nmf
0355: nmf.clean();
0356: }
0357:
0358: // IMPLEMENTATION OF THE PNameCoder INTERFACE //
0359: //--------------------------------------------//
0360: public boolean codingSupported(int codingtype) {
0361: return (codingtype & CTCOMPOSITE) != 0;
0362: }
0363:
0364: public PName decode(byte[] en) throws PExceptionNaming {
0365: return null;
0366: }
0367:
0368: public PName decodeAbstract(Object oid, Object context)
0369: throws PExceptionNaming, UnsupportedOperationException {
0370: Class clazz = null;
0371: ConnectionHolder conn = null;
0372: if (context != null) {
0373: if (!(context instanceof ConnectionHolder)) {
0374: clazz = (Class) context;
0375: } else {
0376: conn = (ConnectionHolder) context;
0377: }
0378: }
0379: if (oid instanceof PName) {
0380: try {
0381: return ((PName) oid).resolve(conn);
0382: } catch (PException e) {
0383: throw personality.newUserRuntimeException(
0384: "Impossible to decode the identifier "
0385: + oid
0386: + (clazz == null ? ""
0387: : " of the class "
0388: + clazz.getName()), e);
0389: }
0390: }
0391: PBinder binder = null;
0392: PName pn = null;
0393: try {
0394: if (clazz != null) {
0395: binder = getPBinder(clazz);
0396: }
0397: pn = nmf.decode(binder, oid, clazz, this );
0398: } catch (PException e) {
0399: throw personality.newUserRuntimeException(
0400: "Impossible to decode the identifier "
0401: + oid
0402: + (clazz == null ? "" : " of the class "
0403: + clazz.getName()), e);
0404: }
0405: if (pn != null) {
0406: return pn;
0407: }
0408: if (binder != null) {
0409: return binder.decodeAbstract(oid, null);
0410: }
0411: throw personality
0412: .newUserRuntimeException("Impossible to decode the identifier "
0413: + oid
0414: + (clazz == null ? "" : " of the class "
0415: + clazz.getName()));
0416: }
0417:
0418: public PName decodeByte(byte en) throws PExceptionNaming,
0419: UnsupportedOperationException {
0420: return decodeAbstract(new Byte(en), null);
0421: }
0422:
0423: public PName decodeObyte(Byte en) throws PExceptionNaming,
0424: UnsupportedOperationException {
0425: return decodeAbstract(en, null);
0426: }
0427:
0428: public PName decodeChar(char en) throws PExceptionNaming,
0429: UnsupportedOperationException {
0430: return decodeAbstract(new Character(en), null);
0431: }
0432:
0433: public PName decodeOchar(Character en) throws PExceptionNaming,
0434: UnsupportedOperationException {
0435: return decodeAbstract(en, null);
0436: }
0437:
0438: public PName decodeInt(int en) throws PExceptionNaming,
0439: UnsupportedOperationException {
0440: return decodeAbstract(new Integer(en), null);
0441: }
0442:
0443: public PName decodeOint(Integer en) throws PExceptionNaming,
0444: UnsupportedOperationException {
0445: return decodeAbstract(en, null);
0446: }
0447:
0448: public PName decodeLong(long en) throws PExceptionNaming,
0449: UnsupportedOperationException {
0450: return decodeAbstract(new Long(en), null);
0451: }
0452:
0453: public PName decodeOlong(Long en) throws PExceptionNaming,
0454: UnsupportedOperationException {
0455: return decodeAbstract(en, null);
0456: }
0457:
0458: public PName decodeShort(short en) throws PExceptionNaming,
0459: UnsupportedOperationException {
0460: return decodeAbstract(new Short(en), null);
0461: }
0462:
0463: public PName decodeOshort(Short en) throws PExceptionNaming,
0464: UnsupportedOperationException {
0465: return decodeAbstract(en, null);
0466: }
0467:
0468: public PName decodeString(String en) throws PExceptionNaming {
0469: return decodeAbstract(en, null);
0470: }
0471:
0472: public PName decodeCharArray(char[] en) throws PExceptionNaming {
0473: return decodeAbstract(en, null);
0474: }
0475:
0476: public PName decodeDate(Date en) throws PExceptionNaming {
0477: return decodeAbstract(en, null);
0478: }
0479:
0480: public PName decodeBigInteger(BigInteger en)
0481: throws PExceptionNaming {
0482: return decodeAbstract(en, null);
0483: }
0484:
0485: public PName decodeBigDecimal(BigDecimal en)
0486: throws PExceptionNaming {
0487: return decodeAbstract(en, null);
0488: }
0489:
0490: public byte[] encode(PName pn) throws PExceptionNaming {
0491: return pn.encode();
0492: }
0493:
0494: public Object encodeAbstract(PName pn) throws PExceptionNaming,
0495: UnsupportedOperationException {
0496: try {
0497: return nmf.encode(pn);
0498: } catch (PException e) {
0499: throw new SpeedoRuntimeException(
0500: "Impossible to encode the identifier :" + pn);
0501: }
0502: }
0503:
0504: public byte encodeByte(PName pn) throws PExceptionNaming,
0505: UnsupportedOperationException {
0506: throw new UnsupportedOperationException(
0507: "Impossible to encode to a byte");
0508: }
0509:
0510: public Byte encodeObyte(PName pn) throws PExceptionNaming,
0511: UnsupportedOperationException {
0512: throw new UnsupportedOperationException(
0513: "Impossible to encode to a Byte");
0514: }
0515:
0516: public char encodeChar(PName pn) throws PExceptionNaming,
0517: UnsupportedOperationException {
0518: throw new UnsupportedOperationException(
0519: "Impossible to encode to a char");
0520: }
0521:
0522: public Character encodeOchar(PName pn) throws PExceptionNaming,
0523: UnsupportedOperationException {
0524: throw new UnsupportedOperationException(
0525: "Impossible to encode to a Character");
0526: }
0527:
0528: public int encodeInt(PName pn) throws PExceptionNaming,
0529: UnsupportedOperationException {
0530: throw new UnsupportedOperationException(
0531: "Impossible to encode to a int");
0532: }
0533:
0534: public Integer encodeOint(PName pn) throws PExceptionNaming,
0535: UnsupportedOperationException {
0536: throw new UnsupportedOperationException(
0537: "Impossible to encode to a Integer");
0538: }
0539:
0540: public long encodeLong(PName pn) throws PExceptionNaming,
0541: UnsupportedOperationException {
0542: throw new UnsupportedOperationException(
0543: "Impossible to encode to a long");
0544: }
0545:
0546: public Long encodeOlong(PName pn) throws PExceptionNaming,
0547: UnsupportedOperationException {
0548: throw new UnsupportedOperationException(
0549: "Impossible to encode to a Long");
0550: }
0551:
0552: public short encodeShort(PName pn) throws PExceptionNaming,
0553: UnsupportedOperationException {
0554: throw new UnsupportedOperationException(
0555: "Impossible to encode to a short");
0556: }
0557:
0558: public Short encodeOshort(PName pn) throws PExceptionNaming,
0559: UnsupportedOperationException {
0560: throw new UnsupportedOperationException(
0561: "Impossible to encode to a Short");
0562: }
0563:
0564: public String encodeString(PName pn) throws PExceptionNaming {
0565: throw new UnsupportedOperationException(
0566: "Impossible to encode to a String");
0567: }
0568:
0569: public char[] encodeCharArray(PName pn) throws PExceptionNaming {
0570: throw new UnsupportedOperationException(
0571: "Impossible to encode to a char[]");
0572: }
0573:
0574: public Date encodeDate(PName pn) throws PExceptionNaming {
0575: throw new UnsupportedOperationException(
0576: "Impossible to encode to a Date");
0577: }
0578:
0579: public BigInteger encodeBigInteger(PName pn)
0580: throws PExceptionNaming {
0581: throw new UnsupportedOperationException(
0582: "Impossible to encode to a BigInteger");
0583: }
0584:
0585: public BigDecimal encodeBigDecimal(PName pn)
0586: throws PExceptionNaming {
0587: throw new UnsupportedOperationException(
0588: "Impossible to encode to a BigDecimal");
0589: }
0590:
0591: public PName getNull() {
0592: return null;
0593: }
0594:
0595: public void setNullPName(Object o) throws PException {
0596: }
0597:
0598: public boolean supportDynamicComposite() {
0599: return false;
0600: }
0601:
0602: public boolean supportCompositeField(String fn, PType ft) {
0603: return false;
0604: }
0605:
0606: public boolean supportStaticComposite() {
0607: return false;
0608: }
0609:
0610: public PType getPType() {
0611: return null;
0612: }
0613:
0614: public void setPType(PType pt) {
0615: }
0616:
0617: // PRIVATE METHODS //
0618: //-----------------//
0619:
0620: /**
0621: * Fetch the configuration properties of a persistent class. The current
0622: * speedo implementation make available the properties throught the
0623: * method getClassProperties() of the home class.
0624: * The method implementation of this method invokes the method.
0625: * @param clazz is the java.lang.Class of a persistent class
0626: * @return the java.util.Properties instance describing the configuration
0627: * properties of the given persistent class.
0628: * @throws PException if an error occurs during the method invocation.
0629: */
0630: private Properties getClassProperties(Class clazz)
0631: throws PException {
0632: PClassMapping pcm = getPClassMapping(clazz.getName(), clazz
0633: .getClassLoader());
0634: return ((HomeItf) pcm).getClassProperties();
0635: }
0636:
0637: /**
0638: * This method is the real implementation of the getPClassMapping methods
0639: * from the JormFactory interface. It instanciates and configure a
0640: * persistent class. That represents
0641: * - the instanciation of the PClassMapping
0642: * - its configuration: fetching PNamingContext instances for each reference
0643: * and allocating GenClassMapping for each gen class reference (collection).
0644: * - the mapping of class (map operation on the mapper)
0645: * - the management of data strucutre for the cluster (creation table)
0646: *
0647: * @param className is the class name of the persistent class which the
0648: * PClasMapping is asked
0649: * @param classLoader is the classloader for the persistent class. It
0650: * assumes that the classloader contains the Speedo/Jorm classes about the
0651: * persistent class (PClassMapping, PAccessor, PName, PBinder, PNG, ...)
0652: * @return The PClassMapping of the persistent class
0653: * @throws PException
0654: */
0655: public synchronized PClassMapping getPClassMapping(
0656: String className, ClassLoader classLoader)
0657: throws PException {
0658: boolean debug = logger.isLoggable(BasicLevel.DEBUG);
0659: HomeItf pcm = (HomeItf) cn2pcm.get(className);
0660: if (pcm != null) {
0661: if (debug)
0662: logger.log(BasicLevel.DEBUG, "PClassMapping for class "
0663: + className + " is being configured:" + pcm);
0664: return pcm;
0665: }
0666:
0667: pcm = (HomeItf) mapper.lookup(className);
0668: if (pcm != null) {
0669: if (debug)
0670: logger.log(BasicLevel.DEBUG, "PClassMapping for class "
0671: + className + " already exist:" + pcm);
0672: return pcm;
0673: }
0674:
0675: // Creates the PClassMapping, its PBinder and the PNC
0676: if (debug) {
0677: logger.log(BasicLevel.DEBUG,
0678: "Looking for the PClassMapping of the class "
0679: + className);
0680: }
0681: String pcmcn = NamingRules.fqMappingName(className);
0682: try {
0683: pcm = (HomeItf) classLoader.loadClass(pcmcn).newInstance();
0684: } catch (Exception e) {
0685: throw new PException(e,
0686: "Impossible to instanciate the PClassMapping of the class "
0687: + className + ": " + pcmcn);
0688: }
0689: pcm.setTransactionalPersistenceManager(tpm);
0690: pcm.setPOManagerFactory(pmf);
0691: Properties classProperties = pcm.getClassProperties();
0692: if (debug) {
0693: logger.log(BasicLevel.DEBUG, "Jorm config:"
0694: + classProperties);
0695: }
0696: //Load the Jorm Meta information
0697: loadJormSpeedoMI(className, classProperties, classLoader);
0698:
0699: // Fetch the Binder
0700: PBinder binder = findPBinder(className, classLoader,
0701: classProperties.getProperty(JormPathHelper
0702: .getPath(className)));
0703: pcm.setPBinder(binder);
0704: binder.setPClassMapping(pcm);
0705:
0706: // Fetch the PNC of the class
0707: PNameCoder classPnc = findPNameManager(className, classLoader,
0708: pcm, classProperties.getProperty(JormPathHelper
0709: .getPath(className)));
0710: ((PClassMappingCtrl) pcm).setClassPNameCoder(classPnc);
0711: //Configure references (PNameCoder and GenClassMappping)
0712: RefConfig refConfig = new RefConfig(classProperties,
0713: classLoader);
0714: cn2pcm.put(className, pcm);//register the pcm in order to avoid double configuration
0715: pcm.configureRefFields(refConfig);
0716: cn2pcm.remove(className);
0717: if (debug) {
0718: logger.log(BasicLevel.DEBUG,
0719: "PClassMapping/PBinder/PNC created for the class "
0720: + className);
0721: logger.log(BasicLevel.DEBUG, "- pcm: " + pcm);
0722: logger.log(BasicLevel.DEBUG, "- binder: " + binder);
0723: logger.log(BasicLevel.DEBUG, "-pnc: " + classPnc);
0724: }
0725: // Maps the class
0726: mapper.map(null, pcm);
0727: pcm.configureRefFields(new GCMHomeConfig(pcm));
0728: cpm.applyProperties(pcm);
0729: logger.log(BasicLevel.DEBUG, "Class " + className + " mapped");
0730: //Manage the cluster of classes
0731: PMapCluster cluster = mapper.getPMappingStructuresManager()
0732: .getPMapCluster(className);
0733: if (cluster.isDefined()) { //cluster is full (all classes are mapped)
0734: if (mappingStructuresRule >= CREATE_IF_REQUIRED) {
0735: if (mappingStructuresRule == FORCE_CREATE) {
0736: cluster.deleteMappingStructures();
0737: }
0738: cluster
0739: .createMappingStructures(mappingStructuresRule == FORCE_CREATE);
0740: if (mappingStructuresRule == DELETE_DATA) {
0741: cluster.deleteData();
0742: }
0743: }
0744: if (logger.isLoggable(BasicLevel.INFO)) {
0745: String msr = null;
0746: switch (mappingStructuresRule) {
0747: case CREATE_IF_REQUIRED:
0748: msr = "CREATE_IF_REQUIRED";
0749: break;
0750: case FORCE_CREATE:
0751: msr = "FORCE_CREATE";
0752: break;
0753: case DELETE_DATA:
0754: msr = "DELETE_DATA";
0755: break;
0756: case DO_NOTHING:
0757: msr = "DO_NOTHING";
0758: break;
0759: }
0760: logger.log(BasicLevel.INFO, "Classes "
0761: + cluster.getClusterClasses()
0762: + " initialized (" + msr + ").");
0763: }
0764: } else { // some classes are not already mapped
0765: //ask the mapping of the next
0766: getPClassMapping((String) cluster
0767: .getUnResolvedDependencies().iterator().next(),
0768: classLoader);
0769: }
0770: return pcm;
0771: }
0772:
0773: /**
0774: * Load a class from a given classLoader
0775: * @param classname is the name of the class to load
0776: * (non null value is required).
0777: * @param cl is the classloader contains the class
0778: * (non null value is required).
0779: * @return the Class object (never null)
0780: */
0781: private Class getClass(String classname, ClassLoader cl)
0782: throws PException {
0783: if (cl == null) {
0784: throw new PException("Impossible to load the class "
0785: + classname + " without a classLoader(" + cl + ")");
0786: }
0787: try {
0788: return cl.loadClass(classname);
0789: } catch (Exception e) {
0790: throw new PException(e, "Impossible to load the class '"
0791: + classname + "' with the class loader :" + cl);
0792: }
0793: }
0794:
0795: /**
0796: * Retrieves a PBinder managing a given persistent class.
0797: * This implementation delegates the PBinder allocation to NamingManager.
0798: * @see org.objectweb.speedo.naming.api.NamingManager
0799: *
0800: * @param className is the name of the persistent class which the asked
0801: * PBinder must managed
0802: * @param classLoader is the classloader for the persistent class. It
0803: * assumes that the classloader contains the Speedo/Jorm classes about the
0804: * persistent class (PClassMapping, PAccessor, PName, PBinder, PNG, ...)
0805: * @param hints is a string data permitting to allocate and to configure
0806: * the PBinder.
0807: * @return the PBinder managing the given persistent class.
0808: */
0809: public synchronized PBinder findPBinder(String className,
0810: ClassLoader classLoader, String hints) throws PException {
0811: if (hints == null || hints.length() == 0)
0812: throw new PException(
0813: "Impossible to get the PNamingContext of the class "
0814: + className
0815: + ": Specified binder class is not valid: "
0816: + hints);
0817: PBinder binder = (PBinder) binders.get(className);
0818: if (binder != null)
0819: return binder;
0820: binder = nmf.getNamingManager(hints, classLoader).getPBinder(
0821: className, hints, classLoader, mappingStructuresRule,
0822: binders, pnamingContexts);
0823: //binder.setCacheManager(cache);
0824: binders.put(className, binder);
0825: return binder;
0826: }
0827:
0828: /**
0829: * Retrieves a PNameManager managing a given persistent class and its sub
0830: * classes. This implementation delegates the PNameManager allocation to
0831: * NamingManager.
0832: * @see org.objectweb.speedo.naming.api.NamingManager
0833: *
0834: * @param className is the name of the persistent class which the asked
0835: * PNameManager must managed (non null value is required)
0836: * @param classLoader is the classloader for the persistent class. It
0837: * assumes that the classloader contains the Speedo/Jorm classes about the
0838: * persistent class (PClassMapping, PAccessor, PName, PBinder, PNG, ...)
0839: * (non null value is required)
0840: * @param hints is a string data permitting to allocate and to configure
0841: * the PNameManager. (non null value is required)
0842: * @return the PNameManager managing the given persistent class and its
0843: * sub classes.
0844: */
0845: protected synchronized PNameManager findPNameManager(
0846: String className, ClassLoader classLoader,
0847: PClassMapping pcm, String hints) throws PException {
0848: if (hints == null || hints.length() == 0)
0849: throw new SpeedoRuntimeException(
0850: "Impossible to get the PNamingContext of the class "
0851: + className
0852: + ": Specified PNameManager class is not valid: "
0853: + hints);
0854: PNameManager pnm = (PNameManager) pnamingContexts
0855: .get(className);
0856: if (pnm != null
0857: && (hints.indexOf(NamingManagerHelper.POLYMORPHIC_PNC) == -1))
0858: return pnm;
0859: NamingManager nm = nmf.getNamingManager(hints, classLoader);
0860: if (nm.supportPNamingcontext()) {
0861: pnm = nm.getPNamingContext(className, hints, classLoader,
0862: mappingStructuresRule, binders, pnamingContexts,
0863: mapper.getMetaInfoManager(), pcm);
0864: } else {
0865: pnm = findPBinder(className, classLoader, hints);
0866: }
0867: pnamingContexts.put(className, pnm);
0868: return pnm;
0869: }
0870:
0871: /**
0872: * Is defines a PClassMapping.ReferenceConfigurator permitting to configure
0873: * the reference of a persistent class.
0874: */
0875: private class RefConfig implements
0876: PClassMapping.ReferenceConfigurator {
0877:
0878: /**
0879: * The properties of the persistent class. This properties contains the
0880: * information permitting to allowing the naming manager for the class
0881: * and its references.
0882: */
0883: private Map classProperties = null;
0884:
0885: /**
0886: * is the classloader for the persistent class. It assumes that the
0887: * classloader contains the Speedo/Jorm classes about the persistent
0888: * class (PClassMapping, PAccessor, PName, PBinder, PNG, ...)
0889: * (non null value is required).
0890: */
0891: private ClassLoader classLoader = null;
0892:
0893: public RefConfig(Map _classProperties, ClassLoader cl) {
0894: this .classProperties = _classProperties;
0895: this .classLoader = cl;
0896: }
0897:
0898: // IMPLEMENTATION OF THE PClassMapping.PNCGetter INTERFACE //
0899: //---------------------------------------------------------//
0900:
0901: public PNameCoder getPNameCoder(String sourceclassName,
0902: String refFieldName, String destclassName) {
0903: try {
0904: PNamingContext pnc = getPNamingContext(destclassName,
0905: classLoader);
0906: if (logger.isLoggable(BasicLevel.DEBUG))
0907: logger.log(BasicLevel.DEBUG,
0908: "Assign the PNamingContext for the field "
0909: + sourceclassName + "."
0910: + refFieldName
0911: + " which references the class "
0912: + destclassName + ": " + pnc);
0913: logger.log(BasicLevel.DEBUG, "getPNameManager("
0914: + destclassName + ") ==>" + pnc);
0915: return pnc;
0916: } catch (PException e) {
0917: throw new SpeedoRuntimeException(
0918: "ERROR during the assignation of the PNameManager of the reference "
0919: + refFieldName + " of the class "
0920: + sourceclassName, e);
0921: }
0922: }
0923:
0924: public PNameCoder getPNameCoder(String sourceclassName,
0925: String refFieldName, String[] genClassNames) {
0926: String path = JormPathHelper.getPath(sourceclassName,
0927: refFieldName, genClassNames);
0928: String hints = (String) classProperties.get(path);
0929: try {
0930: PNamingContext pnc = (PNamingContext) findPNameManager(
0931: path, classLoader, null, hints);
0932: logger.log(BasicLevel.DEBUG, "getPNameManager(" + path
0933: + ") ==>" + pnc);
0934: return pnc;
0935: } catch (PException e) {
0936: throw new SpeedoRuntimeException(e.getMessage(), e);
0937: }
0938: }
0939:
0940: public PClassMapping getGenClassMapping(String sourceclassName,
0941: String refFieldName, String[] genClassNames) {
0942:
0943: String cn = JormPathHelper.getPath(sourceclassName,
0944: refFieldName, genClassNames);
0945: String hints = (String) classProperties.get(cn);
0946: logger.log(BasicLevel.DEBUG, "getGenClassMapping(" + cn
0947: + ")");
0948: logger.log(BasicLevel.DEBUG, "\thints=" + hints);
0949: try {
0950: PClassMapping gcm = (PClassMapping) Class.forName(
0951: getGCMClassName(mapper.getMapperName()))
0952: .newInstance();
0953: logger.log(BasicLevel.DEBUG, "\tgcm=" + gcm);
0954: PBinder pb = findPBinder(cn, classLoader, hints);
0955: logger.log(BasicLevel.DEBUG, "\tbinder=" + pb);
0956: gcm.setPBinder(pb);
0957: pb.setPClassMapping(gcm);
0958: return gcm;
0959: } catch (Exception e) {
0960: throw new SpeedoRuntimeException(e.getMessage(), e);
0961: }
0962: }
0963:
0964: public PClassMapping getGenClassMapping(String sourceclassName,
0965: String refFieldName, String[] genClassNames,
0966: String destclassName) {
0967: String cn = JormPathHelper.getPath(sourceclassName,
0968: refFieldName, genClassNames);
0969: String hints = (String) classProperties.get(cn);
0970: try {
0971: PClassMapping gcm = (PClassMapping) Class.forName(
0972: getGCMClassName(mapper.getMapperName()))
0973: .newInstance();
0974: logger.log(BasicLevel.DEBUG, "getGenClassMapping(" + cn
0975: + ")");
0976: logger.log(BasicLevel.DEBUG, "\tgcm=" + gcm);
0977: PBinder pb = findPBinder(cn, classLoader, hints);
0978: logger.log(BasicLevel.DEBUG, "\tbinder=" + pb);
0979: gcm.setPBinder(pb);
0980: pb.setPClassMapping(gcm);
0981: PNamingContext pnc = getPNamingContext(destclassName,
0982: classLoader);
0983: logger.log(BasicLevel.DEBUG, "\tpnc=" + pnc);
0984: ((PClassMappingCtrl) gcm).setPNameCoder(pnc);
0985: return gcm;
0986: } catch (Exception e) {
0987: throw new SpeedoRuntimeException(e.getMessage(), e);
0988: }
0989: }
0990: }
0991:
0992: private class GCMHomeConfig implements
0993: PClassMapping.ReferenceConfigurator {
0994: PClassMapping pcm;
0995:
0996: GCMHomeConfig(PClassMapping _pcm) {
0997: this .pcm = _pcm;
0998: }
0999:
1000: public PNameCoder getPNameCoder(String sourceclassName,
1001: String refFieldName, String destclassName) {
1002: return pcm.getPNameCoder(refFieldName);
1003: }
1004:
1005: public PNameCoder getPNameCoder(String sourceclassName,
1006: String refFieldName, String[] genClassNames) {
1007: return pcm.getPNameCoder(refFieldName);
1008: }
1009:
1010: public PClassMapping getGenClassMapping(String sourceclassName,
1011: String refFieldName, String[] genClassNames) {
1012: PClassMapping gcm = pcm.getGenClassMapping(refFieldName);
1013: gcm = newGenClassHome(gcm, tpm, pmf, sourceclassName + "#"
1014: + refFieldName);
1015: gcm.getPBinder().setPClassMapping(gcm);
1016: logger.log(BasicLevel.DEBUG, "Insert the home=" + gcm);
1017: cpm.applyProperties((HomeItf) gcm);
1018: return gcm;
1019: }
1020:
1021: public PClassMapping getGenClassMapping(String sourceclassName,
1022: String refFieldName, String[] genClassNames,
1023: String destclassName) {
1024: PClassMapping gcm = pcm.getGenClassMapping(refFieldName);
1025: gcm = newGenClassHome(gcm, tpm, pmf, sourceclassName + "#"
1026: + refFieldName);
1027: gcm.getPBinder().setPClassMapping(gcm);
1028: logger.log(BasicLevel.DEBUG, "Insert the home=" + gcm);
1029: try {
1030: HomeItf refHome = (HomeItf) getPClassMapping(
1031: destclassName, pcm.getClass().getClassLoader());
1032: cpm.applyProperties((HomeItf) gcm, refHome);
1033: } catch (PException e) {
1034: logger.log(BasicLevel.WARN,
1035: "Impossible to fetch the Home of the class '"
1036: + destclassName + "'.", e);
1037: }
1038: return gcm;
1039: }
1040: }
1041:
1042: /**
1043: * Instanciates a new home for a generic class. The used class depends
1044: * on the Personality.
1045: * @param _pcm is the real pcm to link to the home
1046: * @param _tpm is the transactional persistence manager to link to the home
1047: * @param _pmf is the PO manager factory to link to the home
1048: * @param path is the path identifing the genclass.
1049: * @return a new instance of HomeItf managing a genclass
1050: */
1051: HomeItf newGenClassHome(PClassMapping _pcm,
1052: TransactionalPersistenceManager _tpm,
1053: POManagerFactoryItf _pmf, String path) {
1054: String cn = pmf.getPersonality().getPersonalityClassName(
1055: "org.objectweb.speedo.genclass", "GenClassHome");
1056: try {
1057: AbstractGenClassHome gcHome = (AbstractGenClassHome) Class
1058: .forName(cn).newInstance();
1059: gcHome.init(_pcm, _tpm, _pmf, path);
1060: return gcHome;
1061: } catch (Exception e) {
1062: throw new SpeedoRuntimeException(e);
1063: }
1064: }
1065:
1066: /**
1067: * Load the jorm/speedo meta information for a persistent class.
1068: *
1069: * @param className is the name of class which the Jorm meta information
1070: * has to be loaded.
1071: * @param classProperties is the properties of the persistent class. This
1072: * properties contains the information about file name containing the JMI.
1073: * @param classLoader is the classloader for the persistent class. It
1074: * assumes that the classloader contains the Speedo/Jorm classes about the
1075: * persistent class (PClassMapping, PAccessor, PName, PBinder, PNG, ...)
1076: * (non null value is required)
1077: */
1078: private void loadJormSpeedoMI(String className,
1079: Properties classProperties, ClassLoader classLoader) {
1080: JormManager m = (JormManager) mapper.getMetaInfoManager();
1081: synchronized (m) {
1082: if (m.getClass(className) != null) {
1083: return;
1084: }
1085: //deserialize the JMI from the file
1086: Set mos = null;
1087: String fn = classProperties
1088: .getProperty(Object2StringSerializer.DESC_FILE_NAME_PROP);
1089: try {
1090: mos = (Set) Object2StringSerializer.deserialize(fn,
1091: classLoader, logger);
1092: } catch (Exception e) {
1093: throw personality
1094: .newRuntimeException(
1095: "Impossible to load the jorm meta "
1096: + "information for the class '"
1097: + className
1098: + "' from the file '"
1099: + fn
1100: + "' (You must use the same Speedo version for the"
1101: + " enhancement and for the runtime): ",
1102: e);
1103: }
1104:
1105: //insert the Jorm meta object into the Jorm MI mamager
1106: for (Iterator it = mos.iterator(); it.hasNext();) {
1107: Object o = it.next();
1108: if (o instanceof BasicClass) {
1109: BasicClass c = (BasicClass) o;
1110: Package s = m.createPackage(((Package) c
1111: .getParent()).getName());
1112: s.addClass(c);
1113: c.setParent(s);
1114: c.setLogger(m.getLogger());
1115: logger.log(BasicLevel.DEBUG,
1116: "Jorm Meta Object Class " + c.getFQName()
1117: + " loaded");
1118: } else if (o instanceof BasicCompositeName) {
1119: BasicCompositeName cn = (BasicCompositeName) o;
1120: Package s = m.createPackage(((Package) cn
1121: .getParent()).getName());
1122: s.addCompositeName(cn);
1123: cn.setLogger(m.getLogger());
1124: logger.log(BasicLevel.DEBUG,
1125: "Jorm Meta Object CompositeName "
1126: + cn.getFQName() + " loaded");
1127: } else if (o instanceof SpeedoSequenceItf) {
1128: //add the sequence to the sequence manager of the pmf
1129: pmf.getSequenceManager().addSequence(o);
1130: logger.log(BasicLevel.DEBUG,
1131: "Speedo Meta Object Sequence " + o
1132: + " loaded");
1133: } else if (o instanceof SpeedoIndex) {
1134: //SpeedoIndex si = (SpeedoIndex) o;
1135: //TODO handle speedo index
1136: } else
1137: throw new SpeedoRuntimeException(
1138: "Umanaged Jorm/Speedo Meta Object " + o);
1139: }
1140: if (m.getClass(className) == null) {
1141: throw new SpeedoRuntimeException(
1142: "Internal ERROR: No meta information found about the persistent class '"
1143: + className + "' in the file '" + fn
1144: + "'.");
1145: }
1146: }
1147: }
1148:
1149: /**
1150: * Retrieves the class name of the PClassMapping implementation for the
1151: * generic class for a given mapper name.
1152: * @param mapperName is a name of a Jorm Mapper (rdb, rdb.postgres, fos, ..)
1153: */
1154: protected String getGCMClassName(String mapperName) {
1155: if (mapperName.startsWith("rdb")) {
1156: return "org.objectweb.jorm.mapper.rdb.genclass.RdbGenClassMapping";
1157: } else {
1158: throw new SpeedoRuntimeException("Umanaged mapper: "
1159: + mapperName);
1160: }
1161: }
1162:
1163: /**
1164: * Find the class loader of a java class. This is a tool method managing the
1165: * fact that the clazz.getClassCloader() method could return null. In this
1166: * case the Speedo class loader is returned.
1167: *
1168: * @param clazz is a java.lang.Class object
1169: */
1170: private ClassLoader getClassLoader(Class clazz) {
1171: ClassLoader cl = clazz.getClassLoader();
1172: if (cl == null) {
1173: cl = this .getClass().getClassLoader();
1174: if (cl == null) {
1175: cl = ClassLoader.getSystemClassLoader();
1176: logger.log(BasicLevel.DEBUG,
1177: "Use the system class loader for the class '"
1178: + clazz.getName() + "': " + cl);
1179: } else {
1180: logger.log(BasicLevel.DEBUG,
1181: "Use the Speedo class loader for the class '"
1182: + clazz.getName() + "': " + cl);
1183: }
1184: } else {
1185: logger.log(BasicLevel.DEBUG,
1186: "Use the Application class loader for the class '"
1187: + clazz.getName() + "': " + cl);
1188: }
1189: return cl;
1190: }
1191:
1192: }
|