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