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 018 package org.apache.geronimo.jaxws.builder; 019 020 import java.io.IOException; 021 import java.io.InputStream; 022 import java.net.URL; 023 import java.util.Map; 024 import java.util.jar.JarFile; 025 026 import org.apache.commons.logging.Log; 027 import org.apache.commons.logging.LogFactory; 028 import org.apache.geronimo.common.DeploymentException; 029 import org.apache.geronimo.deployment.DeploymentContext; 030 import org.apache.geronimo.deployment.service.EnvironmentBuilder; 031 import org.apache.geronimo.deployment.util.DeploymentUtil; 032 import org.apache.geronimo.gbean.AbstractName; 033 import org.apache.geronimo.gbean.GBeanData; 034 import org.apache.geronimo.gbean.GBeanInfo; 035 import org.apache.geronimo.j2ee.annotation.Holder; 036 import org.apache.geronimo.j2ee.deployment.EARContext; 037 import org.apache.geronimo.j2ee.deployment.Module; 038 import org.apache.geronimo.j2ee.deployment.WebModule; 039 import org.apache.geronimo.j2ee.deployment.WebServiceBuilder; 040 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 041 import org.apache.geronimo.jaxws.JAXWSUtils; 042 import org.apache.geronimo.jaxws.PortInfo; 043 import org.apache.geronimo.jaxws.annotations.AnnotationHolder; 044 import org.apache.geronimo.kernel.GBeanAlreadyExistsException; 045 import org.apache.geronimo.kernel.GBeanNotFoundException; 046 import org.apache.geronimo.kernel.repository.Environment; 047 048 public abstract class JAXWSServiceBuilder implements WebServiceBuilder { 049 private static final Log LOG = LogFactory.getLog(JAXWSServiceBuilder.class); 050 051 protected final Environment defaultEnvironment; 052 protected WebServiceFinder webServiceFinder; 053 054 public JAXWSServiceBuilder(Environment defaultEnvironment) { 055 this.defaultEnvironment = defaultEnvironment; 056 } 057 058 protected void setWebServiceFinder(WebServiceFinder finder) { 059 this.webServiceFinder = finder; 060 } 061 062 protected String getKey() { 063 return getClass().getName(); 064 } 065 066 public void findWebServices(Module module, 067 boolean isEJB, 068 Map servletLocations, 069 Environment environment, 070 Map sharedContext) throws DeploymentException { 071 Map portMap = null; 072 String path = isEJB ? "META-INF/webservices.xml" : "WEB-INF/webservices.xml"; 073 JarFile moduleFile = module.getModuleFile(); 074 try { 075 URL wsDDUrl = DeploymentUtil.createJarURL(moduleFile, path); 076 InputStream in = wsDDUrl.openStream(); 077 portMap = parseWebServiceDescriptor(in, wsDDUrl, moduleFile, isEJB, servletLocations); 078 } catch (IOException e) { 079 // webservices.xml does not exist 080 portMap = discoverWebServices(module, isEJB, servletLocations); 081 } 082 083 if (portMap != null && !portMap.isEmpty()) { 084 EnvironmentBuilder.mergeEnvironments(environment, defaultEnvironment); 085 sharedContext.put(getKey(), portMap); 086 } 087 088 } 089 090 private Map<String, PortInfo> discoverWebServices(Module module, 091 boolean isEJB, 092 Map correctedPortLocations) 093 throws DeploymentException { 094 if (this.webServiceFinder == null) { 095 throw new DeploymentException("WebServiceFinder not configured"); 096 } 097 return this.webServiceFinder.discoverWebServices(module, isEJB, correctedPortLocations); 098 } 099 100 protected abstract Map<String, PortInfo> parseWebServiceDescriptor(InputStream in, 101 URL wsDDUrl, 102 JarFile moduleFile, 103 boolean isEJB, 104 Map correctedPortLocations) 105 throws DeploymentException; 106 107 public boolean configurePOJO(GBeanData targetGBean, 108 String servletName, 109 Module module, 110 String servletClassName, 111 DeploymentContext context) 112 throws DeploymentException { 113 Map sharedContext = ((WebModule) module).getSharedContext(); 114 Map portInfoMap = (Map) sharedContext.get(getKey()); 115 if (portInfoMap == null) { 116 // not ours 117 return false; 118 } 119 PortInfo portInfo = (PortInfo) portInfoMap.get(servletName); 120 if (portInfo == null) { 121 // not ours 122 return false; 123 } 124 125 // verify that the class is loadable and is a JAX-WS web service 126 ClassLoader classLoader = context.getClassLoader(); 127 Class servletClass = loadClass(servletClassName, classLoader); 128 if (!JAXWSUtils.isWebService(servletClass)) { 129 return false; 130 } 131 132 Map componentContext = null; 133 Holder moduleHolder = null; 134 try { 135 GBeanData moduleGBean = context.getGBeanInstance(context.getModuleName()); 136 componentContext = (Map)moduleGBean.getAttribute("componentContext"); 137 moduleHolder = (Holder)moduleGBean.getAttribute("holder"); 138 } catch (GBeanNotFoundException e) { 139 LOG.warn("ModuleGBean not found. JNDI resource injection will not work."); 140 } 141 142 AnnotationHolder serviceHolder = 143 (AnnotationHolder)sharedContext.get(WebServiceContextAnnotationHelper.class.getName()); 144 if (serviceHolder == null) { 145 serviceHolder = new AnnotationHolder(moduleHolder); 146 sharedContext.put(WebServiceContextAnnotationHelper.class.getName(), serviceHolder); 147 } 148 WebServiceContextAnnotationHelper.addWebServiceContextInjections(serviceHolder, servletClass); 149 150 String location = portInfo.getLocation(); 151 LOG.info("Configuring JAX-WS Web Service: " + servletName + " at " + location); 152 153 AbstractName containerFactoryName = context.getNaming().createChildName(targetGBean.getAbstractName(), getContainerFactoryGBeanInfo().getName(), NameFactory.GERONIMO_SERVICE); 154 GBeanData containerFactoryData = new GBeanData(containerFactoryName, getContainerFactoryGBeanInfo()); 155 containerFactoryData.setAttribute("portInfo", portInfo); 156 containerFactoryData.setAttribute("endpointClassName", servletClassName); 157 containerFactoryData.setAttribute("componentContext", componentContext); 158 containerFactoryData.setAttribute("holder", serviceHolder); 159 containerFactoryData.setAttribute("contextRoot", ((WebModule) module).getContextRoot()); 160 try { 161 context.addGBean(containerFactoryData); 162 } catch (GBeanAlreadyExistsException e) { 163 throw new DeploymentException("Could not add web service container factory gbean", e); 164 } 165 166 targetGBean.setReferencePattern("WebServiceContainerFactory", containerFactoryName); 167 // our web container does not use that property 168 targetGBean.setAttribute("pojoClassName", "java.lang.Object"); 169 170 if (context instanceof EARContext) { 171 containerFactoryData.setReferencePattern("TransactionManager", 172 ((EARContext)context).getTransactionManagerName()); 173 } 174 175 initialize(containerFactoryData, servletClass, portInfo, module); 176 177 return true; 178 } 179 180 protected abstract GBeanInfo getContainerFactoryGBeanInfo(); 181 182 public boolean configureEJB(GBeanData targetGBean, 183 String ejbName, 184 Module module, 185 Map sharedContext, 186 ClassLoader classLoader) 187 throws DeploymentException { 188 Map portInfoMap = (Map) sharedContext.get(getKey()); 189 if (portInfoMap == null) { 190 // not ours 191 return false; 192 } 193 PortInfo portInfo = (PortInfo) portInfoMap.get(ejbName); 194 if (portInfo == null) { 195 // not ours 196 return false; 197 } 198 199 String beanClassName = (String)targetGBean.getAttribute("ejbClass"); 200 // verify that the class is loadable and is a JAX-WS web service 201 Class beanClass = loadClass(beanClassName, classLoader); 202 if (!JAXWSUtils.isWebService(beanClass)) { 203 return false; 204 } 205 206 String location = portInfo.getLocation(); 207 if (location == null) { 208 throw new DeploymentException("Endpoint URI for EJB WebService is missing"); 209 } 210 211 LOG.info("Configuring EJB JAX-WS Web Service: " + ejbName + " at " + location); 212 213 targetGBean.setAttribute("portInfo", portInfo); 214 215 initialize(targetGBean, beanClass, portInfo, module); 216 217 return true; 218 } 219 220 protected void initialize(GBeanData targetGBean, Class wsClass, PortInfo info, Module module) 221 throws DeploymentException { 222 } 223 224 Class<?> loadClass(String className, ClassLoader loader) throws DeploymentException { 225 try { 226 return loader.loadClass(className); 227 } catch (ClassNotFoundException ex) { 228 throw new DeploymentException("Unable to load Web Service class: " + className, ex); 229 } 230 } 231 }