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 }