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.File;
021 import java.io.IOException;
022 import java.net.MalformedURLException;
023 import java.net.URL;
024 import java.util.ArrayList;
025 import java.util.Enumeration;
026 import java.util.List;
027 import java.util.Map;
028 import java.util.jar.JarEntry;
029 import java.util.jar.JarFile;
030
031 import javax.jws.WebService;
032 import javax.xml.ws.WebServiceProvider;
033
034 import org.apache.commons.logging.Log;
035 import org.apache.commons.logging.LogFactory;
036 import org.apache.geronimo.common.DeploymentException;
037 import org.apache.geronimo.deployment.util.DeploymentUtil;
038 import org.apache.geronimo.deployment.util.NestedJarFile;
039 import org.apache.geronimo.deployment.util.UnpackedJarFile;
040 import org.apache.geronimo.j2ee.deployment.Module;
041 import org.apache.geronimo.jaxws.PortInfo;
042 import org.apache.geronimo.kernel.classloader.JarFileClassLoader;
043 import org.apache.xbean.finder.ClassFinder;
044
045 public class WARWebServiceFinder implements WebServiceFinder {
046
047 private static final Log LOG = LogFactory.getLog(WARWebServiceFinder.class);
048
049 private static final WebServiceFinder webServiceFinder = getWebServiceFinder();
050
051 private static WebServiceFinder getWebServiceFinder() {
052 boolean useSimpleFinder =
053 Boolean.getBoolean("org.apache.geronimo.jaxws.builder.useSimpleFinder");
054
055 WebServiceFinder webServiceFinder = null;
056
057 if (useSimpleFinder) {
058 webServiceFinder = new SimpleWARWebServiceFinder();
059 } else {
060 webServiceFinder = new AdvancedWARWebServiceFinder();
061 }
062
063 return webServiceFinder;
064 }
065
066 public Map<String, PortInfo> discoverWebServices(Module module,
067 boolean isEJB,
068 Map correctedPortLocations)
069 throws DeploymentException {
070 return webServiceFinder.discoverWebServices(module, isEJB, correctedPortLocations);
071 }
072
073 /**
074 * Returns a list of any classes annotated with @WebService or
075 * @WebServiceProvider annotation.
076 */
077 static List<Class> discoverWebServices(JarFile moduleFile,
078 boolean isEJB,
079 ClassLoader parentClassLoader)
080 throws DeploymentException {
081 LOG.debug("Discovering web service classes");
082
083 File tmpDir = null;
084 List<URL> urlList = new ArrayList<URL>();
085 if (isEJB) {
086 File jarFile = new File(moduleFile.getName());
087 try {
088 urlList.add(jarFile.toURL());
089 } catch (MalformedURLException e) {
090 // this should not happen
091 throw new DeploymentException(e);
092 }
093 } else {
094 File baseDir = null;
095
096 if (moduleFile instanceof UnpackedJarFile) {
097 // war directory is being deployed (--inPlace)
098 baseDir = ((UnpackedJarFile)moduleFile).getBaseDir();
099 } else if (moduleFile instanceof NestedJarFile && ((NestedJarFile)moduleFile).isUnpacked()) {
100 // ear directory is being deployed (--inPlace)
101 baseDir = new File(moduleFile.getName());
102 } else {
103 // war file or ear file is being deployed
104 /*
105 * Can't get ClassLoader to load nested Jar files, so
106 * unpack the module Jar file and discover all nested Jar files
107 * within it and the classes/ directory.
108 */
109 try {
110 tmpDir = DeploymentUtil.createTempDir();
111 /*
112 * This is needed becuase DeploymentUtil.unzipToDirectory()
113 * always closes the passed JarFile.
114 */
115 JarFile module = new JarFile(moduleFile.getName());
116 DeploymentUtil.unzipToDirectory(module, tmpDir);
117 } catch (IOException e) {
118 if (tmpDir != null) {
119 DeploymentUtil.recursiveDelete(tmpDir);
120 }
121 throw new DeploymentException("Failed to expand the module archive", e);
122 }
123
124 baseDir = tmpDir;
125 }
126
127 // create URL list
128 Enumeration<JarEntry> jarEnum = moduleFile.entries();
129 while (jarEnum.hasMoreElements()) {
130 JarEntry entry = jarEnum.nextElement();
131 String name = entry.getName();
132 if (name.equals("WEB-INF/classes/")) {
133 // ensure it is first
134 File classesDir = new File(baseDir, "WEB-INF/classes/");
135 try {
136 urlList.add(0, classesDir.toURL());
137 } catch (MalformedURLException e) {
138 // this should not happen, ignore
139 }
140 } else if (name.startsWith("WEB-INF/lib/")
141 && name.endsWith(".jar")) {
142 File jarFile = new File(baseDir, name);
143 try {
144 urlList.add(jarFile.toURL());
145 } catch (MalformedURLException e) {
146 // this should not happen, ignore
147 }
148 }
149 }
150 }
151
152 URL[] urls = urlList.toArray(new URL[] {});
153 JarFileClassLoader tempClassLoader = new JarFileClassLoader(null, urls, parentClassLoader);
154 ClassFinder classFinder = new ClassFinder(tempClassLoader, urlList);
155
156 List<Class> classes = new ArrayList<Class>();
157
158 classes.addAll(classFinder.findAnnotatedClasses(WebService.class));
159 classes.addAll(classFinder.findAnnotatedClasses(WebServiceProvider.class));
160
161 tempClassLoader.destroy();
162
163 if (tmpDir != null) {
164 DeploymentUtil.recursiveDelete(tmpDir);
165 }
166
167 return classes;
168 }
169 }