/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2005-2006, JBoss Inc.
*/
package org.jboss.internal.soa.esb.webservice;
import org.jboss.internal.soa.esb.util.JBossDeployerUtil;
import org.jboss.soa.esb.client.ServiceInvoker;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.LoaderClassPath;
import javassist.Modifier;
import javassist.NotFoundException;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ConstPool;
import javassist.bytecode.SignatureAttribute;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.BooleanMemberValue;
import javassist.bytecode.annotation.EnumMemberValue;
import javassist.bytecode.annotation.StringMemberValue;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Provider;
public class JAXWSProviderClassGenerator {
private final ClassPool pool ;
private final CtClass oneWaySuperClass ;
private final CtClass requestResponseSuperClass ;
public JAXWSProviderClassGenerator()
throws WebServicePublishException {
pool = new ClassPool() ;
final ClassLoader tccl = Thread.currentThread().getContextClassLoader() ;
if (tccl != null)
{
pool.appendClassPath(new LoaderClassPath(tccl)) ;
}
pool.appendClassPath(new LoaderClassPath(JAXWSProviderClassGenerator.class.getClassLoader())) ;
try {
oneWaySuperClass = pool.get(OneWayBaseWebService.class.getName());
requestResponseSuperClass = pool.get(RequestResponseBaseWebService.class.getName()) ;
} catch (final NotFoundException nfe) {
throw new WebServicePublishException("Failed to obtain superclasses", nfe) ;
}
}
public byte[] generate(final String deployment, final String category, final String service, final ESBServiceEndpointInfo epInfo, final boolean includeHandlers)
throws WebServicePublishException {
try {
pool.get(epInfo.getClassName());
throw new WebServicePublishException("Duplicate class within context: " + epInfo.getClassName()) ;
} catch (final NotFoundException nfe) {} // ignore
final CtClass seiClass = pool.makeClass(epInfo.getClassName());
try {
if (epInfo.isOneWay())
{
seiClass.setSuperclass(oneWaySuperClass) ;
}
else
{
seiClass.setSuperclass(requestResponseSuperClass) ;
}
ConstPool constantPool = seiClass.getClassFile().getConstPool();
final String superClassName = seiClass.getSuperclass().getName().replace('.', '/') ;
final String interfaceName = Provider.class.getName().replace('.', '/') ;
final String typeName = SOAPMessage.class.getName().replace('.', '/') ;
final String signature = 'L' + superClassName + ';' + 'L' + interfaceName + "<L" + typeName + ";>;" ;
final SignatureAttribute signatureAttribute = new SignatureAttribute(constantPool, signature) ;
seiClass.getClassFile().addAttribute(signatureAttribute) ;
AnnotationsAttribute attribute = new AnnotationsAttribute(
constantPool, AnnotationsAttribute.visibleTag);
Annotation annotation = new Annotation(
"javax.xml.ws.WebServiceProvider", constantPool);
StringMemberValue strValue1 = new StringMemberValue(constantPool);
strValue1.setValue(epInfo.getWSDLFileName());
annotation.addMemberValue("wsdlLocation", strValue1);
StringMemberValue strValue2 = new StringMemberValue(constantPool);
strValue2.setValue(epInfo.getServiceName());
annotation.addMemberValue("serviceName", strValue2);
StringMemberValue strValue3 = new StringMemberValue(constantPool);
strValue3.setValue(epInfo.getPortName());
annotation.addMemberValue("portName", strValue3);
StringMemberValue strValue4 = new StringMemberValue(constantPool);
strValue4.setValue(epInfo.getNamespace());
annotation.addMemberValue("targetNamespace", strValue4);
attribute.addAnnotation(annotation);
Annotation annotation2 = new Annotation("javax.xml.ws.ServiceMode",
constantPool);
EnumMemberValue enumValue = new EnumMemberValue(constantPool);
enumValue.setType("javax.xml.ws.Service$Mode");
enumValue.setValue("MESSAGE");
annotation2.addMemberValue("value", enumValue);
attribute.addAnnotation(annotation2);
if (epInfo.isAddressing() && JBossDeployerUtil.getWSImpl().equals(JBossDeployerUtil.WSIMPL_CXF))
{
Annotation annotation3 = new Annotation("javax.xml.ws.soap.Addressing", constantPool);
BooleanMemberValue boolEnabled = new BooleanMemberValue(constantPool);
boolEnabled.setValue(true);
BooleanMemberValue boolRequired = new BooleanMemberValue(constantPool);
boolRequired.setValue(true);
annotation3.addMemberValue("enabled", boolEnabled);
annotation3.addMemberValue("required", boolEnabled);
attribute.addAnnotation(annotation3);
}
if (includeHandlers)
{
final Annotation handlerChainAnnotation = new Annotation("javax.jws.HandlerChain", constantPool) ;
final StringMemberValue handlerValue = new StringMemberValue(constantPool) ;
handlerValue.setValue("esb-jaxws-handlers.xml") ;
handlerChainAnnotation.addMemberValue("file", handlerValue) ;
attribute.addAnnotation(handlerChainAnnotation) ;
}
seiClass.getClassFile().addAttribute(attribute);
final String siClassName = ServiceInvoker.class.getName() ;
final CtClass siClass = pool.get(siClassName) ;
final String siFieldName = "serviceInvoker" ;
final CtField field = new CtField(siClass, siFieldName, seiClass) ;
field.setModifiers(Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL) ;
seiClass.addField(field, "new " + siClassName + "(\"" + category + "\", \"" + service + "\")") ;
final String constructorStr = "super(" + getParamValue(deployment) + "," + siFieldName + "," +
getParamValue(epInfo.getRequestLocation()) + "," + getParamValue(epInfo.getResponseLocation()) + ", \"" +
epInfo.getResponseAction() + "\");" ;
CtConstructor defaultConstructor = new CtConstructor(null, seiClass) ;
defaultConstructor.setBody(constructorStr) ;
seiClass.addConstructor(defaultConstructor) ;
return seiClass.toBytecode();
} catch (Exception e) {
throw new WebServicePublishException(
"Failed to generate jaxws dispatch class for ESB service",
e);
}
}
private String getParamValue(final String value) {
if (value == null) {
return "null" ;
} else {
return '"' + value + '"' ;
}
}
}