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.naming.deployment;
022
023 import java.lang.reflect.Method;
024 import java.util.HashMap;
025 import java.util.List;
026 import java.util.Map;
027
028 import javax.annotation.PostConstruct;
029 import javax.annotation.PreDestroy;
030
031 import org.apache.geronimo.common.DeploymentException;
032 import org.apache.geronimo.gbean.GBeanInfo;
033 import org.apache.geronimo.gbean.GBeanInfoBuilder;
034 import org.apache.geronimo.j2ee.annotation.Holder;
035 import org.apache.geronimo.j2ee.annotation.LifecycleMethod;
036 import org.apache.geronimo.j2ee.deployment.Module;
037 import org.apache.geronimo.j2ee.deployment.NamingBuilder;
038 import org.apache.geronimo.j2ee.deployment.annotation.AnnotatedApp;
039 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
040 import org.apache.geronimo.kernel.config.ConfigurationModuleType;
041 import org.apache.geronimo.xbeans.javaee.FullyQualifiedClassType;
042 import org.apache.geronimo.xbeans.javaee.JavaIdentifierType;
043 import org.apache.geronimo.xbeans.javaee.LifecycleCallbackType;
044 import org.apache.xbean.finder.ClassFinder;
045 import org.apache.xmlbeans.QNameSet;
046 import org.apache.xmlbeans.XmlObject;
047
048 /**
049 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
050 */
051 public class LifecycleMethodBuilder extends AbstractNamingBuilder {
052 public void buildNaming(XmlObject specDD, XmlObject plan, Module module, Map componentContext) throws DeploymentException {
053 // skip ejb modules... they have alreayd been processed
054 if (module.getType() == ConfigurationModuleType.EJB) {
055 return;
056 }
057
058 ClassFinder classFinder = module.getClassFinder();
059 AnnotatedApp annotatedApp = module.getAnnotatedApp();
060 if (annotatedApp == null) {
061 throw new NullPointerException("No AnnotatedApp supplied");
062 }
063 Map<String, LifecycleCallbackType> postConstructMap = mapLifecycleCallbacks(annotatedApp.getPostConstructArray(), annotatedApp.getComponentType());
064 Map<String, LifecycleCallbackType> preDestroyMap = mapLifecycleCallbacks(annotatedApp.getPreDestroyArray(), annotatedApp.getComponentType());
065 if (module.getClassFinder() != null) {
066 List<Method> postConstructs = classFinder.findAnnotatedMethods(PostConstruct.class);
067 for (Method m : postConstructs) {
068 String methodName = m.getName();
069 String className = m.getDeclaringClass().getName();
070 if (!postConstructMap.containsKey(className)) {
071 LifecycleCallbackType callback = annotatedApp.addPostConstruct();
072 FullyQualifiedClassType classType = callback.addNewLifecycleCallbackClass();
073 classType.setStringValue(className);
074 JavaIdentifierType method = callback.addNewLifecycleCallbackMethod();
075 method.setStringValue(methodName);
076 postConstructMap.put(className, callback);
077 }
078 }
079 List<Method> preDestroys = classFinder.findAnnotatedMethods(PreDestroy.class);
080 for (Method m : preDestroys) {
081 String methodName = m.getName();
082 String className = m.getDeclaringClass().getName();
083 if (!preDestroyMap.containsKey(className)) {
084 LifecycleCallbackType callback = annotatedApp.addPreDestroy();
085 FullyQualifiedClassType classType = callback.addNewLifecycleCallbackClass();
086 classType.setStringValue(className);
087 JavaIdentifierType method = callback.addNewLifecycleCallbackMethod();
088 method.setStringValue(methodName);
089 preDestroyMap.put(className, callback);
090 }
091 }
092 }
093 Map<String, LifecycleMethod> postConstructs = map(postConstructMap);
094 Map<String, LifecycleMethod> preDestroys = map(preDestroyMap);
095 Holder holder = NamingBuilder.INJECTION_KEY.get(componentContext);
096 holder.addPostConstructs(postConstructs);
097 holder.addPreDestroys(preDestroys);
098 }
099
100 private Map<String, LifecycleMethod> map(Map<String, LifecycleCallbackType> lifecycleCallbackTypes) {
101 if (lifecycleCallbackTypes.isEmpty()) {
102 return null;
103 }
104 Map<String, LifecycleMethod> map = new HashMap<String, LifecycleMethod>();
105 for (Map.Entry<String, LifecycleCallbackType> entry : lifecycleCallbackTypes.entrySet()) {
106 String className = entry.getKey();
107 LifecycleCallbackType callback = entry.getValue();
108 LifecycleMethod method = new LifecycleMethod(className, callback.getLifecycleCallbackMethod().getStringValue().trim());
109 map.put(className, method);
110 }
111 return map;
112 }
113
114 private Map<String, LifecycleCallbackType> mapLifecycleCallbacks(LifecycleCallbackType[] callbackArray, String componentType) throws DeploymentException {
115 Map<String, LifecycleCallbackType> map = new HashMap<String, LifecycleCallbackType>();
116 for (LifecycleCallbackType callback : callbackArray) {
117 String className;
118 if (callback.isSetLifecycleCallbackClass()) {
119 className = callback.getLifecycleCallbackClass().getStringValue().trim();
120 } else {
121 if (componentType == null) {
122 throw new DeploymentException("No component type available and none in lifecycle callback");
123 }
124 className = componentType;
125 }
126 map.put(className, callback);
127 }
128 return map;
129 }
130
131 public QNameSet getSpecQNameSet() {
132 return QNameSet.EMPTY;
133 }
134
135 public QNameSet getPlanQNameSet() {
136 return QNameSet.EMPTY;
137 }
138
139 public static final GBeanInfo GBEAN_INFO;
140
141 static {
142 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(LifecycleMethodBuilder.class, NameFactory.MODULE_BUILDER);
143
144 GBEAN_INFO = infoBuilder.getBeanInfo();
145 }
146
147 public static GBeanInfo getGBeanInfo() {
148 return GBEAN_INFO;
149 }
150 }