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;
018:
019: import org.apache.openejb.util.LogCategory;
020: import org.apache.openejb.util.Logger;
021: import org.apache.xbean.recipe.ObjectRecipe;
022: import org.apache.xbean.recipe.Option;
023: import org.apache.xbean.recipe.StaticRecipe;
024:
025: import javax.naming.Context;
026: import javax.naming.NamingException;
027: import java.util.List;
028: import java.util.Map;
029: import java.lang.reflect.Method;
030: import java.lang.reflect.InvocationTargetException;
031:
032: public class InjectionProcessor<T> {
033: private static final Logger logger = Logger.getInstance(
034: LogCategory.OPENEJB, InjectionProcessor.class);
035: private final Class<? extends T> beanClass;
036: private final List<Injection> injections;
037: private final List<Method> postConstructMethods;
038: private final List<Method> preDestroyMethods;
039: private final Context context;
040: private T instance;
041:
042: public InjectionProcessor(Class<? extends T> beanClass,
043: List<Injection> injections,
044: List<Method> postConstructMethods,
045: List<Method> preDestroyMethods, Context context) {
046: this .beanClass = beanClass;
047: this .injections = injections;
048: this .postConstructMethods = postConstructMethods;
049: this .preDestroyMethods = preDestroyMethods;
050: this .context = context;
051: }
052:
053: public T createInstance() throws OpenEJBException {
054: if (instance == null) {
055: construct();
056: }
057: return instance;
058: }
059:
060: public T getInstance() {
061: return instance;
062: }
063:
064: private void construct() throws OpenEJBException {
065: if (instance != null)
066: throw new IllegalStateException(
067: "Instance already constructed");
068:
069: ObjectRecipe objectRecipe = new ObjectRecipe(beanClass);
070: objectRecipe.allow(Option.FIELD_INJECTION);
071: objectRecipe.allow(Option.PRIVATE_PROPERTIES);
072: objectRecipe.allow(Option.IGNORE_MISSING_PROPERTIES);
073:
074: fillInjectionProperties(objectRecipe);
075:
076: Object object = null;
077: try {
078: object = objectRecipe.create(beanClass.getClassLoader());
079: } catch (Exception e) {
080: throw new OpenEJBException("Error while creating bean "
081: + beanClass.getName(), e);
082: }
083:
084: Map unsetProperties = objectRecipe.getUnsetProperties();
085: if (unsetProperties.size() > 0) {
086: for (Object property : unsetProperties.keySet()) {
087: logger.warning("Injection: No such property '"
088: + property + "' in class "
089: + beanClass.getName());
090: }
091: }
092: instance = beanClass.cast(object);
093: }
094:
095: public void postConstruct() throws OpenEJBException {
096: if (instance == null)
097: throw new IllegalStateException(
098: "Instance has not been constructed");
099: if (postConstructMethods == null)
100: return;
101: for (Method postConstruct : postConstructMethods) {
102: try {
103: postConstruct.invoke(instance);
104: } catch (Exception e) {
105: if (e instanceof InvocationTargetException
106: && e.getCause() instanceof Exception) {
107: e = (Exception) e.getCause();
108: }
109: throw new OpenEJBException(
110: "Error while calling post construct method", e);
111: }
112: }
113: }
114:
115: public void preDestroy() {
116: if (instance == null)
117: return;
118: if (preDestroyMethods == null)
119: return;
120: for (Method preDestroy : preDestroyMethods) {
121: try {
122: preDestroy.invoke(instance);
123: } catch (Exception e) {
124: if (e instanceof InvocationTargetException
125: && e.getCause() instanceof Exception) {
126: e = (Exception) e.getCause();
127: }
128: logger.error("Error while calling pre destroy method",
129: e);
130: }
131: }
132: }
133:
134: private void fillInjectionProperties(ObjectRecipe objectRecipe) {
135: if (injections == null)
136: return;
137:
138: for (Injection injection : injections) {
139: if (!injection.getTarget().isAssignableFrom(beanClass))
140: continue;
141: try {
142: String jndiName = injection.getJndiName();
143: Object object = context.lookup("java:comp/env/"
144: + jndiName);
145: if (object instanceof String) {
146: String string = (String) object;
147: // Pass it in raw so it could be potentially converted to
148: // another data type by an xbean-reflect property editor
149: objectRecipe.setProperty(injection.getTarget()
150: .getName()
151: + "/" + injection.getName(), string);
152: } else {
153: objectRecipe.setProperty(injection.getTarget()
154: .getName()
155: + "/" + injection.getName(),
156: new StaticRecipe(object));
157: }
158: } catch (NamingException e) {
159: logger
160: .warning("Injection data not found in JNDI context: jndiName='"
161: + injection.getJndiName()
162: + "', target="
163: + injection.getTarget()
164: + "/" + injection.getName());
165: }
166: }
167: }
168: }
|