/*******************************************************************************
* 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.services.ui.wizards;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.ebayopensource.turmeric.eclipse.buildsystem.services.SOAResourceCreator;
import org.ebayopensource.turmeric.eclipse.buildsystem.utils.BuildSystemCodeGen;
import org.ebayopensource.turmeric.eclipse.buildsystem.utils.BuildSystemUtil;
import org.ebayopensource.turmeric.eclipse.buildsystem.utils.ProjectPropertiesFileUtil;
import org.ebayopensource.turmeric.eclipse.core.logging.SOALogger;
import org.ebayopensource.turmeric.eclipse.core.resources.constants.SOAProjectConstants;
import org.ebayopensource.turmeric.eclipse.core.resources.constants.SOAProjectConstants.SupportedProjectType;
import org.ebayopensource.turmeric.eclipse.exception.resources.SOAResourceModifyFailedException;
import org.ebayopensource.turmeric.eclipse.exception.resources.projects.SOAConsumeNewServiceFailedException;
import org.ebayopensource.turmeric.eclipse.exception.resources.projects.SOACreateNewEnvironmentFailedException;
import org.ebayopensource.turmeric.eclipse.exception.resources.projects.SOARemoveConsumedServiceFailedException;
import org.ebayopensource.turmeric.eclipse.exception.resources.projects.SOARemoveEnvironmentFailedException;
import org.ebayopensource.turmeric.eclipse.repositorysystem.core.GlobalRepositorySystem;
import org.ebayopensource.turmeric.eclipse.repositorysystem.core.ISOAAssetRegistry;
import org.ebayopensource.turmeric.eclipse.repositorysystem.core.ISOAProjectConfigurer;
import org.ebayopensource.turmeric.eclipse.repositorysystem.core.TrackingEvent;
import org.ebayopensource.turmeric.eclipse.repositorysystem.utils.TurmericServiceUtils;
import org.ebayopensource.turmeric.eclipse.resources.model.AssetInfo;
import org.ebayopensource.turmeric.eclipse.resources.model.ISOAConsumerProject.SOAClientConfig;
import org.ebayopensource.turmeric.eclipse.resources.model.SOAConsumerProject;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAClientConfigUtil;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAConsumerUtil;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAConsumerUtil.EnvironmentItem;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAConsumerUtil.ModifyConsumerIDResult;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAIntfUtil;
import org.ebayopensource.turmeric.eclipse.services.ui.wizards.pages.ConsumeNewServiceWizardPage;
import org.ebayopensource.turmeric.eclipse.ui.SOABaseWizard;
import org.ebayopensource.turmeric.eclipse.utils.collections.ListUtil;
import org.ebayopensource.turmeric.eclipse.utils.plugin.ProgressUtil;
import org.ebayopensource.turmeric.eclipse.utils.plugin.ProjectUtil;
import org.ebayopensource.turmeric.eclipse.utils.plugin.WorkspaceUtil;
import org.ebayopensource.turmeric.eclipse.utils.ui.ProjectUtils;
import org.ebayopensource.turmeric.eclipse.utils.ui.UIUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.osgi.framework.Version;
/**
* The Class ConsumeNewServiceWizard.
*
* @author yayu
*/
public class ConsumeNewServiceWizard extends SOABaseWizard {
private ConsumeNewServiceWizardPage consumeNewServicePage;
private IProject consumerProject;
private static final SOALogger logger = SOALogger.getLogger();
/**
* Instantiates a new consume new service wizard.
*/
public ConsumeNewServiceWizard() {
super();
}
/*
* (non-Javadoc)
*
* @see org.ebayopensource.turmeric.eclipse.ui.SOABaseWizard#getContentPages()
*/
@Override
public IWizardPage[] getContentPages() {
try {
if (getSelection().isEmpty() == false
&& getSelection().getFirstElement() instanceof IAdaptable) {
final Object obj = ((IAdaptable) getSelection()
.getFirstElement()).getAdapter(IProject.class);
if (obj instanceof IProject) {
consumerProject = (IProject) obj;
consumeNewServicePage = new ConsumeNewServiceWizardPage(
consumerProject);
}
}
} catch (Exception exception) {
logger.error(exception);
throw new RuntimeException(exception);
}
return new IWizardPage[] { consumeNewServicePage };
}
/* (non-Javadoc)
* @see org.ebayopensource.turmeric.eclipse.ui.SOABaseWizard#preValidate()
*/
@Override
public IStatus preValidate() {
// bypass the pre validation
return Status.OK_STATUS;
}
/* (non-Javadoc)
* @see org.ebayopensource.turmeric.eclipse.ui.SOABaseWizard#performFinish()
*/
@Override
public boolean performFinish() {
try {
if (SOALogger.DEBUG)
logger.entering();
if (consumeNewServicePage != null) {
final String clientName = consumeNewServicePage.getClientName();
final String consumerId = consumeNewServicePage.getConsumerId();
final boolean isZeroConfig = consumeNewServicePage.isZeroConfig();
final Set<AssetInfo> fullServiceList = consumeNewServicePage
.getServices();
final Set<AssetInfo> addedServices = consumeNewServicePage
.getAddedServices();
final Set<AssetInfo> removedServices = consumeNewServicePage
.getRemovedServices();
final Map<String, EnvironmentItem> addedEnvironments = isZeroConfig ?
new HashMap<String, EnvironmentItem>(1) : consumeNewServicePage
.getAddedEnvironments();
final Set<String> removedEnvironments = isZeroConfig ?
new HashSet<String>(1) : consumeNewServicePage
.getRemovedEnvironments();
final Set<String> environments = isZeroConfig ?
new HashSet<String>(1) : consumeNewServicePage
.getEnvironments();
// checking if the intf project is built
final Collection<String> addedServiceList = new ArrayList<String>(
addedServices.size());
for (AssetInfo asset : addedServices) {
addedServiceList.add(asset.getName());
}
if (ProjectUtils.isProjectGoodForConsumption(addedServiceList
.toArray(new String[0])) == false) {
return false;
}
final boolean allowModifyConsumerID = consumeNewServicePage
.isConsumerIdEditable();
final String projectName = consumerProject.getName();
WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
@Override
protected void execute(IProgressMonitor monitor)
throws CoreException, InvocationTargetException,
InterruptedException {
long startTime = System.currentTimeMillis();
final int totalWork = ProgressUtil.PROGRESS_STEP * 30;
monitor.beginTask(
"Modifying service consumption configurations for project->"
+ consumerProject.getName(), totalWork);
ProgressUtil.progressOneStep(monitor);
try {
if (TurmericServiceUtils
.isSOAConsumerProject(consumerProject) == false) {
// does not have consumer nature yet, add it now
BuildSystemUtil
.addSOAConsumerSupport(
consumerProject,
GlobalRepositorySystem
.instanceOf()
.getActiveRepositorySystem()
.getProjectNatureId(
SupportedProjectType.CONSUMER),
monitor);
logger
.warning("Added SOA consumer project nature to the impl project->"
+ projectName);
SOAResourceCreator
.createConsumerPropertiesFileForImplProjects(
consumerProject, clientName,
consumerId, monitor);
logger
.warning("Created service_consumer_project.properties to the impl project->"
+ projectName);
}
ProgressUtil.progressOneStep(monitor);
// add environments
if (addedEnvironments.isEmpty() == false) {
logger.info("Creating new environments->",
addedEnvironments);
List<String> clonedEnvs = new ArrayList<String>();
for (String newEnvName : addedEnvironments
.keySet()) {
final EnvironmentItem cloneEnv = addedEnvironments
.get(newEnvName);
if (cloneEnv != null && StringUtils.isNotBlank(cloneEnv.getName())) {
logger
.info(
"Cloning existing environment ->",
cloneEnv.getName(),
" to new environment->",
newEnvName);
SOAConsumerUtil.cloneEnvironment(
consumerProject, cloneEnv
.getName(), newEnvName,
monitor);
clonedEnvs.add(newEnvName);
}
}
addedEnvironments.keySet()
.removeAll(clonedEnvs);
}
ProgressUtil.progressOneStep(monitor);
} catch (Exception e) {
logger.error(e);
throw new SOACreateNewEnvironmentFailedException(
"Failed to create new environment for project->"
+ consumerProject.getName(), e);
}
// remove environments
try {
if (removedEnvironments.isEmpty() == false) {
logger.info("Removing environments->",
removedEnvironments);
SOAConsumerUtil.removeEnvironments(
consumerProject, monitor,
removedEnvironments
.toArray(new String[0]));
ProgressUtil.progressOneStep(monitor);
}
} catch (Exception e) {
logger.error(e);
throw new SOARemoveEnvironmentFailedException(
"Failed to remove existing environment from project->"
+ consumerProject.getName(), e);
}
// services configuration
ISOAProjectConfigurer configurer = GlobalRepositorySystem
.instanceOf().getActiveRepositorySystem()
.getProjectConfigurer();
try {
// removing existing services
if (removedServices.isEmpty() == false) {
logger.info("Removing services->",
removedServices);
configurer.removeDependencies(projectName,
ListUtil.arrayList(removedServices),
monitor);
Collection<String> serviceNames = new ArrayList<String>();
for (AssetInfo removedService : removedServices) {
serviceNames.add(removedService.getName());
}
if (isZeroConfig == false) {
SOAConsumerUtil.removeClientConfigFiles(
consumerProject, monitor, serviceNames
.toArray(new String[0]));
}
ProgressUtil.progressOneStep(monitor);
}
} catch (Exception e) {
logger.error(e);
throw new SOARemoveConsumedServiceFailedException(
"Failed to remove service from project->"
+ consumerProject.getName(), e);
}
try {
// manage the not_generate_base_consumer property
final Collection<String> removedServiceList = new ArrayList<String>(
removedServices.size());
for (AssetInfo asset : removedServices) {
removedServiceList.add(asset.getName());
}
final Collection<String> addedServiceNames = new ArrayList<String>(
addedServiceList.size());
final ISOAAssetRegistry assetRegistry = GlobalRepositorySystem
.instanceOf().getActiveRepositorySystem()
.getAssetRegistry();
for (AssetInfo asset : addedServices) {
final String assetLocation = assetRegistry
.getAssetLocation(asset);
final Version version = SOAIntfUtil
.getServiceMetadataVersion(asset
.getName(), assetLocation);
if (version
.compareTo(SOAProjectConstants.DEFAULT_PROPERTY_VERSION) >= 0) {
// the project is post 2.4
addedServiceNames.add(asset.getName());
}
}
SOAConsumerUtil.modifyNotGenerateBaseConsumers(
consumerProject, addedServiceNames,
removedServiceList, monitor);
} catch (Exception e) {
logger.error(e);
throw new SOAResourceModifyFailedException(
"Failed to modify the not_generate_base_consumer property->"
+ consumerProject.getName(), e);
}
// add services
try {
if (addedServices.isEmpty() == false) {
logger.info("Consuming new services->",
addedServices);
configurer.addDependencies(projectName,
ListUtil.arrayList(addedServices),
monitor);
ProgressUtil.progressOneStep(monitor);
BuildSystemUtil
.updateSOAClasspathContainer(consumerProject);
ProgressUtil.progressOneStep(monitor);
}
} catch (Exception e) {
logger.error(e);
throw new SOAConsumeNewServiceFailedException(
"Failed to add new service to project->"
+ consumerProject.getName(), e);
}
try {
if (fullServiceList.isEmpty() == true
&& TurmericServiceUtils
.isSOAImplProject(consumerProject)) {
// no services remained
logger
.info(
"All consumed services by the underlying implementation project have been removed->",
consumerProject);
ProjectUtil
.removeNatures(
consumerProject,
monitor,
GlobalRepositorySystem
.instanceOf()
.getActiveRepositorySystem()
.getProjectNatureId(
SupportedProjectType.CONSUMER));
IFile file = SOAConsumerUtil
.getConsumerPropertiesFile(consumerProject);
if (file.exists() == true) {
FileUtils.forceDelete(file.getLocation()
.toFile());
logger
.info(
"Removed service_consumer_project.properties file->",
file.getLocation());
}
final IFolder folder = consumerProject
.getFolder(SOAConsumerProject.FOLDER_META_SRC_ClIENT);
if (folder.exists() == true) {
FileUtils.forceDelete(folder.getLocation()
.toFile());
logger.info(
"Removed client config folder->",
folder.getLocation());
}
}
} catch (Exception e) {
logger.error(e);
throw new SOAResourceModifyFailedException(
"Failed to remove consumer natures from the underlying implementation projects->"
+ consumerProject.getName(), e);
}
WorkspaceUtil.refresh(consumerProject);
final TrackingEvent event = new TrackingEvent(
"SetupServiceConsumptions",
new Date(startTime), System.currentTimeMillis()
- startTime);
GlobalRepositorySystem.instanceOf()
.getActiveRepositorySystem().trackingUsage(
event);
monitor.done();
}
};
if (addedServices.isEmpty() == false
|| removedServices.isEmpty() == false
|| addedEnvironments.isEmpty() == false
|| removedEnvironments.isEmpty() == false) {
getContainer().run(false, true, operation);
operation = new WorkspaceModifyOperation() {
@Override
protected void execute(IProgressMonitor monitor)
throws CoreException,
InvocationTargetException, InterruptedException {
// add services
try {
if (addedServices.isEmpty() == false) {
logger
.info(
"Generating artifacts for new services->",
addedServices);
ProgressUtil.progressOneStep(monitor);
if (addedServices.isEmpty() == false && isZeroConfig == false) {
BuildSystemCodeGen
.generateArtifactsForAddedService(
consumerProject,
clientName,
ListUtil
.arrayList(environments),
addedServices, monitor);
}
}
} catch (Exception e) {
logger.error(e);
throw new SOAConsumeNewServiceFailedException(
"Failed to generate artifacts for new service to project->"
+ consumerProject.getName(), e);
}
if (removedServices.isEmpty() == false
&& addedServices.isEmpty() == true) {
// need to udpate the classpath container
BuildSystemUtil
.updateSOAClasspathContainer(consumerProject);
}
try {
// the remaining new environments that have to
// be added
// after new services being added
if (addedEnvironments.isEmpty() == false) {
logger.info(
"Generating new environments->",
addedEnvironments);
BuildSystemCodeGen
.generateArtifactsForAddedService(
consumerProject,
clientName,
ListUtil
.arrayList(addedEnvironments
.keySet()),
fullServiceList, monitor);
}
} catch (Exception e) {
logger.error(e);
throw new SOACreateNewEnvironmentFailedException(
"Failed to create new environment for project->"
+ consumerProject.getName(), e);
}
}
};
getContainer().run(false, true, operation);
}
if (allowModifyConsumerID == true
&& StringUtils.isNotBlank(consumerId)) {
final ModifyConsumerIDResult result = SOAConsumerUtil
.updateConsumerId(consumerId, consumerProject);
if (result != null) {
// the consumerID has been updated
if (result.getOldClientConfigs().isEmpty() == false) {
// some CC.xml contains <invocation-use-case>
StringBuffer msg = new StringBuffer();
msg
.append("The following ClientConfig.xml files contain the deprecated element <invocation-use-case>, ");
msg
.append("which will be removed. Backups of the ClientConfig.xml files will be created with \".bak\" suffix.\n");
for (SOAClientConfig config : result
.getOldClientConfigs()) {
msg.append("\n");
msg.append(config.getFile().getLocation());
}
MessageDialog.openWarning(getShell(), "Warnings",
msg.toString());
}
final WorkspaceModifyOperation op = new ConsumerNewServiceWorkspaceModifyOperation(clientName, consumerId, result);
getContainer().run(false, true, op);
changePerspective();
}
}
if (removedServices.isEmpty() == false) {
MessageDialog
.openInformation(
UIUtil.getActiveShell(),
"Services Removed",
"Services have been successfully removed, please either backup or remove the corresponding base consumer classes if applicable.");
}
}
} catch (Exception e) {
logger.error(e);
UIUtil.showErrorDialog(e);
if (SOALogger.DEBUG)
logger.exiting(false);
return false;
}
if (SOALogger.DEBUG)
logger.exiting(true);
return true;
}
private class ConsumerNewServiceWorkspaceModifyOperation extends WorkspaceModifyOperation {
private String clientName;
private String consumerId;
private ModifyConsumerIDResult result;
public ConsumerNewServiceWorkspaceModifyOperation (String clientName, String consumerId, ModifyConsumerIDResult result) {
this.clientName = clientName;
this.consumerId = consumerId;
this.result = result;
}
@Override
protected void execute(IProgressMonitor monitor)
throws CoreException,
InvocationTargetException,
InterruptedException {
logger
.warning(
"The consumer ID has been changed, re-generate the service_consumer_project.properties and "
+ "modify all ClientConfig.xml files for project->",
consumerProject);
try {
ProjectPropertiesFileUtil
.createPropsFileForImplProjects(
consumerProject,
clientName,
consumerId,
monitor);
for (SOAClientConfig clientConfig : result
.getClientConfigs()) {
String protocalProcessorClassName = GlobalRepositorySystem
.instanceOf()
.getActiveRepositorySystem()
.getActiveOrganizationProvider()
.getSOAPProtocolProcessorClassName();
SOAClientConfigUtil
.save(clientConfig, result
.getOldClientConfigs()
.contains(clientConfig), protocalProcessorClassName);
}
} catch (Exception e) {
logger.error(e);
throw new SOAResourceModifyFailedException(
"Failed to modify consumerID for the underlying consumer projects->"
+ consumerProject.getName(),
e);
} finally {
consumerProject.refreshLocal(
IProject.DEPTH_INFINITE, monitor);
}
}
}
}