001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.injection;
023:
024: import org.jboss.annotation.IgnoreDependency;
025: import org.jboss.ejb3.EJBContainer;
026: import org.jboss.logging.Logger;
027: import org.jboss.metamodel.descriptor.BaseEjbRef;
028: import org.jboss.metamodel.descriptor.EjbLocalRef;
029: import org.jboss.metamodel.descriptor.EjbRef;
030: import org.jboss.metamodel.descriptor.EnvironmentRefGroup;
031:
032: import javax.ejb.EJB;
033: import javax.ejb.EJBs;
034: import javax.naming.NameNotFoundException;
035: import java.lang.reflect.AccessibleObject;
036: import java.lang.reflect.Field;
037: import java.lang.reflect.Method;
038: import java.util.Collection;
039: import java.util.Iterator;
040: import java.util.Map;
041:
042: /**
043: * Searches bean class for all @Inject and create Injectors
044: *
045: * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
046: * @version $Revision: 60233 $
047: */
048: public class EJBHandler implements InjectionHandler {
049: private static final Logger log = Logger
050: .getLogger(EJBHandler.class);
051:
052: protected void addDependency(String refName, EJBContainer refcon,
053: InjectionContainer container) {
054: // Do not depend on myself
055: if (!container.equals(refcon))
056: container.getDependencyPolicy().addDependency(
057: refcon.getObjectName().getCanonicalName());
058: }
059:
060: public void loadXml(EnvironmentRefGroup xml,
061: InjectionContainer container) {
062: if (xml != null) {
063: if (xml.getEjbLocalRefs() != null)
064: loadEjbLocalXml(xml.getEjbLocalRefs(), container);
065: log.trace("ejbRefs = " + xml.getEjbRefs());
066: if (xml.getEjbRefs() != null)
067: loadEjbRefXml(xml.getEjbRefs(), container);
068: }
069: }
070:
071: protected void loadEjbLocalXml(Collection<EjbLocalRef> refs,
072: InjectionContainer container) {
073: for (EjbLocalRef ref : refs) {
074: String interfaceName = ref.getLocal();
075: String errorType = "<ejb-local-ref>";
076:
077: ejbRefXml(ref, interfaceName, container, errorType);
078: }
079: }
080:
081: protected void loadEjbRefXml(Collection<EjbRef> refs,
082: InjectionContainer container) {
083: for (EjbRef ref : refs) {
084: String interfaceName = ref.getRemote();
085: String errorType = "<ejb-ref>";
086:
087: ejbRefXml(ref, interfaceName, container, errorType);
088: }
089: }
090:
091: protected void ejbRefXml(BaseEjbRef ref, String interfaceName,
092: InjectionContainer container, String errorType) {
093: String encName = "env/" + ref.getEjbRefName();
094: InjectionUtil.injectionTarget(encName, ref, container,
095: container.getEncInjections());
096: if (container.getEncInjectors().containsKey(encName))
097: return;
098:
099: String mappedName = ref.getMappedName();
100: if (mappedName != null && mappedName.equals(""))
101: mappedName = null;
102:
103: String link = ref.getEjbLink();
104: if (link != null && link.trim().equals(""))
105: link = null;
106:
107: Class refClass = null;
108:
109: if (interfaceName != null) {
110: try {
111: refClass = container.getClassloader().loadClass(
112: interfaceName);
113: } catch (ClassNotFoundException e) {
114: throw new RuntimeException("could not find "
115: + errorType + "'s local interface "
116: + interfaceName + " in "
117: + container.getDeploymentDescriptorType()
118: + " of " + container.getIdentifier());
119: }
120: }
121:
122: //----- injectors
123:
124: if (mappedName == null && refClass == null && link == null) {
125: // must be jboss.xml only with @EJB used to define reference. jboss.xml used to tag for ignore dependency
126: // i think it is ok to assume this because the ejb-jar.xml schema should handle any missing elements
127: } else {
128: ejbRefEncInjector(mappedName, encName, refClass, link,
129: errorType, container);
130: if (ref.isIgnoreDependency()) {
131: log.debug("IGNORING <ejb-ref> DEPENDENCY: " + encName);
132: return;
133: }
134:
135: ejbRefDependency(link, container, refClass, errorType,
136: encName);
137: }
138: }
139:
140: protected void ejbRefDependency(String link,
141: InjectionContainer container, Class refClass,
142: String errorType, String encName) {
143: EJBContainer refcon = null;
144:
145: if (refClass != null
146: && (refClass.equals(Object.class) || refClass
147: .equals(void.class)))
148: refClass = null;
149:
150: if (refClass != null) {
151: if (link != null && !link.trim().equals("")) {
152: refcon = (EJBContainer) container.resolveEjbContainer(
153: link, refClass);
154: if (refcon == null) {
155: String msg = "IGNORING DEPENDENCY: unable to find "
156: + errorType + " of interface "
157: + refClass.getName() + " and ejbLink of "
158: + link + " in "
159: + container.getDeploymentDescriptorType()
160: + " of " + container.getIdentifier()
161: + " it might not be deployed yet";
162: log.warn(msg);
163: }
164: } else {
165: try {
166: refcon = (EJBContainer) container
167: .resolveEjbContainer(refClass);
168: if (refcon == null) {
169: String msg = "IGNORING DEPENDENCY: unable to find "
170: + errorType
171: + " from interface only "
172: + refClass.getName()
173: + " in "
174: + container
175: .getDeploymentDescriptorType()
176: + " of " + container.getIdentifier();
177: log.warn(msg);
178: }
179: } catch (NameNotFoundException e) {
180: String msg = "IGNORING DEPENDENCY: unable to find "
181: + errorType + " from interface only "
182: + refClass.getName() + " in "
183: + container.getDeploymentDescriptorType()
184: + " of " + container.getIdentifier()
185: + e.getMessage();
186: log.warn(msg);
187: }
188: }
189: } else {
190: String msg = "IGNORING DEPENDENCY: unable to resolve dependency of EJB, there is too little information";
191: log.warn(msg);
192: }
193:
194: if (refcon != null) {
195: addDependency(encName, refcon, container);
196: }
197: }
198:
199: protected void ejbRefEncInjector(String mappedName, String encName,
200: Class refClass, String link, String errorType,
201: InjectionContainer container) {
202: if (refClass != null
203: && (refClass.equals(Object.class) || refClass
204: .equals(void.class)))
205: refClass = null;
206: if (mappedName != null && mappedName.trim().equals(""))
207: mappedName = null;
208:
209: EncInjector injector = null;
210:
211: if (mappedName == null) {
212: injector = new EjbEncInjector(encName, refClass, link,
213: errorType);
214: } else {
215: injector = new EjbEncInjector(encName, mappedName,
216: errorType);
217: }
218:
219: container.getEncInjectors().put(encName, injector);
220: }
221:
222: public static EJBContainer getEjbContainer(EJB ref,
223: InjectionContainer container, Class memberType) {
224: EJBContainer rtn = null;
225:
226: if (ref.mappedName() != null && !"".equals(ref.mappedName())) {
227: return null;
228: }
229:
230: if (ref.beanName().equals("") && memberType == null)
231: throw new RuntimeException(
232: "For deployment "
233: + container.getIdentifier()
234: + "not enough information for @EJB. Please fill out the beanName and/or businessInterface attributes");
235:
236: Class businessInterface = memberType;
237: if (!ref.beanInterface().getName().equals(
238: Object.class.getName())) {
239: businessInterface = ref.beanInterface();
240: }
241:
242: if (ref.beanName().equals("")) {
243: try {
244: rtn = (EJBContainer) container
245: .resolveEjbContainer(businessInterface);
246: } catch (NameNotFoundException e) {
247: log
248: .warn("For deployment "
249: + container.getIdentifier()
250: + " could not find jndi binding based on interface only for @EJB("
251: + businessInterface.getName() + ") "
252: + e.getMessage());
253: }
254: } else {
255: rtn = (EJBContainer) container.resolveEjbContainer(ref
256: .beanName(), businessInterface);
257: }
258:
259: return rtn;
260: }
261:
262: public static String getJndiName(EJB ref,
263: InjectionContainer container, Class memberType) {
264: String jndiName;
265:
266: if (ref.mappedName() != null && !"".equals(ref.mappedName())) {
267: return ref.mappedName();
268: }
269:
270: if (ref.beanName().equals("") && memberType == null)
271: throw new RuntimeException(
272: "For deployment "
273: + container.getIdentifier()
274: + "not enough information for @EJB. Please fill out the beanName and/or businessInterface attributes");
275:
276: Class businessInterface = memberType;
277: if (!ref.beanInterface().getName().equals(
278: Object.class.getName())) {
279: businessInterface = ref.beanInterface();
280: }
281:
282: if (ref.beanName().equals("")) {
283: try {
284: jndiName = container.getEjbJndiName(businessInterface);
285: } catch (NameNotFoundException e) {
286: throw new RuntimeException(
287: "For deployment "
288: + container.getIdentifier()
289: + " could not find jndi binding based on interface only for @EJB("
290: + businessInterface.getName() + ") "
291: + e.getMessage());
292: }
293: if (jndiName == null) {
294: throw new RuntimeException(
295: "For deployment "
296: + container.getIdentifier()
297: + " could not find jndi binding based on interface only for @EJB("
298: + businessInterface.getName() + ")");
299: }
300: } else {
301: jndiName = container.getEjbJndiName(ref.beanName(),
302: businessInterface);
303: if (jndiName == null) {
304: throw new RuntimeException(
305: "For EJB "
306: + container.getIdentifier()
307: + "could not find jndi binding based on beanName and business interface for @EJB("
308: + ref.beanName() + ", "
309: + businessInterface.getName() + ")");
310: }
311: }
312:
313: return jndiName;
314: }
315:
316: public void handleClassAnnotations(Class clazz,
317: InjectionContainer container) {
318: EJBs ref = container.getAnnotation(EJBs.class, clazz);
319: if (ref != null) {
320: EJB[] ejbs = ref.value();
321:
322: for (EJB ejb : ejbs) {
323: handleClassAnnotation(ejb, clazz, container);
324: }
325: }
326: EJB ejbref = container.getAnnotation(EJB.class, clazz);
327: if (ejbref != null)
328: handleClassAnnotation(ejbref, clazz, container);
329: }
330:
331: protected void handleClassAnnotation(EJB ejb, Class clazz,
332: InjectionContainer container) {
333: String encName = ejb.name();
334: if (encName == null || encName.equals("")) {
335: throw new RuntimeException(
336: "JBoss requires the name of the @EJB in the @EJBs: "
337: + clazz);
338: }
339: encName = "env/" + encName;
340:
341: if (container.getEncInjectors().containsKey(encName))
342: return;
343: ejbRefEncInjector(ejb.mappedName(), encName, ejb
344: .beanInterface(), ejb.beanName(), "@EJB", container);
345:
346: // handle dependencies
347:
348: if (isIgnoreDependency(container, ejb))
349: log.debug("IGNORING <ejb-ref> DEPENDENCY: " + encName);
350: else
351: ejbRefDependency(ejb.beanName(), container, ejb
352: .beanInterface(), "@EJB", encName);
353: }
354:
355: public void handleMethodAnnotations(Method method,
356: InjectionContainer container,
357: Map<AccessibleObject, Injector> injectors) {
358:
359: EJB ref = method.getAnnotation(EJB.class);
360: if (ref != null) {
361: if (!method.getName().startsWith("set"))
362: throw new RuntimeException(
363: "@EJB can only be used with a set method: "
364: + method);
365: String encName = ref.name();
366: if (encName == null || encName.equals("")) {
367: encName = InjectionUtil.getEncName(method);
368: } else {
369: encName = "env/" + encName;
370: }
371: if (!container.getEncInjectors().containsKey(encName)) {
372: ejbRefEncInjector(ref.mappedName(), encName, method
373: .getParameterTypes()[0], ref.beanName(),
374: "@EJB", container);
375:
376: if (container.getAnnotation(IgnoreDependency.class,
377: method) == null) {
378: if (isIgnoreDependency(container, ref))
379: log.debug("IGNORING <ejb-ref> DEPENDENCY: "
380: + encName);
381: else
382: ejbRefDependency(ref.beanName(), container,
383: method.getParameterTypes()[0], "@EJB",
384: encName);
385: }
386: }
387:
388: injectors.put(method, new JndiMethodInjector(method,
389: encName, container.getEnc()));
390: }
391: }
392:
393: public void handleFieldAnnotations(Field field,
394: InjectionContainer container,
395: Map<AccessibleObject, Injector> injectors) {
396: EJB ref = field.getAnnotation(EJB.class);
397: if (ref != null) {
398: String encName = ref.name();
399: if (encName == null || encName.equals("")) {
400: encName = InjectionUtil.getEncName(field);
401: } else {
402: encName = "env/" + encName;
403: }
404: if (!container.getEncInjectors().containsKey(encName)) {
405: if (container.getAnnotation(IgnoreDependency.class,
406: field) == null) {
407: if (isIgnoreDependency(container, ref))
408: log.debug("IGNORING <ejb-ref> DEPENDENCY: "
409: + encName);
410: else
411: ejbRefDependency(ref.beanName(), container,
412: field.getType(), "@EJB", encName);
413: }
414: ejbRefEncInjector(ref.mappedName(), encName, field
415: .getType(), ref.beanName(), "@EJB", container);
416: }
417: injectors.put(field, new JndiFieldInjector(field, encName,
418: container.getEnc()));
419:
420: }
421: }
422:
423: protected boolean isIgnoreDependency(InjectionContainer container,
424: EJB ref) {
425: EnvironmentRefGroup refGroup = (EnvironmentRefGroup) container
426: .getEnvironmentRefGroup();
427:
428: if (refGroup != null) {
429: Iterator<EjbRef> ejbRefs = refGroup.getEjbRefs().iterator();
430: while (ejbRefs.hasNext()) {
431: EjbRef ejbRef = ejbRefs.next();
432: if (ejbRef.getEjbRefName().equals(ref.name())) {
433: if (ejbRef.isIgnoreDependency())
434: return true;
435: else
436: return false;
437: }
438: }
439: }
440:
441: return false;
442: }
443: }
|