/* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
*/ | |
package org.apache.axis2.jaxws.framework; | |
import org.apache.axis2.AxisFault; | |
import org.apache.axis2.Constants; | |
import org.apache.axis2.context.ConfigurationContext; | |
import org.apache.axis2.deployment.Deployer; | |
import org.apache.axis2.deployment.DeploymentEngine; | |
import org.apache.axis2.deployment.DeploymentErrorMsgs; | |
import org.apache.axis2.deployment.DeploymentException; | |
import org.apache.axis2.deployment.repository.util.DeploymentFileData; | |
import org.apache.axis2.deployment.util.Utils; | |
import org.apache.axis2.description.AxisOperation; | |
import org.apache.axis2.description.AxisService; | |
import org.apache.axis2.description.AxisServiceGroup; | |
import org.apache.axis2.description.Parameter; | |
import org.apache.axis2.engine.AxisConfiguration; | |
import org.apache.axis2.i18n.Messages; | |
import org.apache.axis2.jaxws.addressing.util.EndpointContextMap; | |
import org.apache.axis2.jaxws.addressing.util.EndpointContextMapManager; | |
import org.apache.axis2.jaxws.addressing.util.EndpointKey; | |
import org.apache.axis2.jaxws.description.DescriptionFactory; | |
import org.apache.axis2.jaxws.description.EndpointDescription; | |
import org.apache.axis2.jaxws.server.JAXWSMessageReceiver; | |
import org.apache.axis2.util.Loader; | |
import org.apache.commons.io.FileUtils; | |
import org.apache.commons.logging.Log; | |
import org.apache.commons.logging.LogFactory; | |
import javax.jws.WebService; | |
import javax.xml.namespace.QName; | |
import javax.xml.ws.WebServiceProvider; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.IOException; | |
import java.io.PrintWriter; | |
import java.io.StringWriter; | |
import java.net.URL; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.jar.JarInputStream; | |
import java.util.zip.ZipEntry; | |
import java.util.zip.ZipInputStream; | |
/* | |
* JAXWSDeployer is a custom deployer modeled after the POJODeployer. Its purpose | |
* is to deploy .wars and expanded .war directories | |
*/ | |
public class JAXWSDeployer implements Deployer { | |
private static Log log = LogFactory.getLog(JAXWSDeployer.class); | |
protected ConfigurationContext configCtx; | |
protected AxisConfiguration axisConfig; | |
//To initialize the deployer | |
public void init(ConfigurationContext configCtx) { | |
this.configCtx = configCtx; | |
this.axisConfig = configCtx.getAxisConfiguration(); | |
deployServicesInWARClassPath(); | |
}//Will process the file and add that to axisConfig | |
protected void deployServicesInWARClassPath() { | |
String dir = DeploymentEngine.getWebLocationString(); | |
if (dir != null) { | |
File file = new File(dir + "/WEB-INF/classes/"); | |
URL repository = axisConfig.getRepository(); | |
if (!file.isDirectory() || repository == null) | |
return; | |
ArrayList classList = getClassesInWebInfDirectory(file); | |
ClassLoader threadClassLoader = null; | |
try { | |
threadClassLoader = Thread.currentThread().getContextClassLoader(); | |
ArrayList urls = new ArrayList(); | |
urls.add(repository); | |
String webLocation = DeploymentEngine.getWebLocationString(); | |
if (webLocation != null) { | |
urls.add(new File(webLocation).toURL()); | |
} | |
ClassLoader classLoader = Utils.createClassLoader( | |
urls, | |
axisConfig.getSystemClassLoader(), | |
true, | |
(File) axisConfig. | |
getParameterValue(Constants.Configuration.ARTIFACTS_TEMP_DIR)); | |
Thread.currentThread().setContextClassLoader(classLoader); | |
deployClasses("JAXWS-Builtin", file.toURL(), Thread.currentThread().getContextClassLoader(), classList); | |
} catch (Exception e) { | |
log.info(Messages.getMessage("deployingexception", e.getMessage()), e); | |
} finally { | |
if (threadClassLoader != null) { | |
Thread.currentThread().setContextClassLoader(threadClassLoader); | |
} | |
} | |
} | |
} | |
protected ArrayList getClassesInWebInfDirectory(File file) { | |
String filePath = file.getAbsolutePath(); | |
Collection files = FileUtils.listFiles(file, new String[]{"class"}, true); | |
ArrayList classList = new ArrayList(); | |
for (Iterator iterator = files.iterator(); iterator.hasNext();) { | |
File f = (File) iterator.next(); | |
String fPath = f.getAbsolutePath(); | |
String fqcn = fPath.substring(filePath.length() + 1); | |
fqcn = fqcn.substring(0, fqcn.length() - ".class".length()); | |
fqcn = fqcn.replace('/', '.'); | |
fqcn = fqcn.replace('\\', '.'); | |
classList.add(fqcn); | |
} | |
return classList; | |
} | |
public void deploy(DeploymentFileData deploymentFileData) { | |
ClassLoader threadClassLoader = null; | |
try { | |
threadClassLoader = Thread.currentThread().getContextClassLoader(); | |
String groupName = deploymentFileData.getName(); | |
URL location = deploymentFileData.getFile().toURL(); | |
if (isJar(deploymentFileData.getFile())) { | |
log.info("Deploying artifact : " + deploymentFileData.getName()); | |
ArrayList urls = new ArrayList(); | |
urls.add(deploymentFileData.getFile().toURL()); | |
urls.add(axisConfig.getRepository()); | |
String webLocation = DeploymentEngine.getWebLocationString(); | |
if (webLocation != null) { | |
urls.add(new File(webLocation).toURL()); | |
} | |
ClassLoader classLoader = Utils.createClassLoader( | |
urls, | |
axisConfig.getSystemClassLoader(), | |
true, | |
(File) axisConfig. | |
getParameterValue(Constants.Configuration.ARTIFACTS_TEMP_DIR)); | |
Thread.currentThread().setContextClassLoader(classLoader); | |
ArrayList classList = getListOfClasses(deploymentFileData); | |
AxisServiceGroup serviceGroup = deployClasses(groupName, location, classLoader, classList); | |
if(serviceGroup == null) { | |
String msg = "Error:\n No annotated classes found in the jar: " + | |
location.toString() + | |
". Service deployment failed."; | |
log.error(msg); | |
axisConfig.getFaultyServices(). | |
put(deploymentFileData.getFile().getAbsolutePath(), msg); | |
} | |
} | |
} catch (Throwable t) { | |
log.debug(Messages.getMessage("stroringfaultyservice", t.getMessage()), t); | |
storeFaultyService(deploymentFileData, t); | |
} finally { | |
if (threadClassLoader != null) { | |
Thread.currentThread().setContextClassLoader(threadClassLoader); | |
} | |
} | |
} | |
protected AxisServiceGroup deployClasses(String groupName, URL location, ClassLoader classLoader, List classList) | |
throws ClassNotFoundException, InstantiationException, IllegalAccessException, AxisFault { | |
ArrayList axisServiceList = new ArrayList(); | |
for (int i = 0, size = classList.size(); i < size; i++) { | |
String className = (String) classList.get(i); | |
Class pojoClass; | |
try { | |
pojoClass = Loader.loadClass(classLoader, className); | |
} catch (Exception e){ | |
continue; | |
} | |
WebService wsAnnotation = (WebService) pojoClass.getAnnotation(WebService.class); | |
WebServiceProvider wspAnnotation = null; | |
if (wsAnnotation == null) { | |
wspAnnotation = (WebServiceProvider) pojoClass.getAnnotation(WebServiceProvider.class); | |
} | |
// Create an Axis Service only if the class is not an interface and it has either | |
// @WebService annotation or @WebServiceProvider annotation. | |
if ((wsAnnotation != null | |
|| wspAnnotation != null) | |
&& !pojoClass.isInterface()) { | |
AxisService axisService; | |
axisService = | |
createAxisService(classLoader, | |
className, | |
location); | |
if(axisService != null) { | |
log.info("Deploying JAXWS annotated class " + className + " as a service - " + axisService.getName()); | |
axisServiceList.add(axisService); | |
} | |
} | |
} | |
int size = axisServiceList.size(); | |
if (size <= 0) { | |
return null; | |
} | |
AxisServiceGroup serviceGroup = new AxisServiceGroup(); | |
serviceGroup.setServiceGroupName(groupName); | |
for (int i = 0; i < size; i++) { | |
AxisService axisService = (AxisService) axisServiceList.get(i); | |
serviceGroup.addService(axisService); | |
} | |
axisConfig.addServiceGroup(serviceGroup); | |
configureAddressing(serviceGroup); | |
return serviceGroup; | |
} | |
protected ArrayList getListOfClasses(DeploymentFileData deploymentFileData) throws IOException { | |
ArrayList classList; | |
FileInputStream fin = null; | |
ZipInputStream zin = null; | |
try { | |
fin = new FileInputStream(deploymentFileData.getAbsolutePath()); | |
zin = new ZipInputStream(fin); | |
ZipEntry entry; | |
classList = new ArrayList(); | |
while ((entry = zin.getNextEntry()) != null) { | |
String name = entry.getName(); | |
if (name.endsWith(".class")) { | |
name = name.replaceAll(".class", ""); | |
name = name.replaceAll("/", "."); | |
classList.add(name); | |
} | |
} | |
zin.close(); | |
fin.close(); | |
} catch (Exception e) { | |
log.debug(Messages.getMessage("deployingexception", e.getMessage()), e); | |
throw new DeploymentException(e); | |
} finally { | |
if (zin != null) { | |
zin.close(); | |
} | |
if (fin != null) { | |
fin.close(); | |
} | |
} | |
return classList; | |
} | |
protected void storeFaultyService(DeploymentFileData deploymentFileData, Throwable t) { | |
StringWriter errorWriter = new StringWriter(); | |
PrintWriter ptintWriter = new PrintWriter(errorWriter); | |
t.printStackTrace(ptintWriter); | |
String error = "Error:\n" + errorWriter.toString(); | |
axisConfig.getFaultyServices(). | |
put(deploymentFileData.getFile().getAbsolutePath(), error); | |
} | |
protected AxisService createAxisService(ClassLoader classLoader, | |
String className, | |
URL serviceLocation) throws ClassNotFoundException, | |
InstantiationException, | |
IllegalAccessException, | |
AxisFault { | |
Class pojoClass = Loader.loadClass(classLoader, className); | |
AxisService axisService; | |
try { | |
axisService = DescriptionFactory.createAxisService(pojoClass, configCtx); | |
} catch (Throwable t) { | |
log.info("Exception creating Axis Service : " + t.getCause(), t); | |
return null; | |
} | |
if (axisService != null) { | |
Iterator operations = axisService.getOperations(); | |
while (operations.hasNext()) { | |
AxisOperation axisOperation = (AxisOperation) operations.next(); | |
if (axisOperation.getMessageReceiver() == null) { | |
axisOperation.setMessageReceiver(new JAXWSMessageReceiver()); | |
} | |
} | |
axisService.setElementFormDefault(false); | |
axisService.setFileName(serviceLocation); | |
axisService.setClassLoader(classLoader); | |
axisService.addParameter(new Parameter(org.apache.axis2.jaxws.spi.Constants.CACHE_CLASSLOADER, classLoader)); | |
} | |
return axisService; | |
} | |
public void setDirectory(String directory) { | |
} | |
public void setExtension(String extension) { | |
} | |
public void unDeploy(String fileName) { | |
fileName = Utils.getShortFileName(fileName); | |
if (isJar(new File(fileName))) { | |
try { | |
AxisServiceGroup serviceGroup = | |
axisConfig.removeServiceGroup(fileName); | |
if(configCtx != null) { | |
configCtx.removeServiceGroupContext(serviceGroup); | |
} | |
log.info(Messages.getMessage(DeploymentErrorMsgs.SERVICE_REMOVED, | |
fileName)); | |
} catch (AxisFault axisFault) { | |
//May be a faulty service | |
log.debug(Messages.getMessage(DeploymentErrorMsgs.FAULTY_SERVICE_REMOVAL, | |
axisFault.getMessage()), axisFault); | |
axisConfig.removeFaultyService(fileName); | |
} | |
} | |
} | |
/** | |
* Check if this inputstream is a jar/zip | |
* | |
* @param is | |
* @return true if inputstream is a jar | |
*/ | |
public static boolean isJar(File f) { | |
try { | |
JarInputStream jis = new JarInputStream(new FileInputStream(f)); | |
if (jis.getNextEntry() != null) { | |
return true; | |
} | |
} catch (IOException ioe) { | |
} | |
return false; | |
} | |
private boolean isEmpty(String string) { | |
return (string == null || "".equals(string)); | |
} | |
//Store the address URIs that we will need to create endpoint references at runtime. | |
private void configureAddressing(AxisServiceGroup serviceGroup) { | |
EndpointContextMap map = | |
(EndpointContextMap) configCtx.getProperty(org.apache.axis2.jaxws.Constants.ENDPOINT_CONTEXT_MAP); | |
if (map == null) { | |
map = EndpointContextMapManager.getEndpointContextMap(); | |
configCtx.setProperty(org.apache.axis2.jaxws.Constants.ENDPOINT_CONTEXT_MAP, map); | |
} | |
Iterator iterator = serviceGroup.getServices(); | |
while (iterator.hasNext()) { | |
AxisService axisService = (AxisService) iterator.next(); | |
Parameter param = | |
axisService.getParameter(EndpointDescription.AXIS_SERVICE_PARAMETER); | |
EndpointDescription ed = (EndpointDescription) param.getValue(); | |
QName serviceName = ed.getServiceQName(); | |
QName portName = ed.getPortQName(); | |
EndpointKey key = new EndpointKey(serviceName, portName); | |
map.put(key, axisService); | |
} | |
} | |
} | |