Author: mmerz Date: Fri Jan 21 10:26:05 2005 New Revision: 125950 URL: http://svn.apache.org/viewcvs?view=rev&rev=125950 Log: Additional build-time checks.
Modified: incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181MethodMetadataImpl.java incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181TypeMetadataImpl.java incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/processor/apt/WsmAnnotationProcessor.java Modified: incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181MethodMetadataImpl.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181MethodMetadataImpl.java?view=diff&rev=125950&p1=incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181MethodMetadataImpl.java&r1=125949&p2=incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181MethodMetadataImpl.java&r2=125950 ============================================================================== --- incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181MethodMetadataImpl.java (original) +++ incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181MethodMetadataImpl.java Fri Jan 21 10:26:05 2005 @@ -58,6 +58,7 @@ public Jsr181MethodMetadataImpl( String javaMethodName, Class javaReturnType, + Jsr181Modifiers modifiers, boolean throwsExceptions, Collection<Annotation> annotations, List<? extends Jsr181ParameterMetadata> webParams @@ -73,17 +74,13 @@ this.javaMethodName = javaMethodName; this.javaReturnType = javaReturnType; - // NOTE: commented the statements below for the service endpoint interface. - // All methods defined in a service endpoint interface are automatically - // considered @WebMethods -- whether they are annotated or not. - // check required parameters - // if (null == methodAnnotation) { - // throw new IllegalArgumentException("@WebMethod is required"); - // } - + // initialize @WebResult.name setWrName(DEFAULT_WRNAME); // enforce JSR-181 rules + if (! modifiers.isPublic()) { + throw new ValidationException("@WebMethod must be public: " + javaMethodName); + } if (AnnotationModel.hasAnnotationType(annotations, Oneway.class)) { // prohibit @Oneway with @WebResult if (AnnotationModel.hasAnnotationType(annotations, WebResult.class)) { Modified: incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181TypeMetadataImpl.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181TypeMetadataImpl.java?view=diff&rev=125950&p1=incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181TypeMetadataImpl.java&r1=125949&p2=incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181TypeMetadataImpl.java&r2=125950 ============================================================================== --- incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181TypeMetadataImpl.java (original) +++ incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/model/Jsr181TypeMetadataImpl.java Fri Jan 21 10:26:05 2005 @@ -75,7 +75,7 @@ private SecurityRolesInfo securityRoles; private String siValue; private String className; - private File classLocation; + private File baseLocation; /** * Default constructor. @@ -86,17 +86,20 @@ /** * @param wsAnnotation The @WebService annotation of the class. * @param className The fully-qualified name of the class. - * @param classLocation The location of the class file being processed; - * can be source or binary depending on the context; if null, relative - * paths e.g. in @HandlerChain would not work, however. + * @param baseLocation The location of the file being processed; + * if null, relative paths (e.g. in @HandlerChain) cannot be resolved. * @param annotations All annotations (including @WebService) of the class. * @param webMethods All methods that are published by the service. * @throws Exception */ public Jsr181TypeMetadataImpl( WebService wsAnnotation, + boolean isInterface, + boolean hasDefaultConstructor, + boolean hasFinalize, String className, - File classLocation, + File baseLocation, + Jsr181Modifiers modifiers, Collection<Annotation> annotations, Collection<? extends Jsr181MethodMetadata> webMethods ) throws Exception @@ -105,26 +108,57 @@ // check required parameter: wsAnnotation if (null == wsAnnotation) { - throw new IllegalArgumentException("@WebService is required for service implementation beans"); + throw new IllegalArgumentException("missing annotation: @WebService"); + } + + // check required parameters: annotations, webMethods + if ((null == annotations) || (null == webMethods)) { + throw new IllegalArgumentException("annotations or webMethods are null"); } // check required parameter: className if ((null == className) || (0 == className.length())) { - throw new IllegalArgumentException("service implementation bean class not set"); + throw new IllegalArgumentException("web service class is null"); } this.className = className; - this.classLocation = classLocation; - - // check required parameters: annotations, webMethods - if ((null == annotations) || (null == webMethods)) { - throw new IllegalArgumentException("annotations or webMethods is null"); - } + this.baseLocation = baseLocation; // enforce JSR-181 rules + if (modifiers.isFinal() || ! modifiers.isPublic()) { + throw new ValidationException("@WebService class must be public but not final"); + } + if (hasFinalize) { + throw new ValidationException("web service class must not declare method: finalize()"); + } + if (isInterface) { + if (null != wsAnnotation.endpointInterface() && 0 < wsAnnotation.endpointInterface().trim().length()) { + throw new ValidationException("@WebService.endpointInterface not allowed on interfaces"); + } + if (null != wsAnnotation.serviceName() && 0 < wsAnnotation.serviceName().trim().length()) { + throw new ValidationException("@WebService.serviceName not allowed on interfaces"); + } + } + else { + if (modifiers.isAbstract()) { + throw new ValidationException("service implementation bean must not be abstract"); + } + if (! hasDefaultConstructor) { + throw new ValidationException("service implementation bean must have default constructor"); + } + } if (AnnotationModel.hasAnnotationType(annotations, SOAPMessageHandlers.class) && AnnotationModel.hasAnnotationType(annotations, HandlerChain.class)) { - // todo needs to be proper Exception subclass (e.g. ObjectModelException) - throw new Exception("Illegal combination of @SOAPMessageHandlers and @HandlerChain"); + throw new ValidationException("Illegal combination of @SOAPMessageHandlers and @HandlerChain"); + } + String wsdlLocation = wsAnnotation.wsdlLocation(); + if (null != wsdlLocation && 0 < wsdlLocation.trim().length()) { + URL wsdlUrl = null; + try { + findResource(wsdlLocation.trim(), baseLocation).openStream(); + } + catch (Throwable t) { + throw new ValidationException("wsdlLocation does not exist: " + wsdlLocation); + } } // initilize instance @@ -313,13 +347,11 @@ throws Exception { // get URL for handler-chain config - URL handlerChainConfigURL = findHandlerChainConfig(handlerChainConfigPath); - - // throw an exception if we can't find the file + URL handlerChainConfigURL = findResource(handlerChainConfigPath, baseLocation); if (null == handlerChainConfigURL) { - throw new Exception("Cannot find handler-chain configuration file: " + handlerChainConfigPath); + throw new Exception("@HandlerChain: cannot resolve relative URL: " + handlerChainConfigPath + "(base directory: " + baseLocation + ")"); } - + // parse handler-chain config and add handler-chain to object model initHandlersFromChainConfig(handlerChainConfigURL, handlerChainName); } @@ -329,48 +361,59 @@ * Starts with '/': URL relative to class' base dir * Else: URL relative to class */ - private URL findHandlerChainConfig(String handlerChainConfigPath) - throws MalformedURLException - { - // validate handlerChainConfigPath - if (null == handlerChainConfigPath || 0 == handlerChainConfigPath.length()) { - throw new MalformedURLException("@HandlerChain: empty path for handler-chain config"); + private URL findResource(String resourcePath, File basePath) { + + URL resourceURL = null; + + // validate path + if (null == resourcePath || 0 == resourcePath.length()) { + return null; } - URL handlerChainConfigURL = null; - // handle absolute URL - if (0 < handlerChainConfigPath.indexOf(":/")) { - handlerChainConfigURL = new URL(handlerChainConfigPath); + if (0 < resourcePath.indexOf(":/")) { + try { + resourceURL = new URL(resourcePath); + return resourceURL; + } + catch (MalformedURLException e) { + return null; + } } - // handle relative URL (e.g. "/dir/Handler", "dir/Handler") - if (null == classLocation) { - throw new MalformedURLException("@HandlerChain: cannot resolve relative URL: " + handlerChainConfigPath); + // handle relative URL + if ((null == basePath) || (! basePath.exists())) { + return null; } - String classLocationString = classLocation.toString(); - String baseDir = null; - if (handlerChainConfigPath.startsWith("/")) { + String base = basePath.toString(); + if (resourcePath.startsWith("/")) { String temp = className; int lastIdx = className.lastIndexOf('.'); if (0 < lastIdx) { temp = temp.substring(0, lastIdx); } temp = temp.replace('.', File.separatorChar); - if (! classLocationString.endsWith(temp)) { - throw new MalformedURLException("@HandlerChain: cannot resolve relative URL, handler-chain config path inconsistent with package name: " + handlerChainConfigPath + " -> " + temp); + if (! base.endsWith(temp)) { + return null; + } + temp = base.substring(0, temp.length()); + try { + resourceURL = new File(new File(temp, resourcePath), resourcePath).toURL(); + } + catch (MalformedURLException e) { + return null; } - temp = classLocationString.substring(0, temp.length()); - handlerChainConfigURL = new File(new File(temp, handlerChainConfigPath), handlerChainConfigPath).toURL(); } else { - handlerChainConfigURL = new File(classLocation, handlerChainConfigPath).toURL(); - } - if (null == handlerChainConfigURL) { - throw new MalformedURLException("@HandlerChain: cannot resolve relative URL: " + handlerChainConfigPath); + try { + resourceURL = new File(base, resourcePath).toURL(); + } + catch (MalformedURLException e) { + return null; + } } - return handlerChainConfigURL; + return resourceURL; } /** Modified: incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/processor/apt/WsmAnnotationProcessor.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/processor/apt/WsmAnnotationProcessor.java?view=diff&rev=125950&p1=incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/processor/apt/WsmAnnotationProcessor.java&r1=125949&p2=incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/processor/apt/WsmAnnotationProcessor.java&r2=125950 ============================================================================== --- incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/processor/apt/WsmAnnotationProcessor.java (original) +++ incubator/beehive/trunk/wsm/src/runtime/org/apache/beehive/wsm/jsr181/processor/apt/WsmAnnotationProcessor.java Fri Jan 21 10:26:05 2005 @@ -19,6 +19,7 @@ */ import java.io.File; +import java.io.IOException; import java.lang.annotation.Annotation; import java.util.ArrayList; @@ -31,6 +32,7 @@ import javax.jws.WebMethod; import javax.jws.WebService; + import com.sun.mirror.apt.AnnotationProcessorEnvironment; import com.sun.mirror.apt.Filer; import com.sun.mirror.apt.Messager; @@ -38,6 +40,7 @@ import com.sun.mirror.declaration.AnnotationMirror; import com.sun.mirror.declaration.AnnotationTypeDeclaration; import com.sun.mirror.declaration.ClassDeclaration; +import com.sun.mirror.declaration.ConstructorDeclaration; import com.sun.mirror.declaration.Declaration; import com.sun.mirror.declaration.InterfaceDeclaration; import com.sun.mirror.declaration.MethodDeclaration; @@ -45,11 +48,11 @@ import com.sun.mirror.declaration.TypeDeclaration; import com.sun.mirror.type.AnnotationType; -import java.io.IOException; import org.apache.beehive.wsm.jsr181.model.AnnotationMetadata; import org.apache.beehive.wsm.jsr181.model.Jsr181MethodMetadata; import org.apache.beehive.wsm.jsr181.model.Jsr181MethodMetadataImpl; +import org.apache.beehive.wsm.jsr181.model.Jsr181Modifiers; import org.apache.beehive.wsm.jsr181.model.Jsr181ParameterMetadata; import org.apache.beehive.wsm.jsr181.model.Jsr181ParameterMetadataImpl; import org.apache.beehive.wsm.jsr181.model.Jsr181TypeMetadata; @@ -121,7 +124,7 @@ om = getEndpointInterfaceObjectModel(endpointInterface); // merge abstract and concrete object models - Jsr181TypeMetadata com = getWebServiceTYPEMetadata(classDecl, false); + Jsr181TypeMetadata com = getWebServiceTYPEMetadata(classDecl); if (null == com) { messager.printError(classDecl.getPosition(), "cannot load object model for service implementation bean: " + classDecl.getQualifiedName()); return; @@ -134,7 +137,7 @@ // create object model from scratch else { - om = getWebServiceTYPEMetadata(classDecl, false); + om = getWebServiceTYPEMetadata(classDecl); } // check if we have an object model @@ -153,7 +156,7 @@ messager.printNotice("processing service endpoint interface: " + interfaceDecl.getQualifiedName()); // create object model - Jsr181TypeMetadata om = getWebServiceTYPEMetadata(interfaceDecl, true); + Jsr181TypeMetadata om = getWebServiceTYPEMetadata(interfaceDecl); if (null == om) { return; } @@ -183,7 +186,7 @@ // todo: persist all object models that have been created [by check()] } - protected Jsr181TypeMetadata getWebServiceTYPEMetadata(TypeDeclaration decl, boolean isServiceEndpointInterface) { + protected Jsr181TypeMetadata getWebServiceTYPEMetadata(TypeDeclaration decl) { Jsr181TypeMetadata objectModel = null; @@ -200,6 +203,7 @@ Collection<Annotation> annotations = new ArrayList(); // add all methods from service endpoint interface + boolean isServiceEndpointInterface = (decl instanceof InterfaceDeclaration); if (isServiceEndpointInterface) { for (MethodDeclaration mdecl : decl.getMethods()) { webMethods.add(getWebServiceMETHODMetadata(mdecl)); @@ -216,13 +220,50 @@ } } } + + // check default constructor + boolean hasDefaultConstructor = false; + if (isServiceEndpointInterface) { + hasDefaultConstructor = true; // not used for interface + } + else { + ClassDeclaration cdecl = (ClassDeclaration) decl; + for (ConstructorDeclaration c : cdecl.getConstructors()) { + if (c.getParameters().isEmpty()) { + hasDefaultConstructor = true; + break; + } + } + } + + // check finalize + boolean hasFinalize = false; + if (isServiceEndpointInterface) { + hasFinalize = false; // not used for interface + } + else { + for (MethodDeclaration mdecl : decl.getMethods()) { + if (mdecl.getSimpleName().equals("finalize") && (null == mdecl.getParameters() || mdecl.getParameters().isEmpty())) { + hasFinalize = true; + } + } + } // create & return WebService + Jsr181Modifiers modifiers = new Jsr181Modifiers( + decl.getModifiers().contains(com.sun.mirror.declaration.Modifier.ABSTRACT), + decl.getModifiers().contains(com.sun.mirror.declaration.Modifier.FINAL), + decl.getModifiers().contains(com.sun.mirror.declaration.Modifier.PUBLIC) + ); try { objectModel = new Jsr181TypeMetadataImpl( wsAnnotation, + isServiceEndpointInterface, + hasDefaultConstructor, + hasFinalize, decl.getQualifiedName(), decl.getPosition().file().getParentFile(), + modifiers, getAnnotations(decl), webMethods ); @@ -235,6 +276,9 @@ } protected Jsr181MethodMetadata getWebServiceMETHODMetadata(MethodDeclaration decl) { + + Jsr181MethodMetadata wsmm = null; + // get webMethod's webParams List<Jsr181ParameterMetadata> webParams = new ArrayList<Jsr181ParameterMetadata>(); @@ -243,16 +287,23 @@ if (null != wspm) { webParams.add(wspm); } - } + } // create & return webMethod - Jsr181MethodMetadata wsmm = null; + Jsr181Modifiers modifiers = new Jsr181Modifiers( + decl.getModifiers().contains(com.sun.mirror.declaration.Modifier.ABSTRACT), + decl.getModifiers().contains(com.sun.mirror.declaration.Modifier.FINAL), + decl.getModifiers().contains(com.sun.mirror.declaration.Modifier.PUBLIC) + ); try { - wsmm = new Jsr181MethodMetadataImpl(decl.getSimpleName(), - TypeMirrorUtil.classForName(decl.getReturnType()), - (0 < decl.getThrownTypes().size()), - getAnnotations(decl), - webParams); + wsmm = new Jsr181MethodMetadataImpl( + decl.getSimpleName(), + TypeMirrorUtil.classForName(decl.getReturnType()), + modifiers, + (0 < decl.getThrownTypes().size()), + getAnnotations(decl), + webParams + ); } catch (Throwable t) { _env.getMessager().printError(decl.getPosition(), t.getMessage());
