/******************************************************************************* * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved. * 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 *******************************************************************************/ package org.ebayopensource.turmeric.tools.codegen.builders; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.wsdl.Definition; import javax.wsdl.WSDLException; import javax.xml.namespace.QName; import org.ebayopensource.turmeric.runtime.common.impl.utils.LogManager; import org.ebayopensource.turmeric.tools.codegen.CodeGenContext; import org.ebayopensource.turmeric.tools.codegen.CodeGenInfoFinder; import org.ebayopensource.turmeric.tools.codegen.InputOptions; import org.ebayopensource.turmeric.tools.codegen.SourceGenerator; import org.ebayopensource.turmeric.tools.codegen.InputOptions.InputType; import org.ebayopensource.turmeric.tools.codegen.exception.CodeGenFailedException; import org.ebayopensource.turmeric.tools.codegen.exception.PreProcessFailedException; import org.ebayopensource.turmeric.tools.codegen.external.WSDLUtil; import org.ebayopensource.turmeric.tools.codegen.util.CodeGenConstants; import org.ebayopensource.turmeric.tools.codegen.util.CodeGenUtil; /** * Service Meta data File generator. * * Generates the service_metadata.properties file. */ public class ServiceMetadataFileGenerator implements SourceGenerator { private static final String SERVICE_METADATA_FILE_DIR = "META-INF/soa/common/config"; private static final String SERVICE_METADATA_FILE_NAME = "service_metadata.properties"; private static final String SERVICE_INTF_PROP_FILE_NAME = "service_intf_project.properties"; private static Logger s_logger = LogManager.getInstance(ServiceMetadataFileGenerator.class); private static ServiceMetadataFileGenerator s_svcMetadataFileGenerator = new ServiceMetadataFileGenerator(); private ServiceMetadataFileGenerator() { } public static ServiceMetadataFileGenerator getInstance() { return s_svcMetadataFileGenerator; } private Logger getLogger() { return s_logger; } public boolean continueOnError() { return false; } public void generate(CodeGenContext codeGenCtx) throws CodeGenFailedException, WSDLException { InputOptions inputOptions = codeGenCtx.getInputOptions(); Properties svcMetadataProps = new Properties(); String serviceName = codeGenCtx.getInputOptions().getServiceName(); String namespace = inputOptions.getNamespace(); //These values need to be derived from service_intf_project.properties file. //location at <projectRoot>\service_intf_project.properties //should not use CodegenInfoFinder for reading this file since serviceName might chnage. Properties sipProperty = getvaluesFromSvcIntfPropertiesFile(codeGenCtx); String serviceAdminName = sipProperty.getProperty(CodeGenConstants.ADMIN_NAME,codeGenCtx.getServiceAdminName()); String serviceVersion =sipProperty.getProperty(CodeGenConstants.SERVICE_VERSION,inputOptions.getSvcCurrVersion()); String serviceLayer = sipProperty.getProperty(CodeGenConstants.SERVICE_LAYER, inputOptions.getServiceLayer()); String svcIntfClassName = sipProperty.getProperty(CodeGenConstants.SERVICE_INTF_CLASS_NAME); String wsdlUri = sipProperty.getProperty(CodeGenConstants.ORIGINAL_WSDL_URI); String namespacePart = sipProperty.getProperty(CodeGenConstants.SERVICE_NS_PART); String domainName = sipProperty.getProperty(CodeGenConstants.SVC_DOMAIN_NAME); String nonXSDFormats = sipProperty.getProperty(CodeGenConstants.NON_XSD_FORMATS); String supportZeroConfig = sipProperty.getProperty(CodeGenConstants.SUPPORT_ZERO_CONFIG); String wsdlLoc = inputOptions.getOriginalInputType() == InputType.WSDL ? inputOptions.getInputFile() : null; String serviceNameFromWsdl = serviceName; if (!CodeGenUtil.isEmptyString(wsdlLoc)) { // get ServiceName and namespace from wsdl. //overriding serviceName would lead to side effects like chnage in structure of smp try{ serviceNameFromWsdl = getFirstServiceNameFromWsdl(wsdlLoc,codeGenCtx); namespace = getTargetNamespacefromWsdl(wsdlLoc,codeGenCtx); }catch (PreProcessFailedException exception) { CodeGenFailedException codeGenFailedException = new CodeGenFailedException(exception.getMessage(), exception); codeGenFailedException.setMessageFormatted(true); throw codeGenFailedException; } } svcMetadataProps.put(CodeGenConstants.SERVICE_NAME,serviceNameFromWsdl); String serviceLocation = codeGenCtx.getInputOptions().getServiceLocation(); if(CodeGenUtil.isEmptyString(serviceLocation)){ Definition wsdlDefinition = codeGenCtx.getWsdlDefinition(); if(wsdlDefinition != null){ String[] serviceLocationsAvailable = CodeGenUtil.getServiceLocations(wsdlDefinition); if(serviceLocationsAvailable != null && serviceLocationsAvailable.length > 0) serviceLocation = serviceLocationsAvailable[0]; } } if(!CodeGenUtil.isEmptyString(serviceLocation)) svcMetadataProps.put(CodeGenConstants.SERVICE_LOCATION,serviceLocation); if(! CodeGenUtil.isEmptyString(namespacePart)) svcMetadataProps.put(CodeGenConstants.SERVICE_NS_PART, namespacePart); if(! CodeGenUtil.isEmptyString(domainName)) svcMetadataProps.put(CodeGenConstants.SVC_DOMAIN_NAME, domainName); //adminName should be put inside smp file only if it is post 2.4 project if(! CodeGenUtil.isEmptyString(sipProperty.getProperty(CodeGenConstants.SERVICE_VERSION))) svcMetadataProps.put(CodeGenConstants.ADMIN_NAME, serviceAdminName); //smp needs to be updated with smp_version String version = sipProperty.getProperty(CodeGenConstants.SVC_INTF_PROJECT_PROPERTIES_FILE_VERSION); if(! CodeGenUtil.isEmptyString(version)) svcMetadataProps.put(CodeGenConstants.SVC_CONSUMER_VERSION,version); svcMetadataProps.put(CodeGenConstants.SERVICE_VERSION, serviceVersion); svcMetadataProps.put(CodeGenConstants.SERVICE_LAYER, serviceLayer); svcMetadataProps.put(CodeGenConstants.ENABLE_NAMESPACE_FOLDING,Boolean.toString(inputOptions.isEnabledNamespaceFoldingSet())); if(! CodeGenUtil.isEmptyString(namespace)) svcMetadataProps.put(CodeGenConstants.SERVICE_NAMESPACE, namespace); if( ! CodeGenUtil.isEmptyString(inputOptions.getPublicServiceName())) svcMetadataProps.put(CodeGenConstants.PUBLIC_SERVICE_NAME, inputOptions.getPublicServiceName()); /* * for input type INTERFACE get the package and interface details from the -interface option * for other input types get the value from -gin and -gip options */ if(CodeGenUtil.isEmptyString(svcIntfClassName)){ if(inputOptions.getOriginalInputType() == InputType.INTERFACE ){ svcIntfClassName = CodeGenUtil.toQualifiedClassName(inputOptions.getInputFile()); } else { String inputPackageName = inputOptions.getGenInterfacePackage(); String inputInterfaceName = inputOptions.getGenInterfaceName(); if( ! ( CodeGenUtil.isEmptyString(inputPackageName) || CodeGenUtil.isEmptyString(inputInterfaceName) ) ) svcIntfClassName = inputPackageName + "." + inputInterfaceName ; } } //still svcIntfClassName might be null if(! CodeGenUtil.isEmptyString(svcIntfClassName)) svcMetadataProps.put(CodeGenConstants.SERVICE_INTF_CLASS_NAME, svcIntfClassName ); /* * Logic for deriving the Interface details * 1. get the value from -gin and -gip options * 2. if either/both -gin or -gip is null and the input type is INTERFACE then * try to derive the corresponding value from the value passed to "-interface" option */ /* String inputPackageName = inputOptions.getGenInterfacePackage(); String inputInterfaceName = inputOptions.getGenInterfaceName(); if( ! ( CodeGenUtil.isEmptyString(inputPackageName) || CodeGenUtil.isEmptyString(inputInterfaceName) ) ) { svcMetadataProps.put(CodeGenConstants.SERVICE_INTF_CLASS_NAME, inputPackageName + "." + inputInterfaceName ); } else if(inputOptions.getOriginalInputType() == InputType.INTERFACE ) { String inputInterface = CodeGenUtil.toQualifiedClassName(inputOptions.getInputFile()); String derivedPackageName = CodeGenUtil.getPackageName(inputInterface); if(CodeGenUtil.isEmptyString(inputPackageName)) inputPackageName = CodeGenUtil.getPackageName(inputInterface); if(CodeGenUtil.isEmptyString(inputInterfaceName)) inputInterfaceName = inputInterface.substring(derivedPackageName.length()+1,inputInterface.length()); svcMetadataProps.put(CodeGenConstants.SERVICE_INTF_CLASS_NAME, inputPackageName + "." + inputInterfaceName ); }*/ /* the following If statement has been based on the following things * a) only for gen type "ServiceMetadataProps" the service_metatdata.properties file would be created. * b) for gen type "ServiceMetadataProps", the pre-process logic wont be called */ if(inputOptions.getOriginalInputType() == InputType.WSDL ){ if(CodeGenUtil.isEmptyString(wsdlUri)){ if (!CodeGenUtil.isEmptyString(inputOptions.getInputFile())) wsdlUri = inputOptions.getInputFile(); } svcMetadataProps.put(CodeGenConstants.ORIGINAL_WSDL_URI, wsdlUri); } if(! CodeGenUtil.isEmptyString(nonXSDFormats)) svcMetadataProps.put(CodeGenConstants.NON_XSD_FORMATS, nonXSDFormats ); if(! CodeGenUtil.isEmptyString(supportZeroConfig)) svcMetadataProps.put(CodeGenConstants.SUPPORT_ZERO_CONFIG, supportZeroConfig ); generateSvcMetadataPropFile(svcMetadataProps, codeGenCtx); } private Properties getvaluesFromSvcIntfPropertiesFile(CodeGenContext ctx) throws CodeGenFailedException { Properties props = new Properties(); String root = ctx.getProjectRoot(); if(CodeGenUtil.isEmptyString(root)) root = ctx.getDestLocation(); String pathOfSiPFile = CodeGenUtil.toOSFilePath(root) + SERVICE_INTF_PROP_FILE_NAME; String SIPFilepath = CodeGenUtil.toOSFilePath(pathOfSiPFile); FileInputStream in = null; try { in = new FileInputStream(SIPFilepath); props.load(in); } catch (FileNotFoundException e) { s_logger.log(Level.WARNING,"Could not find service_intf_project.properties "); } catch (IOException e) { s_logger.log(Level.WARNING,"Could not load service_intf_project.properties "); } finally { CodeGenUtil.closeQuietly(in); } return props; } private void generateSvcMetadataPropFile( Properties svcMetadataProps, CodeGenContext codeGenCtx) throws CodeGenFailedException { OutputStream outputStream = null; InputOptions options = null; String mDestRootPath = null; try{ options = codeGenCtx.getInputOptions(); String projectRoot = options.getProjectRoot(); if(!CodeGenUtil.isEmptyString(projectRoot)){ mDestRootPath = projectRoot; } else { mDestRootPath = options.getMetaSrcDestLocation(); if(CodeGenUtil.isEmptyString(mDestRootPath) ) mDestRootPath = codeGenCtx.getDestLocation(); } String metaSrcPath = CodeGenUtil.toOSFilePath(mDestRootPath) + CodeGenConstants.META_SRC_FOLDER; String genMetaSrcPath; if( InputOptions.DEFAULT_DIR.equals( codeGenCtx.getMetaSrcDestLocation()) ) { // Default Dir genMetaSrcPath = CodeGenUtil.toOSFilePath(mDestRootPath) + CodeGenConstants.GEN_META_SRC_FOLDER; } else { // Specified Dir genMetaSrcPath = codeGenCtx.getMetaSrcDestLocation(); } String destFolderPath = CodeGenUtil.genDestFolderPath( metaSrcPath, codeGenCtx.getServiceAdminName(), SERVICE_METADATA_FILE_DIR); String smpFileLocation = destFolderPath + File.separatorChar + SERVICE_METADATA_FILE_NAME; File smpFile = new File(smpFileLocation); // if serviceIntf project is pre 2.4 i.e smp exists in older path, it should not be regenerated. if(smpFile.exists()) return; else //chnage the path for smp file if it does not exist in older path destFolderPath = CodeGenUtil.genDestFolderPath( genMetaSrcPath, codeGenCtx.getServiceAdminName(), SERVICE_METADATA_FILE_DIR); outputStream = CodeGenUtil.getFileOutputStream(destFolderPath, SERVICE_METADATA_FILE_NAME); svcMetadataProps.store(outputStream, "*** Generated file, any changes will be lost upon regeneration ***"); getLogger().log(Level.INFO, "Successfully generated " + SERVICE_METADATA_FILE_NAME + " under " + destFolderPath); //calling to update the properties map try{ CodeGenInfoFinder.updateMetaDataMap(options); }catch(Exception exception){ String errMsg = "Could not update the properties Map"; getLogger().log(Level.WARNING, errMsg, exception); } //not required to delte this file from now on //check for the old properties file under gen-meta-src and delete the same since we now have the new one generated under meta-src // String oldDestFolderPath = // CodeGenUtil.genDestFolderPath( // fileToBeDeletedInPath, // codeGenCtx.getServiceAdminName(), // SERVICE_METADATA_FILE_DIR); // // String oldPropertiesFilePath = CodeGenUtil.normalizePath(oldDestFolderPath) + SERVICE_METADATA_FILE_NAME; // try{ // CodeGenUtil.deleteFile(new File(oldPropertiesFilePath)); // // }catch(IOException iEx) { // String errMsg = "Failed to delete the old properties file : " + oldPropertiesFilePath; // getLogger().log(Level.INFO, errMsg, iEx); // } } catch (IOException ioEx) { String errMsg = "Failed to generate : " + SERVICE_METADATA_FILE_NAME; getLogger().log(Level.SEVERE, errMsg, ioEx); throw new CodeGenFailedException(errMsg, ioEx); } finally { CodeGenUtil.closeQuietly(outputStream); } } public String getTargetNamespacefromWsdl(String wsdlLoc,CodeGenContext ctx) throws WSDLException, PreProcessFailedException { Definition wsdldef = ctx.getWsdlDefinition()!=null?ctx.getWsdlDefinition() :WSDLUtil.getWSDLDefinition(wsdlLoc); ctx.setWsdlDefinition(wsdldef); return wsdldef.getTargetNamespace(); } public String getFirstServiceNameFromWsdl(String wsdlLoc,CodeGenContext ctx) throws WSDLException, PreProcessFailedException { Definition wsdldef = ctx.getWsdlDefinition()!=null ? ctx.getWsdlDefinition() :WSDLUtil.getWSDLDefinition(wsdlLoc); //Wsdl might have various services. Return one of the serviceName //codegen supports single service currently. @SuppressWarnings("unchecked") Map<QName, String> serviceMap = wsdldef.getServices(); Set<QName> qnameSet = serviceMap.keySet(); Iterator<QName> iterator = qnameSet.iterator(); return iterator.next().getLocalPart(); } public String getFilePath(String serviceAdminName, String interfaceName) { String filePath = CodeGenUtil.toOSFilePath(SERVICE_METADATA_FILE_DIR)+ serviceAdminName + File.separatorChar + SERVICE_METADATA_FILE_NAME ; return filePath; } }