001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.tomcat.catalina;
018:
019: import org.apache.catalina.core.NamingContextListener;
020: import org.apache.catalina.core.StandardContext;
021: import org.apache.catalina.deploy.ContextEjb;
022: import org.apache.catalina.deploy.ContextEnvironment;
023: import org.apache.catalina.deploy.ContextResource;
024: import org.apache.catalina.deploy.ContextResourceEnvRef;
025: import org.apache.catalina.deploy.ContextTransaction;
026: import org.apache.catalina.deploy.NamingResources;
027: import org.apache.naming.ContextAccessController;
028: import org.apache.naming.factory.Constants;
029: import org.apache.openejb.Injection;
030: import org.apache.openejb.OpenEJBException;
031: import org.apache.openejb.spi.ContainerSystem;
032: import org.apache.openejb.assembler.classic.EjbLocalReferenceInfo;
033: import org.apache.openejb.assembler.classic.EjbReferenceInfo;
034: import org.apache.openejb.assembler.classic.EnvEntryInfo;
035: import org.apache.openejb.assembler.classic.PersistenceContextReferenceInfo;
036: import org.apache.openejb.assembler.classic.PersistenceUnitReferenceInfo;
037: import org.apache.openejb.assembler.classic.PortRefInfo;
038: import org.apache.openejb.assembler.classic.ResourceEnvReferenceInfo;
039: import org.apache.openejb.assembler.classic.ResourceReferenceInfo;
040: import org.apache.openejb.assembler.classic.ServiceReferenceInfo;
041: import org.apache.openejb.assembler.classic.WebAppInfo;
042: import org.apache.openejb.assembler.classic.WsBuilder;
043: import org.apache.openejb.core.webservices.HandlerChainData;
044: import org.apache.openejb.core.webservices.PortRefData;
045: import org.apache.openejb.loader.SystemInstance;
046: import org.apache.openejb.persistence.JtaEntityManager;
047: import org.apache.openejb.persistence.JtaEntityManagerRegistry;
048: import static org.apache.openejb.tomcat.common.NamingUtil.DEPLOYMENT_ID;
049: import static org.apache.openejb.tomcat.common.NamingUtil.EXTENDED;
050: import static org.apache.openejb.tomcat.common.NamingUtil.EXTERNAL;
051: import static org.apache.openejb.tomcat.common.NamingUtil.JNDI_NAME;
052: import static org.apache.openejb.tomcat.common.NamingUtil.JNDI_PROVIDER_ID;
053: import static org.apache.openejb.tomcat.common.NamingUtil.LOCAL;
054: import static org.apache.openejb.tomcat.common.NamingUtil.NAME;
055: import static org.apache.openejb.tomcat.common.NamingUtil.RESOURCE_ID;
056: import static org.apache.openejb.tomcat.common.NamingUtil.UNIT;
057: import static org.apache.openejb.tomcat.common.NamingUtil.WSDL_URL;
058: import static org.apache.openejb.tomcat.common.NamingUtil.WS_CLASS;
059: import static org.apache.openejb.tomcat.common.NamingUtil.WS_ID;
060: import static org.apache.openejb.tomcat.common.NamingUtil.WS_PORT_QNAME;
061: import static org.apache.openejb.tomcat.common.NamingUtil.WS_QNAME;
062: import static org.apache.openejb.tomcat.common.NamingUtil.setStaticValue;
063: import org.apache.openejb.tomcat.common.EjbFactory;
064: import org.apache.openejb.tomcat.common.WsFactory;
065: import org.apache.openejb.tomcat.common.ResourceFactory;
066: import org.apache.openejb.tomcat.common.PersistenceUnitFactory;
067: import org.apache.openejb.tomcat.common.PersistenceContextFactory;
068: import org.apache.openejb.tomcat.common.UserTransactionFactory;
069: import org.apache.openejb.tomcat.common.NamingUtil;
070:
071: import javax.persistence.EntityManager;
072: import javax.persistence.EntityManagerFactory;
073: import javax.transaction.UserTransaction;
074: import javax.naming.Context;
075: import javax.naming.NamingException;
076: import java.net.MalformedURLException;
077: import java.net.URI;
078: import java.net.URISyntaxException;
079: import java.net.URL;
080: import java.util.ArrayList;
081: import java.util.List;
082:
083: public class TomcatJndiBuilder {
084: private final StandardContext standardContext;
085: private final WebAppInfo webAppInfo;
086: private final List<Injection> injections;
087: private final boolean replaceEntry;
088: private boolean useCrossClassLoaderRef = true;
089: private NamingContextListener namingContextListener;
090:
091: public TomcatJndiBuilder(StandardContext standardContext,
092: WebAppInfo webAppInfo, List<Injection> injections) {
093: this .injections = injections;
094: this .standardContext = standardContext;
095: this .namingContextListener = BackportUtil
096: .getNamingContextListener(standardContext);
097: this .webAppInfo = webAppInfo;
098:
099: String parameter = standardContext
100: .findParameter("openejb.start.late");
101: replaceEntry = Boolean.parseBoolean(parameter);
102: }
103:
104: public boolean isUseCrossClassLoaderRef() {
105: return useCrossClassLoaderRef;
106: }
107:
108: public void setUseCrossClassLoaderRef(boolean useCrossClassLoaderRef) {
109: this .useCrossClassLoaderRef = useCrossClassLoaderRef;
110: }
111:
112: public void mergeJndi() throws OpenEJBException {
113:
114: NamingResources naming = standardContext.getNamingResources();
115:
116: URI moduleUri;
117: try {
118: moduleUri = new URI(webAppInfo.moduleId);
119: } catch (URISyntaxException e) {
120: throw new OpenEJBException(e);
121: }
122:
123: for (EnvEntryInfo ref : webAppInfo.jndiEnc.envEntries) {
124: mergeRef(naming, ref);
125: }
126: for (EjbReferenceInfo ref : webAppInfo.jndiEnc.ejbReferences) {
127: mergeRef(naming, ref);
128: }
129: for (EjbLocalReferenceInfo ref : webAppInfo.jndiEnc.ejbLocalReferences) {
130: mergeRef(naming, ref);
131: }
132: for (PersistenceContextReferenceInfo ref : webAppInfo.jndiEnc.persistenceContextRefs) {
133: mergeRef(naming, ref, moduleUri);
134: }
135: for (PersistenceUnitReferenceInfo ref : webAppInfo.jndiEnc.persistenceUnitRefs) {
136: mergeRef(naming, ref, moduleUri);
137: }
138: for (ResourceReferenceInfo ref : webAppInfo.jndiEnc.resourceRefs) {
139: mergeRef(naming, ref);
140: }
141: for (ResourceEnvReferenceInfo ref : webAppInfo.jndiEnc.resourceEnvRefs) {
142: mergeRef(naming, ref);
143: }
144: for (ServiceReferenceInfo ref : webAppInfo.jndiEnc.serviceRefs) {
145: mergeRef(naming, ref);
146: }
147: ContextTransaction contextTransaction = new ContextTransaction();
148: contextTransaction.setProperty(Constants.FACTORY,
149: UserTransactionFactory.class.getName());
150: naming.setTransaction(contextTransaction);
151: }
152:
153: public void mergeRef(NamingResources naming, EnvEntryInfo ref) {
154: ContextEnvironment environment = naming
155: .findEnvironment(ref.name);
156: boolean addEntry = false;
157: if (environment == null) {
158: environment = new ContextEnvironment();
159: environment.setName(ref.name);
160: addEntry = true;
161: }
162:
163: environment.setType(ref.type);
164: environment.setValue(ref.value);
165:
166: if (addEntry) {
167: naming.addEnvironment(environment);
168: }
169:
170: if (replaceEntry) {
171: ContextAccessController.setWritable(namingContextListener
172: .getName(), standardContext);
173: if (!addEntry)
174: namingContextListener.removeEnvironment(environment
175: .getName());
176: namingContextListener.addEnvironment(environment);
177: ContextAccessController.setReadOnly(namingContextListener
178: .getName());
179: }
180: }
181:
182: public void mergeRef(NamingResources naming, EjbReferenceInfo ref) {
183: ContextEjb ejb = naming.findEjb(ref.referenceName);
184: boolean addEntry = false;
185: if (ejb == null) {
186: ejb = new ContextEjb();
187: ejb.setName(ref.referenceName);
188: addEntry = true;
189: }
190:
191: ejb.setProperty(Constants.FACTORY, EjbFactory.class.getName());
192: ejb.setProperty(NAME, ref.referenceName);
193: ejb.setHome(ref.homeType);
194: ejb.setRemote(ref.interfaceType);
195: ejb.setLink(null);
196: ejb.setType(ref.interfaceType);
197: if (useCrossClassLoaderRef) {
198: ejb.setProperty(EXTERNAL, "" + ref.externalReference);
199: }
200:
201: if (ref.ejbDeploymentId != null) {
202: ejb.setProperty(DEPLOYMENT_ID, ref.ejbDeploymentId);
203: }
204:
205: if (ref.location != null) {
206: ejb.setProperty(JNDI_NAME, ref.location.jndiName);
207: ejb.setProperty(JNDI_PROVIDER_ID,
208: ref.location.jndiProviderId);
209: }
210:
211: if (addEntry) {
212: naming.addEjb(ejb);
213: }
214:
215: if (replaceEntry) {
216: ContextAccessController.setWritable(namingContextListener
217: .getName(), standardContext);
218: if (!addEntry)
219: namingContextListener.removeEjb(ejb.getName());
220: namingContextListener.addEjb(ejb);
221: ContextAccessController.setReadOnly(namingContextListener
222: .getName());
223: }
224: }
225:
226: public void mergeRef(NamingResources naming,
227: EjbLocalReferenceInfo ref) {
228: // NamingContextListener.addLocalEjb is empty so we'll just use an ejb ref
229: ContextEjb ejb = naming.findEjb(ref.referenceName);
230: boolean addEntry = false;
231: if (ejb == null) {
232: ejb = new ContextEjb();
233: ejb.setName(ref.referenceName);
234: addEntry = true;
235: }
236:
237: ejb.setProperty(Constants.FACTORY, EjbFactory.class.getName());
238: ejb.setProperty(NAME, ref.referenceName);
239: ejb.setHome(ref.homeType);
240: ejb.setRemote(null);
241: ejb.setProperty(LOCAL, ref.interfaceType);
242: ejb.setLink(null);
243: ejb.setType(ref.interfaceType);
244:
245: if (ref.ejbDeploymentId != null) {
246: ejb.setProperty(DEPLOYMENT_ID, ref.ejbDeploymentId);
247: }
248:
249: if (ref.location != null) {
250: ejb.setProperty(JNDI_NAME, ref.location.jndiName);
251: ejb.setProperty(JNDI_PROVIDER_ID,
252: ref.location.jndiProviderId);
253: }
254:
255: if (addEntry) {
256: naming.addEjb(ejb);
257: }
258:
259: if (replaceEntry) {
260: ContextAccessController.setWritable(namingContextListener
261: .getName(), standardContext);
262: if (!addEntry)
263: namingContextListener.removeEjb(ejb.getName());
264: namingContextListener.addEjb(ejb);
265: ContextAccessController.setReadOnly(namingContextListener
266: .getName());
267: }
268: }
269:
270: @SuppressWarnings({"UnusedDeclaration"})
271: public void mergeRef(NamingResources naming,
272: PersistenceContextReferenceInfo ref, URI moduleUri) {
273: ContextResource resource = naming
274: .findResource(ref.referenceName);
275: boolean addEntry = false;
276: if (resource == null) {
277: resource = new ContextResource();
278: resource.setName(ref.referenceName);
279: addEntry = true;
280: }
281:
282: resource.setProperty(Constants.FACTORY,
283: PersistenceContextFactory.class.getName());
284: resource.setProperty(NAME, ref.referenceName);
285: resource.setType(EntityManager.class.getName());
286:
287: if (ref.persistenceUnitName != null) {
288: resource.setProperty(UNIT, ref.persistenceUnitName);
289: }
290: resource.setProperty(EXTENDED, "" + ref.extended);
291: if (ref.properties != null) {
292: // resource.setProperty(NamingConstants.PROPERTIES, ref.properties);
293: }
294:
295: if (ref.location != null) {
296: resource.setProperty(JNDI_NAME, ref.location.jndiName);
297: resource.setProperty(JNDI_PROVIDER_ID,
298: ref.location.jndiProviderId);
299: } else {
300: Context context = SystemInstance.get().getComponent(
301: ContainerSystem.class).getJNDIContext();
302: EntityManagerFactory factory;
303: try {
304: factory = (EntityManagerFactory) context
305: .lookup("openejb/PersistenceUnit/" + ref.unitId);
306: } catch (NamingException e) {
307: throw new IllegalStateException("PersistenceUnit '"
308: + ref.unitId + "' not found for EXTENDED ref '"
309: + ref.referenceName + "'");
310: }
311:
312: JtaEntityManagerRegistry jtaEntityManagerRegistry = SystemInstance
313: .get().getComponent(JtaEntityManagerRegistry.class);
314: JtaEntityManager jtaEntityManager = new JtaEntityManager(
315: jtaEntityManagerRegistry, factory, ref.properties,
316: ref.extended);
317: Object object = jtaEntityManager;
318: setResource(resource, object);
319: }
320:
321: if (addEntry) {
322: naming.addResource(resource);
323: }
324:
325: if (replaceEntry) {
326: ContextAccessController.setWritable(namingContextListener
327: .getName(), standardContext);
328: if (!addEntry)
329: namingContextListener
330: .removeResource(resource.getName());
331: namingContextListener.addResource(resource);
332: ContextAccessController.setReadOnly(namingContextListener
333: .getName());
334: }
335: }
336:
337: @SuppressWarnings({"UnusedDeclaration"})
338: public void mergeRef(NamingResources naming,
339: PersistenceUnitReferenceInfo ref, URI moduleUri) {
340: ContextResource resource = naming
341: .findResource(ref.referenceName);
342: boolean addEntry = false;
343: if (resource == null) {
344: resource = new ContextResource();
345: resource.setName(ref.referenceName);
346: addEntry = true;
347: }
348:
349: resource.setProperty(Constants.FACTORY,
350: PersistenceUnitFactory.class.getName());
351: resource.setProperty(NAME, ref.referenceName);
352: resource.setType(EntityManagerFactory.class.getName());
353:
354: if (ref.persistenceUnitName != null) {
355: resource.setProperty(UNIT, ref.persistenceUnitName);
356: }
357:
358: if (ref.location != null) {
359: resource.setProperty(JNDI_NAME, ref.location.jndiName);
360: resource.setProperty(JNDI_PROVIDER_ID,
361: ref.location.jndiProviderId);
362: } else {
363: // TODO: This will not work if webapps don't use AutoConfi
364: Context context = SystemInstance.get().getComponent(
365: ContainerSystem.class).getJNDIContext();
366: EntityManagerFactory factory;
367: try {
368: factory = (EntityManagerFactory) context
369: .lookup("openejb/PersistenceUnit/" + ref.unitId);
370: } catch (NamingException e) {
371: throw new IllegalStateException("PersistenceUnit '"
372: + ref.unitId + "' not found for EXTENDED ref '"
373: + ref.referenceName + "'");
374: }
375: setResource(resource, factory);
376: }
377:
378: if (addEntry) {
379: naming.addResource(resource);
380: }
381:
382: if (replaceEntry) {
383: ContextAccessController.setWritable(namingContextListener
384: .getName(), standardContext);
385: if (!addEntry)
386: namingContextListener
387: .removeResource(resource.getName());
388: namingContextListener.addResource(resource);
389: ContextAccessController.setReadOnly(namingContextListener
390: .getName());
391: }
392: }
393:
394: public void mergeRef(NamingResources naming,
395: ResourceReferenceInfo ref) {
396: ContextResource resource = naming
397: .findResource(ref.referenceName);
398: boolean addEntry = false;
399: if (resource == null) {
400: resource = new ContextResource();
401: resource.setName(ref.referenceName);
402: addEntry = true;
403: }
404:
405: resource.setProperty(Constants.FACTORY, ResourceFactory.class
406: .getName());
407: resource.setProperty(NAME, ref.referenceName);
408: resource.setType(ref.referenceType);
409: resource.setAuth(ref.referenceAuth);
410:
411: if (ref.resourceID != null) {
412: resource.setProperty(RESOURCE_ID, ref.resourceID);
413: }
414:
415: if (ref.properties != null) {
416: // resource.setProperty(NamingConstants.PROPERTIES, ref.properties);
417: }
418:
419: if (ref.location != null) {
420: resource.setProperty(JNDI_NAME, ref.location.jndiName);
421: resource.setProperty(JNDI_PROVIDER_ID,
422: ref.location.jndiProviderId);
423: }
424:
425: if (addEntry) {
426: naming.addResource(resource);
427: }
428:
429: if (replaceEntry) {
430: ContextAccessController.setWritable(namingContextListener
431: .getName(), standardContext);
432: if (!addEntry)
433: namingContextListener
434: .removeResource(resource.getName());
435: namingContextListener.addResource(resource);
436: ContextAccessController.setReadOnly(namingContextListener
437: .getName());
438: }
439: }
440:
441: public void mergeRef(NamingResources naming,
442: ResourceEnvReferenceInfo ref) {
443: ContextResourceEnvRef resourceEnv = naming
444: .findResourceEnvRef(ref.resourceEnvRefName);
445: boolean addEntry = false;
446: if (resourceEnv == null) {
447: resourceEnv = new ContextResourceEnvRef();
448: resourceEnv.setName(ref.resourceEnvRefName);
449: addEntry = true;
450: }
451:
452: if (UserTransaction.class.getName().equals(
453: ref.resourceEnvRefType)) {
454: resourceEnv.setProperty(Constants.FACTORY,
455: UserTransactionFactory.class.getName());
456: } else {
457: resourceEnv.setProperty(Constants.FACTORY,
458: ResourceFactory.class.getName());
459: resourceEnv.setProperty(NAME, ref.resourceEnvRefName);
460: resourceEnv.setType(ref.resourceEnvRefType);
461:
462: if (ref.resourceID != null) {
463: resourceEnv.setProperty(RESOURCE_ID, ref.resourceID);
464: }
465:
466: if (ref.location != null) {
467: resourceEnv.setProperty(JNDI_NAME,
468: ref.location.jndiName);
469: resourceEnv.setProperty(JNDI_PROVIDER_ID,
470: ref.location.jndiProviderId);
471: }
472: }
473:
474: if (addEntry) {
475: naming.addResourceEnvRef(resourceEnv);
476: }
477:
478: if (replaceEntry) {
479: ContextAccessController.setWritable(namingContextListener
480: .getName(), standardContext);
481: if (!addEntry)
482: namingContextListener.removeResourceEnvRef(resourceEnv
483: .getName());
484: namingContextListener.addResourceEnvRef(resourceEnv);
485: ContextAccessController.setReadOnly(namingContextListener
486: .getName());
487: }
488: }
489:
490: public void mergeRef(NamingResources naming,
491: ServiceReferenceInfo ref) {
492: ContextResource resource = naming
493: .findResource(ref.referenceName);
494: boolean addEntry = false;
495: if (resource == null) {
496: resource = new ContextResource();
497: resource.setName(ref.referenceName);
498: addEntry = true;
499: }
500:
501: resource.setProperty(Constants.FACTORY, WsFactory.class
502: .getName());
503: resource.setProperty(NAME, ref.referenceName);
504: if (ref.referenceType != null) {
505: resource.setType(ref.referenceType);
506: } else {
507: resource.setType(ref.serviceType);
508: }
509:
510: if (ref.location != null) {
511: resource.setProperty(JNDI_NAME, ref.location.jndiName);
512: resource.setProperty(JNDI_PROVIDER_ID,
513: ref.location.jndiProviderId);
514: } else {
515: // ID
516: if (ref.id != null) {
517: resource.setProperty(WS_ID, ref.id);
518: }
519: // Service QName
520: if (ref.serviceQName != null) {
521: resource.setProperty(WS_QNAME, ref.serviceQName
522: .toString());
523: }
524: // Service Class
525: resource.setProperty(WS_CLASS, ref.serviceType);
526:
527: // Port QName
528: if (ref.portQName != null) {
529: resource.setProperty(WS_PORT_QNAME, ref.portQName
530: .toString());
531: }
532:
533: // add the wsdl url
534: URL wsdlURL = getWsdlUrl(ref);
535: if (wsdlURL != null) {
536: resource.setProperty(WSDL_URL, wsdlURL.toString());
537: }
538:
539: // add port refs
540: if (!ref.portRefs.isEmpty()) {
541: List<PortRefData> portRefs = new ArrayList<PortRefData>(
542: ref.portRefs.size());
543: for (PortRefInfo portRefInfo : ref.portRefs) {
544: PortRefData portRef = new PortRefData();
545: portRef.setQName(portRefInfo.qname);
546: portRef
547: .setServiceEndpointInterface(portRefInfo.serviceEndpointInterface);
548: portRef.setEnableMtom(portRefInfo.enableMtom);
549: portRef.getProperties().putAll(
550: portRefInfo.properties);
551: portRefs.add(portRef);
552: }
553: setResource(resource, "port-refs", portRefs);
554: }
555:
556: // add the handle chains
557: if (!ref.handlerChains.isEmpty()) {
558: try {
559: List<HandlerChainData> handlerChains = WsBuilder
560: .toHandlerChainData(ref.handlerChains,
561: standardContext.getLoader()
562: .getClassLoader());
563: setResource(resource, "handler-chains",
564: handlerChains);
565: setResource(resource, "injections", injections);
566: } catch (OpenEJBException e) {
567: throw new IllegalArgumentException(
568: "Error creating handler chain for web service-ref "
569: + ref.referenceName);
570: }
571: }
572: }
573:
574: // if there was a service entry, remove it
575: String serviceName = BackportUtil.findServiceName(naming,
576: ref.referenceName);
577: if (serviceName != null) {
578: ContextAccessController.setWritable(namingContextListener
579: .getName(), standardContext);
580: if (!addEntry)
581: BackportUtil.removeService(namingContextListener,
582: serviceName);
583: ContextAccessController.setReadOnly(namingContextListener
584: .getName());
585: }
586:
587: // add the new resource entry
588: if (addEntry) {
589: naming.addResource(resource);
590: }
591:
592: // or replace the exisitng resource entry
593: if (replaceEntry) {
594: ContextAccessController.setWritable(namingContextListener
595: .getName(), standardContext);
596: if (!addEntry)
597: namingContextListener
598: .removeResource(resource.getName());
599: namingContextListener.addResource(resource);
600: ContextAccessController.setReadOnly(namingContextListener
601: .getName());
602: }
603: }
604:
605: private URL getWsdlUrl(ServiceReferenceInfo ref) {
606: if (ref.wsdlFile == null)
607: return null;
608:
609: URL wsdlUrl = null;
610: try {
611: wsdlUrl = new URL(ref.wsdlFile);
612: } catch (MalformedURLException e) {
613: }
614:
615: if (wsdlUrl == null) {
616: wsdlUrl = standardContext.getLoader().getClassLoader()
617: .getResource(ref.wsdlFile);
618: }
619:
620: if (wsdlUrl == null) {
621: try {
622: wsdlUrl = standardContext.getServletContext()
623: .getResource("/" + ref.wsdlFile);
624: } catch (MalformedURLException e) {
625: }
626: }
627:
628: if (wsdlUrl == null) {
629: throw new IllegalArgumentException("WSDL file "
630: + ref.wsdlFile + " for web service-ref "
631: + ref.referenceName + " not found");
632: }
633:
634: return wsdlUrl;
635: }
636:
637: private void setResource(ContextResource resource, String name,
638: Object object) {
639: setStaticValue(new Resource(resource), name, object);
640: }
641:
642: private void setResource(ContextResource resource, Object object) {
643: setStaticValue(new Resource(resource), object);
644: }
645:
646: private static class Resource implements NamingUtil.Resource {
647: private final ContextResource contextResource;
648:
649: public Resource(ContextResource contextResource) {
650: this .contextResource = contextResource;
651: }
652:
653: public void setProperty(String name, Object value) {
654: contextResource.setProperty(name, value);
655: }
656: }
657: }
|