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.jaxws.builder;
018    
019    import java.net.URL;
020    import java.util.Collection;
021    import java.util.HashMap;
022    import java.util.List;
023    import java.util.Map;
024    import java.util.jar.JarFile;
025    
026    import org.apache.geronimo.common.DeploymentException;
027    import org.apache.geronimo.deployment.ModuleIDBuilder;
028    import org.apache.geronimo.deployment.service.EnvironmentBuilder;
029    import org.apache.geronimo.gbean.AbstractName;
030    import org.apache.geronimo.gbean.AbstractNameQuery;
031    import org.apache.geronimo.gbean.GBeanData;
032    import org.apache.geronimo.gbean.GBeanInfo;
033    import org.apache.geronimo.gbean.GBeanInfoBuilder;
034    import org.apache.geronimo.j2ee.deployment.EARContext;
035    import org.apache.geronimo.j2ee.deployment.Module;
036    import org.apache.geronimo.j2ee.deployment.ModuleBuilderExtension;
037    import org.apache.geronimo.j2ee.deployment.WebServiceBuilder;
038    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
039    import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
040    import org.apache.geronimo.kernel.Kernel;
041    import org.apache.geronimo.kernel.Naming;
042    import org.apache.geronimo.kernel.config.ConfigurationModuleType;
043    import org.apache.geronimo.kernel.config.ConfigurationStore;
044    import org.apache.geronimo.kernel.repository.Environment;
045    import org.apache.geronimo.openejb.deployment.EjbModule;
046    import org.apache.openejb.assembler.classic.EnterpriseBeanInfo;
047    import org.apache.openejb.jee.oejb2.GeronimoEjbJarType;
048    import org.apache.openejb.jee.oejb2.WebServiceBindingType;
049    import org.apache.openejb.jee.oejb2.WebServiceBindingType.WebServiceSecurityType;
050    
051    /**
052     * @version $Rev$ $Date$
053     */
054    public class JAXWSEJBModuleBuilderExtension implements ModuleBuilderExtension {
055    
056        protected WebServiceBuilder jaxwsBuilder;
057        protected AbstractNameQuery listener;    
058        protected GBeanInfo wsGBeanInfo;
059        protected Environment defaultEnvironment;
060    
061        public JAXWSEJBModuleBuilderExtension() throws Exception {
062            this(null, null, null, null, null);
063        }
064    
065        public JAXWSEJBModuleBuilderExtension(WebServiceBuilder wsBuilder,
066                                              Environment defaultEnvironment,
067                                              AbstractNameQuery listener,
068                                              Object dataLink,
069                                              Kernel kernel) throws Exception {
070            this.jaxwsBuilder = wsBuilder;
071            this.listener = listener;    
072            this.defaultEnvironment = defaultEnvironment;
073            this.wsGBeanInfo = getGBeanInfo(kernel, dataLink);
074        }
075        
076        private static GBeanInfo getGBeanInfo(Kernel kernel, Object webServiceLinkTemplate) throws Exception {
077            AbstractName webServiceLinkTemplateName = kernel.getAbstractNameFor(webServiceLinkTemplate);
078            return kernel.getGBeanInfo(webServiceLinkTemplateName);
079        }
080    
081        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 {
082            if (this.defaultEnvironment != null) {
083                EnvironmentBuilder.mergeEnvironments(environment, this.defaultEnvironment);
084            } 
085        }
086    
087        public void installModule(JarFile earFile, EARContext earContext, Module module, Collection configurationStores, ConfigurationStore targetConfigurationStore, Collection repository) throws DeploymentException {
088        }
089    
090        public void initContext(EARContext earContext, Module module, ClassLoader cl) throws DeploymentException {
091            if (module.getType() != ConfigurationModuleType.EJB) {
092                return;
093            }
094           
095            EjbModule ejbModule = (EjbModule) module;
096            Environment environment = module.getEnvironment();
097                    
098            //overridden web service locations       
099            Map correctedPortLocations = new HashMap();         
100            GeronimoEjbJarType geronimoEjbJarType = 
101                (GeronimoEjbJarType) ejbModule.getEjbModule().getAltDDs().get("geronimo-openejb.xml");
102            if (geronimoEjbJarType != null) {
103               for (WebServiceBindingType bt : geronimoEjbJarType.getWebServiceBinding()) {
104                   String location = bt.getWebServiceAddress();
105                   if (location != null) {
106                       location = location.trim();
107                       if (!location.startsWith("/")) {
108                           location = "/" + location;
109                       }
110                       correctedPortLocations.put(bt.getEjbName(), location);
111                   }
112               }
113            }      
114            
115            jaxwsBuilder.findWebServices(module, true, correctedPortLocations, environment, ejbModule.getSharedContext());
116        }
117    
118        public void addGBeans(EARContext earContext, Module module, ClassLoader cl, Collection repository) throws DeploymentException {
119            if (module.getType() != ConfigurationModuleType.EJB) {
120                return;
121            }
122    
123            EjbModule ejbModule = (EjbModule) module;
124    
125            Map<String, WebServiceBindingType> wsBindingMap = 
126                createWebServiceBindingMap(ejbModule);
127            
128            for (EnterpriseBeanInfo bean : ejbModule.getEjbJarInfo().enterpriseBeans) {
129                if (bean.type != EnterpriseBeanInfo.STATELESS) {
130                    continue;
131                }
132                
133                String ejbName = bean.ejbName;
134    
135                AbstractName sessionName = earContext.getNaming().createChildName(module.getModuleName(), ejbName, NameFactory.STATELESS_SESSION_BEAN);
136    
137                assert sessionName != null: "StatelesSessionBean object name is null";
138    
139                AbstractName ejbWebServiceName = earContext.getNaming().createChildName(sessionName, ejbName, NameFactory.WEB_SERVICE_LINK);
140                
141                GBeanData ejbWebServiceGBean = new GBeanData(ejbWebServiceName, this.wsGBeanInfo);
142    
143                ejbWebServiceGBean.setAttribute("ejbName", ejbName);
144                ejbWebServiceGBean.setAttribute("ejbClass", bean.ejbClass);
145                
146                WebServiceBindingType wsBinding = wsBindingMap.get(ejbName);
147                if (wsBinding != null) {
148                    List<String> ddVirtualHosts = wsBinding.getWebServiceVirtualHost();
149                    if (ddVirtualHosts != null) {                    
150                        String[] virtualHosts = new String[ddVirtualHosts.size()];
151                        for (int i=0; i<ddVirtualHosts.size(); i++) {                    
152                            virtualHosts[i] = ddVirtualHosts.get(i).trim();
153                        }
154                        ejbWebServiceGBean.setAttribute("virtualHosts", virtualHosts);
155                    }
156                    
157                    WebServiceSecurityType wsSecurity = wsBinding.getWebServiceSecurity();
158                    if (wsSecurity != null) {
159                        ejbWebServiceGBean.setAttribute("securityRealmName", wsSecurity.getSecurityRealmName().trim());
160                        ejbWebServiceGBean.setAttribute("transportGuarantee", wsSecurity.getTransportGuarantee().toString());
161                        ejbWebServiceGBean.setAttribute("authMethod", wsSecurity.getAuthMethod().value());
162                        if (wsSecurity.getRealmName() != null) {
163                            ejbWebServiceGBean.setAttribute("realmName", wsSecurity.getRealmName().trim());                    
164                        }
165                    }
166                }
167                
168                if (jaxwsBuilder.configureEJB(ejbWebServiceGBean, bean.ejbName, ejbModule, 
169                                              ejbModule.getSharedContext(), cl)) {
170    
171                    try {
172                        earContext.addGBean(ejbWebServiceGBean);
173                    } catch (GBeanAlreadyExistsException e) {
174                        throw new DeploymentException(
175                                "Could not add ejb web service gbean to context",
176                                e);
177                    }
178                    
179                    if (this.listener != null) {
180                        ejbWebServiceGBean.setReferencePattern("WebServiceContainer", this.listener);
181                    }
182                    
183                    ejbWebServiceGBean.setReferencePattern("EjbDeployment", sessionName);
184                }
185                
186                ejbWebServiceGBean.clearAttribute("ejbName");
187                ejbWebServiceGBean.clearAttribute("ejbClass");
188                
189            }
190        }
191        
192        private Map<String, WebServiceBindingType> createWebServiceBindingMap(EjbModule ejbModule) {
193            Map<String, WebServiceBindingType> wsBindingMap = 
194                new HashMap<String, WebServiceBindingType>();
195            GeronimoEjbJarType geronimoEjbJarType = 
196                (GeronimoEjbJarType) ejbModule.getEjbModule().getAltDDs().get("geronimo-openejb.xml");
197            if (geronimoEjbJarType != null) {
198                for (WebServiceBindingType bt : geronimoEjbJarType.getWebServiceBinding()) {
199                    wsBindingMap.put(bt.getEjbName(), bt);
200                }
201            }
202            return wsBindingMap;
203        } 
204        
205        public static final GBeanInfo GBEAN_INFO;
206    
207        static {
208            GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(JAXWSEJBModuleBuilderExtension.class, NameFactory.MODULE_BUILDER);
209            infoBuilder.addInterface(ModuleBuilderExtension.class);
210            infoBuilder.addReference("WebServiceBuilder", WebServiceBuilder.class, NameFactory.MODULE_BUILDER);
211            infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true);
212            infoBuilder.addAttribute("listener", AbstractNameQuery.class, true);
213            infoBuilder.addReference("WebServiceLinkTemplate", Object.class, NameFactory.WEB_SERVICE_LINK);
214            infoBuilder.addAttribute("kernel", Kernel.class, false);
215    
216            infoBuilder.setConstructor(new String[]{
217                    "WebServiceBuilder",
218                    "defaultEnvironment", 
219                    "listener", 
220                    "WebServiceLinkTemplate",
221                    "kernel"
222            });
223    
224            GBEAN_INFO = infoBuilder.getBeanInfo();
225        }
226    
227        public static GBeanInfo getGBeanInfo() {
228            return GBEAN_INFO;
229        }    
230        
231    }