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 }