001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with 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, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020 021 package org.apache.geronimo.j2ee.annotation; 022 023 import java.io.Serializable; 024 import java.lang.reflect.InvocationTargetException; 025 import java.util.ArrayList; 026 import java.util.HashMap; 027 import java.util.List; 028 import java.util.Map; 029 030 import javax.naming.Context; 031 import javax.naming.NamingException; 032 033 import org.apache.xbean.recipe.ObjectRecipe; 034 import org.apache.xbean.recipe.Option; 035 import org.apache.xbean.recipe.StaticRecipe; 036 037 /** 038 * @version $Rev: 549455 $ $Date: 2007-06-21 08:12:27 -0400 (Thu, 21 Jun 2007) $ 039 */ 040 public class Holder implements Serializable { 041 042 public static final Holder EMPTY = new Holder() { 043 }; 044 045 private Map<String, List<Injection>> injectionMap; 046 private Map<String, LifecycleMethod> postConstruct; 047 private Map<String, LifecycleMethod> preDestroy; 048 049 050 public Holder() { 051 } 052 053 054 public void addInjection(String className, Injection injection) { 055 if (injectionMap == null) { 056 injectionMap = new HashMap<String, List<Injection>>(); 057 } 058 List<Injection> injections = injectionMap.get(className); 059 if (injections == null) { 060 injections = new ArrayList<Injection>(); 061 injectionMap.put(className, injections); 062 } 063 injections.add(injection); 064 } 065 066 public void addPostConstructs(Map<String, LifecycleMethod> newPostConstructs) { 067 this.postConstruct = merge(postConstruct, newPostConstructs); 068 } 069 070 public void addPreDestroys(Map<String, LifecycleMethod> newPreDestroys) { 071 this.preDestroy = merge(preDestroy, newPreDestroys); 072 } 073 074 private Map<String, LifecycleMethod> merge(Map<String, LifecycleMethod> old, Map<String, LifecycleMethod> additional) { 075 if (old == null) { 076 return additional; 077 } 078 if (additional == null) { 079 return old; 080 } 081 old.putAll(additional); 082 return old; 083 } 084 085 public List<Injection> getInjections(String className) { 086 if (injectionMap == null) { 087 return null; 088 } 089 return injectionMap.get(className); 090 } 091 092 public Map<String, LifecycleMethod> getPostConstruct() { 093 return postConstruct; 094 } 095 096 public Map<String, LifecycleMethod> getPreDestroy() { 097 return preDestroy; 098 } 099 100 public boolean isEmpty() { 101 return (injectionMap == null || injectionMap.isEmpty()) 102 && (postConstruct == null || postConstruct.isEmpty()) 103 && (preDestroy == null || preDestroy.isEmpty()); 104 } 105 106 public Object newInstance(String className, ClassLoader classLoader, Context context) throws IllegalAccessException, InstantiationException { 107 ObjectRecipe objectRecipe = new ObjectRecipe(className); 108 objectRecipe.allow(Option.FIELD_INJECTION); 109 objectRecipe.allow(Option.PRIVATE_PROPERTIES); 110 Class clazz; 111 try { 112 clazz = classLoader.loadClass(className); 113 } catch (ClassNotFoundException e) { 114 throw (InstantiationException)new InstantiationException("Can't load class " + className + " in classloader: " + classLoader).initCause(e); 115 } 116 List<NamingException> problems = new ArrayList<NamingException>(); 117 while (clazz != Object.class) { 118 addInjections(clazz.getName(), context, objectRecipe, problems); 119 clazz = clazz.getSuperclass(); 120 } 121 if (!problems.isEmpty()) { 122 throw new InstantiationException("Some objects to be injected were not found in jndi: " + problems); 123 } 124 Object result = objectRecipe.create(classLoader); 125 if (getPostConstruct() != null) { 126 try { 127 apply(result, null, postConstruct); 128 } catch (InvocationTargetException e) { 129 Throwable cause = e.getCause(); 130 throw (InstantiationException) new InstantiationException("Could not call postConstruct method").initCause(cause); 131 } 132 } 133 return result; 134 } 135 136 private void addInjections(String className, Context context, ObjectRecipe objectRecipe, List<NamingException> problems) { 137 List<Injection> callbackHandlerinjections = getInjections(className); 138 if (callbackHandlerinjections != null) { 139 for (Injection injection : callbackHandlerinjections) { 140 try { 141 String jndiName = injection.getJndiName(); 142 //our componentContext is attached to jndi at "java:comp" so we remove that when looking stuff up in it 143 Object object = context.lookup("env/" + jndiName); 144 if (object instanceof String) { 145 String string = (String) object; 146 // Pass it in raw so it could be potentially converted to 147 // another data type by an xbean-reflect property editor 148 objectRecipe.setProperty(injection.getTargetName(), string); 149 } else { 150 objectRecipe.setProperty(injection.getTargetName(), new StaticRecipe(object)); 151 } 152 } catch (NamingException e) { 153 problems.add(e); 154 } 155 } 156 } 157 } 158 159 public void destroyInstance(Object o) throws Exception { 160 Class clazz = o.getClass(); 161 Map<String, LifecycleMethod> preDestroy = getPreDestroy(); 162 if (preDestroy != null) { 163 apply(o, clazz, preDestroy); 164 } 165 } 166 167 public static void apply(Object o, Class clazz, Map<String, LifecycleMethod> map) throws IllegalAccessException, InvocationTargetException { 168 if (clazz == null) { 169 clazz = o.getClass(); 170 } 171 ArrayList<Class> classes = new ArrayList<Class>(); 172 while (clazz != null && clazz != Object.class) { 173 classes.add(clazz); 174 clazz = clazz.getSuperclass(); 175 } 176 for (int i = classes.size() - 1; i > -1; i--) { 177 Class clazz1 = classes.get(i); 178 LifecycleMethod m = map.get(clazz1.getName()); 179 if (m != null) { 180 m.call(o, clazz1); 181 } 182 } 183 } 184 185 }