/* * gvNIX is an open source tool for rapid application development (RAD). * Copyright (C) 2010 Generalitat Valenciana * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program 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 for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ package org.gvnix.service.roo.addon.addon.ws.export; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import java.util.logging.Logger; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.gvnix.service.roo.addon.addon.JavaParserService; import org.gvnix.service.roo.addon.addon.security.SecurityService; import org.gvnix.service.roo.addon.addon.util.WsdlParserUtils; import org.gvnix.service.roo.addon.addon.ws.WSCompilationUnit; import org.gvnix.service.roo.addon.addon.ws.WSConfigService; import org.gvnix.service.roo.addon.annotations.GvNIXWebService; import org.gvnix.service.roo.addon.annotations.GvNIXXmlElement; import org.springframework.roo.classpath.PhysicalTypeCategory; import org.springframework.roo.classpath.PhysicalTypeIdentifier; import org.springframework.roo.classpath.details.ConstructorMetadata; import org.springframework.roo.classpath.details.FieldMetadata; import org.springframework.roo.classpath.details.MethodMetadata; import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue; import org.springframework.roo.classpath.details.annotations.AnnotationMetadata; import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder; import org.springframework.roo.classpath.details.annotations.BooleanAttributeValue; import org.springframework.roo.classpath.details.annotations.EnumAttributeValue; import org.springframework.roo.classpath.details.annotations.StringAttributeValue; import org.springframework.roo.file.monitor.NotifiableFileMonitorService; import org.springframework.roo.file.monitor.event.FileDetails; import org.springframework.roo.model.EnumDetails; import org.springframework.roo.model.JavaPackage; import org.springframework.roo.model.JavaSymbolName; import org.springframework.roo.model.JavaType; import org.springframework.roo.process.manager.FileManager; import org.springframework.roo.project.LogicalPath; import org.springframework.roo.project.Path; import org.springframework.roo.project.ProjectOperations; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.github.antlrjavaparser.JavaParser; import com.github.antlrjavaparser.ParseException; import com.github.antlrjavaparser.api.CompilationUnit; import com.github.antlrjavaparser.api.PackageDeclaration; import com.github.antlrjavaparser.api.body.BodyDeclaration; import com.github.antlrjavaparser.api.body.ClassOrInterfaceDeclaration; import com.github.antlrjavaparser.api.body.ConstructorDeclaration; import com.github.antlrjavaparser.api.body.EnumConstantDeclaration; import com.github.antlrjavaparser.api.body.EnumDeclaration; import com.github.antlrjavaparser.api.body.FieldDeclaration; import com.github.antlrjavaparser.api.body.MethodDeclaration; import com.github.antlrjavaparser.api.body.TypeDeclaration; import com.github.antlrjavaparser.api.expr.AnnotationExpr; import com.github.antlrjavaparser.api.expr.FieldAccessExpr; import com.github.antlrjavaparser.api.expr.MarkerAnnotationExpr; import com.github.antlrjavaparser.api.expr.MemberValuePair; import com.github.antlrjavaparser.api.expr.NormalAnnotationExpr; import com.github.antlrjavaparser.api.expr.SingleMemberAnnotationExpr; import com.github.antlrjavaparser.api.expr.StringLiteralExpr; import com.github.antlrjavaparser.api.type.ClassOrInterfaceType; /** * @author <a href="http://www.disid.com">DISID Corporation S.L.</a> made for <a * href="http://www.dgti.gva.es">General Directorate for Information * Technologies (DGTI)</a> */ @Component @Service public class WSExportWsdlConfigServiceImpl implements WSExportWsdlConfigService { /* * Variables to store web files of web service generated by maven wsdl2java * plugin. TODO THIS IS NO THREAD-SAFE. EXTRACT IT to a process class and * identify in every WsExportWsdlListener call what process refers the file */ private List<File> xmlElements = new ArrayList<File>(); private List<File> webFaults = new ArrayList<File>(); private List<File> webServices = new ArrayList<File>(); private List<File> webServiceInterfaces = new ArrayList<File>(); private File schemaPackage = new File(""); static final String PACKAGE_INFO_FILE = "package-info.java"; static final String webService = "javax.jws.WebService"; static final String webServiceInterface = "WebService"; static final String soapBinding = "SOAPBinding"; static final String xmlRootElement = "XmlRootElement"; static final String xmlAccessorType = "XmlAccessorType"; static final String xmlType = "XmlType"; static final String xmlEnum = "XmlEnum"; static final String webFault = "WebFault"; @Reference private WSConfigService wSConfigService; @Reference private ProjectOperations projectOperations; @Reference private NotifiableFileMonitorService fileMonitorService; @Reference private SecurityService securityService; @Reference private WsExportWsdl wsExportWsdl; @Reference private FileManager fileManager; @Reference private JavaParserService javaParserService; protected static Logger logger = Logger .getLogger(WSExportWsdlConfigService.class.getName()); /** * {@inheritDoc} */ public void generateJavaFromWsdl(String wsdlLocation) { // Check if WSDL is RPC enconded and copy file to project Document wsdlDocument = checkWSDLFile(wsdlLocation); // Configure plugin cxf to generate java code using WSDL wSConfigService.addWsdlLocation(wsdlLocation, wsdlDocument); // Reset to generate file list resetGeneratedFilesList(); try { // Run maven generate-sources command wSConfigService.mvn(WSConfigService.GENERATE_SOURCES, WSConfigService.GENERATE_SOURCES_INFO); } catch (IOException e) { throw new IllegalStateException( "There is an error generating java sources with '" + wsdlLocation + "'.\n" + e.getMessage()); } // Remove plugin execution wSConfigService.disableWsdlLocation(); } /** * Get XML document representation from WSDL if valid. * <p> * Check WSDL is not RPC Encoded and has only one compatible port. * </p> * * @param url from WSDL file to export * @return XML document representation of WSDL */ protected Document checkWSDLFile(String url) { // Check URL connection and WSDL format Element root = securityService.getWsdl(url).getDocumentElement(); Validate.isTrue(!WsdlParserUtils.isRpcEncoded(root), "This Wsdl '" + url + "' is RPC Encoded and is not supported by the Add-on."); // Check if is compatible port defined with SOAP12 or SOAP11. WsdlParserUtils.checkCompatiblePort(root); return root.getOwnerDocument(); } /** * Reset files values. */ protected void resetGeneratedFilesList() { // Reset File List xmlElements = new ArrayList<File>(); webFaults = new ArrayList<File>(); webServices = new ArrayList<File>(); webServiceInterfaces = new ArrayList<File>(); schemaPackage = new File(""); } /** * {@inheritDoc} * <p> * Monitoring file creation only. * </p> */ public void monitorFolder(String folder) { // Get path to monitoring folder String path = projectOperations.getPathResolver().getIdentifier( LogicalPath.getInstance(Path.ROOT, ""), folder); resetGeneratedFilesList(); SortedSet<FileDetails> files = fileMonitorService .findMatchingAntPath(path + "/**"); for (FileDetails file : files) { parseFile(file.getFile()); } } /** * Parse target file for src generation when is valid. * <p> * Consider only when: * </p> * <ul> * <li>File is not a directory and included on generated sources dir</li> * </ul> * <p> * Include file for generation when is a package info file (special * generated java file). Or check file first java type first valid * annotation type and name if type is a class, interface or enumeration: * </p> * <p> * Only files with valid annotations will be included * {@link WSExportWsdlImpl#includeFileValidAnnot(File, AnnotationExpr, TypeDeclaration)} * </p> * * @param file File **/ protected void parseFile(File file) { // Is not a directory and is included on generated sources dir if (file.getAbsolutePath().contains(wsExportWsdl.getGenSourcesDir()) && !file.isDirectory()) { // When is a package info file (special generated java file) if (file.getName().contentEquals(PACKAGE_INFO_FILE)) { setSchemaPackageInfoFile(file); return; } try { // Get java types from java file List<TypeDeclaration> types = JavaParser.parse(file).getTypes(); if (types != null) { // Get fist java type TypeDeclaration type = types.get(0); // If java type is a class, interface or enumeration if ((type instanceof ClassOrInterfaceDeclaration) || (type instanceof EnumDeclaration)) { logger.fine(file.getAbsolutePath()); // First valid annot type and name include generate for (AnnotationExpr annot : type.getAnnotations()) { if (includeFileValidAnnot(file, annot, type)) { break; } } } } } catch (ParseException e) { throw new IllegalStateException( "Generated web service java file has errors:\n" + e.getMessage()); } catch (IOException e) { e.printStackTrace(); throw new IllegalStateException( "Generated web service java file has errors:\n" + e.getMessage()); } } } /** * Updates package info file location. <b>For {@link WSExportWsdlImpl} uses * only</b> * * @param schemaPackageInfoFile File absolute path. */ private void setSchemaPackageInfoFile(File schemaPackageInfoFile) { this.schemaPackage = schemaPackageInfoFile; } /** * When annotation has a valid class and name, include file for generation. * <ul> * <li>Xml root element or xml accessor type: include file for xml element * generation</li> * <li>Web fault: include file for web fault generation</li> * <li>Web service: include file for web service generation * <li>Web service interface: include file for web service interface * generation</li> * <li>Xml enum: include file for xml element generation</li> * </ul> * <p> * Only files with valid annotations names will be included * {@link WSExportWsdlImpl#includeFileValidAnnotName(File, TypeDeclaration, String)} * </p> * * @param file Generated file * @param annot File type annotation * @param type File type * @return Is valid annotation class and name included for generation ? */ private boolean includeFileValidAnnot(File file, AnnotationExpr annot, TypeDeclaration type) { if (annot instanceof NormalAnnotationExpr) { return includeFileValidAnnotName(file, type, ((NormalAnnotationExpr) annot).getName().toString()); } else if (annot instanceof MarkerAnnotationExpr) { return includeFileValidAnnotName(file, type, ((MarkerAnnotationExpr) annot).getName().toString()); } else if (annot instanceof SingleMemberAnnotationExpr) { return includeFileValidAnnotName(file, type, ((SingleMemberAnnotationExpr) annot).getName().toString()); } return false; } /** * When annotation has a valid name, include file for generation. * <ul> * <li>Xml root element or xml accessor type: include file for xml element * generation</li> * <li>Web fault: include file for web fault generation</li> * <li>Web service: include file for web service generation</li> * <li>Web service interface: include file for web service interface * generation</li> * <li>Xml enum: include file for xml element generation</li> * </ul> * * @param file Generated file * @param annot File type annotation * @param name Annotation name * @return Is valid annotation name included for generation ? */ private boolean includeFileValidAnnotName(File file, TypeDeclaration type, String name) { if (name.equals(xmlRootElement) || name.equals(xmlAccessorType)) { addFileToUpdateAnnotation(file, GvNIXAnnotationType.XML_ELEMENT); return true; } else if (name.equals(webFault)) { addFileToUpdateAnnotation(file, GvNIXAnnotationType.WEB_FAULT); return true; } else if (name.equals(webService)) { addFileToUpdateAnnotation(file, GvNIXAnnotationType.WEB_SERVICE); return true; } else if (name.equals(webServiceInterface)) { addFileToUpdateAnnotation(file, GvNIXAnnotationType.WEB_SERVICE_INTERFACE); return true; } else if (name.equals(xmlEnum)) { addFileToUpdateAnnotation(file, GvNIXAnnotationType.XML_ELEMENT); return true; } return false; } /** * Updates list of files generated to update with '@gvNIX' annotations. * <b>For {@link WSExportWsdlImpl} uses only</b> * * @param file scanned to add to list. * @param gvNIXAnnotationType to select the list where add the file. */ private void addFileToUpdateAnnotation(File file, GvNIXAnnotationType gvNIXAnnotationType) { switch (gvNIXAnnotationType) { case XML_ELEMENT: xmlElements.add(file); break; case WEB_FAULT: webFaults.add(file); break; case WEB_SERVICE: webServices.add(file); break; case WEB_SERVICE_INTERFACE: webServiceInterfaces.add(file); break; } } /** * {@inheritDoc} */ public List<JavaType> createGvNixClasses() { // Create java classes with @GvNIXXmlElement annotation createGvNixXmlElementsClasses(); // Create java classes with @GvNIXWebFault annotation createGvNixWebFaultClasses(); // Create java classes with @GvNIXWebService annotation return createGvNixWebServiceClasses(); } /** * Create in 'src/main/java' gvNIX xml elements from wsdl2java classes list. * <p> * The wsdl2java classes list are registered by {@link WSExportWsdlImpl} * </p> */ protected void createGvNixXmlElementsClasses() { for (File file : xmlElements) { // File directory String path = file.getAbsolutePath(); path = path.substring(0, path.lastIndexOf(File.separator) + 1); try { // Get first type from java file CompilationUnit compUnit = JavaParser.parse(file); List<TypeDeclaration> types = compUnit.getTypes(); if (types != null) { createGvNixXmlElementClass(types.get(0), compUnit, path); } } catch (ParseException e) { throw new IllegalStateException( "Generated Xml Element service java file '" + file.getAbsolutePath() + "' has errors:\n" + e.getMessage()); } catch (IOException e) { throw new IllegalStateException( "Generated Xml Element service java file '" + file.getAbsolutePath() + "' has errors:\n" + e.getMessage()); } } // Copy 'package-info.java' from generated to sources folder createPackageInfoClass(); } /** * <p> * Creates web service fail java files in 'src/main/java' from result of * wsdl2java plugin. In addition, adds @GvNIXWebService annotation. * </p> * <p> * This files will be registered by {@link WSExportWsdlImpl} * </p> * TODO to be removed from interface. This method need a sequence of * operations to be useful. */ protected void createGvNixWebFaultClasses() { List<AnnotationMetadata> gvNixAnnotationList; // GvNIXWebFault annotation. AnnotationMetadata gvNIXWebFaultAnnotation; for (File webFaultFile : webFaults) { // Parse Java file. CompilationUnit compilationUnit; PackageDeclaration packageDeclaration; JavaType javaType; String declaredByMetadataId; // CompilationUnitServices to create the class in fileSystem. WSCompilationUnit compilationUnitServices; gvNixAnnotationList = new ArrayList<AnnotationMetadata>(); try { compilationUnit = JavaParser.parse(webFaultFile); packageDeclaration = compilationUnit.getPackage(); String packageName = packageDeclaration.getName().toString(); // Get the first class or interface Java type List<TypeDeclaration> types = compilationUnit.getTypes(); if (types != null) { TypeDeclaration type = types.get(0); ClassOrInterfaceDeclaration classOrInterfaceDeclaration; if (type instanceof ClassOrInterfaceDeclaration) { javaType = new JavaType(packageName.concat(".").concat( type.getName())); classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration) type; declaredByMetadataId = PhysicalTypeIdentifier .createIdentifier(javaType, LogicalPath .getInstance(Path.SRC_MAIN_JAVA, "")); // Retrieve correct values. // Get field declarations. List<FieldMetadata> fieldMetadataList = new ArrayList<FieldMetadata>(); List<ConstructorMetadata> constructorMetadataList = new ArrayList<ConstructorMetadata>(); List<MethodMetadata> methodMetadataList = new ArrayList<MethodMetadata>(); // Extended classes. List<JavaType> extendedClassesList = new ArrayList<JavaType>(); List<ClassOrInterfaceType> extendsClasses = classOrInterfaceDeclaration .getExtends(); JavaType extendedJavaType; for (ClassOrInterfaceType classOrInterfaceType : extendsClasses) { extendedJavaType = new JavaType( classOrInterfaceType.getName()); extendedClassesList.add(extendedJavaType); } // CompilationUnitServices to create the class. compilationUnitServices = new WSCompilationUnit( new JavaPackage(compilationUnit.getPackage() .getName().toString()), javaType, compilationUnit.getImports(), new ArrayList<TypeDeclaration>(), PhysicalTypeCategory.CLASS); for (BodyDeclaration bodyDeclaration : classOrInterfaceDeclaration .getMembers()) { if (bodyDeclaration instanceof FieldDeclaration) { wsExportWsdl.loadFaultFieldDeclaration( declaredByMetadataId, compilationUnitServices, fieldMetadataList, bodyDeclaration); } else if (bodyDeclaration instanceof ConstructorDeclaration) { wsExportWsdl.loadFaultConstructorDeclaration( declaredByMetadataId, compilationUnitServices, constructorMetadataList, bodyDeclaration); } else if (bodyDeclaration instanceof MethodDeclaration) { wsExportWsdl.loadFaultMethodDeclaration( declaredByMetadataId, compilationUnitServices, methodMetadataList, (MethodDeclaration) bodyDeclaration); } } // GvNIXWebFault Annotation.Get all annotations. gvNIXWebFaultAnnotation = wsExportWsdl .getGvNIXWebFaultAnnotation( classOrInterfaceDeclaration, javaType); gvNixAnnotationList.add(gvNIXWebFaultAnnotation); javaParserService.createGvNixWebServiceClass(javaType, gvNixAnnotationList, GvNIXAnnotationType.WEB_FAULT, fieldMetadataList, methodMetadataList, constructorMetadataList, extendedClassesList, PhysicalTypeCategory.CLASS, null); } } } catch (ParseException e) { throw new IllegalStateException( "Generated Web Fault service Element java file '" + webFaultFile.getAbsolutePath() + "' has errors:\n" + e.getMessage()); } catch (IOException e) { throw new IllegalStateException( "Generated Web Fault service Element java file '" + webFaultFile.getAbsolutePath() + "' has errors:\n" + e.getMessage()); } } } /** * <p> * Creates web service java files in 'src/main/java' from result of * wsdl2java plugin. In addition, adds @GvNIXWebService annotation. * </p> * <p> * This files will be registered by {@link WSExportWsdlImpl} * </p> * TODO to be removed from interface. This method need a sequence of * operations to be useful. * * @return implementation class list */ protected List<JavaType> createGvNixWebServiceClasses() { List<AnnotationMetadata> gvNixAnnotationList; List<JavaType> implementationClasses = new ArrayList<JavaType>(); // GvNIXWebService annotation. AnnotationMetadata gvNIXWebServiceAnnotation; for (File webServiceFile : webServices) { // Parse Java file. CompilationUnit compilationUnit; PackageDeclaration packageDeclaration; JavaType javaType; String declaredByMetadataId; // CompilationUnitServices to create the class in fileSystem. WSCompilationUnit compilationUnitServices; gvNixAnnotationList = new ArrayList<AnnotationMetadata>(); try { compilationUnit = JavaParser.parse(webServiceFile); packageDeclaration = compilationUnit.getPackage(); String packageName = packageDeclaration.getName().toString(); List<TypeDeclaration> types = compilationUnit.getTypes(); if (types == null) { // nothing to do return implementationClasses; } // Get the first class or interface Java type TypeDeclaration type = types.get(0); ClassOrInterfaceDeclaration classOrInterfaceDeclaration; ClassOrInterfaceDeclaration implementedInterface; if (type instanceof ClassOrInterfaceDeclaration) { javaType = new JavaType(packageName.concat(".").concat( type.getName())); classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration) type; declaredByMetadataId = PhysicalTypeIdentifier .createIdentifier(javaType, LogicalPath .getInstance(Path.SRC_MAIN_JAVA, "")); // Retrieve implemented interface. implementedInterface = getWebServiceInterface(classOrInterfaceDeclaration); // Retrieve correct values. // Get field declarations. List<FieldMetadata> fieldMetadataList = new ArrayList<FieldMetadata>(); List<ConstructorMetadata> constructorMetadataList = new ArrayList<ConstructorMetadata>(); List<MethodMetadata> methodMetadataList = new ArrayList<MethodMetadata>(); // Extended classes. List<JavaType> extendedClassesList = new ArrayList<JavaType>(); // CompilationUnitServices to create the class. compilationUnitServices = new WSCompilationUnit( new JavaPackage(compilationUnit.getPackage() .getName().toString()), javaType, compilationUnit.getImports(), new ArrayList<TypeDeclaration>(), PhysicalTypeCategory.CLASS); // GvNIXWebFault Annotation.Get all annotations. gvNIXWebServiceAnnotation = getGvNIXWebServiceAnnotation( classOrInterfaceDeclaration, implementedInterface, javaType); gvNixAnnotationList.add(gvNIXWebServiceAnnotation); // Default Web Service Namespace. AnnotationAttributeValue<?> tarNamespaceAnnAttrVal = gvNIXWebServiceAnnotation .getAttribute(new JavaSymbolName("targetNamespace")); String defaultNamespace = ((StringAttributeValue) tarNamespaceAnnAttrVal) .getValue(); // @GvNIXWebMethod annotations. for (BodyDeclaration bodyDeclaration : classOrInterfaceDeclaration .getMembers()) { if (bodyDeclaration instanceof FieldDeclaration) { wsExportWsdl.loadWebServiceFieldDeclaration( declaredByMetadataId, compilationUnitServices, fieldMetadataList, bodyDeclaration); } else if (bodyDeclaration instanceof MethodDeclaration) { wsExportWsdl.loadWebServiceMethodDeclaration( declaredByMetadataId, compilationUnitServices, implementedInterface, methodMetadataList, defaultNamespace, bodyDeclaration); } } javaParserService.createGvNixWebServiceClass(javaType, gvNixAnnotationList, GvNIXAnnotationType.WEB_SERVICE, fieldMetadataList, methodMetadataList, constructorMetadataList, extendedClassesList, PhysicalTypeCategory.CLASS, null); implementationClasses.add(javaType); } } catch (ParseException e) { throw new IllegalStateException( "Generated Web Service java file '" + webServiceFile.getAbsolutePath() + "' has errors:\n" + e.getMessage()); } catch (IOException e) { e.printStackTrace(); throw new IllegalStateException( "Generated Web Service java file '" + webServiceFile.getAbsolutePath() + "' has errors:\n" + e.getMessage()); } } return implementationClasses; } /** * Generate declared java type classes and its inner types from declaration. * * @param typeDecl class to convert to JavaType * @param compUnit Values from class to check * @param fileDir to check 'package-info.java' annotation values */ private void createGvNixXmlElementClass(TypeDeclaration typeDecl, CompilationUnit compUnit, String fileDir) { // Compilation unit package String pkg = compUnit.getPackage().getName().toString(); // Java type to generate from JavaType type = new JavaType(pkg.concat(".").concat(typeDecl.getName())); // Initial values for gvNIX xml element annotation creation PhysicalTypeCategory physicalTypeCategory = PhysicalTypeCategory.CLASS; List<JavaSymbolName> enumConstants = new ArrayList<JavaSymbolName>(); boolean isEnum = typeDecl instanceof EnumDeclaration; List<FieldMetadata> fields = new ArrayList<FieldMetadata>(); if (isEnum) { // Type is an enumeration // Define physical type as enumeration physicalTypeCategory = PhysicalTypeCategory.ENUMERATION; // Add all enumeration constant entries names to a list for (EnumConstantDeclaration enumDecl : ((EnumDeclaration) typeDecl) .getEntries()) { enumConstants.add(new JavaSymbolName(enumDecl.getName())); } } else if (typeDecl instanceof ClassOrInterfaceDeclaration) { // Type is a class or interface // For each type member for (BodyDeclaration body : typeDecl.getMembers()) { if (body instanceof FieldDeclaration) { // Member is a field: add gvNIX xml element field annotation wsExportWsdl.loadFieldFromType(PhysicalTypeIdentifier .createIdentifier(type, LogicalPath.getInstance( Path.SRC_MAIN_JAVA, "")), new WSCompilationUnit(new JavaPackage(pkg), type, compUnit.getImports(), new ArrayList<TypeDeclaration>(), PhysicalTypeCategory.CLASS), fields, body); } else if (body instanceof ClassOrInterfaceDeclaration) { // Member is class or interface: add gvNIX xml element annot createGvNixXmlElementClass((TypeDeclaration) body, compUnit, fileDir); } } } List<AnnotationMetadata> annots = new ArrayList<AnnotationMetadata>(); // ROO annotation to generate get and set methods if is not an enum if (!isEnum) { annots.add(new AnnotationMetadataBuilder( new JavaType( "org.springframework.roo.addon.javabean.annotations.RooJavaBean"), new ArrayList<AnnotationAttributeValue<?>>()).build()); } // Create gvNIX xml element annotation and add it to list annots.add(getGvNixXmlElementAnnot(typeDecl)); // Create gvNIX web service type with annots, fields, type and enums javaParserService.createGvNixWebServiceClass(type, annots, GvNIXAnnotationType.XML_ELEMENT, fields, new ArrayList<MethodMetadata>(), new ArrayList<ConstructorMetadata>(), new ArrayList<JavaType>(), physicalTypeCategory, enumConstants); } /** * Copy package info file from generated folder to sources folder. */ private void createPackageInfoClass() { // If schema package file exists if (schemaPackage.exists()) { try { // Schema package file absolute path String path = schemaPackage.getAbsolutePath(); // Remove sources dir folder prefix path = StringUtils.remove( path, projectOperations.getPathResolver().getIdentifier( LogicalPath.getInstance(Path.ROOT, ""), WsExportWsdl.GENERATED_CXF_SOURCES_DIR)); // Create file into sources folder at same location fileManager.createOrUpdateTextFileIfRequired( projectOperations.getPathResolver() .getIdentifier( LogicalPath.getInstance( Path.SRC_MAIN_JAVA, ""), path), IOUtils.toString(new InputStreamReader( new FileInputStream(schemaPackage))), true); } catch (FileNotFoundException e) { throw new IllegalStateException( "Generated 'package-info.java' file '" + schemaPackage.getAbsolutePath() + "' doesn't exist:\n" + e.getMessage()); } catch (IOException e) { throw new IllegalStateException( "Generated 'package-info.java' file '" + schemaPackage.getAbsolutePath() + "' has errors:\n" + e.getMessage()); } } } /** * Retrieve Web Service implemented interface from interface list. TODO to * be removed?. This method could be useless outside this service. * * @param classOrInterfaceDeclaration to retrieve its implemented interface. * @return {@link ClassOrInterfaceDeclaration} interface that implements * classOrInterfaceDeclaratio, null if not exists. * @throws IOException * @throws ParseException */ private ClassOrInterfaceDeclaration getWebServiceInterface( ClassOrInterfaceDeclaration classOrInterfaceDeclaration) throws ParseException, IOException { ClassOrInterfaceDeclaration implementedInterface = null; List<ClassOrInterfaceType> implementedInterfacesList = classOrInterfaceDeclaration .getImplements(); String interfaceName; String fileInterfaceName; CompilationUnit compilationUnit; TypeDeclaration type; for (ClassOrInterfaceType classOrInterfaceType : implementedInterfacesList) { interfaceName = classOrInterfaceType.getName(); interfaceName = interfaceName.concat(".java"); for (File interfaceFile : webServiceInterfaces) { fileInterfaceName = wsExportWsdl.getFilename(interfaceFile .getAbsolutePath()); if (!fileInterfaceName.contentEquals(interfaceName)) { continue; } compilationUnit = JavaParser.parse(interfaceFile); List<TypeDeclaration> types = compilationUnit.getTypes(); if (types == null) { continue; } type = types.get(0); if (type instanceof ClassOrInterfaceDeclaration) { implementedInterface = (ClassOrInterfaceDeclaration) type; return implementedInterface; } } } return implementedInterface; } /** * Convert annotation @WebService values from * {@link ClassOrInterfaceDeclaration} to {@link GvNIXWebService}. TODO to * be removed from interface?. This method could be useless outside this * service. * * @param classOrInterfaceDeclaration to retrieve values from @WebService * annotations and convert to {@link GvNIXWebService} values. * @param implementedInterface Web Service interface. * @param javaType to retrieve mandatory Annotation attributed with its * values. * @return {@link GvNIXWebService} to define in class. */ private AnnotationMetadata getGvNIXWebServiceAnnotation( ClassOrInterfaceDeclaration classOrInterfaceDeclaration, ClassOrInterfaceDeclaration implementedInterface, JavaType javaType) { AnnotationMetadata gvNIXWServAnnMdata; List<AnnotationAttributeValue<?>> gvNIXWServAnnAttr = new ArrayList<AnnotationAttributeValue<?>>(); /* * Class: * * @javax.jws.WebService( serviceName = "TempConvert", portName = * "TempConvertSoap12", targetNamespace = "http://tempuri.org/", * wsdlLocation = * "http://www.w3schools.com/webservices/tempconvert.asmx?WSDL", * endpointInterface = "org.tempuri.TempConvertSoap") Interface: * * @WebService(targetNamespace = "http://tempuri.org/", name = * "TempConvertSoap") Result: * * @WebService(name = "TempConvertSoap",portName = "TempConvertSoap12", * targetNamespace = "http://tempuri.org/", serviceName = * "TempConvert"); * * @WebService(targetNamespace = * "http://fps.amazonaws.com/doc/2008-09-17/", name = * "AmazonFPSPortType") * * @XmlSeeAlso({ObjectFactory.class}) * * @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) */ /* * @GvNIXWebService address = X name. */ // Search for interface annotation attribute values. List<AnnotationExpr> annotationInterfaceExprList = implementedInterface .getAnnotations(); for (AnnotationExpr annotationExpr : annotationInterfaceExprList) { if (annotationExpr instanceof NormalAnnotationExpr) { NormalAnnotationExpr normalAnnotationExpr = (NormalAnnotationExpr) annotationExpr; StringAttributeValue addressStringAttributeValue; if (normalAnnotationExpr.getName().getName() .contains(webServiceInterface)) { // Retrieve values. for (MemberValuePair pair : normalAnnotationExpr.getPairs()) { if (pair.getName().contentEquals("name")) { // address addressStringAttributeValue = new StringAttributeValue( new JavaSymbolName("name"), ((StringLiteralExpr) pair.getValue()) .getValue()); gvNIXWServAnnAttr.add(addressStringAttributeValue); break; } } } else if (normalAnnotationExpr.getName().getName() .contains(soapBinding)) { for (MemberValuePair pair : normalAnnotationExpr.getPairs()) { EnumAttributeValue enumparamStyleAttrVal; // TODO this is dead code, to Remove it or it's a bug?? // enumparameterStyleAttributeValue = new // EnumAttributeValue( // new JavaSymbolName("parameterStyle"), // new EnumDetails( // new JavaType( // "org.gvnix.service.roo.addon.annotations.GvNIXWebService.GvNIXWebServiceParameterStyle"), // new JavaSymbolName("WRAPPED"))); if (pair.getName().contentEquals("parameterStyle")) { enumparamStyleAttrVal = new EnumAttributeValue( new JavaSymbolName("parameterStyle"), new EnumDetails( new JavaType( "org.gvnix.service.roo.addon.annotations.GvNIXWebService.GvNIXWebServiceParameterStyle"), new JavaSymbolName( ((FieldAccessExpr) pair .getValue()) .getField()))); gvNIXWServAnnAttr.add(enumparamStyleAttrVal); } } } } } /* * @GvNIXWebService name = class portName. serviceName = class * serviceName. targetNamespace = class targetNamespace. */ List<AnnotationExpr> annotationExprList = classOrInterfaceDeclaration .getAnnotations(); for (AnnotationExpr annotationExpr : annotationExprList) { if (annotationExpr instanceof NormalAnnotationExpr) { NormalAnnotationExpr normalAnnotationExpr = (NormalAnnotationExpr) annotationExpr; StringAttributeValue nameStringAttributeValue; StringAttributeValue tarNamespaceStrAttrVal; StringAttributeValue servNameStrAttrVal; // Retrieve values. for (MemberValuePair pair : normalAnnotationExpr.getPairs()) { if (pair.getName().contentEquals("serviceName")) { // serviceName servNameStrAttrVal = new StringAttributeValue( new JavaSymbolName("serviceName"), ((StringLiteralExpr) pair.getValue()) .getValue()); gvNIXWServAnnAttr.add(servNameStrAttrVal); continue; } else if (pair.getName().contentEquals("targetNamespace")) { // targetNamespace tarNamespaceStrAttrVal = new StringAttributeValue( new JavaSymbolName("targetNamespace"), ((StringLiteralExpr) pair.getValue()) .getValue()); gvNIXWServAnnAttr.add(tarNamespaceStrAttrVal); continue; } else if (pair.getName().contentEquals("portName")) { // name nameStringAttributeValue = new StringAttributeValue( new JavaSymbolName("address"), ((StringLiteralExpr) pair.getValue()) .getValue()); gvNIXWServAnnAttr.add(nameStringAttributeValue); continue; } } } } // fullyQualifiedTypeName StringAttributeValue fullyQualStrAttrVal = new StringAttributeValue( new JavaSymbolName("fullyQualifiedTypeName"), javaType.getFullyQualifiedTypeName()); gvNIXWServAnnAttr.add(fullyQualStrAttrVal); // exported BooleanAttributeValue exportedAttributeValue = new BooleanAttributeValue( new JavaSymbolName("exported"), true); gvNIXWServAnnAttr.add(exportedAttributeValue); // Create GvNIXWebService annotation. gvNIXWServAnnMdata = new AnnotationMetadataBuilder(new JavaType( GvNIXWebService.class.getName()), gvNIXWServAnnAttr).build(); return gvNIXWServAnnMdata; } /** * Convert annotation @XmlElement values to GvNIXXmlElement. * <p> * Searches for Jaxb annotations in {@link ClassOrInterfaceDeclaration} to * convert values to {@link GvNIXXmlElement}. * </p> * * @param typeDecl To retrieve values from @XmlElement annotations * @return {@link GvNIXXmlElement} to define in class */ private AnnotationMetadata getGvNixXmlElementAnnot(TypeDeclaration typeDecl) { // Attribute value list. List<AnnotationAttributeValue<?>> attrs = new ArrayList<AnnotationAttributeValue<?>>(); boolean isNamespace = false; boolean isPropOrder = false; for (AnnotationExpr typeAnnot : typeDecl.getAnnotations()) { if (typeAnnot instanceof NormalAnnotationExpr) { NormalAnnotationExpr normalAnnot = (NormalAnnotationExpr) typeAnnot; String name = normalAnnot.getName().getName(); List<MemberValuePair> pairs = normalAnnot.getPairs(); if (name.contains(xmlRootElement)) { // It's @XmlRootElement wsExportWsdl.addNameAttr(attrs, pairs); } else if (name.contains(xmlType)) { // It's @XmlType for (MemberValuePair pair : pairs) { if (pair.getName().contentEquals("name")) { // @XmlType.name wsExportWsdl.addXmlTypeNameAttr(attrs, pair); } else if (pair.getName().contentEquals("propOrder")) { // @XmlType.propOrder wsExportWsdl.addElementListAttr(attrs, pair); isPropOrder = true; } else if (pair.getName().contentEquals("namespace")) { // @XmlType.namespace wsExportWsdl.addNamespaceAttr(attrs, pair); isNamespace = true; } } } } } // Check correct values for @GvNIXXmlElement. if (!isPropOrder) { wsExportWsdl.addElementListAttr(attrs); } if (!isNamespace) { addNamespaceAttr(attrs); } wsExportWsdl.addExportedAttr(attrs); wsExportWsdl.addEnumElementAttr(typeDecl, attrs); // Create annotation return new AnnotationMetadataBuilder(new JavaType( GvNIXXmlElement.class.getName()), attrs).build(); } private void addNamespaceAttr(List<AnnotationAttributeValue<?>> annotAttrs) { try { String ns = ""; boolean exists = false; List<AnnotationExpr> annots = JavaParser.parse(schemaPackage) .getPackage().getAnnotations(); for (AnnotationExpr annot : annots) { if (annot instanceof NormalAnnotationExpr) { NormalAnnotationExpr normalAnnot = (NormalAnnotationExpr) annot; if (normalAnnot.getName().toString() .contains("javax.xml.bind.annotation.XmlSchema")) { // @XmlSchema for (MemberValuePair pair : normalAnnot.getPairs()) { if (pair.getName().contentEquals("namespace")) { ns = ((StringLiteralExpr) pair.getValue()) .getValue(); exists = true; break; } } } } if (exists) { break; } } // look for @XmlSchema annotAttrs.add(new StringAttributeValue(new JavaSymbolName( "namespace"), ns)); } catch (ParseException e) { throw new IllegalStateException( "Generated Xml Element service java file has errors:\n" + e.getMessage()); } catch (IOException e) { e.printStackTrace(); throw new IllegalStateException( "Generated Xml Element service java file has errors:\n" + e.getMessage()); } } }