001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb.assembler.classic;
017:
018: import org.apache.openejb.Injection;
019: import org.apache.openejb.OpenEJBException;
020: import org.apache.openejb.spi.ContainerSystem;
021: import org.apache.openejb.core.CoreUserTransaction;
022: import org.apache.openejb.core.ivm.naming.CrossClassLoaderJndiReference;
023: import org.apache.openejb.core.ivm.naming.IntraVmJndiReference;
024: import org.apache.openejb.core.ivm.naming.IvmContext;
025: import org.apache.openejb.core.ivm.naming.JaxWsServiceReference;
026: import org.apache.openejb.core.ivm.naming.JndiReference;
027: import org.apache.openejb.core.ivm.naming.JndiUrlReference;
028: import org.apache.openejb.core.ivm.naming.NameNode;
029: import org.apache.openejb.core.ivm.naming.ParsedName;
030: import org.apache.openejb.core.ivm.naming.PersistenceContextReference;
031: import org.apache.openejb.core.ivm.naming.Reference;
032: import org.apache.openejb.core.ivm.naming.SystemComponentReference;
033: import org.apache.openejb.core.ivm.naming.URLReference;
034: import org.apache.openejb.core.webservices.HandlerChainData;
035: import org.apache.openejb.core.webservices.PortRefData;
036: import org.apache.openejb.core.webservices.ServiceRefData;
037: import org.apache.openejb.loader.SystemInstance;
038: import org.apache.openejb.persistence.JtaEntityManager;
039: import org.apache.openejb.persistence.JtaEntityManagerRegistry;
040: import org.apache.openejb.util.LogCategory;
041: import org.apache.openejb.util.Logger;
042: import org.apache.openejb.core.timer.TimerServiceWrapper;
043: import org.apache.xbean.naming.context.WritableContext;
044: import org.omg.CORBA.ORB;
045:
046: import javax.ejb.EJBContext;
047: import javax.ejb.TimerService;
048: import javax.ejb.spi.HandleDelegate;
049: import javax.naming.Context;
050: import javax.naming.LinkRef;
051: import javax.naming.Name;
052: import javax.naming.NamingException;
053: import javax.persistence.EntityManagerFactory;
054: import javax.transaction.TransactionManager;
055: import javax.transaction.TransactionSynchronizationRegistry;
056: import javax.transaction.UserTransaction;
057: import javax.xml.ws.Service;
058: import javax.xml.ws.WebServiceContext;
059: import java.net.MalformedURLException;
060: import java.net.URI;
061: import java.net.URISyntaxException;
062: import java.net.URL;
063: import java.util.HashMap;
064: import java.util.Iterator;
065: import java.util.List;
066: import java.util.Map;
067: import java.util.ArrayList;
068:
069: /**
070: * TODO: This class is essentially an over glorified sym-linker. The names
071: * we were linking to are no longer guaranteed to be what we assume them to
072: * be. We need to come up with a different internal naming structure for
073: * the global JNDI and finally create the default which will be the default
074: * symlinked version of all the components.
075: */
076: public class JndiEncBuilder {
077: public static final Logger logger = Logger.getInstance(
078: LogCategory.OPENEJB_STARTUP, JndiEncBuilder.class
079: .getPackage().getName());
080:
081: private final boolean beanManagedTransactions;
082: private final JndiEncInfo jndiEnc;
083: private final URI moduleUri;
084: private final List<Injection> injections;
085: private final ClassLoader classLoader;
086:
087: private boolean useCrossClassLoaderRef = true;
088: private boolean client = false;
089:
090: public JndiEncBuilder(JndiEncInfo jndiEnc,
091: List<Injection> injections, String moduleId,
092: ClassLoader classLoader) throws OpenEJBException {
093: this (jndiEnc, injections, null, moduleId, classLoader);
094: }
095:
096: public JndiEncBuilder(JndiEncInfo jndiEnc,
097: List<Injection> injections, String transactionType,
098: String moduleId, ClassLoader classLoader)
099: throws OpenEJBException {
100: this .jndiEnc = jndiEnc;
101: this .injections = injections;
102: beanManagedTransactions = transactionType != null
103: && transactionType.equalsIgnoreCase("Bean");
104:
105: try {
106: moduleUri = new URI(moduleId);
107: } catch (URISyntaxException e) {
108: throw new OpenEJBException(e);
109: }
110: this .classLoader = classLoader;
111: }
112:
113: public boolean isUseCrossClassLoaderRef() {
114: return useCrossClassLoaderRef;
115: }
116:
117: public void setUseCrossClassLoaderRef(boolean useCrossClassLoaderRef) {
118: this .useCrossClassLoaderRef = useCrossClassLoaderRef;
119: }
120:
121: public boolean isClient() {
122: return client;
123: }
124:
125: public void setClient(boolean client) {
126: this .client = client;
127: }
128:
129: public Context build() throws OpenEJBException {
130: Map<String, Object> bindings = buildMap();
131:
132: Context context;
133: if (System.getProperty("openejb.naming", "ivm").equals("xbean")) {
134: context = createXBeanWritableContext(bindings);
135: } else {
136: context = createIvmContext();
137:
138: // bind the bindings
139: for (Iterator iterator = bindings.entrySet().iterator(); iterator
140: .hasNext();) {
141: Map.Entry entry = (Map.Entry) iterator.next();
142: String name = (String) entry.getKey();
143: Object value = entry.getValue();
144: if (value == null)
145: continue;
146: try {
147: context.bind(name, value);
148: } catch (NamingException e) {
149: throw new org.apache.openejb.SystemException(
150: "Unable to bind '" + name
151: + "' into bean's enc.", e);
152: }
153: }
154: }
155: return context;
156: }
157:
158: public Map<String, Object> buildMap() throws OpenEJBException {
159: Map<String, Object> bindings = new HashMap<String, Object>();
160:
161: // bind TransactionManager
162: TransactionManager transactionManager = SystemInstance.get()
163: .getComponent(TransactionManager.class);
164: bindings
165: .put("java:comp/TransactionManager", transactionManager);
166:
167: // bind TransactionSynchronizationRegistry
168: TransactionSynchronizationRegistry synchronizationRegistry = SystemInstance
169: .get().getComponent(
170: TransactionSynchronizationRegistry.class);
171: bindings.put("java:comp/TransactionSynchronizationRegistry",
172: synchronizationRegistry);
173:
174: bindings.put("java:comp/ORB", new SystemComponentReference(
175: ORB.class));
176: bindings.put("java:comp/HandleDelegate",
177: new SystemComponentReference(HandleDelegate.class));
178:
179: // get JtaEntityManagerRegistry
180: JtaEntityManagerRegistry jtaEntityManagerRegistry = SystemInstance
181: .get().getComponent(JtaEntityManagerRegistry.class);
182:
183: // bind UserTransaction if bean managed transactions
184: UserTransaction userTransaction = null;
185: if (beanManagedTransactions) {
186: userTransaction = new CoreUserTransaction(
187: transactionManager);
188: bindings.put("java:comp/UserTransaction", userTransaction);
189: }
190:
191: // bind TimerService
192: bindings.put("java:comp/TimerService",
193: new TimerServiceWrapper());
194:
195: for (EjbReferenceInfo referenceInfo : jndiEnc.ejbReferences) {
196:
197: Reference reference = null;
198:
199: if (referenceInfo.location != null) {
200: reference = buildReferenceLocation(referenceInfo.location);
201: } else if (referenceInfo.ejbDeploymentId == null) {
202: reference = new LazyEjbReference(
203: new Ref(referenceInfo), moduleUri,
204: useCrossClassLoaderRef);
205: } else {
206: String jndiName = "java:openejb/Deployment/"
207: + referenceInfo.ejbDeploymentId + "/"
208: + referenceInfo.interfaceType;
209: if (useCrossClassLoaderRef
210: && referenceInfo.externalReference) {
211: reference = new CrossClassLoaderJndiReference(
212: jndiName);
213: } else {
214: reference = new IntraVmJndiReference(jndiName);
215: }
216: }
217: bindings.put(normalize(referenceInfo.referenceName),
218: reference);
219: }
220:
221: for (EjbReferenceInfo referenceInfo : jndiEnc.ejbLocalReferences) {
222:
223: Reference reference = null;
224:
225: if (referenceInfo.location != null) {
226: reference = buildReferenceLocation(referenceInfo.location);
227: } else if (referenceInfo.ejbDeploymentId == null) {
228: reference = new LazyEjbReference(
229: new Ref(referenceInfo), moduleUri, false);
230: } else {
231: String jndiName = "java:openejb/Deployment/"
232: + referenceInfo.ejbDeploymentId + "/"
233: + referenceInfo.interfaceType;
234: reference = new IntraVmJndiReference(jndiName);
235: }
236: bindings.put(normalize(referenceInfo.referenceName),
237: reference);
238: }
239:
240: for (EnvEntryInfo entry : jndiEnc.envEntries) {
241:
242: if (entry.location != null) {
243: Reference reference = buildReferenceLocation(entry.location);
244: bindings.put(normalize(entry.name), reference);
245: continue;
246: }
247:
248: try {
249: Class type = Class.forName(entry.type.trim());
250: Object obj = null;
251: if (type == String.class)
252: obj = new String(entry.value);
253: else if (type == Double.class) {
254: obj = new Double(entry.value);
255: } else if (type == Integer.class) {
256: obj = new Integer(entry.value);
257: } else if (type == Long.class) {
258: obj = new Long(entry.value);
259: } else if (type == Float.class) {
260: obj = new Float(entry.value);
261: } else if (type == Short.class) {
262: obj = new Short(entry.value);
263: } else if (type == Boolean.class) {
264: obj = new Boolean(entry.value);
265: } else if (type == Byte.class) {
266: obj = new Byte(entry.value);
267: } else if (type == Character.class) {
268: StringBuilder sb = new StringBuilder(entry.value
269: + " ");
270: obj = new Character(sb.charAt(0));
271: } else if (type == URL.class) {
272: obj = new URL(entry.value);
273: } else {
274: throw new IllegalArgumentException(
275: "Invalid env-ref-type " + type);
276: }
277:
278: bindings.put(normalize(entry.name), obj);
279: } catch (ClassNotFoundException e) {
280: throw new IllegalArgumentException(
281: "Invalid environment entry type: "
282: + entry.type.trim() + " for entry: "
283: + entry.name, e);
284: } catch (NumberFormatException e) {
285: throw new IllegalArgumentException(
286: "The env-entry-value for entry " + entry.name
287: + " was not recognizable as type "
288: + entry.type + ". Received Message: "
289: + e.getLocalizedMessage(), e);
290: } catch (MalformedURLException e) {
291: throw new IllegalArgumentException("URL for reference "
292: + entry.name + " was not a valid URL: "
293: + entry.value, e);
294: }
295: }
296:
297: for (ResourceReferenceInfo referenceInfo : jndiEnc.resourceRefs) {
298: Reference reference = null;
299:
300: if ("java.net.URL".equals(referenceInfo.referenceType)) {
301: if (referenceInfo.location != null) {
302: reference = buildReferenceLocation(referenceInfo.location);
303: } else {
304: reference = new URLReference(
305: referenceInfo.resourceID);
306: }
307: } else if (referenceInfo.location != null) {
308: reference = buildReferenceLocation(referenceInfo.location);
309: } else if (referenceInfo.resourceID != null) {
310: String jndiName = "java:openejb/Resource/"
311: + referenceInfo.resourceID;
312: reference = new IntraVmJndiReference(jndiName);
313: } else {
314: String jndiName = "java:openejb/Resource/"
315: + referenceInfo.referenceName;
316: reference = new IntraVmJndiReference(jndiName);
317: }
318: bindings.put(normalize(referenceInfo.referenceName),
319: reference);
320: }
321:
322: for (ResourceEnvReferenceInfo referenceInfo : jndiEnc.resourceEnvRefs) {
323: LinkRef linkRef = null;
324: try {
325: Class<?> type = Class.forName(
326: referenceInfo.resourceEnvRefType, true,
327: EJBContext.class.getClassLoader());
328: if (EJBContext.class.isAssignableFrom(type)) {
329: String jndiName = "java:comp/EJBContext";
330: linkRef = new LinkRef(jndiName);
331: bindings
332: .put(
333: normalize(referenceInfo.resourceEnvRefName),
334: linkRef);
335: continue;
336: } else if (WebServiceContext.class.equals(type)) {
337: String jndiName = "java:comp/WebServiceContext";
338: linkRef = new LinkRef(jndiName);
339: bindings
340: .put(
341: normalize(referenceInfo.resourceEnvRefName),
342: linkRef);
343: continue;
344: } else if (TimerService.class.equals(type)) {
345: String jndiName = "java:comp/TimerService";
346: linkRef = new LinkRef(jndiName);
347: bindings
348: .put(
349: normalize(referenceInfo.resourceEnvRefName),
350: linkRef);
351: continue;
352: }
353: } catch (ClassNotFoundException e) {
354: }
355:
356: Object reference = null;
357: if (UserTransaction.class.getName().equals(
358: referenceInfo.resourceEnvRefType)) {
359: reference = userTransaction;
360: } else if (referenceInfo.location != null) {
361: reference = buildReferenceLocation(referenceInfo.location);
362: } else if (referenceInfo.resourceID != null) {
363: String jndiName = "java:openejb/Resource/"
364: + referenceInfo.resourceID;
365: reference = new IntraVmJndiReference(jndiName);
366: } else {
367: String jndiName = "java:openejb/Resource/"
368: + referenceInfo.resourceEnvRefName;
369: reference = new IntraVmJndiReference(jndiName);
370: }
371: if (reference != null) {
372: bindings.put(
373: normalize(referenceInfo.resourceEnvRefName),
374: reference);
375: }
376: }
377:
378: for (PersistenceUnitReferenceInfo referenceInfo : jndiEnc.persistenceUnitRefs) {
379: if (referenceInfo.location != null) {
380: Reference reference = buildReferenceLocation(referenceInfo.location);
381: bindings.put(normalize(referenceInfo.referenceName),
382: reference);
383: continue;
384: }
385:
386: String jndiName = "java:openejb/PersistenceUnit/"
387: + referenceInfo.unitId;
388: Reference reference = new IntraVmJndiReference(jndiName);
389: bindings.put(normalize(referenceInfo.referenceName),
390: reference);
391: }
392:
393: for (PersistenceContextReferenceInfo contextInfo : jndiEnc.persistenceContextRefs) {
394: if (contextInfo.location != null) {
395: Reference reference = buildReferenceLocation(contextInfo.location);
396: bindings.put(normalize(contextInfo.referenceName),
397: reference);
398: continue;
399: }
400:
401: Context context = SystemInstance.get().getComponent(
402: ContainerSystem.class).getJNDIContext();
403: EntityManagerFactory factory;
404: try {
405: factory = (EntityManagerFactory) context
406: .lookup("openejb/PersistenceUnit/"
407: + contextInfo.unitId);
408: } catch (NamingException e) {
409: throw new OpenEJBException("PersistenceUnit '"
410: + contextInfo.unitId
411: + "' not found for EXTENDED ref '"
412: + contextInfo.referenceName + "'");
413: }
414:
415: JtaEntityManager jtaEntityManager = new JtaEntityManager(
416: jtaEntityManagerRegistry, factory,
417: contextInfo.properties, contextInfo.extended);
418: Reference reference = new PersistenceContextReference(
419: jtaEntityManager);
420: bindings.put(normalize(contextInfo.referenceName),
421: reference);
422: }
423:
424: for (ServiceReferenceInfo referenceInfo : jndiEnc.serviceRefs) {
425: if (referenceInfo.location != null) {
426: Reference reference = buildReferenceLocation(referenceInfo.location);
427: bindings.put(normalize(referenceInfo.referenceName),
428: reference);
429: continue;
430: }
431:
432: // load service class which is used to construct the port
433: Class<? extends Service> serviceClass = Service.class;
434: if (referenceInfo.serviceType != null) {
435: try {
436: serviceClass = classLoader.loadClass(
437: referenceInfo.serviceType).asSubclass(
438: Service.class);
439: } catch (Exception e) {
440: throw new OpenEJBException(
441: "Could not load service type class "
442: + referenceInfo.serviceType, e);
443: }
444: }
445:
446: // load the reference class which is the ultimate type of the port
447: Class<?> referenceClass = null;
448: if (referenceInfo.referenceType != null) {
449: try {
450: referenceClass = classLoader
451: .loadClass(referenceInfo.referenceType);
452: } catch (Exception e) {
453: throw new OpenEJBException(
454: "Could not load reference type class "
455: + referenceInfo.referenceType, e);
456: }
457: }
458:
459: // if ref class is a subclass of Service, use it for the service class
460: if (referenceClass != null
461: && Service.class.isAssignableFrom(referenceClass)) {
462: serviceClass = referenceClass.asSubclass(Service.class);
463: }
464:
465: // determine the location of the wsdl file
466: URL wsdlUrl = null;
467: if (referenceInfo.wsdlFile != null) {
468: try {
469: wsdlUrl = new URL(referenceInfo.wsdlFile);
470: } catch (MalformedURLException e) {
471: wsdlUrl = classLoader
472: .getResource(referenceInfo.wsdlFile);
473: if (wsdlUrl == null) {
474: logger.warning("Error obtaining WSDL: "
475: + referenceInfo.wsdlFile, e);
476: }
477:
478: }
479: }
480:
481: // port refs
482: List<PortRefData> portRefs = new ArrayList<PortRefData>(
483: referenceInfo.portRefs.size());
484: for (PortRefInfo portRefInfo : referenceInfo.portRefs) {
485: PortRefData portRef = new PortRefData();
486: portRef.setQName(portRefInfo.qname);
487: portRef
488: .setServiceEndpointInterface(portRefInfo.serviceEndpointInterface);
489: portRef.setEnableMtom(portRefInfo.enableMtom);
490: portRef.getProperties().putAll(portRefInfo.properties);
491: portRefs.add(portRef);
492: }
493:
494: // create the handle chains
495: List<HandlerChainData> handlerChains = null;
496: if (!referenceInfo.handlerChains.isEmpty()) {
497: handlerChains = WsBuilder.toHandlerChainData(
498: referenceInfo.handlerChains, classLoader);
499: }
500:
501: if (!client) {
502: Reference reference = new JaxWsServiceReference(
503: referenceInfo.id, referenceInfo.serviceQName,
504: serviceClass, referenceInfo.portQName,
505: referenceClass, wsdlUrl, portRefs,
506: handlerChains, injections);
507: bindings.put(normalize(referenceInfo.referenceName),
508: reference);
509: } else {
510: ServiceRefData serviceRefData = new ServiceRefData(
511: referenceInfo.id, referenceInfo.serviceQName,
512: serviceClass, referenceInfo.portQName,
513: referenceClass, wsdlUrl, handlerChains,
514: portRefs);
515: bindings.put(normalize(referenceInfo.referenceName),
516: serviceRefData);
517: }
518: }
519: return bindings;
520: }
521:
522: private WritableContext createXBeanWritableContext(
523: Map<String, Object> bindings) {
524: boolean hasEnv = false;
525: for (String name : bindings.keySet()) {
526: if (name.startsWith("java:comp/env")) {
527: hasEnv = true;
528: break;
529: }
530: }
531: if (!hasEnv)
532: bindings.put("java:comp/env/dummy", "dummy");
533:
534: WritableContext context = null;
535: try {
536: context = new WritableContext("", bindings);
537: } catch (NamingException e) {
538: throw new IllegalStateException(e);
539: }
540: return context;
541: }
542:
543: private IvmContext createIvmContext() {
544: IvmContext context = new IvmContext(new NameNode(null,
545: new ParsedName("comp"), null, null));
546: try {
547: context.createSubcontext("comp").createSubcontext("env");
548: // todo remove this... IvmContext seems to drop empty nodes
549: context.bind("java:comp/env/dummy", "dummy");
550: } catch (NamingException e) {
551: throw new IllegalStateException(
552: "Unable to create subcontext 'java:comp/env'. Exception:"
553: + e.getMessage(), e);
554: }
555: return context;
556: }
557:
558: public static boolean bindingExists(Context context,
559: Name contextName) {
560: try {
561: return context.lookup(contextName) != null;
562: } catch (NamingException e) {
563: }
564: return false;
565: }
566:
567: private Reference buildReferenceLocation(
568: ReferenceLocationInfo location) {
569: if (location.jndiProviderId != null) {
570: String subContextName = "java:openejb/remote_jndi_contexts/"
571: + location.jndiProviderId;
572: return new JndiReference(subContextName, location.jndiName);
573: } else {
574: return new JndiUrlReference(location.jndiName);
575: }
576: }
577:
578: private String normalize(String name) {
579: if (name.charAt(0) == '/')
580: name = name.substring(1);
581: if (!(name.startsWith("java:comp/env") || name
582: .startsWith("comp/env"))) {
583: if (name.startsWith("env/"))
584: name = "java:comp/" + name;
585: else
586: name = "java:comp/env/" + name;
587: }
588: return name;
589: }
590:
591: private static class Ref implements EjbResolver.Reference {
592: private final EjbReferenceInfo info;
593:
594: public Ref(EjbReferenceInfo info) {
595: this .info = info;
596: }
597:
598: public String getEjbLink() {
599: return info.link;
600: }
601:
602: public String getHome() {
603: return info.homeType;
604: }
605:
606: public String getInterface() {
607: return info.interfaceType;
608: }
609:
610: public String getMappedName() {
611: return null;
612: }
613:
614: public String getName() {
615: return info.referenceName;
616: }
617:
618: public EjbResolver.Type getRefType() {
619: if (info instanceof EjbLocalReferenceInfo) {
620: return EjbResolver.Type.LOCAL;
621: } else if (info.homeType != null) {
622: return EjbResolver.Type.REMOTE;
623: } else {
624: return EjbResolver.Type.UNKNOWN;
625: }
626: }
627: }
628: }
|