/*******************************************************************************
* 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.eclipse.buildsystem.utils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.ebayopensource.turmeric.eclipse.codegen.model.GenTypeClientConfig;
import org.ebayopensource.turmeric.eclipse.codegen.model.GenTypeConsumer;
import org.ebayopensource.turmeric.eclipse.codegen.model.GenTypeServiceConfig;
import org.ebayopensource.turmeric.eclipse.codegen.model.GenTypeServiceMetadataProps;
import org.ebayopensource.turmeric.eclipse.codegen.utils.CodegenInvoker;
import org.ebayopensource.turmeric.eclipse.core.resources.constants.SOAProjectConstants;
import org.ebayopensource.turmeric.eclipse.repositorysystem.core.GlobalRepositorySystem;
import org.ebayopensource.turmeric.eclipse.repositorysystem.core.ISOAAssetRegistry;
import org.ebayopensource.turmeric.eclipse.repositorysystem.core.ISOAConfigurationRegistry;
import org.ebayopensource.turmeric.eclipse.repositorysystem.model.BaseCodeGenModel;
import org.ebayopensource.turmeric.eclipse.resources.model.AssetInfo;
import org.ebayopensource.turmeric.eclipse.resources.model.SOAConsumerMetadata;
import org.ebayopensource.turmeric.eclipse.resources.model.SOAConsumerProject;
import org.ebayopensource.turmeric.eclipse.resources.model.SOAImplProject;
import org.ebayopensource.turmeric.eclipse.resources.model.SOAIntfMetadata;
import org.ebayopensource.turmeric.eclipse.resources.model.SOAIntfProject;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAConsumerUtil;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAImplUtil;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAIntfUtil;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAServiceUtil;
import org.ebayopensource.turmeric.eclipse.utils.io.PropertiesFileUtil;
import org.ebayopensource.turmeric.eclipse.utils.plugin.EclipseMessageUtils;
import org.ebayopensource.turmeric.eclipse.utils.plugin.ProgressUtil;
import org.ebayopensource.turmeric.eclipse.utils.plugin.WorkspaceUtil;
import org.ebayopensource.turmeric.eclipse.utils.xml.FreeMarkerUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
/**
* Code Generation Engine. Most of the Code generation calls hit here this class
* and generates the the model required for calling codegen. Codegen invoker
* understands the intermediate model of these APIs. The Codegen invoker is
* finally called for real code generation.
*
* @author smathew
*
* @see CodegenInvoker
*
*/
public class BuildSystemCodeGen {
//private static final SOALogger logger = SOALogger.getLogger();
/**
* Generates the interface metadata properties file.
*
* @param intfProject the intf project
* @param nameSpace the name space
* @throws Exception the exception
*/
public static void generateServiceMetadataProperties(
SOAIntfProject intfProject, String nameSpace) throws Exception {
GenTypeServiceMetadataProps codeGenModel = new GenTypeServiceMetadataProps();
final SOAIntfMetadata metadata = intfProject.getMetadata();
if (metadata.getOriginalWSDLUrl() != null) {
codeGenModel.setOriginalWsdlUrl(metadata
.getOriginalWSDLUrl().toString());
}
codeGenModel.setAdminName(metadata.getServiceName());
codeGenModel.setNamespace(nameSpace);
codeGenModel.setProjectRoot(intfProject.getProject()
.getLocation().toString());
codeGenModel.setServiceName(metadata.getServiceName());
codeGenModel.setServiceVersion(metadata
.getServiceVersion());
codeGenModel.setServiceLayer(metadata
.getServiceLayer());
codeGenModel.setServiceInterface(metadata
.getServiceInterface());
CodegenInvoker codegenInvoker = CodegenInvoker.init(intfProject
.getProject());
codegenInvoker.execute(codeGenModel);
intfProject.getProject().getFolder(SOAProjectConstants.FOLDER_GEN_META_SRC).refreshLocal(IResource.DEPTH_INFINITE, null);
}
/**
* -scgn Service config group name -wsdl to get the QName of the service (
* iff -servicename is not used ) -sicn service impl class name -namespace
* -servicename -scv service version.
*
* @param implProject the impl project
* @throws Exception the exception
*/
public static void generateServiceConfigXml(final SOAImplProject implProject)
throws Exception {
GenTypeServiceConfig genTypeServiceConfig = new GenTypeServiceConfig();
final SOAIntfMetadata intfMetadata = implProject.getMetadata()
.getIntfMetadata();
genTypeServiceConfig.setNamespace(intfMetadata.getTargetNamespace());
genTypeServiceConfig.setServiceInterface(intfMetadata
.getServiceInterface());
genTypeServiceConfig.setServiceName(intfMetadata.getServiceName());
genTypeServiceConfig
.setServiceVersion(intfMetadata.getServiceVersion());
genTypeServiceConfig.setServiceImplClassName(implProject.getMetadata()
.getServiceImplClassName());
final IProject project = implProject.getProject();
genTypeServiceConfig.setSourceDirectory(project.getFolder(
SOAProjectConstants.FOLDER_SRC).getLocation().toString());
genTypeServiceConfig.setDestination(project.getLocation().toString());
genTypeServiceConfig.setOutputDirectory(project.getFolder(
SOAProjectConstants.CODEGEN_FOLDER_OUTPUT_DIR).getLocation()
.toString());
genTypeServiceConfig.setMetadataDirectory(project.getLocation()
.toString()
+ WorkspaceUtil.PATH_SEPERATOR
+ SOAProjectConstants.FOLDER_META_SRC);
final ISOAConfigurationRegistry config = GlobalRepositorySystem.instanceOf()
.getActiveRepositorySystem().getConfigurationRegistry();
genTypeServiceConfig.setServiceConfigGroup(config.getServiceConfigGroup());
// get the useExternalServiceFactory property value and set it to gen model.
IFile svcImplProperties = SOAImplUtil
.getServiceImplPropertiesFile(project);
if (svcImplProperties.isAccessible() == true) {
String useExternalFac = PropertiesFileUtil
.getPropertyValueByKey(
svcImplProperties.getContents(),
SOAProjectConstants.PROPS_KEY_USE_EXTERNAL_SERVICE_FACTORY);
genTypeServiceConfig.setUseExternalServiceFactory(Boolean
.valueOf(useExternalFac));
}
genTypeServiceConfig.setProjectRoot(implProject.getProject().getLocation().toFile().toString());
CodegenInvoker codegenInvoker = CodegenInvoker.init(project);
codegenInvoker.execute(genTypeServiceConfig);
project.refreshLocal(IResource.DEPTH_INFINITE, null);
}
/**
* Generates the Client Config xml.
*
* @param consumerProject the consumer project
* @param clientName the client name
* @param environments the environments
* @param addedServices the added services
* @return the gen type client config
* @throws Exception the exception
*/
public static GenTypeClientConfig generateGenTypeClientConfigXml(
final IProject consumerProject, final String clientName,
final List<String> environments,
final Collection<SOAIntfMetadata> addedServices) throws Exception {
final GenTypeClientConfig genTypeClientConfig = new GenTypeClientConfig();
// these are all the service related data
genTypeClientConfig.setSourceDirectory(consumerProject.getFolder(
SOAProjectConstants.FOLDER_SRC).getLocation().toString());
genTypeClientConfig.setDestination(consumerProject.getLocation()
.toString());
genTypeClientConfig.setOutputDirectory(consumerProject.getFolder(
SOAProjectConstants.CODEGEN_FOLDER_OUTPUT_DIR).getLocation()
.toString());
genTypeClientConfig.setMetadataDirectory(consumerProject.getLocation()
.toString()
+ WorkspaceUtil.PATH_SEPERATOR
+ SOAProjectConstants.FOLDER_META_SRC);
final ISOAConfigurationRegistry config = GlobalRepositorySystem.instanceOf()
.getActiveRepositorySystem().getConfigurationRegistry();
genTypeClientConfig.setClientConfigGroup(config.getClientConfigGroup());
// these are all the service related data
final Map<String, Map<String, String>> requiredServices = new LinkedHashMap<String, Map<String, String>>();
for (final SOAIntfMetadata addedService : addedServices) {
final String serviceName = addedService.getServiceName();
final String serviceInterface = addedService.getServiceInterface();
final String namespace = addedService.getTargetNamespace();
final String serviceLocation = addedService.getServiceLocation();
final Map<String, String> data = new ConcurrentHashMap<String, String>();
data.put(BaseCodeGenModel.PARAM_SERVICE_NAME, serviceName);
data.put(BaseCodeGenModel.PARAM_INTERFACE, serviceInterface);
//data.put(BaseCodeGenModel.PARAM_CN, serviceName);
data.put(BaseCodeGenModel.PARAM_NAMESPACE, namespace);
data.put(BaseCodeGenModel.PARAM_SL, serviceLocation);
requiredServices.put(serviceName, data);
}
genTypeClientConfig.setClientName(clientName);
final Properties props = SOAConsumerUtil.loadConsumerProperties(consumerProject);
if (props.containsKey(SOAProjectConstants.PROPS_KEY_CONSUMER_ID)) {
genTypeClientConfig.setConsumerId(StringUtils.trim(props.getProperty(
SOAProjectConstants.PROPS_KEY_CONSUMER_ID)));
}
genTypeClientConfig.setRequiredServices(requiredServices);
genTypeClientConfig.setEnvironments(environments);
return genTypeClientConfig;
}
/**
* Generate client config xml.
*
* @param consumerProject the consumer project
* @param monitor the monitor
* @throws Exception the exception
*/
public static void generateClientConfigXml(
SOAConsumerProject consumerProject, IProgressMonitor monitor) throws Exception {
final SOAConsumerMetadata metadata = consumerProject.getMetadata();
GenTypeClientConfig genTypeClientConfig = generateGenTypeClientConfigXml(
consumerProject.getProject(), metadata.getClientName(),
metadata.getEnvironments(),
consumerProject.getRequiredServices().values());
CodegenInvoker codegenInvoker = CodegenInvoker.init(consumerProject
.getProject());
codegenInvoker.execute(genTypeClientConfig);
consumerProject.getProject().refreshLocal(IResource.DEPTH_INFINITE,
monitor);
}
/**
* generate client configure for newly created service.
*
* @param consumerProject the consumer project
* @param addServices the add services
* @param consumerEnvs the consumer envs
* @param monitor the monitor
* @throws Exception the exception
*/
public static void generateClientConfigXmlForAddedService(
SOAConsumerProject consumerProject,
Collection<SOAIntfMetadata> addServices, List<String> consumerEnvs,
IProgressMonitor monitor) throws Exception {
final SOAConsumerMetadata metadata = consumerProject.getMetadata();
GenTypeClientConfig genTypeClientConfig = generateGenTypeClientConfigXml(
consumerProject.getProject(), metadata.getClientName(),
consumerEnvs, addServices);
CodegenInvoker codegenInvoker = CodegenInvoker.init(consumerProject
.getProject());
codegenInvoker.execute(genTypeClientConfig);
consumerProject.getProject().refreshLocal(IResource.DEPTH_INFINITE,
monitor);
}
/**
* Generates the ClientConfig.xml and Consumer code for the given newly
* created consumer project.
*
* @param consumerProject the consumer project
* @param monitor the monitor
* @throws Exception the exception
*/
public static void generateArtifactsForConsumerProject(
final SOAConsumerProject consumerProject,
final IProgressMonitor monitor) throws Exception {
final IProject project = consumerProject.getProject();
final GenTypeConsumer gentypeConsumer = generateGenTypeConsumer(
project, consumerProject.getMetadata().getEnvironments().get(0),
consumerProject.getRequiredServices().values());
ProgressUtil.progressOneStep(monitor);
final SOAConsumerMetadata metadata = consumerProject.getMetadata();
final GenTypeClientConfig gentypeClientConfig = generateGenTypeClientConfigXml(
project, metadata.getClientName(), metadata.getEnvironments(),
consumerProject.getRequiredServices().values());
ProgressUtil.progressOneStep(monitor);
final CodegenInvoker codegenInvoker = CodegenInvoker.init(project);
codegenInvoker.execute(gentypeClientConfig);
ProgressUtil.progressOneStep(monitor);
codegenInvoker.execute(gentypeConsumer);
ProgressUtil.progressOneStep(monitor);
project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
}
/**
* generate the ClientConfig.xml and Consumer code for the given list of
* newly added services.
*
* @param consumerProject the consumer project
* @param clientName the client name
* @param environments the environments
* @param addedServices the added services
* @param monitor the monitor
* @throws Exception the exception
*/
public static void generateArtifactsForAddedService(
final IProject consumerProject,
final String clientName,
final List<String> environments,
final Collection<AssetInfo> addedServices,
final IProgressMonitor monitor) throws Exception {
final ISOAAssetRegistry assetRegistry = GlobalRepositorySystem
.instanceOf().getActiveRepositorySystem().getAssetRegistry();
final Collection<SOAIntfMetadata> metadatas = new LinkedHashSet<SOAIntfMetadata>(
addedServices.size());
for (final AssetInfo addedService : addedServices) {
final String assetLocation = assetRegistry
.getAssetLocation(addedService);
final SOAIntfMetadata metadata = SOAIntfUtil.loadIntfMetadata(
assetLocation, addedService.getName());
metadatas.add(metadata);
}
ProgressUtil.progressOneStep(monitor);
final GenTypeConsumer gentypeConsumer = generateGenTypeConsumer(
consumerProject, environments.get(0), metadatas);
ProgressUtil.progressOneStep(monitor);
final GenTypeClientConfig gentypeClientConfig = generateGenTypeClientConfigXml(
consumerProject, clientName, environments, metadatas);
ProgressUtil.progressOneStep(monitor);
final CodegenInvoker codegenInvoker = CodegenInvoker
.init(consumerProject.getProject());
codegenInvoker.execute(gentypeClientConfig);
ProgressUtil.progressOneStep(monitor);
codegenInvoker.execute(gentypeConsumer);
ProgressUtil.progressOneStep(monitor);
consumerProject.getProject().refreshLocal(IResource.DEPTH_INFINITE,
monitor);
}
/**
* Adds the env mapper to gen type consumer.
*
* @param genTypeConsumer the gen type consumer
* @param project the project
* @throws CoreException the core exception
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void addEnvMapperToGenTypeConsumer(GenTypeConsumer genTypeConsumer,
IProject project) throws CoreException, IOException {
final IFile conFile = SOAConsumerUtil.getConsumerPropertiesFile(project);
if (conFile.isAccessible()) {
final String envMapper = SOAConsumerUtil.getEnvMapperFromConsumerProperties(project);
if (StringUtils.isNotBlank(envMapper)) {
genTypeConsumer.setEnvMapper(envMapper);
}
}
}
/**
* Generates a consumer from the scratch. This is a one time generation and
* in builders it is mostly a no operation.
*
* @param consumerProject the consumer project
* @param defaultEnvName the default env name
* @param addedServices the added services
* @return the gen type consumer
* @throws Exception the exception
*/
public static GenTypeConsumer generateGenTypeConsumer(
final IProject consumerProject, final String defaultEnvName,
final Collection<SOAIntfMetadata> addedServices) throws Exception {
final IProject project = consumerProject.getProject();
final GenTypeConsumer genTypeConsumer = new GenTypeConsumer();
genTypeConsumer.setSourceDirectory(project.getFolder(
SOAProjectConstants.FOLDER_SRC).getLocation().toString());
genTypeConsumer.setDestination(project.getLocation().toString());
genTypeConsumer.setOutputDirectory(project.getFolder(
SOAProjectConstants.CODEGEN_FOLDER_OUTPUT_DIR).getLocation()
.toString());
genTypeConsumer.setProjectRoot(project.getLocation().toString());
final IFolder genFolder = SOAServiceUtil.getBaseConsumerFolder(project,
GlobalRepositorySystem.instanceOf()
.getActiveRepositorySystem().getProjectType(project));
genTypeConsumer.setGenFolder(genFolder.getLocation().toString());
genTypeConsumer.setDefaultEnvironmentName(defaultEnvName);
final String clientName = SOAConsumerUtil.getClientName(project);
genTypeConsumer.setClientName(clientName);
addEnvMapperToGenTypeConsumer(genTypeConsumer, project);
// these are all the service related data
final Map<String, Map<String, String>> requiredServices = new LinkedHashMap<String, Map<String, String>>();
for (final SOAIntfMetadata intfMetadata : addedServices) {
final Map<String, String> serviceData = new ConcurrentHashMap<String, String>();
serviceData.put(BaseCodeGenModel.PARAM_SERVICE_NAME, intfMetadata
.getServiceName());
serviceData.put(BaseCodeGenModel.PARAM_INTERFACE, intfMetadata
.getServiceInterface());
serviceData.put(BaseCodeGenModel.PARAM_SCV, intfMetadata
.getServiceVersion());
serviceData.put(BaseCodeGenModel.PARAM_SLAYER, intfMetadata
.getServiceLayer());
serviceData.put(BaseCodeGenModel.PARAM_NAMESPACE, intfMetadata
.getTargetNamespace());
serviceData.put(BaseCodeGenModel.PARAM_SL, intfMetadata
.getServiceLocation());
requiredServices.put(intfMetadata.getServiceName(), serviceData);
}
genTypeConsumer.setRequiredServices(requiredServices);
return genTypeConsumer;
}
/**
* Returns the test client name for a given service name. Simply adds a
* suffix.
*
* @param serviceName the service name
* @return the test client name
*/
public static String getTestClientName(final String serviceName) {
return serviceName + SOAProjectConstants.CLIENT_NAME_SUFFIX_TEST;
}
/**
* Generates the consumer artifacts.
*
* @param consumerProject the consumer project
* @throws Exception the exception
*/
public static void generateConsumer(SOAConsumerProject consumerProject)
throws Exception {
final IProject project = consumerProject.getProject();
final GenTypeConsumer genTypeConsumer = generateGenTypeConsumer(
project, consumerProject.getMetadata().getEnvironments().get(0),
consumerProject.getRequiredServices().values());
CodegenInvoker codegenInvoker = CodegenInvoker.init(consumerProject
.getProject());
codegenInvoker.execute(genTypeConsumer);
consumerProject.getProject().refreshLocal(IResource.DEPTH_INFINITE,
null);
}
/**
* Generate artifacts from templates.
*
* @param templateLoadingClass the template loading class
* @param templates the templates
* @param templateData the template data
* @param destinationFolder the destination folder
* @param monitor the monitor
* @return the list
* @throws CoreException the core exception
*/
public static List<IFile> generateArtifactsFromTemplates(
final Class<?> templateLoadingClass,
final Map<String, String> templates,
final Map<String, Object> templateData,
final IFolder destinationFolder, final IProgressMonitor monitor)
throws CoreException {
final List<IFile> result = new ArrayList<IFile>();
if (templates.isEmpty() == false && templateLoadingClass != null) {// index
// page
try {
for (final String fileName : templates.keySet()) {
final String templateFileName = templates.get(fileName);
final File file = destinationFolder.getFile(fileName)
.getLocation().toFile();
if (file.exists()) {
FileUtils.forceDelete(file);
WorkspaceUtil.refresh(monitor, destinationFolder);
}
FreeMarkerUtil.generate(templateData, templateLoadingClass,
templateFileName, new FileOutputStream(file));
if (file.exists())
result.add(destinationFolder.getFile(fileName));
}
} catch (Exception e) {
throw new CoreException(EclipseMessageUtils
.createErrorStatus(e));
}
}
return result;
}
}