001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.corba.deployment;
018    
019    import java.util.Collection;
020    import java.util.Map;
021    import java.util.HashMap;
022    import java.util.List;
023    import java.util.jar.JarFile;
024    import java.io.File;
025    import java.net.URI;
026    import java.net.URL;
027    
028    import org.apache.geronimo.common.DeploymentException;
029    import org.apache.geronimo.corba.TSSLinkGBean;
030    import org.apache.geronimo.deployment.ModuleIDBuilder;
031    import org.apache.geronimo.deployment.service.EnvironmentBuilder;
032    import org.apache.geronimo.gbean.AbstractName;
033    import org.apache.geronimo.gbean.AbstractNameQuery;
034    import org.apache.geronimo.gbean.GBeanData;
035    import org.apache.geronimo.gbean.GBeanInfo;
036    import org.apache.geronimo.gbean.GBeanInfoBuilder;
037    import org.apache.geronimo.j2ee.deployment.EARContext;
038    import org.apache.geronimo.j2ee.deployment.Module;
039    import org.apache.geronimo.j2ee.deployment.ModuleBuilderExtension;
040    import org.apache.geronimo.j2ee.deployment.WebServiceBuilder;
041    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
042    import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
043    import org.apache.geronimo.kernel.GBeanNotFoundException;
044    import org.apache.geronimo.kernel.Kernel;
045    import org.apache.geronimo.kernel.Naming;
046    import org.apache.geronimo.kernel.config.ConfigurationModuleType;
047    import org.apache.geronimo.kernel.config.ConfigurationStore;
048    import org.apache.geronimo.kernel.repository.Environment;
049    import org.apache.geronimo.naming.deployment.ENCConfigBuilder;
050    import org.apache.geronimo.openejb.deployment.EjbModule;
051    import org.apache.openejb.assembler.classic.EnterpriseBeanInfo;
052    
053    import org.apache.openejb.jee.oejb2.GeronimoEjbJarType; 
054    import org.apache.openejb.jee.oejb2.TssLinkType; 
055    
056    import org.apache.geronimo.openejb.xbeans.ejbjar.OpenejbGeronimoEjbJarType;
057    import org.apache.geronimo.openejb.xbeans.ejbjar.OpenejbTssLinkType;
058    
059    /**
060     * @version $Rev: 518564 $ $Date: 2007-03-15 06:27:08 -0400 (Thu, 15 Mar 2007) $
061     */
062    public class CorbaModuleBuilderExtension implements ModuleBuilderExtension {
063        // our default environment 
064        protected Environment defaultEnvironment;
065    
066        public CorbaModuleBuilderExtension() throws Exception {
067            this(null);
068        }
069    
070        public CorbaModuleBuilderExtension(Environment defaultEnvironment) {
071            this.defaultEnvironment = defaultEnvironment;
072        }
073    
074        /**
075         * Early module creation.  If this module contains
076         * and CORBA enablement links, the corba default 
077         * environment is merged in.
078         * 
079         * @param module     The module being deployed.
080         * @param plan       The module plan
081         * @param moduleFile The jar file containing the module.
082         * @param targetPath The module path.
083         * @param specDDUrl  The schema information.
084         * @param environment
085         *                   The current environment (used for the merge).
086         * @param moduleContextInfo
087         *                   The module context.
088         * @param earName    The name of the ear file.
089         * @param naming     The naming context.
090         * @param idBuilder
091         * 
092         * @exception DeploymentException
093         */
094        public void createModule(Module module, Object plan, JarFile moduleFile, String targetPath, URL specDDUrl, Environment environment, Object moduleContextInfo, AbstractName earName, Naming naming, ModuleIDBuilder idBuilder) throws DeploymentException {
095            if (module.getType() != ConfigurationModuleType.EJB) {
096                return;
097            }
098            
099            // if we have a default environment specified, we merge it in, but only if 
100            // this module has tss links.  The vendorDD isn't available yet, so we'll have to look at the  
101            // jaxb version of this information now. 
102            if (this.defaultEnvironment != null) {
103                EjbModule ejbModule = (EjbModule)module;
104                GeronimoEjbJarType geronimoEjbJarType = (GeronimoEjbJarType) ejbModule.getEjbModule().getAltDDs().get("geronimo-openejb.xml");
105                
106                if (geronimoEjbJarType != null) {
107                    List<TssLinkType> links = geronimoEjbJarType.getTssLink(); 
108                    if (links != null && links.size() > 0) {
109                        EnvironmentBuilder.mergeEnvironments(environment, this.defaultEnvironment);
110                    }
111                }
112            }        
113        }
114    
115        public void installModule(JarFile earFile, EARContext earContext, Module module, Collection configurationStores, ConfigurationStore targetConfigurationStore, Collection repository) throws DeploymentException {
116        }
117    
118        public void initContext(EARContext earContext, Module module, ClassLoader cl) throws DeploymentException {
119        }
120    
121        /**
122         * Add any GBeans to the deployment that might be 
123         * required by the presence of tss-link definitions
124         * in the ejb plans.
125         * 
126         * @param earContext The earContext of the module deployment.
127         * @param module     The module being deployed.
128         * @param cl         The module class loader instance.
129         * @param repository The repository.
130         * 
131         * @exception DeploymentException
132         *                   Thrown if any of the tss-link information cannot
133         *                   be resolved (missing ejb or TSSBean).
134         */
135        public void addGBeans(EARContext earContext, Module module, ClassLoader cl, Collection repository) throws DeploymentException {
136    
137            if (module.getType() != ConfigurationModuleType.EJB) {
138                return;
139            }
140            EjbModule ejbModule = (EjbModule) module;
141            OpenejbGeronimoEjbJarType jarInfo = ejbModule.getVendorDD(); 
142    
143            OpenejbTssLinkType[] links = jarInfo.getTssLinkArray(); 
144            // if there are no links, then there's nothing to do. 
145            if (links == null || links.length == 0) {
146                return; 
147            }
148            
149            URI moduleURI = module.getModuleURI();
150            String moduleString = moduleURI == null ? null : moduleURI.toString();
151            
152            for (OpenejbTssLinkType link : links) {
153                AbstractName tssBeanName = resolveTssBean(earContext, link.getTssName(), moduleString); 
154                AbstractName ejbName = resolveEjb(earContext, ejbModule, link.getEjbName());
155                
156                AbstractName tssLinkName = earContext.getNaming().createChildName(ejbName, link.getTssName(), NameFactory.CORBA_TSS_LINK);
157                GBeanData tssLinkData = new GBeanData(tssLinkName, TSSLinkGBean.GBEAN_INFO);
158                tssLinkData.setAttribute("jndiNames", link.getJndiNameArray());
159                tssLinkData.setReferencePattern("EJB", ejbName);
160                tssLinkData.setReferencePattern("TSSBean", tssBeanName);
161                try {
162                    earContext.addGBean(tssLinkData);
163                } catch (GBeanAlreadyExistsException e) {
164                    throw new DeploymentException("tss link gbean already present", e);
165                }
166            }
167        }
168        
169        /**
170         * Resolve a TSSBean name specified in a tss-link 
171         * item to the bean's abstract name.  
172         * 
173         * @param context The ear context for the module were processing
174         * @param name    The target name of the TSSBean.
175         * @param module  The module name used to qualifiy the look ups.
176         * 
177         * @return An AbstractName for the target TSSBean. 
178         * @exception DeploymentException
179         *                   Thrown if the target TSSBean could not be located.
180         */
181        private AbstractName resolveTssBean(EARContext context, String name, String module) throws DeploymentException {
182            AbstractNameQuery tssBeanName = ENCConfigBuilder.buildAbstractNameQuery(null, module, name, NameFactory.CORBA_TSS, NameFactory.EJB_MODULE);
183            try {
184                return context.findGBean(tssBeanName);
185            } catch (GBeanNotFoundException e) {
186                tssBeanName = ENCConfigBuilder.buildAbstractNameQuery(null, null, name, NameFactory.CORBA_TSS, null);
187                try {
188                    return context.findGBean(tssBeanName);
189                } catch (GBeanNotFoundException e1) {
190                    throw new DeploymentException("No tss bean " + name + " not found for module " + module, e);
191                }
192            }
193        }
194        
195        /**
196         * Resolve an EJB name used in a tss-link element to
197         * the abstract name for that EJB.  The EJB must be part
198         * of the current module bean set to be resolveable.
199         * 
200         * @param context   The ear context used for resolution.
201         * @param ejbModule The EJBModule we're currently processing.
202         * @param name      The name of the target EJB.
203         * 
204         * @return An AbstractName for the referenced EJB.
205         * @exception DeploymentException
206         *                   Thrown if the ejb does not exist in the current
207         *                   module.
208         */
209        private AbstractName resolveEjb(EARContext earContext, EjbModule ejbModule, String name) throws DeploymentException {
210            for (EnterpriseBeanInfo bean : ejbModule.getEjbJarInfo().enterpriseBeans) {
211                // search for the target ejb 
212                if (name.equals(bean.ejbName)) {
213                    switch (bean.type) {
214                        case EnterpriseBeanInfo.STATELESS: {
215                            return earContext.getNaming().createChildName(ejbModule.getModuleName(), name, NameFactory.STATELESS_SESSION_BEAN);
216                        }
217                        case EnterpriseBeanInfo.STATEFUL: {
218                            return earContext.getNaming().createChildName(ejbModule.getModuleName(), name, NameFactory.STATEFUL_SESSION_BEAN);
219                        }
220                        case EnterpriseBeanInfo.ENTITY: {
221                            return earContext.getNaming().createChildName(ejbModule.getModuleName(), name, NameFactory.ENTITY_BEAN);
222                        }
223                        case EnterpriseBeanInfo.MESSAGE: {
224                            return earContext.getNaming().createChildName(ejbModule.getModuleName(), name, NameFactory.MESSAGE_DRIVEN_BEAN);
225                        }
226                    }
227                }
228            }
229            throw new DeploymentException("EJB " + name + " not found for module " + ejbModule.getModuleName());
230        }
231    
232    
233        public static final GBeanInfo GBEAN_INFO;
234    
235        static {
236            GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(CorbaModuleBuilderExtension.class, NameFactory.MODULE_BUILDER);
237            infoBuilder.addInterface(ModuleBuilderExtension.class);
238            infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true);
239    
240            infoBuilder.setConstructor(new String[]{"defaultEnvironment"});
241    
242            GBEAN_INFO = infoBuilder.getBeanInfo();
243        }
244    
245        public static GBeanInfo getGBeanInfo() {
246            return GBEAN_INFO;
247        }
248    }
249