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.util.ArrayList;
021 import java.util.HashMap;
022 import java.util.List;
023 import java.util.Map;
024
025 import org.apache.commons.logging.Log;
026 import org.apache.commons.logging.LogFactory;
027 import org.apache.geronimo.common.DeploymentException;
028 import org.apache.geronimo.j2ee.deployment.Module;
029 import org.apache.geronimo.j2ee.deployment.WebModule;
030 import org.apache.geronimo.jaxws.JAXWSUtils;
031 import org.apache.geronimo.jaxws.PortInfo;
032 import org.apache.geronimo.xbeans.javaee.ServletMappingType;
033 import org.apache.geronimo.xbeans.javaee.ServletType;
034 import org.apache.geronimo.xbeans.javaee.WebAppType;
035
036 public class AdvancedWARWebServiceFinder implements WebServiceFinder {
037
038 private static final Log LOG = LogFactory.getLog(AdvancedWARWebServiceFinder.class);
039
040 public Map<String, PortInfo> discoverWebServices(Module module,
041 boolean isEJB,
042 Map correctedPortLocations)
043 throws DeploymentException {
044 Map<String, PortInfo> map = new HashMap<String, PortInfo>();
045 discoverPOJOWebServices(module, correctedPortLocations, map);
046 return map;
047 }
048
049 private void discoverPOJOWebServices(Module module,
050 Map portLocations,
051 Map<String, PortInfo> map)
052 throws DeploymentException {
053 ClassLoader classLoader = module.getEarContext().getClassLoader();
054 WebAppType webApp = (WebAppType) module.getSpecDD();
055
056 if (webApp.isSetMetadataComplete()) {
057 // full web.xml, just examine all servlet entries for web services
058
059 ServletType[] servletTypes = webApp.getServletArray();
060 for (ServletType servletType : servletTypes) {
061 String servletName = servletType.getServletName().getStringValue().trim();
062 PortInfo portInfo = getPortInfo(servletType, classLoader, portLocations);
063 if (portInfo != null) {
064 LOG.debug("Found POJO Web Service: " + servletName);
065 map.put(servletName, portInfo);
066 }
067 }
068
069 } else {
070 // partial web.xml, discover all web service classes
071
072 Map<String, List<String>> classServletMap = createClassServetMap(webApp);
073 List<Class> services = WARWebServiceFinder.discoverWebServices(module.getModuleFile(), false, classLoader);
074 String contextRoot = ((WebModule) module).getContextRoot();
075 for (Class service : services) {
076 // skip interfaces and such
077 if (!JAXWSUtils.isWebService(service)) {
078 continue;
079 }
080
081 LOG.debug("Discovered POJO Web Service class: " + service.getName());
082
083 List<String> mappedServlets = classServletMap.get(service.getName());
084 if (mappedServlets == null) {
085 // no <servlet/> entry, add one
086
087 LOG.debug("POJO Web Service class " + service.getName() + " is not mapped to any servlet");
088
089 ServletType servlet = webApp.addNewServlet();
090 servlet.addNewServletName().setStringValue(service.getName());
091 servlet.addNewServletClass().setStringValue(service.getName());
092
093 String location = (String)portLocations.get(service.getName());
094 if (location == null) {
095 // add new <servlet-mapping/> element
096 location = "/" + JAXWSUtils.getServiceName(service);
097 ServletMappingType servletMapping = webApp.addNewServletMapping();
098 servletMapping.addNewServletName().setStringValue(service.getName());
099 servletMapping.addNewUrlPattern().setStringValue(location);
100 } else {
101 // weird, there was no servlet entry for this class but
102 // servlet-mapping exists
103 LOG.warn("Found <servlet-mapping> but corresponding <servlet> was not defined");
104 }
105
106 // map service
107 PortInfo portInfo = new PortInfo();
108 portInfo.setLocation(contextRoot + location);
109 map.put(service.getName(), portInfo);
110 } else {
111 // found at least one mapped <servlet/> entry
112 for (String servlet : mappedServlets) {
113 LOG.debug("POJO Web Service class " + service.getName() + " is mapped to " + servlet + " servlet");
114 PortInfo portInfo = createPortInfo(servlet, portLocations);
115 map.put(servlet, portInfo);
116 }
117 }
118 }
119
120 // double check servlets in case we missed something
121 ServletType[] servletTypes = webApp.getServletArray();
122 for (ServletType servletType : servletTypes) {
123 String servletName = servletType.getServletName().getStringValue().trim();
124 if (map.get(servletName) == null) {
125 PortInfo portInfo = getPortInfo(servletType, classLoader, portLocations);
126 if (portInfo != null) {
127 LOG.debug("Found POJO Web Service: " + servletName);
128 map.put(servletName, portInfo);
129 }
130 }
131 }
132 }
133 }
134
135 private PortInfo getPortInfo(ServletType servletType,
136 ClassLoader classLoader,
137 Map portLocations) throws DeploymentException {
138 PortInfo portInfo = null;
139 if (servletType.isSetServletClass()) {
140 String servletClassName = servletType.getServletClass().getStringValue().trim();
141 try {
142 Class servletClass = classLoader.loadClass(servletClassName);
143 if (JAXWSUtils.isWebService(servletClass)) {
144 String servletName = servletType.getServletName().getStringValue().trim();
145 portInfo = createPortInfo(servletName, portLocations);
146 }
147 } catch (ClassNotFoundException e) {
148 throw new DeploymentException("Failed to load servlet class "
149 + servletClassName, e);
150 }
151 }
152 return portInfo;
153 }
154
155 private PortInfo createPortInfo(String servlet, Map portLocations) {
156 PortInfo portInfo = new PortInfo();
157 String location = (String)portLocations.get(servlet);
158 if (location != null) {
159 portInfo.setLocation(location);
160 }
161 return portInfo;
162 }
163
164 /*
165 * Create servlet-class to servlet-names mapping
166 */
167 private Map<String, List<String>> createClassServetMap(WebAppType webApp) {
168 Map<String, List<String>> map = new HashMap<String, List<String>>();
169
170 ServletType[] servletTypes = webApp.getServletArray();
171 if (servletTypes != null) {
172 for (ServletType servletType : servletTypes) {
173 String servletName = servletType.getServletName().getStringValue().trim();
174 if (servletType.isSetServletClass()) {
175 String servletClassName = servletType.getServletClass().getStringValue().trim();
176 List<String> servlets = map.get(servletClassName);
177 if (servlets == null) {
178 servlets = new ArrayList<String>();
179 map.put(servletClassName, servlets);
180 }
181 servlets.add(servletName);
182 }
183 }
184 }
185
186 return map;
187 }
188
189 }