0001: /*
0002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003: *
0004: * This file is part of Resin(R) Open Source
0005: *
0006: * Each copy or derived work must preserve the copyright notice and this
0007: * notice unmodified.
0008: *
0009: * Resin Open Source is free software; you can redistribute it and/or modify
0010: * it under the terms of the GNU General Public License as published by
0011: * the Free Software Foundation; either version 2 of the License, or
0012: * (at your option) any later version.
0013: *
0014: * Resin Open Source is distributed in the hope that it will be useful,
0015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017: * of NON-INFRINGEMENT. See the GNU General Public License for more
0018: * details.
0019: *
0020: * You should have received a copy of the GNU General Public License
0021: * along with Resin Open Source; if not, write to the
0022: *
0023: * Free Software Foundation, Inc.
0024: * 59 Temple Place, Suite 330
0025: * Boston, MA 02111-1307 USA
0026: *
0027: * @author Scott Ferguson
0028: */
0029:
0030: package com.caucho.ejb.cfg;
0031:
0032: import com.caucho.ejb.cfg21.EjbEntityBean;
0033: import com.caucho.ejb.cfg21.CmrMap;
0034: import com.caucho.ejb.cfg21.CmpRelationRole;
0035: import com.caucho.ejb.cfg21.CmpRelation;
0036: import com.caucho.ejb.cfg21.CmrManyToOne;
0037: import com.caucho.ejb.cfg21.CmrOneToMany;
0038: import com.caucho.ejb.cfg21.CmrManyToMany;
0039: import com.caucho.config.Config;
0040: import com.caucho.config.ConfigException;
0041: import com.caucho.config.LineConfigException;
0042: import com.caucho.config.types.EjbLocalRef;
0043: import com.caucho.config.types.FileSetType;
0044: import com.caucho.config.types.ResourceEnvRef;
0045: import com.caucho.ejb.AbstractServer;
0046: import com.caucho.ejb.amber.AmberConfig;
0047: import com.caucho.ejb.manager.EjbContainer;
0048: import com.caucho.ejb.ql.FunExpr;
0049: import com.caucho.java.gen.JavaClassGenerator;
0050: import com.caucho.loader.Environment;
0051: import com.caucho.loader.EnvironmentClassLoader;
0052: import com.caucho.log.Log;
0053: import com.caucho.util.L10N;
0054: import com.caucho.vfs.JarPath;
0055: import com.caucho.vfs.Path;
0056:
0057: import java.util.ArrayList;
0058: import java.util.Collection;
0059: import java.util.Collections;
0060: import java.util.Comparator;
0061: import java.util.HashMap;
0062: import java.util.Map;
0063: import java.util.logging.Logger;
0064:
0065: /**
0066: * Manages the EJB configuration files.
0067: */
0068: public class EjbConfig {
0069: private static final L10N L = new L10N(EjbConfig.class);
0070: private static final Logger log = Log.open(EjbConfig.class);
0071:
0072: private final EjbContainer _ejbContainer;
0073:
0074: private ArrayList<FileSetType> _fileSetList = new ArrayList<FileSetType>();
0075:
0076: private HashMap<String, EjbBean> _cfgBeans = new HashMap<String, EjbBean>();
0077: private ArrayList<CmpRelation> _relations = new ArrayList<CmpRelation>();
0078:
0079: private ArrayList<EjbBean> _pendingBeans = new ArrayList<EjbBean>();
0080: private ArrayList<EjbBean> _deployingBeans = new ArrayList<EjbBean>();
0081:
0082: private ArrayList<EjbBeanConfigProxy> _proxyList = new ArrayList<EjbBeanConfigProxy>();
0083:
0084: private ArrayList<FunctionSignature> _functions = new ArrayList<FunctionSignature>();
0085:
0086: private String _booleanTrue = "1";
0087: private String _booleanFalse = "0";
0088:
0089: private boolean _isAllowPOJO;
0090: private HashMap<String, MessageDestination> _messageDestinations;
0091:
0092: private ArrayList<Interceptor> _cfgInterceptors = new ArrayList<Interceptor>();
0093:
0094: private ArrayList<InterceptorBinding> _cfgInterceptorBindings = new ArrayList<InterceptorBinding>();
0095:
0096: private ArrayList<ApplicationExceptionConfig> _cfgApplicationExceptions = new ArrayList<ApplicationExceptionConfig>();
0097:
0098: public EjbConfig(EjbContainer ejbContainer) {
0099: _ejbContainer = ejbContainer;
0100:
0101: _functions.addAll(FunExpr.getStandardFunctions());
0102: }
0103:
0104: /**
0105: * Adds a path for an EJB config file to the config list.
0106: */
0107: public void addFileSet(FileSetType fileSet) {
0108: if (_fileSetList.contains(fileSet))
0109: return;
0110:
0111: _fileSetList.add(fileSet);
0112:
0113: for (Path path : fileSet.getPaths()) {
0114: addEjbPath(path);
0115: }
0116: }
0117:
0118: /**
0119: * Adds a path for an EJB config file to the config list.
0120: */
0121: public void addEjbPath(Path path) throws ConfigException {
0122: throw new UnsupportedOperationException();
0123: }
0124:
0125: public void addProxy(EjbBeanConfigProxy proxy) {
0126: _proxyList.add(proxy);
0127: }
0128:
0129: /**
0130: * Returns the schema name.
0131: */
0132: public String getSchema() {
0133: return "com/caucho/ejb/cfg/resin-ejb.rnc";
0134: }
0135:
0136: /**
0137: * Returns the EJB manager.
0138: */
0139: public EjbContainer getEjbContainer() {
0140: return _ejbContainer;
0141: }
0142:
0143: /**
0144: * Sets the boolean true literal.
0145: */
0146: public void setBooleanTrue(String trueLiteral) {
0147: _booleanTrue = trueLiteral;
0148: }
0149:
0150: /**
0151: * Gets the boolean true literal.
0152: */
0153: public String getBooleanTrue() {
0154: return _booleanTrue;
0155: }
0156:
0157: /**
0158: * Sets the boolean false literal.
0159: */
0160: public void setBooleanFalse(String falseLiteral) {
0161: _booleanFalse = falseLiteral;
0162: }
0163:
0164: /**
0165: * Gets the boolean false literal.
0166: */
0167: public String getBooleanFalse() {
0168: return _booleanFalse;
0169: }
0170:
0171: /**
0172: * Returns the cfg bean with the given name.
0173: */
0174: public EjbBean getBeanConfig(String name) {
0175: assert name != null;
0176:
0177: return _cfgBeans.get(name);
0178: }
0179:
0180: /**
0181: * Sets the cfg bean with the given name.
0182: */
0183: public void setBeanConfig(String name, EjbBean bean) {
0184: if (name == null || bean == null)
0185: throw new NullPointerException();
0186:
0187: EjbBean oldBean = _cfgBeans.get(name);
0188:
0189: if (oldBean == bean)
0190: return;
0191: else if (oldBean != null) {
0192: throw new IllegalStateException(L.l("Duplicate bean '{0}'",
0193: name));
0194: }
0195:
0196: _pendingBeans.add(bean);
0197: _cfgBeans.put(name, bean);
0198: }
0199:
0200: /**
0201: * Returns the interceptor with the given class name.
0202: */
0203: public Interceptor getInterceptor(String className) {
0204: assert className != null;
0205:
0206: for (Interceptor interceptor : _cfgInterceptors) {
0207: if (interceptor.getInterceptorClass().equals(className))
0208: return interceptor;
0209: }
0210:
0211: return null;
0212: }
0213:
0214: /**
0215: * Adds an interceptor.
0216: */
0217: public void addInterceptor(Interceptor interceptor) {
0218: if (interceptor == null)
0219: throw new NullPointerException();
0220:
0221: _cfgInterceptors.add(interceptor);
0222: }
0223:
0224: /**
0225: * Returns the interceptor bindings for a given ejb name.
0226: */
0227: public InterceptorBinding getInterceptorBinding(String ejbName,
0228: boolean isExcludeDefault) {
0229: assert ejbName != null;
0230:
0231: for (InterceptorBinding binding : _cfgInterceptorBindings) {
0232: if (binding.getEjbName().equals(ejbName))
0233: return binding;
0234: }
0235:
0236: // ejb/0fbe vs ejb/0fbf
0237: for (InterceptorBinding binding : _cfgInterceptorBindings) {
0238: if (binding.getEjbName().equals("*")) {
0239: if (isExcludeDefault)
0240: continue;
0241:
0242: return binding;
0243: }
0244: }
0245:
0246: return null;
0247: }
0248:
0249: /**
0250: * Adds an application exception.
0251: */
0252: public void addApplicationException(
0253: ApplicationExceptionConfig applicationException) {
0254: _cfgApplicationExceptions.add(applicationException);
0255: }
0256:
0257: /**
0258: * Returns the application exceptions.
0259: */
0260: public ArrayList<ApplicationExceptionConfig> getApplicationExceptions() {
0261: return _cfgApplicationExceptions;
0262: }
0263:
0264: /**
0265: * Binds an interceptor to an ejb.
0266: */
0267: public void addInterceptorBinding(
0268: InterceptorBinding interceptorBinding) {
0269: _cfgInterceptorBindings.add(interceptorBinding);
0270: }
0271:
0272: /**
0273: * Adds the message destination mapping
0274: */
0275: public void addMessageDestination(
0276: MessageDestination messageDestination) {
0277: if (_messageDestinations == null)
0278: _messageDestinations = new HashMap<String, MessageDestination>();
0279:
0280: String name = messageDestination.getMessageDestinationName();
0281:
0282: _messageDestinations.put(name, messageDestination);
0283: }
0284:
0285: public MessageDestination getMessageDestination(String name) {
0286: if (_messageDestinations == null)
0287: return null;
0288:
0289: return _messageDestinations.get(name);
0290: }
0291:
0292: /**
0293: * Sets true if POJO are allowed.
0294: */
0295: public void setAllowPOJO(boolean allowPOJO) {
0296: _isAllowPOJO = allowPOJO;
0297: }
0298:
0299: /**
0300: * Return true if POJO are allowed.
0301: */
0302: public boolean isAllowPOJO() {
0303: return _isAllowPOJO;
0304: }
0305:
0306: public void addIntrospectableClass(String className) {
0307: try {
0308: ClassLoader loader = _ejbContainer
0309: .getIntrospectionClassLoader();
0310:
0311: Class type = Class.forName(className, false, loader);
0312:
0313: if (type.isAnnotationPresent(javax.ejb.Stateless.class)) {
0314: EjbStatelessBean bean = new EjbStatelessBean(this ,
0315: "resin-ejb");
0316: bean.setEJBClass(type);
0317: bean.setAllowPOJO(true);
0318:
0319: setBeanConfig(bean.getEJBName(), bean);
0320: } else if (type
0321: .isAnnotationPresent(javax.ejb.Stateful.class)) {
0322: EjbStatefulBean bean = new EjbStatefulBean(this ,
0323: "resin-ejb");
0324: bean.setAllowPOJO(true);
0325: bean.setEJBClass(type);
0326:
0327: setBeanConfig(bean.getEJBName(), bean);
0328: } else if (type
0329: .isAnnotationPresent(javax.ejb.MessageDriven.class)) {
0330: EjbMessageBean bean = new EjbMessageBean(this ,
0331: "resin-ejb");
0332: bean.setAllowPOJO(true);
0333: bean.setEJBClass(type);
0334:
0335: setBeanConfig(bean.getEJBName(), bean);
0336: }
0337: } catch (ConfigException e) {
0338: throw e;
0339: } catch (Exception e) {
0340: throw ConfigException.create(e);
0341: }
0342: }
0343:
0344: /**
0345: * Finds an entity bean by its abstract schema.
0346: */
0347: public EjbEntityBean findEntityBySchema(String schemaName) {
0348: for (EjbBean bean : _cfgBeans.values()) {
0349: if (bean instanceof EjbEntityBean) {
0350: EjbEntityBean entity = (EjbEntityBean) bean;
0351:
0352: if (schemaName.equals(entity.getAbstractSchemaName()))
0353: return entity;
0354: }
0355: }
0356:
0357: return null;
0358: }
0359:
0360: /**
0361: * Finds an entity bean by its abstract schema.
0362: */
0363: public EjbEntityBean findEntityByLocal(Class cl) {
0364: for (EjbBean bean : _cfgBeans.values()) {
0365: if (bean instanceof EjbEntityBean) {
0366: EjbEntityBean entity = (EjbEntityBean) bean;
0367:
0368: for (ApiClass apiClass : entity.getLocalList()) {
0369: if (apiClass.getJavaClass().equals(cl))
0370: return entity;
0371: }
0372: }
0373: }
0374:
0375: return null;
0376: }
0377:
0378: /**
0379: * Adds a relation.
0380: */
0381: public CmpRelation addRelation(String relationName,
0382: String sourceEJB, String sourceField) {
0383: CmpRelation relation = findRelation(relationName, sourceEJB,
0384: sourceField);
0385:
0386: if (relation != null)
0387: return relation;
0388:
0389: relation = new CmpRelation();
0390: relation.setName(relationName);
0391: relation.setSourceEJB(sourceEJB);
0392: relation.setSourceField(sourceField);
0393:
0394: _relations.add(relation);
0395:
0396: return relation;
0397: }
0398:
0399: /**
0400: * Adds a relation.
0401: */
0402: public CmpRelation findRelation(String relationName,
0403: String sourceEJB, String sourceField) {
0404: for (int i = 0; i < _relations.size(); i++) {
0405: CmpRelation relation = _relations.get(i);
0406:
0407: if (relationName != null
0408: && relationName.equals(relation.getName()))
0409: return relation;
0410:
0411: if (relation.getSourceEJB().equals(sourceEJB)
0412: && relation.getSourceField().equals(sourceField))
0413: return relation;
0414: }
0415:
0416: return null;
0417: }
0418:
0419: public void addRelation(CmpRelation rel) throws ConfigException {
0420: CmpRelation oldRel = findRelation(rel.getName(), rel
0421: .getSourceEJB(), rel.getSourceField());
0422:
0423: if (oldRel == null) {
0424: _relations.add(rel);
0425:
0426: return;
0427: }
0428:
0429: if (!rel.getTargetEJB().equals(oldRel.getTargetEJB())) {
0430: throw new ConfigException(
0431: L
0432: .l(
0433: "relationship '{0}.{1}' target EJB '{2}' does not match old target EJB '{3}' from {4}",
0434: rel.getSourceEJB(), rel
0435: .getSourceField(), rel
0436: .getTargetEJB(), oldRel
0437: .getTargetEJB(), oldRel
0438: .getLocation()));
0439: } else if (rel.getTargetField() != oldRel.getTargetField()
0440: && (rel.getTargetField() == null || !rel
0441: .getTargetField().equals(
0442: oldRel.getTargetField()))) {
0443: throw new ConfigException(
0444: L
0445: .l(
0446: "relationship '{0}.{1}' target field '{2}' does not match old target field '{3}' from {4}",
0447: rel.getSourceEJB(), rel
0448: .getSourceField(), rel
0449: .getTargetEJB(), oldRel
0450: .getTargetEJB(), oldRel
0451: .getLocation()));
0452: }
0453:
0454: oldRel.merge(rel);
0455: }
0456:
0457: public CmpRelation[] getRelations() {
0458: return _relations.toArray(new CmpRelation[_relations.size()]);
0459: }
0460:
0461: /**
0462: * Adds a function.
0463: */
0464: public void addFunction(FunctionSignature sig, String sql) {
0465: _functions.add(sig);
0466: }
0467:
0468: /**
0469: * Gets the function list.
0470: */
0471: public ArrayList<FunctionSignature> getFunctions() {
0472: return _functions;
0473: }
0474:
0475: /**
0476: * Configures the pending beans.
0477: */
0478: public void configure() throws ConfigException {
0479: findConfigurationFiles();
0480:
0481: try {
0482: ArrayList<EjbBean> beanConfig = new ArrayList<EjbBean>(
0483: _pendingBeans);
0484: _pendingBeans.clear();
0485:
0486: _deployingBeans.addAll(beanConfig);
0487:
0488: EnvironmentClassLoader parentLoader = _ejbContainer
0489: .getClassLoader();
0490:
0491: Path workDir = _ejbContainer.getWorkDir();
0492:
0493: JavaClassGenerator javaGen = new JavaClassGenerator();
0494: // need to be compatible with enhancement
0495: javaGen.setWorkDir(workDir);
0496: javaGen.setParentLoader(parentLoader);
0497:
0498: configureRelations();
0499:
0500: for (EjbBeanConfigProxy proxy : _proxyList) {
0501: EjbBean bean = _cfgBeans.get(proxy.getEJBName());
0502:
0503: if (bean != null)
0504: proxy.getBuilderProgram().configure(bean);
0505: }
0506:
0507: for (EjbBean bean : beanConfig) {
0508: bean.init();
0509: }
0510:
0511: Collections.sort(beanConfig, new BeanComparator());
0512:
0513: AmberConfig amberConfig = new AmberConfig(this );
0514:
0515: for (EjbBean bean : beanConfig) {
0516: bean.configureAmber(amberConfig);
0517: }
0518:
0519: amberConfig.configureRelations();
0520:
0521: if (_ejbContainer.isAutoCompile())
0522: amberConfig.generate(javaGen);
0523:
0524: for (EjbBean bean : beanConfig) {
0525: bean.generate(javaGen, _ejbContainer.isAutoCompile());
0526: }
0527:
0528: javaGen.compilePendingJava();
0529: } catch (RuntimeException e) {
0530: throw e;
0531: } catch (Exception e) {
0532: throw ConfigException.create(e);
0533: }
0534: }
0535:
0536: /**
0537: * Configures the pending beans.
0538: */
0539: private void findConfigurationFiles() throws ConfigException {
0540: for (FileSetType fileSet : _fileSetList) {
0541: for (Path path : fileSet.getPaths()) {
0542: addEjbPath(path);
0543: }
0544: }
0545: }
0546:
0547: /**
0548: * Configures the pending beans.
0549: */
0550: public void deploy() throws ConfigException {
0551: try {
0552: ClassLoader parentLoader = _ejbContainer.getClassLoader();
0553:
0554: Path workDir = _ejbContainer.getWorkDir();
0555:
0556: JavaClassGenerator javaGen = new JavaClassGenerator();
0557: javaGen.setWorkDir(workDir);
0558: javaGen.setParentLoader(parentLoader);
0559:
0560: ArrayList<EjbBean> deployingBeans = new ArrayList<EjbBean>(
0561: _deployingBeans);
0562: _deployingBeans.clear();
0563:
0564: deployBeans(deployingBeans, javaGen);
0565: } catch (RuntimeException e) {
0566: throw e;
0567: } catch (Exception e) {
0568: throw ConfigException.create(e);
0569: }
0570: }
0571:
0572: /**
0573: * Configures the pending beans.
0574: */
0575: public void deployBeans(ArrayList<EjbBean> beanConfig,
0576: JavaClassGenerator javaGen) throws Exception {
0577: Thread thread = Thread.currentThread();
0578: ClassLoader oldLoader = thread.getContextClassLoader();
0579:
0580: try {
0581: thread
0582: .setContextClassLoader(_ejbContainer
0583: .getClassLoader());
0584:
0585: // ejb/0g1c, ejb/0f68, ejb/0f69
0586: ArrayList<EjbBean> beanList = new ArrayList<EjbBean>();
0587:
0588: for (EjbBean bean : beanConfig) {
0589: if (beanList.contains(bean))
0590: continue;
0591:
0592: AbstractServer server = initBean(bean, javaGen);
0593: ArrayList<String> dependList = bean.getBeanDependList();
0594:
0595: for (String depend : dependList) {
0596: for (EjbBean b : beanConfig) {
0597: if (bean == b)
0598: continue;
0599:
0600: if (depend.equals(b.getEJBName())) {
0601: beanList.add(b);
0602:
0603: AbstractServer dependServer = initBean(b,
0604: javaGen);
0605:
0606: initResources(b, dependServer);
0607:
0608: thread.setContextClassLoader(server
0609: .getClassLoader());
0610: }
0611: }
0612: }
0613:
0614: initResources(bean, server);
0615: }
0616: } finally {
0617: thread.setContextClassLoader(oldLoader);
0618: }
0619: }
0620:
0621: private AbstractServer initBean(EjbBean bean,
0622: JavaClassGenerator javaGen) throws Exception {
0623: AbstractServer server = bean.deployServer(_ejbContainer,
0624: javaGen);
0625:
0626: server.init();
0627:
0628: return server;
0629: }
0630:
0631: private void initResources(EjbBean bean, AbstractServer server)
0632: throws Exception {
0633: /*
0634: for (ResourceEnvRef ref : bean.getResourceEnvRefs())
0635: ref.initBinding(server);
0636:
0637: // XXX TCK, needs QA probably ejb/0gc4 ejb/0gc5
0638: for (EjbLocalRef ref : bean.getEjbLocalRefs())
0639: ref.initBinding(server);
0640: */
0641: _ejbContainer.addServer(server);
0642: }
0643:
0644: /**
0645: * Match up the relations.
0646: */
0647: protected void configureRelations() throws ConfigException {
0648: for (CmpRelation relation : _relations) {
0649: try {
0650: CmpRelationRole sourceRole = relation.getSourceRole();
0651: CmpRelationRole targetRole = relation.getTargetRole();
0652:
0653: String sourceEJB = sourceRole.getEJBName();
0654: EjbEntityBean sourceEntity = (EjbEntityBean) _cfgBeans
0655: .get(sourceEJB);
0656:
0657: if (sourceEntity == null)
0658: throw new ConfigException(L.l(
0659: "'{0}' is an unknown EJB bean.", sourceEJB));
0660:
0661: String sourceField = sourceRole.getFieldName();
0662: ApiMethod sourceMethod = sourceEntity
0663: .getFieldGetter(sourceField);
0664:
0665: ApiMethod sourceMapMethod = null;
0666:
0667: if (sourceField != null)
0668: sourceMapMethod = getMapMethod(sourceEntity,
0669: sourceField);
0670:
0671: if (sourceField != null && sourceMethod == null
0672: && sourceMapMethod == null)
0673: throw new ConfigException(
0674: L
0675: .l(
0676: "{0}: relation field '{1}' does not have a corresponding getter method. cmr-relations must define abstract getter methods returning a local interface.",
0677: sourceEntity.getEJBClass()
0678: .getName(),
0679: sourceField));
0680:
0681: String targetEJB = targetRole.getEJBName();
0682: EjbEntityBean targetEntity = (EjbEntityBean) _cfgBeans
0683: .get(targetEJB);
0684:
0685: if (targetEntity == null)
0686: throw new ConfigException(L.l(
0687: "'{0}' is an unknown EJB bean.", targetEJB));
0688:
0689: String targetField = targetRole.getFieldName();
0690: ApiMethod targetMethod = targetEntity
0691: .getFieldGetter(targetField);
0692:
0693: ApiMethod targetMapMethod = null;
0694:
0695: if (targetField != null)
0696: targetMapMethod = getMapMethod(targetEntity,
0697: targetField);
0698:
0699: if (targetField != null && targetMethod == null
0700: && targetMapMethod == null)
0701: throw new ConfigException(
0702: L
0703: .l(
0704: "{0}: relation field '{1}' does not have a corresponding getter method. cmr-relations must define abstract getter methods returning a local interface.",
0705: targetEntity.getEJBClass()
0706: .getName(),
0707: targetField));
0708:
0709: boolean sourceOneToMany = false;
0710: boolean sourceManyToOne = false;
0711: boolean sourceMap = false;
0712:
0713: if (sourceMethod == null) {
0714: } else if (Collection.class
0715: .isAssignableFrom(sourceMethod.getReturnType()))
0716: sourceOneToMany = true;
0717: else if (Map.class.isAssignableFrom(sourceMethod
0718: .getReturnType()))
0719: sourceMap = true;
0720: else
0721: sourceManyToOne = true;
0722:
0723: boolean targetOneToMany = false;
0724: boolean targetManyToOne = false;
0725: boolean targetMap = false;
0726:
0727: if (targetMapMethod != null)
0728: targetMap = true;
0729:
0730: if (targetMethod == null) {
0731: } else if (Collection.class
0732: .isAssignableFrom(targetMethod.getReturnType()))
0733: targetOneToMany = true;
0734: else if (Map.class.isAssignableFrom(targetMethod
0735: .getReturnType()))
0736: targetMap = true;
0737: else
0738: targetManyToOne = true;
0739:
0740: if (sourceMap) {
0741: createMap(targetEntity, targetField, targetRole,
0742: sourceEntity, sourceField, sourceRole,
0743: sourceMapMethod);
0744: } else if (targetMap) {
0745: createMap(sourceEntity, sourceField, sourceRole,
0746: targetEntity, targetField, targetRole,
0747: targetMapMethod);
0748: } else if (sourceOneToMany && targetManyToOne) {
0749: CmrOneToMany srcRel = new CmrOneToMany(
0750: sourceEntity, sourceField, targetEntity,
0751: targetField);
0752:
0753: srcRel.setSQLColumns(sourceRole.getSQLColumns());
0754: srcRel.setOrderBy(sourceRole.getOrderBy());
0755: // srcRel.setCascadeDelete(sourceRole.getCascadeDelete());
0756:
0757: sourceEntity.addRelation(srcRel);
0758:
0759: CmrManyToOne dstRel = new CmrManyToOne(
0760: targetEntity, targetField, sourceEntity);
0761:
0762: dstRel.setSQLColumns(targetRole.getSQLColumns());
0763: dstRel.setSourceCascadeDelete(targetRole
0764: .getCascadeDelete());
0765: dstRel.setTargetCascadeDelete(sourceRole
0766: .getCascadeDelete());
0767:
0768: targetEntity.addRelation(dstRel);
0769:
0770: srcRel.setTargetRelation(dstRel);
0771: dstRel.setTargetRelation(srcRel);
0772: } else if (sourceOneToMany && targetOneToMany) {
0773: CmrManyToMany srcRel = new CmrManyToMany(
0774: sourceEntity, sourceField, targetEntity,
0775: targetField);
0776:
0777: srcRel.setLocation(relation.getLocation());
0778:
0779: srcRel.setRelationName(relation.getName());
0780: srcRel.setSQLTable(relation.getSQLTable());
0781: srcRel.setOrderBy(sourceRole.getOrderBy());
0782:
0783: srcRel.setKeySQLColumns(sourceRole.getSQLColumns());
0784: srcRel.setDstSQLColumns(targetRole.getSQLColumns());
0785:
0786: sourceEntity.addRelation(srcRel);
0787:
0788: CmrManyToMany dstRel = new CmrManyToMany(
0789: targetEntity, targetField, sourceEntity,
0790: sourceField);
0791:
0792: dstRel.setLocation(relation.getLocation());
0793:
0794: dstRel.setRelationName(relation.getName());
0795: dstRel.setSQLTable(relation.getSQLTable());
0796: dstRel.setOrderBy(targetRole.getOrderBy());
0797:
0798: dstRel.setKeySQLColumns(targetRole.getSQLColumns());
0799: dstRel.setDstSQLColumns(sourceRole.getSQLColumns());
0800:
0801: targetEntity.addRelation(dstRel);
0802: /*
0803:
0804: srcRel.setTargetRelation(dstRel);
0805: dstRel.setTargetRelation(srcRel);
0806: CmrOneToMany srcRel = new CmrOneToMany(sourceEntity,
0807: sourceField,
0808: targetEntity,
0809: targetField);
0810:
0811: // manyToOne.setSQLColumns(sourceRole.getSQLColumns());
0812:
0813: sourceEntity.addRelation(srcRel);
0814:
0815: CmrOneToMany dstRel = new CmrOneToMany(targetEntity,
0816: targetField,
0817: sourceEntity,
0818: sourceField);
0819:
0820: // dstRel.setSQLColumns(sourceRole.getSQLColumns());
0821:
0822: targetEntity.addRelation(dstRel);
0823:
0824: srcRel.setTargetRelation(dstRel);
0825: dstRel.setTargetRelation(srcRel);
0826: */
0827: } else if (sourceOneToMany) {
0828: CmrManyToMany srcRel = new CmrManyToMany(
0829: sourceEntity, sourceField, targetEntity,
0830: targetField);
0831:
0832: srcRel.setLocation(relation.getLocation());
0833:
0834: if (relation.getName() != null)
0835: srcRel.setRelationName(relation.getName());
0836: else if (relation.getSQLTable() != null)
0837: srcRel.setRelationName(relation.getSQLTable());
0838: else
0839: srcRel.setRelationName(sourceField);
0840:
0841: if (relation.getSQLTable() != null
0842: || relation.getName() != null)
0843: srcRel.setSQLTable(relation.getSQLTable());
0844: else
0845: srcRel.setSQLTable(sourceField);
0846:
0847: srcRel.setOrderBy(sourceRole.getOrderBy());
0848:
0849: srcRel.setKeySQLColumns(sourceRole.getSQLColumns());
0850: srcRel.setDstSQLColumns(targetRole.getSQLColumns());
0851:
0852: srcRel.setTargetUnique("One".equals(sourceRole
0853: .getMultiplicity()));
0854:
0855: sourceEntity.addRelation(srcRel);
0856: } else if (sourceManyToOne && targetManyToOne) {
0857: if (relation.getSQLTable() != null)
0858: throw new ConfigException(
0859: L
0860: .l(
0861: "cmr-field '{0}' may not have a sql-table '{1}'. one-to-one relations do not have association tables.",
0862: sourceField, relation
0863: .getSQLTable()));
0864:
0865: CmrManyToOne srcRel = new CmrManyToOne(
0866: sourceEntity, sourceField, targetEntity);
0867:
0868: srcRel.setLocation(relation.getLocation());
0869:
0870: srcRel.setSQLColumns(sourceRole.getSQLColumns());
0871:
0872: /*
0873: if (targetRole.getCascadeDelete() &&
0874: "Many".equals(sourceRole.getMultiplicity()))
0875: throw new ConfigException(L.l("'{0}' may not set cascade-delete because '{0}' has multiplicity 'Many'",
0876: targetField,
0877: sourceField));
0878: */
0879:
0880: srcRel.setSourceCascadeDelete(sourceRole
0881: .getCascadeDelete());
0882: srcRel.setTargetCascadeDelete(targetRole
0883: .getCascadeDelete());
0884:
0885: sourceEntity.addRelation(srcRel);
0886:
0887: CmrManyToOne dstRel = new CmrManyToOne(
0888: targetEntity, targetField, sourceEntity);
0889:
0890: dstRel.setLocation(relation.getLocation());
0891:
0892: dstRel.setSQLColumns(targetRole.getSQLColumns());
0893:
0894: targetEntity.addRelation(dstRel);
0895:
0896: if ((sourceRole.getSQLColumns() == null || sourceRole
0897: .getSQLColumns().length == 0)
0898: && targetRole.getSQLColumns() != null
0899: && targetRole.getSQLColumns().length > 0) {
0900: srcRel.setDependent(true);
0901:
0902: dstRel.setSourceCascadeDelete(targetRole
0903: .getCascadeDelete());
0904: dstRel.setTargetCascadeDelete(sourceRole
0905: .getCascadeDelete());
0906: }
0907:
0908: if ((targetRole.getSQLColumns() == null || targetRole
0909: .getSQLColumns().length == 0)) {
0910: // ejb/06h4
0911: // ejb/06hm
0912: dstRel.setDependent(true);
0913:
0914: srcRel.setSourceCascadeDelete(sourceRole
0915: .getCascadeDelete());
0916: srcRel.setTargetCascadeDelete(targetRole
0917: .getCascadeDelete());
0918: }
0919:
0920: srcRel.setTargetRelation(dstRel);
0921: dstRel.setTargetRelation(srcRel);
0922: } else if (sourceManyToOne && targetOneToMany) {
0923: CmrManyToOne srcRel = new CmrManyToOne(
0924: sourceEntity, sourceField, targetEntity);
0925:
0926: srcRel.setLocation(relation.getLocation());
0927:
0928: srcRel.setSQLColumns(sourceRole.getSQLColumns());
0929:
0930: sourceEntity.addRelation(srcRel);
0931:
0932: CmrOneToMany dstRel = new CmrOneToMany(
0933: targetEntity, targetField, sourceEntity,
0934: sourceField);
0935:
0936: dstRel.setLocation(relation.getLocation());
0937: dstRel.setSQLColumns(sourceRole.getSQLColumns());
0938: dstRel.setOrderBy(targetRole.getOrderBy());
0939:
0940: targetEntity.addRelation(dstRel);
0941:
0942: srcRel.setTargetRelation(dstRel);
0943: dstRel.setTargetRelation(srcRel);
0944:
0945: if (targetRole.getCascadeDelete()
0946: && "Many".equals(sourceRole
0947: .getMultiplicity()))
0948: throw new ConfigException(
0949: L
0950: .l(
0951: "'{0}' may not set cascade-delete because '{1}' has multiplicity 'Many'",
0952: targetField,
0953: sourceField));
0954: } else if (sourceManyToOne) {
0955: CmrManyToOne srcRel = new CmrManyToOne(
0956: sourceEntity, sourceField, targetEntity);
0957:
0958: srcRel.setSQLColumns(sourceRole.getSQLColumns());
0959:
0960: srcRel.setSourceCascadeDelete(sourceRole
0961: .getCascadeDelete());
0962: srcRel.setTargetCascadeDelete(targetRole
0963: .getCascadeDelete());
0964:
0965: sourceEntity.addRelation(srcRel);
0966: } else if (targetManyToOne) {
0967: CmrManyToOne dstRel = new CmrManyToOne(
0968: targetEntity, targetField, sourceEntity);
0969:
0970: dstRel.setSQLColumns(targetRole.getSQLColumns());
0971:
0972: dstRel.setSourceCascadeDelete(targetRole
0973: .getCascadeDelete());
0974: dstRel.setTargetCascadeDelete(sourceRole
0975: .getCascadeDelete());
0976:
0977: targetEntity.addRelation(dstRel);
0978: } else if (targetOneToMany) {
0979: CmrOneToMany dstRel = new CmrOneToMany(
0980: targetEntity, targetField, sourceEntity,
0981: sourceField);
0982:
0983: dstRel.setSQLColumns(targetRole.getSQLColumns());
0984: dstRel.setOrderBy(targetRole.getOrderBy());
0985:
0986: targetEntity.addRelation(dstRel);
0987: } else {
0988: throw new ConfigException(L
0989: .l("unsupported relation"));
0990: }
0991: } catch (LineConfigException e) {
0992: throw e;
0993: } catch (ConfigException e) {
0994: throw new LineConfigException(relation.getLocation()
0995: + e.getMessage(), e);
0996: }
0997: }
0998: }
0999:
1000: private void createMap(EjbEntityBean sourceEntity, String idField,
1001: CmpRelationRole sourceRole, EjbEntityBean targetEntity,
1002: String targetField, CmpRelationRole targetRole,
1003: ApiMethod targetMapMethod) throws ConfigException {
1004: CmrManyToOne srcRel = new CmrManyToOne(sourceEntity, idField,
1005: targetEntity);
1006:
1007: srcRel.setSQLColumns(sourceRole.getSQLColumns());
1008: /*
1009: dstRel.setSQLColumns(targetRole.getSQLColumns());
1010: dstRel.setCascadeDelete(targetRole.getCascadeDelete());
1011: */
1012:
1013: sourceEntity.addRelation(srcRel);
1014:
1015: CmrMap map = new CmrMap(targetEntity, targetField,
1016: sourceEntity, srcRel);
1017:
1018: map.setMapMethod(targetMapMethod);
1019:
1020: targetEntity.addRelation(map);
1021: }
1022:
1023: /**
1024: * Returns the map method.
1025: */
1026: public ApiMethod getMapMethod(EjbEntityBean entityBean, String field) {
1027: String methodName = ("get"
1028: + Character.toUpperCase(field.charAt(0)) + field
1029: .substring(1));
1030:
1031: for (ApiMethod method : entityBean.getEJBClassWrapper()
1032: .getMethods()) {
1033: if (!method.getName().equals(methodName))
1034: continue;
1035: else if (method.getParameterTypes().length != 1)
1036: continue;
1037: else if ("void".equals(method.getReturnType().getName()))
1038: continue;
1039: else if (!method.isAbstract())
1040: continue;
1041: else
1042: return method;
1043: }
1044:
1045: return null;
1046: }
1047:
1048: static class BeanComparator implements Comparator {
1049: public int compare(Object a, Object b) {
1050: if (a == b)
1051: return 0;
1052:
1053: EjbBean beanA = (EjbBean) a;
1054: EjbBean beanB = (EjbBean) b;
1055:
1056: if (!(a instanceof EjbEntityBean)
1057: && !(b instanceof EjbEntityBean))
1058: return beanA.getEJBName().compareTo(beanB.getEJBName());
1059: else if (!(a instanceof EjbEntityBean))
1060: return 1;
1061: else if (!(b instanceof EjbEntityBean))
1062: return -1;
1063:
1064: EjbEntityBean entityA = (EjbEntityBean) a;
1065: EjbEntityBean entityB = (EjbEntityBean) b;
1066:
1067: if (entityB.dependsOn(entityA))
1068: return -1;
1069: else if (entityA.dependsOn(entityB))
1070: return 1;
1071: else
1072: return entityA.getEJBName().compareTo(
1073: entityB.getEJBName());
1074: }
1075: }
1076: }
|