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.geronimo.openejb.deployment;
018:
019: import java.security.PermissionCollection;
020: import java.security.Permissions;
021: import java.util.ArrayList;
022: import java.util.Collections;
023: import java.util.HashMap;
024: import java.util.List;
025: import java.util.Map;
026: import java.util.TreeMap;
027:
028: import org.apache.geronimo.common.DeploymentException;
029: import org.apache.geronimo.connector.outbound.connectiontracking.TrackedConnectionAssociator;
030: import org.apache.geronimo.gbean.AbstractName;
031: import org.apache.geronimo.gbean.AbstractNameQuery;
032: import org.apache.geronimo.gbean.GBeanData;
033: import org.apache.geronimo.j2ee.deployment.EARContext;
034: import org.apache.geronimo.j2ee.deployment.NamingBuilder;
035: import org.apache.geronimo.j2ee.deployment.annotation.AnnotatedEjbJar;
036: import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
037: import org.apache.geronimo.naming.deployment.AbstractNamingBuilder;
038: import org.apache.geronimo.naming.deployment.GBeanResourceEnvironmentBuilder;
039: import org.apache.geronimo.naming.deployment.ResourceEnvironmentSetter;
040: import org.apache.geronimo.openejb.EntityDeploymentGBean;
041: import org.apache.geronimo.openejb.MessageDrivenDeploymentGBean;
042: import org.apache.geronimo.openejb.OpenEjbSystem;
043: import org.apache.geronimo.openejb.StatefulDeploymentGBean;
044: import org.apache.geronimo.openejb.StatelessDeploymentGBean;
045: import org.apache.geronimo.openejb.xbeans.ejbjar.OpenejbGeronimoEjbJarType;
046: import org.apache.geronimo.security.deployment.SecurityConfiguration;
047: import org.apache.geronimo.security.jacc.ComponentPermissions;
048: import org.apache.geronimo.xbeans.geronimo.naming.GerResourceRefType;
049: import org.apache.geronimo.xbeans.javaee.EjbJarType;
050: import org.apache.geronimo.xbeans.javaee.EnterpriseBeansType;
051: import org.apache.geronimo.xbeans.javaee.EntityBeanType;
052: import org.apache.geronimo.xbeans.javaee.MessageDrivenBeanType;
053: import org.apache.geronimo.xbeans.javaee.ResourceRefType;
054: import org.apache.geronimo.xbeans.javaee.SessionBeanType;
055: import org.apache.openejb.DeploymentInfo;
056: import org.apache.openejb.jee.EnterpriseBean;
057: import org.apache.openejb.jee.EntityBean;
058: import org.apache.openejb.jee.MessageDrivenBean;
059: import org.apache.openejb.jee.RemoteBean;
060: import org.apache.openejb.jee.SecurityIdentity;
061: import org.apache.openejb.jee.SessionBean;
062: import org.apache.openejb.jee.SessionType;
063: import org.apache.openejb.jee.oejb3.EjbDeployment;
064: import org.apache.xbean.finder.ClassFinder;
065: import org.apache.xmlbeans.XmlObject;
066:
067: /**
068: * Handles building ejb deployment gbeans.
069: */
070: public class EjbDeploymentBuilder {
071: private final EARContext earContext;
072: private final EjbModule ejbModule;
073: private final NamingBuilder namingBuilder;
074: private final ResourceEnvironmentSetter resourceEnvironmentSetter;
075: private final EjbDeploymentGBeanNameBuilder beanNameBuilder;
076: private final Map<String, GBeanData> gbeans = new TreeMap<String, GBeanData>();
077:
078: public EjbDeploymentBuilder(EARContext earContext,
079: EjbModule ejbModule, NamingBuilder namingBuilder,
080: ResourceEnvironmentSetter resourceEnvironmentSetter) {
081: this .earContext = earContext;
082: this .ejbModule = ejbModule;
083: this .namingBuilder = namingBuilder;
084: this .resourceEnvironmentSetter = resourceEnvironmentSetter;
085:
086: beanNameBuilder = new BasicEjbDeploymentGBeanNameBuilder();
087: }
088:
089: public void initContext() throws DeploymentException {
090: for (EnterpriseBean enterpriseBean : ejbModule.getEjbJar()
091: .getEnterpriseBeans()) {
092: AbstractName abstractName = beanNameBuilder.createEjbName(
093: earContext, ejbModule, enterpriseBean);
094: GBeanData gbean = null;
095: if (enterpriseBean instanceof SessionBean) {
096: SessionBean sessionBean = (SessionBean) enterpriseBean;
097: switch (sessionBean.getSessionType()) {
098: case STATELESS:
099: gbean = new GBeanData(abstractName,
100: StatelessDeploymentGBean.GBEAN_INFO);
101: break;
102: case STATEFUL:
103: gbean = new GBeanData(abstractName,
104: StatefulDeploymentGBean.GBEAN_INFO);
105: break;
106: }
107: } else if (enterpriseBean instanceof EntityBean) {
108: gbean = new GBeanData(abstractName,
109: EntityDeploymentGBean.GBEAN_INFO);
110: } else if (enterpriseBean instanceof MessageDrivenBean) {
111: gbean = new GBeanData(abstractName,
112: MessageDrivenDeploymentGBean.GBEAN_INFO);
113: }
114: if (gbean == null) {
115: throw new DeploymentException(
116: "Unknown enterprise bean type "
117: + enterpriseBean.getClass().getName());
118: }
119:
120: String ejbName = enterpriseBean.getEjbName();
121:
122: EjbDeployment ejbDeployment = ejbModule.getOpenejbJar()
123: .getDeploymentsByEjbName().get(ejbName);
124: if (ejbDeployment == null) {
125: throw new DeploymentException(
126: "OpenEJB configuration not found for ejb "
127: + ejbName);
128: }
129: gbean.setAttribute("deploymentId", ejbDeployment
130: .getDeploymentId());
131: gbean.setAttribute("ejbName", ejbName);
132:
133: // set interface class names
134: if (enterpriseBean instanceof RemoteBean) {
135: RemoteBean remoteBean = (RemoteBean) enterpriseBean;
136:
137: // Remote
138: if (remoteBean.getRemote() != null) {
139: String remoteInterfaceName = remoteBean.getRemote();
140: assureEJBObjectInterface(remoteInterfaceName,
141: ejbModule.getClassLoader());
142: gbean.setAttribute(EjbInterface.REMOTE
143: .getAttributeName(), remoteInterfaceName);
144:
145: String homeInterfaceName = remoteBean.getHome();
146: assureEJBHomeInterface(homeInterfaceName, ejbModule
147: .getClassLoader());
148: gbean.setAttribute(EjbInterface.HOME
149: .getAttributeName(), homeInterfaceName);
150: }
151:
152: // Local
153: if (remoteBean.getLocal() != null) {
154: String localInterfaceName = remoteBean.getLocal();
155: assureEJBLocalObjectInterface(localInterfaceName,
156: ejbModule.getClassLoader());
157: gbean.setAttribute(EjbInterface.LOCAL
158: .getAttributeName(), localInterfaceName);
159:
160: String localHomeInterfaceName = remoteBean
161: .getLocalHome();
162: assureEJBLocalHomeInterface(localHomeInterfaceName,
163: ejbModule.getClassLoader());
164: gbean
165: .setAttribute(EjbInterface.LOCAL_HOME
166: .getAttributeName(),
167: localHomeInterfaceName);
168: }
169:
170: if (enterpriseBean instanceof SessionBean
171: && ((SessionBean) enterpriseBean)
172: .getSessionType() == SessionType.STATELESS) {
173: SessionBean statelessBean = (SessionBean) enterpriseBean;
174: gbean.setAttribute(EjbInterface.SERVICE_ENDPOINT
175: .getAttributeName(), statelessBean
176: .getServiceEndpoint());
177: }
178: }
179:
180: // set reference patterns
181: gbean
182: .setReferencePattern("TrackedConnectionAssociator",
183: new AbstractNameQuery(null,
184: Collections.EMPTY_MAP,
185: TrackedConnectionAssociator.class
186: .getName()));
187: gbean.setReferencePattern("OpenEjbSystem",
188: new AbstractNameQuery(null, Collections.EMPTY_MAP,
189: OpenEjbSystem.class.getName()));
190:
191: try {
192: earContext.addGBean(gbean);
193: } catch (GBeanAlreadyExistsException e) {
194: throw new DeploymentException(
195: "Could not add entity bean to context", e);
196: }
197: gbeans.put(ejbName, gbean);
198: }
199: }
200:
201: public void addEjbModuleDependency(AbstractName ejbModuleName) {
202: for (GBeanData gbean : gbeans.values()) {
203: gbean.addDependency(ejbModuleName);
204: }
205: }
206:
207: public ComponentPermissions buildComponentPermissions()
208: throws DeploymentException {
209: ComponentPermissions componentPermissions = new ComponentPermissions(
210: new Permissions(), new Permissions(),
211: new HashMap<String, PermissionCollection>());
212: for (EnterpriseBean enterpriseBean : ejbModule.getEjbJar()
213: .getEnterpriseBeans()) {
214: addSecurityData(enterpriseBean, componentPermissions);
215: }
216: return componentPermissions;
217: }
218:
219: private void addSecurityData(EnterpriseBean enterpriseBean,
220: ComponentPermissions componentPermissions)
221: throws DeploymentException {
222: SecurityConfiguration securityConfiguration = (SecurityConfiguration) earContext
223: .getSecurityConfiguration();
224: if (securityConfiguration != null) {
225: GBeanData gbean = getEjbGBean(enterpriseBean.getEjbName());
226: if (enterpriseBean instanceof RemoteBean) {
227: RemoteBean remoteBean = (RemoteBean) enterpriseBean;
228:
229: SecurityBuilder securityBuilder = new SecurityBuilder();
230: PermissionCollection permissions = new Permissions();
231:
232: securityBuilder.addToPermissions(permissions,
233: remoteBean.getEjbName(), EjbInterface.HOME
234: .getJaccInterfaceName(), remoteBean
235: .getHome(), ejbModule.getClassLoader());
236: securityBuilder.addToPermissions(permissions,
237: remoteBean.getEjbName(), EjbInterface.REMOTE
238: .getJaccInterfaceName(), remoteBean
239: .getRemote(), ejbModule
240: .getClassLoader());
241: securityBuilder
242: .addToPermissions(permissions, remoteBean
243: .getEjbName(), EjbInterface.LOCAL
244: .getJaccInterfaceName(), remoteBean
245: .getLocal(), ejbModule.getClassLoader());
246: securityBuilder.addToPermissions(permissions,
247: remoteBean.getEjbName(),
248: EjbInterface.LOCAL_HOME.getJaccInterfaceName(),
249: remoteBean.getLocalHome(), ejbModule
250: .getClassLoader());
251: if (remoteBean instanceof SessionBean) {
252: securityBuilder.addToPermissions(permissions,
253: remoteBean.getEjbName(),
254: EjbInterface.SERVICE_ENDPOINT
255: .getJaccInterfaceName(),
256: ((SessionBean) remoteBean)
257: .getServiceEndpoint(), ejbModule
258: .getClassLoader());
259: }
260: if (remoteBean.getBusinessRemote() != null
261: && !remoteBean.getBusinessRemote().isEmpty()) {
262: for (String businessRemote : remoteBean
263: .getBusinessRemote()) {
264: securityBuilder.addToPermissions(permissions,
265: remoteBean.getEjbName(),
266: EjbInterface.REMOTE
267: .getJaccInterfaceName(),
268: businessRemote, ejbModule
269: .getClassLoader());
270: }
271: securityBuilder.addToPermissions(
272: componentPermissions
273: .getUncheckedPermissions(),
274: remoteBean.getEjbName(), EjbInterface.HOME
275: .getJaccInterfaceName(),
276: DeploymentInfo.BusinessRemoteHome.class
277: .getName(), ejbModule
278: .getClassLoader());
279: }
280: if (remoteBean.getBusinessLocal() != null
281: && !remoteBean.getBusinessLocal().isEmpty()) {
282: for (String businessLocal : remoteBean
283: .getBusinessLocal()) {
284: securityBuilder.addToPermissions(permissions,
285: remoteBean.getEjbName(),
286: EjbInterface.LOCAL
287: .getJaccInterfaceName(),
288: businessLocal, ejbModule
289: .getClassLoader());
290: }
291: securityBuilder.addToPermissions(
292: componentPermissions
293: .getUncheckedPermissions(),
294: remoteBean.getEjbName(),
295: EjbInterface.LOCAL_HOME
296: .getJaccInterfaceName(),
297: DeploymentInfo.BusinessLocalHome.class
298: .getName(), ejbModule
299: .getClassLoader());
300: }
301:
302: String defaultRole = securityConfiguration
303: .getDefaultRole();
304: securityBuilder.addComponentPermissions(defaultRole,
305: permissions, ejbModule.getEjbJar()
306: .getAssemblyDescriptor(),
307: enterpriseBean.getEjbName(), remoteBean
308: .getSecurityRoleRef(),
309: componentPermissions);
310:
311: }
312: // RunAs subject
313: SecurityIdentity securityIdentity = enterpriseBean
314: .getSecurityIdentity();
315: if (securityIdentity != null
316: && securityIdentity.getRunAs() != null) {
317: String runAsName = securityIdentity.getRunAs();
318: if (runAsName != null) {
319: gbean.setAttribute("runAsRole", runAsName);
320: }
321: }
322:
323: gbean.setAttribute("securityEnabled", true);
324: gbean.setReferencePattern("RunAsSource", earContext
325: .getJaccManagerName());
326: }
327: }
328:
329: public void buildEnc() throws DeploymentException {
330: //
331: // XMLBeans types must be use because Geronimo naming building is coupled via XMLBeans objects
332: //
333:
334: EjbJarType ejbJarType = (EjbJarType) ejbModule.getSpecDD();
335:
336: if (!ejbJarType.getMetadataComplete()) {
337: // Create a classfinder and populate it for the naming builder(s). The absence of a
338: // classFinder in the module will convey whether metadata-complete is set (or not)
339: ejbModule
340: .setClassFinder(createEjbJarClassFinder(ejbModule));
341: }
342:
343: EnterpriseBeansType enterpriseBeans = ejbJarType
344: .getEnterpriseBeans();
345: if (enterpriseBeans != null) {
346: for (SessionBeanType xmlbeansEjb : enterpriseBeans
347: .getSessionArray()) {
348: String ejbName = xmlbeansEjb.getEjbName()
349: .getStringValue().trim();
350: GBeanData gbean = getEjbGBean(ejbName);
351: ResourceRefType[] resourceRefs = xmlbeansEjb
352: .getResourceRefArray();
353: addEnc(gbean, xmlbeansEjb, resourceRefs);
354: }
355: for (MessageDrivenBeanType xmlbeansEjb : enterpriseBeans
356: .getMessageDrivenArray()) {
357: String ejbName = xmlbeansEjb.getEjbName()
358: .getStringValue().trim();
359: GBeanData gbean = getEjbGBean(ejbName);
360: ResourceRefType[] resourceRefs = xmlbeansEjb
361: .getResourceRefArray();
362: addEnc(gbean, xmlbeansEjb, resourceRefs);
363: }
364: for (EntityBeanType xmlbeansEjb : enterpriseBeans
365: .getEntityArray()) {
366: String ejbName = xmlbeansEjb.getEjbName()
367: .getStringValue().trim();
368: GBeanData gbean = getEjbGBean(ejbName);
369: ResourceRefType[] resourceRefs = xmlbeansEjb
370: .getResourceRefArray();
371: addEnc(gbean, xmlbeansEjb, resourceRefs);
372: }
373:
374: }
375:
376: if (!ejbJarType.getMetadataComplete()) {
377: ejbJarType.setMetadataComplete(true);
378: ejbModule.setOriginalSpecDD(ejbModule.getSpecDD()
379: .toString());
380: }
381: }
382:
383: private void addEnc(GBeanData gbean, XmlObject xmlbeansEjb,
384: ResourceRefType[] resourceRefs) throws DeploymentException {
385: OpenejbGeronimoEjbJarType geronimoOpenejb = ejbModule
386: .getVendorDD();
387:
388: //
389: // Build ENC
390: //
391:
392: // Geronimo uses a map to pass data to the naming build and for the results data
393: Map<Object, Object> buildingContext = new HashMap<Object, Object>();
394: buildingContext.put(NamingBuilder.GBEAN_NAME_KEY, gbean
395: .getAbstractName());
396: ((AnnotatedEjbJar) ejbModule.getAnnotatedApp())
397: .setBean(xmlbeansEjb);
398:
399: namingBuilder.buildNaming(xmlbeansEjb, geronimoOpenejb,
400: ejbModule, buildingContext);
401:
402: Map compContext = NamingBuilder.JNDI_KEY.get(buildingContext);
403: gbean.setAttribute("componentContextMap", compContext);
404:
405: //
406: // Process resource refs
407: //
408: GerResourceRefType[] gerResourceRefs = null;
409:
410: if (geronimoOpenejb != null) {
411: gerResourceRefs = geronimoOpenejb.getResourceRefArray();
412: }
413:
414: GBeanResourceEnvironmentBuilder refBuilder = new GBeanResourceEnvironmentBuilder(
415: gbean);
416: resourceEnvironmentSetter.setResourceEnvironment(refBuilder,
417: resourceRefs, gerResourceRefs);
418: }
419:
420: private ClassFinder createEjbJarClassFinder(EjbModule ejbModule)
421: throws DeploymentException {
422:
423: try {
424: // Get the classloader from the module's EARContext
425: ClassLoader classLoader = ejbModule.getEarContext()
426: .getClassLoader();
427:
428: //----------------------------------------------------------------------------------------
429: // Find the list of classes from the ejb-jar.xml we want to search for annotations in
430: //----------------------------------------------------------------------------------------
431: List<Class> classes = new ArrayList<Class>();
432:
433: for (EnterpriseBean bean : ejbModule.getEjbJar()
434: .getEnterpriseBeans()) {
435: classes.add(classLoader.loadClass(bean.getEjbClass()));
436: }
437:
438: return new ClassFinder(classes);
439: } catch (ClassNotFoundException e) {
440: throw new DeploymentException("Unable to load bean class.",
441: e);
442: }
443: }
444:
445: private GBeanData getEjbGBean(String ejbName)
446: throws DeploymentException {
447: GBeanData gbean = gbeans.get(ejbName);
448: if (gbean == null)
449: throw new DeploymentException("EJB not gbean not found "
450: + ejbName);
451: return gbean;
452: }
453:
454: private static Class assureEJBObjectInterface(String remote,
455: ClassLoader cl) throws DeploymentException {
456: return AbstractNamingBuilder.assureInterface(remote,
457: "javax.ejb.EJBObject", "Remote", cl);
458: }
459:
460: private static Class assureEJBHomeInterface(String home,
461: ClassLoader cl) throws DeploymentException {
462: return AbstractNamingBuilder.assureInterface(home,
463: "javax.ejb.EJBHome", "Home", cl);
464: }
465:
466: public static Class assureEJBLocalObjectInterface(String local,
467: ClassLoader cl) throws DeploymentException {
468: return AbstractNamingBuilder.assureInterface(local,
469: "javax.ejb.EJBLocalObject", "Local", cl);
470: }
471:
472: public static Class assureEJBLocalHomeInterface(String localHome,
473: ClassLoader cl) throws DeploymentException {
474: return AbstractNamingBuilder.assureInterface(localHome,
475: "javax.ejb.EJBLocalHome", "LocalHome", cl);
476: }
477: }
|