blob: db23b74437a476e6804bff663975a3615146939e [file] [log] [blame]
/*
* Portions Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.tools.internal.ws.processor.modeler.annotation;
import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.apt.Messager;
import com.sun.mirror.declaration.ClassDeclaration;
import com.sun.mirror.declaration.InterfaceDeclaration;
import com.sun.mirror.declaration.MethodDeclaration;
import com.sun.mirror.declaration.TypeDeclaration;
import com.sun.mirror.declaration.TypeParameterDeclaration;
import com.sun.mirror.type.ClassType;
import com.sun.mirror.type.InterfaceType;
import com.sun.mirror.type.TypeMirror;
import com.sun.mirror.util.SourcePosition;
import com.sun.tools.internal.ws.processor.ProcessorNotificationListener;
import com.sun.tools.internal.ws.processor.ProcessorOptions;
import com.sun.tools.internal.ws.processor.generator.GeneratorUtil;
import com.sun.tools.internal.ws.processor.generator.Names;
import com.sun.tools.internal.ws.processor.model.Model;
import com.sun.tools.internal.ws.processor.model.ModelProperties;
import com.sun.tools.internal.ws.processor.model.Operation;
import com.sun.tools.internal.ws.processor.model.Port;
import com.sun.tools.internal.ws.processor.model.Service;
import com.sun.tools.internal.ws.processor.model.jaxb.JAXBModel;
import com.sun.tools.internal.ws.processor.modeler.ModelerException;
import com.sun.tools.internal.ws.processor.modeler.annotation.AnnotationProcessorContext.SEIContext;
import com.sun.tools.internal.ws.processor.util.ClientProcessorEnvironment;
import com.sun.tools.internal.ws.processor.util.ProcessorEnvironment;
import com.sun.tools.internal.ws.util.ToolBase;
import com.sun.tools.internal.ws.ToolVersion;
import com.sun.tools.internal.xjc.api.JavaCompiler;
import com.sun.tools.internal.xjc.api.Reference;
import com.sun.tools.internal.xjc.api.XJC;
import com.sun.xml.internal.ws.util.localization.Localizable;
import com.sun.xml.internal.ws.util.localization.LocalizableMessage;
import javax.jws.WebService;
import javax.xml.namespace.QName;
import javax.xml.ws.WebServiceProvider;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* WebServiceAP is a APT AnnotationProcessor for processing javax.jws.* and
* javax.xml.ws.* annotations. This class is used either by the WsGen (CompileTool) tool or
* idirectly via the {@link com.sun.istack.internal.ws.WSAP WSAP} when invoked by APT.
*
* @author WS Development Team
*/
public class WebServiceAP extends ToolBase implements AnnotationProcessor, ModelBuilder, WebServiceConstants,
ProcessorNotificationListener {
protected AnnotationProcessorEnvironment apEnv;
protected ProcessorEnvironment env;
private File sourceDir;
// the model being build
private Model model;
private TypeDeclaration remoteDecl;
private TypeDeclaration remoteExceptionDecl;
private TypeDeclaration exceptionDecl;
private TypeDeclaration defHolderDecl;
private Service service;
private Port port;
protected AnnotationProcessorContext context;
private Set<TypeDeclaration> processedTypeDecls = new HashSet<TypeDeclaration>();
protected Messager messager;
private ByteArrayOutputStream output;
private ToolBase tool;
private boolean doNotOverWrite = false;
private boolean wrapperGenerated = false;
/*
* Is this invocation from APT or JavaC?
*/
private boolean isAPTInvocation = false;
public void run() {
}
protected boolean parseArguments(String[] args) {
return true;
}
public WebServiceAP(ToolBase tool, ProcessorEnvironment env, Properties options, AnnotationProcessorContext context) {
super(System.out, "WebServiceAP");
this.context = context;
this.tool = tool;
this.env = env;
if (options != null) {
sourceDir = new File(options.getProperty(ProcessorOptions.SOURCE_DIRECTORY_PROPERTY));
String key = ProcessorOptions.DONOT_OVERWRITE_CLASSES;
this.doNotOverWrite =
Boolean.valueOf(options.getProperty(key));
}
}
public void init(AnnotationProcessorEnvironment apEnv) {
this.apEnv = apEnv;
remoteDecl = this.apEnv.getTypeDeclaration(REMOTE_CLASSNAME);
remoteExceptionDecl = this.apEnv.getTypeDeclaration(REMOTE_EXCEPTION_CLASSNAME);
exceptionDecl = this.apEnv.getTypeDeclaration(EXCEPTION_CLASSNAME);
defHolderDecl = this.apEnv.getTypeDeclaration(HOLDER_CLASSNAME);
if (env == null) {
Map<String, String> apOptions = apEnv.getOptions();
output = new ByteArrayOutputStream();
String classDir = apOptions.get("-d");
if (classDir == null)
classDir = ".";
if (apOptions.get("-s") != null)
sourceDir = new File(apOptions.get("-s"));
else
sourceDir = new File(classDir);
String cp = apOptions.get("-classpath");
String cpath = classDir +
File.pathSeparator +
cp + File.pathSeparator +
System.getProperty("java.class.path");
env = new ClientProcessorEnvironment(output, cpath, this);
((ClientProcessorEnvironment) env).setNames(new Names());
boolean setVerbose = false;
for (String key : apOptions.keySet()) {
if (key.equals("-verbose"))
setVerbose=true;
}
if (setVerbose) {
env.setFlags(ProcessorEnvironment.F_VERBOSE);
}
messager = apEnv.getMessager();
isAPTInvocation = true;
}
env.setFiler(apEnv.getFiler());
}
public AnnotationProcessorEnvironment getAPEnv() {
return apEnv;
}
public ProcessorEnvironment getEnvironment() {
return env;
}
public ProcessorEnvironment getProcessorEnvironment() {
return env;
}
public File getSourceDir() {
return sourceDir;
}
public void onError(String key) {
onError(new LocalizableMessage(getResourceBundleName(), key));
}
public void onError(String key, Object[] args) throws ModelerException {
onError(null, key, args);
}
public void onError(SourcePosition pos, String key, Object[] args) throws ModelerException {
onError(pos, new LocalizableMessage(getResourceBundleName(), key, args));
}
public void onError(Localizable msg) throws ModelerException {
onError(null, msg);
}
public void onError(SourcePosition pos, Localizable msg) throws ModelerException {
if (messager != null) {
messager.printError(pos, localizer.localize(msg));
} else {
throw new ModelerException(msg);
}
}
public void onWarning(String key) {
onWarning(new LocalizableMessage(getResourceBundleName(), key));
}
public void onWarning(Localizable msg) {
String message = localizer.localize(getMessage("webserviceap.warning", localizer.localize(msg)));
if (messager != null) {
messager.printWarning(message);
} else {
report(message);
}
}
public void onInfo(Localizable msg) {
if (messager != null) {
String message = localizer.localize(msg);
messager.printNotice(message);
} else {
String message = localizer.localize(getMessage("webserviceap.info", localizer.localize(msg)));
report(message);
}
}
public void process() {
if (context.getRound() == 1) {
buildModel();
}
if (!wrapperGenerated || // the wrappers already exist
context.getRound() == 2 ||
context.allEncoded()) {
if ((context.getRound() == 2 || !wrapperGenerated) && !context.isModelCompleted()) {
completeModel();
context.setModelCompleted(true);
}
try {
for (SEIContext seiContext : context.getSEIContexts()) {
if (!seiContext.getModelCompiled()) {
runProcessorActions(seiContext.getModel());
seiContext.setModelCompiled(true);
}
}
} catch(Exception e) {
e.printStackTrace();
} finally {
if (messager != null && output != null && output.size() > 0) {
messager.printNotice(output.toString());
}
}
}
context.incrementRound();
}
public boolean checkAndSetProcessed(TypeDeclaration typeDecl) {
if (!processedTypeDecls.contains(typeDecl)) {
processedTypeDecls.add(typeDecl);
return false;
}
return true;
}
public void clearProcessed() {
processedTypeDecls.clear();
}
protected void runProcessorActions(Model model) throws Exception {
if (tool != null)
tool.runProcessorActions();
}
protected String getGenericErrorMessage() {
return "webserviceap.error";
}
protected String getResourceBundleName() {
return "com.sun.tools.internal.ws.resources.webserviceap";
}
public void createModel(TypeDeclaration d, QName modelName, String targetNamespace,
String modelerClassName){
SEIContext seiContext = context.getSEIContext(d);
if (seiContext.getModel() != null) {
onError("webserviceap.model.already.exists");
return;
}
log("creating model: " + modelName);
model = new Model(modelName);
model.setTargetNamespaceURI(targetNamespace);
model.setProperty(
ModelProperties.PROPERTY_MODELER_NAME,
modelerClassName);
seiContext.setModel(model);
}
public void setService(Service service) {
this.service = service;
model.addService(service);
}
public void setPort(Port port) {
this.port = port;
service.addPort(port);
}
public void addOperation(Operation operation) {
port.addOperation(operation);
}
public void setWrapperGenerated(boolean wrapperGenerated) {
this.wrapperGenerated = wrapperGenerated;
}
public TypeDeclaration getTypeDeclaration(String typeName) {
return apEnv.getTypeDeclaration(typeName);
}
public String getSourceVersion() {
return ToolVersion.VERSION.MAJOR_VERSION;
}
private void buildModel() {
WebService webService;
WebServiceProvider webServiceProvider = null;
WebServiceVisitor wrapperGenerator = createWrapperGenerator();
boolean processedEndpoint = false;
for (TypeDeclaration typedecl: apEnv.getTypeDeclarations()) {
if (!(typedecl instanceof ClassDeclaration))
continue;
webServiceProvider = typedecl.getAnnotation(WebServiceProvider.class);
webService = typedecl.getAnnotation(WebService.class);
if (webServiceProvider != null) {
if (webService != null) {
onError("webserviceap.webservice.and.webserviceprovider",
new Object[] {typedecl.getQualifiedName()});
}
processedEndpoint = true;
}
if (!shouldProcessWebService(webService))
continue;
typedecl.accept(wrapperGenerator);
processedEndpoint = true;
}
if (!processedEndpoint) {
if (isAPTInvocation)
onWarning("webserviceap.no.webservice.endpoint.found");
else
onError("webserviceap.no.webservice.endpoint.found");
}
}
protected WebServiceVisitor createWrapperGenerator() {
return new WebServiceWrapperGenerator(this, context);
}
protected WebServiceVisitor createReferenceCollector() {
return new WebServiceReferenceCollector(this, context);
}
protected boolean shouldProcessWebService(WebService webService) {
return webService != null;
}
private void completeModel() {
clearProcessed();
JavaCompiler javaC = XJC.createJavaCompiler();
JAXBModel jaxBModel;
WebServiceVisitor referenceCollector = createReferenceCollector();
for (SEIContext seiContext : context.getSEIContexts()) {
log("completing model for endpoint: "+seiContext.getSEIImplName());
TypeDeclaration decl = apEnv.getTypeDeclaration(seiContext.getSEIImplName());
if (decl == null)
onError("webserviceap.could.not.find.typedecl",
new Object[] {seiContext.getSEIImplName(), context.getRound()});
decl.accept(referenceCollector);
}
clearProcessed();
for (SEIContext seiContext : context.getSEIContexts()) {
TypeDeclaration decl = apEnv.getTypeDeclaration(seiContext.getSEIName());
Collection<Reference> schemaMirrors = seiContext.getSchemaReferences(this);
// System.out.println("schemaMirrors count: " + schemaMirrors.size());
// for (Reference reference : schemaMirrors) {System.out.println("reference: "+reference.type);}
// System.out.println("schemaElementMap count: "+ seiContext.getSchemaElementMap(this).entrySet().size());
// for (Map.Entry<QName, ? extends Reference> entry : seiContext.getSchemaElementMap(this).entrySet()) {
// System.out.println("name: " + entry.getKey()+" value: "+entry.getValue().type);
// }
// System.out.println("setting default namespaceURI: "+seiContext.getNamespaceURI());
jaxBModel = new JAXBModel(javaC.bind(schemaMirrors, seiContext.getSchemaElementMap(this),
seiContext.getNamespaceURI(), apEnv));
// for (JAXBMapping map : jaxBModel.getMappings()) {System.out.println("map.getClazz: "+map.getClazz());}
seiContext.setJAXBModel(jaxBModel);
}
}
public boolean isException(TypeDeclaration typeDecl) {
return isSubtype(typeDecl, exceptionDecl);
}
public boolean isRemoteException(TypeDeclaration typeDecl) {
return isSubtype(typeDecl, remoteExceptionDecl);
}
public boolean isRemote(TypeDeclaration typeDecl) {
return isSubtype(typeDecl, remoteDecl);
}
public static boolean isSubtype(TypeDeclaration d1, TypeDeclaration d2) {
if (d1.equals(d2))
return true;
ClassDeclaration superClassDecl = null;
if (d1 instanceof ClassDeclaration) {
ClassType superClass = ((ClassDeclaration)d1).getSuperclass();
if (superClass != null) {
superClassDecl = superClass.getDeclaration();
if (superClassDecl.equals(d2))
return true;
}
}
InterfaceDeclaration superIntf = null;
for (InterfaceType interfaceType : d1.getSuperinterfaces()) {
superIntf = interfaceType.getDeclaration();
if (superIntf.equals(d2))
return true;
}
if (superIntf != null && isSubtype(superIntf, d2)) {
return true;
} else if (superClassDecl != null && isSubtype(superClassDecl, d2)) {
return true;
}
return false;
}
public static String getMethodSig(MethodDeclaration method) {
StringBuffer buf = new StringBuffer(method.getSimpleName() + "(");
Iterator<TypeParameterDeclaration> params = method.getFormalTypeParameters().iterator();
TypeParameterDeclaration param;
for (int i =0; params.hasNext(); i++) {
if (i > 0)
buf.append(", ");
param = params.next();
buf.append(param.getSimpleName());
}
buf.append(")");
return buf.toString();
}
public String getOperationName(String messageName) {
return messageName;
}
public String getResponseName(String operationName) {
return Names.getResponseName(operationName);
}
public TypeMirror getHolderValueType(TypeMirror type) {
return TypeModeler.getHolderValueType(type, defHolderDecl, apEnv);
}
public boolean canOverWriteClass(String className) {
return !((doNotOverWrite && GeneratorUtil.classExists(env, className)));
}
public void log(String msg) {
if (env != null && env.verbose()) {
String message = "[" + msg + "]";
if (messager != null) {
messager.printNotice(message);
} else {
System.out.println(message);
}
}
}
public String getXMLName(String javaName) {
return javaName;
}
}