/******************************************************************************* | |
* Copyright (c) 2009 Shane Clarke. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Contributors: | |
* Shane Clarke - initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.jst.ws.internal.jaxws.core.annotations.validation; | |
import static org.eclipse.jst.ws.internal.jaxws.core.utils.JAXWSUtils.ENDPOINT_INTERFACE; | |
import static org.eclipse.jst.ws.internal.jaxws.core.utils.JAXWSUtils.EXCLUDE; | |
import static org.eclipse.jst.ws.internal.jaxws.core.utils.JAXWSUtils.OPERATION_NAME; | |
import static org.eclipse.jst.ws.internal.jaxws.core.utils.JAXWSUtils.PORT_NAME; | |
import static org.eclipse.jst.ws.internal.jaxws.core.utils.JAXWSUtils.PORT_SUFFIX; | |
import static org.eclipse.jst.ws.internal.jaxws.core.utils.JAXWSUtils.SERVICE_NAME; | |
import static org.eclipse.jst.ws.internal.jaxws.core.utils.JAXWSUtils.SERVICE_SUFFIX; | |
import static org.eclipse.jst.ws.internal.jaxws.core.utils.JAXWSUtils.STYLE; | |
import static org.eclipse.jst.ws.internal.jaxws.core.utils.JAXWSUtils.TARGET_NAMESPACE; | |
import static org.eclipse.jst.ws.internal.jaxws.core.utils.JAXWSUtils.WSDL_LOCATION; | |
import java.io.IOException; | |
import java.net.MalformedURLException; | |
import java.net.URL; | |
import java.util.Collection; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Set; | |
import javax.jws.Oneway; | |
import javax.jws.WebMethod; | |
import javax.jws.WebService; | |
import javax.wsdl.Binding; | |
import javax.wsdl.Definition; | |
import javax.wsdl.Operation; | |
import javax.wsdl.Port; | |
import javax.wsdl.Service; | |
import javax.wsdl.extensions.soap.SOAPBinding; | |
import javax.wsdl.extensions.soap12.SOAP12Binding; | |
import javax.xml.namespace.QName; | |
import org.eclipse.jst.ws.annotations.core.processor.AbstractAnnotationProcessor; | |
import org.eclipse.jst.ws.annotations.core.utils.AnnotationUtils; | |
import org.eclipse.jst.ws.internal.jaxws.core.JAXWSCoreMessages; | |
import org.eclipse.jst.ws.jaxws.core.utils.JDTUtils; | |
import org.eclipse.jst.ws.jaxws.core.utils.WSDLUtils; | |
import com.sun.mirror.declaration.AnnotationMirror; | |
import com.sun.mirror.declaration.AnnotationTypeDeclaration; | |
import com.sun.mirror.declaration.AnnotationValue; | |
import com.sun.mirror.declaration.ClassDeclaration; | |
import com.sun.mirror.declaration.Declaration; | |
import com.sun.mirror.declaration.MethodDeclaration; | |
import com.sun.mirror.declaration.TypeDeclaration; | |
public class WebServiceWSDLLocationRule extends AbstractAnnotationProcessor { | |
@Override | |
@SuppressWarnings("unchecked") | |
public void process() { | |
AnnotationTypeDeclaration annotationDeclaration = (AnnotationTypeDeclaration) environment | |
.getTypeDeclaration(WebService.class.getName()); | |
Collection<Declaration> annotatedTypes = environment | |
.getDeclarationsAnnotatedWith(annotationDeclaration); | |
for (Declaration declaration : annotatedTypes) { | |
if (declaration instanceof ClassDeclaration) { | |
ClassDeclaration classDeclaration = (ClassDeclaration) declaration; | |
AnnotationMirror webService = AnnotationUtils.getAnnotation(declaration, WebService.class); | |
AnnotationValue wsdlLocationValue = AnnotationUtils.getAnnotationValue(webService, WSDL_LOCATION); | |
if (wsdlLocationValue == null) { | |
break; | |
} | |
String wsdlLocation = wsdlLocationValue.getValue().toString(); | |
if (wsdlLocation != null && wsdlLocation.trim().length() > 0) { | |
try { | |
URL wsdlURL = new URL(wsdlLocation); | |
Definition definition = WSDLUtils.readWSDL(wsdlURL); | |
if (definition != null) { | |
QName serviceQName = getServiceQName(webService, (ClassDeclaration) declaration); | |
Service service = getService(definition, serviceQName); | |
if (service != null) { | |
String portName = getPortName(webService, classDeclaration); | |
Port port = getPort(service, portName); | |
if (port != null) { | |
Binding binding = port.getBinding(); | |
validateBinding(binding, classDeclaration, webService, wsdlLocation); | |
Map<String, MethodDeclaration> methodMap = getWebMethods(classDeclaration, | |
webService); | |
List<Operation> operations = binding.getPortType().getOperations(); | |
for (Operation operation : operations) { | |
MethodDeclaration methodDeclaration = methodMap.get(operation.getName()); | |
if (methodDeclaration == null) { | |
printError(webService.getPosition(), JAXWSCoreMessages.bind( | |
JAXWSCoreMessages.WEBSERVICE_WSDL_LOCATION_NO_OPERTATION_NAME, | |
operation.getName())); | |
} else { | |
AnnotationMirror oneway = AnnotationUtils.getAnnotation( | |
methodDeclaration, Oneway.class); | |
if (oneway != null && operation.getOutput() != null) { | |
printError(methodDeclaration.getPosition(), JAXWSCoreMessages.bind( | |
JAXWSCoreMessages.WEBSERVICE_WSDL_LOCATION_WSDL_OPERATION_OUTPUT_METHOD_ONEWAY, | |
new Object[] {methodDeclaration.getSimpleName(), operation.getName()})); | |
} | |
} | |
} | |
} else { | |
printError(webService.getPosition(), JAXWSCoreMessages.bind( | |
JAXWSCoreMessages.WEBSERVICE_WSDL_LOCATION_NO_PORT_NAME, | |
new Object[] {portName, wsdlLocation})); | |
} | |
} else { | |
printError(webService.getPosition(), JAXWSCoreMessages.bind( | |
JAXWSCoreMessages.WEBSERVICE_WSDL_LOCATION_NO_SERVICE_NAME, | |
new Object[] {serviceQName.getLocalPart(), wsdlLocation})); | |
} | |
} | |
} catch (MalformedURLException murle) { | |
printError(wsdlLocationValue.getPosition(), murle.getLocalizedMessage()); | |
} catch (IOException ioe) { | |
printNotice(wsdlLocationValue.getPosition(), JAXWSCoreMessages.bind( | |
JAXWSCoreMessages.WEBSERVICE_WSDL_LOCATION_UNABLE_TO_LOCATE, wsdlLocation)); | |
} | |
} | |
} | |
} | |
} | |
@SuppressWarnings("unchecked") | |
private void validateBinding(Binding binding, ClassDeclaration classDeclaration, | |
AnnotationMirror webService, String wsdlLocation) { | |
String style = javax.jws.soap.SOAPBinding.Style.DOCUMENT.name(); | |
AnnotationMirror soapBindingAnnotation = getSOAPBinding(classDeclaration, webService); | |
if (soapBindingAnnotation != null) { | |
String styleValue = AnnotationUtils.getStringValue(soapBindingAnnotation, STYLE); | |
if (styleValue != null) { | |
style = styleValue; | |
} | |
} | |
List extensibilityElements = binding.getExtensibilityElements(); | |
for (Object elementExtensible : extensibilityElements) { | |
if (elementExtensible instanceof SOAPBinding) { | |
SOAPBinding soapBinding = (SOAPBinding) elementExtensible; | |
if (style.compareToIgnoreCase(soapBinding.getStyle()) != 0) { | |
printError(soapBindingAnnotation == null ? webService.getPosition() | |
: soapBindingAnnotation.getPosition(), | |
JAXWSCoreMessages.bind(JAXWSCoreMessages.WEBSERVICE_WSDL_LOCATION_SOAP_BINDING_STYLE, | |
new Object[] {wsdlLocation, soapBinding.getStyle(), style})); | |
} | |
} | |
if (elementExtensible instanceof SOAP12Binding) { | |
SOAP12Binding soap12Binding = (SOAP12Binding) elementExtensible; | |
if (style.compareToIgnoreCase(soap12Binding.getStyle()) != 0) { | |
printError(soapBindingAnnotation == null ? webService.getPosition() | |
: soapBindingAnnotation.getPosition(), | |
JAXWSCoreMessages.bind(JAXWSCoreMessages.WEBSERVICE_WSDL_LOCATION_SOAP_BINDING_STYLE, | |
new Object[] {wsdlLocation, soap12Binding.getStyle(), style})); | |
} | |
} | |
} | |
} | |
private AnnotationMirror getSOAPBinding(TypeDeclaration typeDeclaration, AnnotationMirror webService) { | |
String endpointInterface = AnnotationUtils.getStringValue(webService, ENDPOINT_INTERFACE); | |
if (endpointInterface != null) { | |
TypeDeclaration seiDeclaration = environment.getTypeDeclaration(endpointInterface); | |
if (seiDeclaration != null) { | |
typeDeclaration = seiDeclaration; | |
} | |
} | |
return AnnotationUtils.getAnnotation(typeDeclaration, javax.jws.soap.SOAPBinding.class); | |
} | |
private Map<String, MethodDeclaration> getWebMethods(TypeDeclaration typeDeclaration, AnnotationMirror webService) { | |
Map<String, MethodDeclaration> methodMap = new HashMap<String, MethodDeclaration>(); | |
String endpointInterface = AnnotationUtils.getStringValue(webService, ENDPOINT_INTERFACE); | |
if (endpointInterface != null) { | |
TypeDeclaration seiDeclaration = environment.getTypeDeclaration(endpointInterface); | |
if (seiDeclaration != null) { | |
typeDeclaration = seiDeclaration; | |
} | |
} | |
Collection<? extends MethodDeclaration> methods = typeDeclaration.getMethods(); | |
for (MethodDeclaration methodDeclaration : methods) { | |
AnnotationMirror webMethod = AnnotationUtils.getAnnotation(methodDeclaration, WebMethod.class); | |
if (webMethod != null && !isExluded(webMethod)) { | |
methodMap.put(getOperationName(webMethod, methodDeclaration), methodDeclaration); | |
} else { | |
methodMap.put(methodDeclaration.getSimpleName(), methodDeclaration); | |
} | |
} | |
return methodMap; | |
} | |
private boolean isExluded(AnnotationMirror webMethod) { | |
Boolean exclude = AnnotationUtils.getBooleanValue(webMethod, EXCLUDE); | |
if (exclude != null) { | |
return exclude.booleanValue(); | |
} | |
return false; | |
} | |
private String getOperationName(AnnotationMirror webMethod, MethodDeclaration methodDeclaration) { | |
String operationName = AnnotationUtils.getStringValue(webMethod, OPERATION_NAME); | |
if (operationName != null) { | |
return operationName; | |
} | |
return methodDeclaration.getSimpleName(); | |
} | |
@SuppressWarnings("unchecked") | |
private Service getService(Definition definition, QName serviceQName) { | |
Map servicesMap = definition.getServices(); | |
Set<Map.Entry> servicesSet = servicesMap.entrySet(); | |
for (Map.Entry<QName, Service> serviceEntry : servicesSet) { | |
QName serviceEntryKey = serviceEntry.getKey(); | |
if (serviceEntryKey.equals(serviceQName)) { | |
return serviceEntry.getValue(); | |
} | |
} | |
return null; | |
} | |
@SuppressWarnings("unchecked") | |
private Port getPort(Service service, String portName) { | |
Map portsMap = service.getPorts(); | |
Set<Map.Entry> portsSet = portsMap.entrySet(); | |
for (Map.Entry<String, Port> portEntry : portsSet) { | |
String portEntryKey = portEntry.getKey(); | |
if (portEntryKey.equals(portName)) { | |
return portEntry.getValue(); | |
} | |
} | |
return null; | |
} | |
private QName getServiceQName(AnnotationMirror webService, ClassDeclaration classDeclaration) { | |
String serviceName = AnnotationUtils.getStringValue(webService, SERVICE_NAME); | |
if (serviceName == null) { | |
serviceName = classDeclaration.getSimpleName() + SERVICE_SUFFIX; | |
} | |
return new QName(getTargetNamespace(webService, classDeclaration), serviceName); | |
} | |
private String getPortName(AnnotationMirror webService, ClassDeclaration classDeclaration) { | |
String portName = AnnotationUtils.getStringValue(webService, PORT_NAME); | |
if (portName == null) { | |
portName = classDeclaration.getSimpleName() + PORT_SUFFIX; | |
} | |
return portName; | |
} | |
private String getTargetNamespace(AnnotationMirror webService, ClassDeclaration classDeclaration) { | |
String targetNamespace = AnnotationUtils.getStringValue(webService, TARGET_NAMESPACE); | |
if (targetNamespace == null) { | |
targetNamespace = JDTUtils.getTargetNamespaceFromPackageName( | |
classDeclaration.getPackage().getQualifiedName()); | |
} | |
return targetNamespace; | |
} | |
} |