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    }