package org.apache.beehive.wsm.processor.apt;
/*
* Copyright 2004 The Apache Software Foundation
*
* Licensed 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.
*
* $Header:$
*/
import java.util.HashSet;
import java.util.Set;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.apt.Messager;
import com.sun.mirror.declaration.AnnotationTypeDeclaration;
import com.sun.mirror.declaration.ClassDeclaration;
import com.sun.mirror.declaration.Declaration;
import com.sun.mirror.declaration.InterfaceDeclaration;
import com.sun.mirror.declaration.TypeDeclaration;
import javax.jws.WebService;
import org.apache.beehive.wsm.model.BeehiveWsTypeMetadata;
import org.apache.beehive.wsm.model.jsr181.Jsr181ObjectModelStore;
import org.apache.beehive.wsm.model.jsr181.Jsr181TypeMetadataImpl;
/**
* WsmAnnotationProcessor provides an API for IDEs and other applications to
* perform code validation.
* Currently, check() and generate() are not implemented. Since the
* WsmAnnotationProcessor does not generate any artifacts but class files,
* process() is equivalent with check() and generate() is void.
*/
public class WsmAnnotationProcessor extends TwoPhaseAnnotationProcessor {
private Set<TypeDeclaration> handledDecls = new HashSet<TypeDeclaration>();
private Jsr181ObjectModelStore oms;
/**
* Constructor.
*/
public WsmAnnotationProcessor(Set<AnnotationTypeDeclaration> atds, AnnotationProcessorEnvironment env) {
super (atds, env);
oms = new Jsr181ObjectModelStore(env);
}
/**
* Checks whether a source file complies with JSR-181.
* @see TwoPhaseAnnotationProcessor
* todo: should this always run all tests whenever called for any supported annotation?
*/
@Override
public void check(Declaration _decl) {
Messager messager = _env.getMessager();
try {
// check if we've already handled this declaration
if (handledDecls.contains(_decl)) {
return;
}
// check if we're interested in declaration
if (! (_decl instanceof TypeDeclaration)) {
return;
}
WebService wsAnnotation = _decl.getAnnotation(WebService.class);
if (null == wsAnnotation) {
messager.printError(_decl.getPosition(), "@WebService annotation missing; unable to process: " + ((TypeDeclaration) _decl).getQualifiedName());
}
// store declaration so we don't handle it multiple times
handledDecls.add((TypeDeclaration) _decl);
// service implementation bean
if (_decl instanceof ClassDeclaration) {
ClassDeclaration classDecl = (ClassDeclaration) _decl;
messager.printNotice("processing service implementation bean: " + classDecl.getQualifiedName());
BeehiveWsTypeMetadata om = null;
String endpointInterface = wsAnnotation.endpointInterface().trim();
// start from endpoint interface
if (null != endpointInterface && 0 < endpointInterface.length()) {
// get object model for service endpoint interface
om = getEndpointInterfaceObjectModel(endpointInterface);
// merge abstract and concrete object models
om.merge(new MirrorTypeInfo(classDecl, _env));
}
// create object model from scratch
else {
om = new Jsr181TypeMetadataImpl(new MirrorTypeInfo(classDecl, _env));
}
// check if we have an object model
if (null == om) {
return;
}
// persist object model
oms.store(om);
}
// service endpoint interface
else if (_decl instanceof InterfaceDeclaration) {
InterfaceDeclaration interfaceDecl = (InterfaceDeclaration) _decl;
messager.printNotice("processing service endpoint interface: " + interfaceDecl.getQualifiedName());
// create object model
BeehiveWsTypeMetadata om = new Jsr181TypeMetadataImpl(new MirrorTypeInfo(interfaceDecl, _env));
if (null == om) {
return;
}
// store the object model
oms.store(om);
}
// @WebService annotation on unknown/unsupported type definition
else {
messager.printError(_decl.getPosition(), "found unsupported type of TypeDeclaration:" + _decl.getSimpleName());
}
}
// if an exception or error ocurred log it and return
catch (Throwable t) {
messager.printError(_decl.getPosition(), t.getMessage());
}
}
/**
* @see TwoPhaseAnnotationProcessor
*/
@Override
public void generate(Declaration _decl) {
// todo: persist all object models that have been created [by check()]
}
private BeehiveWsTypeMetadata getEndpointInterfaceObjectModel(String endpointInterface) {
BeehiveWsTypeMetadata om = null;
// search for persistent object model
try {
om = Jsr181ObjectModelStore.load(getClass().getClassLoader().getResourceAsStream(Jsr181ObjectModelStore.getLocation(endpointInterface).toString()));
}
catch (Throwable t) { }
// try to generate object model
if (null == om) {
try {
_env.getMessager().printNotice("-> loading object model for required endpoint interface:" + endpointInterface);
check(_env.getTypeDeclaration(endpointInterface));
om = Jsr181ObjectModelStore.load(getClass().getClassLoader().getResourceAsStream(Jsr181ObjectModelStore.getLocation(endpointInterface).toString()));
}
catch (Throwable t) { }
}
return om;
}
}