blob: 34279efd0a9fb20e808e014b8a6ab46f6909133f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2010 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
* yyyymmdd bug Email and other contact information
* -------- -------- -----------------------------------------------------------
* 20060131 121071 rsinha@ca.ibm.com - Rupam Kuehner
* 20060204 124408 rsinha@ca.ibm.com - Rupam Kuehner
* 20060217 126757 rsinha@ca.ibm.com - Rupam Kuehner
* 20060221 119111 rsinha@ca.ibm.com - Rupam Kuehner
* 20060427 126780 rsinha@ca.ibm.com - Rupam Kuehner
* 20060517 126965 kathy@ca.ibm.com - Kathy Chan
* 20060905 156230 kathy@ca.ibm.com - Kathy Chan, Handling projects with no target runtime
* 20070505 184772 kathy@ca.ibm.com - Kathy Chan
* 20080305 220371 kathy@ca.ibm.com - Kathy Chan
* 20080305 220371 kathy@ca.ibm.com - Kathy Chan - reverting previous change to 220371
* 20080326 220371 kathy@ca.ibm.com - Kathy Chan - re-applying 220371
* 20081001 243869 ericdp@ca.ibm.com - Eric D. Peters, Web Service tools allowing mixed J2EE levels
* 20091123 242615 mahutch@ca.ibm.com - Mark Hutchinson, Use project creation operations to create projects
* 20100211 302631 mahutch@ca.ibm.com - Mark Hutchinson, NullPointerException creating utility projects via CreateFacetedProjectCommand
*******************************************************************************/
package org.eclipse.jst.ws.internal.consumption.command.common;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.core.commands.ExecutionException;
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.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jst.j2ee.applicationclient.internal.creation.AppClientFacetProjectCreationDataModelProvider;
import org.eclipse.jst.j2ee.internal.ejb.project.operations.EjbFacetProjectCreationDataModelProvider;
import org.eclipse.jst.j2ee.internal.plugin.IJ2EEModuleConstants;
import org.eclipse.jst.j2ee.internal.web.archive.operations.WebFacetProjectCreationDataModelProvider;
import org.eclipse.jst.j2ee.project.facet.IJ2EEFacetProjectCreationDataModelProperties;
import org.eclipse.jst.j2ee.project.facet.UtilityProjectCreationDataModelProvider;
import org.eclipse.jst.server.core.FacetUtil;
import org.eclipse.jst.ws.internal.common.J2EEUtils;
import org.eclipse.jst.ws.internal.common.ServerUtils;
import org.eclipse.jst.ws.internal.consumption.ConsumptionMessages;
import org.eclipse.jst.ws.internal.consumption.common.FacetMatcher;
import org.eclipse.jst.ws.internal.consumption.common.FacetSetsByTemplateCache;
import org.eclipse.jst.ws.internal.consumption.common.FacetUtils;
import org.eclipse.jst.ws.internal.consumption.common.RequiredFacetVersion;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.command.internal.env.core.common.StatusUtils;
import org.eclipse.wst.common.componentcore.datamodel.properties.IFacetDataModelProperties;
import org.eclipse.wst.common.componentcore.datamodel.properties.IFacetProjectCreationDataModelProperties;
import org.eclipse.wst.common.componentcore.datamodel.properties.IFacetProjectCreationDataModelProperties.FacetDataModelMap;
import org.eclipse.wst.common.componentcore.internal.util.IModuleConstants;
import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelOperation;
import org.eclipse.wst.common.frameworks.datamodel.DataModelFactory;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.IFacetedProjectTemplate;
import org.eclipse.wst.common.project.facet.core.IProjectFacet;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.eclipse.wst.server.core.IRuntime;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerType;
import org.eclipse.wst.server.core.ServerCore;
public class CreateFacetedProjectCommand extends AbstractDataModelOperation
{
//name of the project to be created
private String projectName;
//name of the EAR project associated with projectName
private String earProjectName;
//id of the IFacetedProjectTemplate to be used to create this project.
private String templateId;
//required facet versions that must be satisfied when creating the project (this comes from
//the selected serverRuntime or clientRuntime in the calling scenario)
private RequiredFacetVersion[] requiredFacetVersions;
//server type id - used to determine the facet runtime the created project will be bound to
//if serverInstanceId is null or empty
private String serverFactoryId;
//server id - used to determine the facet runtime the created project will be bound to. May
//be null or empty.
private String serverInstanceId;
//facet runtime determined from the serverInstanceId or serverFactoryId
private org.eclipse.wst.common.project.facet.core.runtime.IRuntime facetRuntime;
private boolean containsWebFacet(Set facetVersions) {
for (Iterator iter = facetVersions.iterator(); iter.hasNext();) {
IProjectFacetVersion requiredFacetVersion = (IProjectFacetVersion) iter.next();
if (requiredFacetVersion.getProjectFacet().getId().equals(IModuleConstants.JST_WEB_MODULE)) {
return true;
}
}
return false;
}
//return the project creation data model for the templateId or null if no data model found
private IDataModel getDataModelForTemplate(Set requiredFixedFacets) {
IDataModel dm = null;
if (templateId == null)
return null;
else if (templateId.equals(IJ2EEModuleConstants.JST_EJB_TEMPLATE)) {
dm = DataModelFactory.createDataModel(new EjbFacetProjectCreationDataModelProvider());
dm.setProperty(IJ2EEFacetProjectCreationDataModelProperties.FACET_PROJECT_NAME, projectName);
dm.setBooleanProperty(IJ2EEFacetProjectCreationDataModelProperties.ADD_TO_EAR, false);
dm.setProperty(IJ2EEFacetProjectCreationDataModelProperties.FACET_RUNTIME, facetRuntime);
}
else if (templateId.equals(IJ2EEModuleConstants.JST_APPCLIENT_TEMPLATE)) {
dm = DataModelFactory.createDataModel(new AppClientFacetProjectCreationDataModelProvider());
dm.setProperty(IJ2EEFacetProjectCreationDataModelProperties.FACET_PROJECT_NAME, projectName);
dm.setProperty(IJ2EEFacetProjectCreationDataModelProperties.FACET_RUNTIME, facetRuntime);
}
else if (templateId.equals(IJ2EEModuleConstants.JST_UTILITY_TEMPLATE)) {
dm = DataModelFactory.createDataModel(new UtilityProjectCreationDataModelProvider());
dm.setProperty(IJ2EEFacetProjectCreationDataModelProperties.FACET_PROJECT_NAME, projectName);
dm.setProperty(IJ2EEFacetProjectCreationDataModelProperties.FACET_RUNTIME, facetRuntime);
}
else if (templateId.equals(IJ2EEModuleConstants.JST_WEB_TEMPLATE) || containsWebFacet(requiredFixedFacets)) {
//we want any project with the web template ID, or that contains a jst.web facet to be created with this data model
dm = DataModelFactory.createDataModel(new WebFacetProjectCreationDataModelProvider());
dm.setProperty(IJ2EEFacetProjectCreationDataModelProperties.FACET_PROJECT_NAME, projectName);
dm.setBooleanProperty(IJ2EEFacetProjectCreationDataModelProperties.ADD_TO_EAR, false);
dm.setProperty(IJ2EEFacetProjectCreationDataModelProperties.FACET_RUNTIME, facetRuntime);
}
return dm;
}
public IStatus execute(IProgressMonitor monitor, IAdaptable info)
{
IStatus status = Status.OK_STATUS;
// check if data ready
status = checkDataReady();
if (status.getSeverity()==Status.ERROR)
{
return status;
}
IProject project = ProjectUtilities.getProject(projectName);
if (!project.exists())
{
try{
IProject createdProject;
IFacetedProject fproject;
Set facetsToAdd = getFacetsToAdd();
IDataModel dm = getDataModelForTemplate(facetsToAdd);
if (dm != null) {
//we found a project creation data model for this template id. use it to create the project
Set missingFacets = new HashSet();
//here we look at the facet versions in facetsToAdd and set the version on the data model to match
//if no facet data model is found we add it to the missingFacets collection to add later
if (dm.isProperty(IFacetProjectCreationDataModelProperties.FACET_DM_MAP)) {
for (Iterator iter = facetsToAdd.iterator(); iter.hasNext();) {
IProjectFacetVersion requiredFacetVersion = (IProjectFacetVersion) iter.next();
final FacetDataModelMap map = (FacetDataModelMap) dm.getProperty(IFacetProjectCreationDataModelProperties.FACET_DM_MAP);
IDataModel facetDM = map.getFacetDataModel(requiredFacetVersion.getProjectFacet().getId());
if (facetDM != null) {
facetDM.setStringProperty(IFacetDataModelProperties.FACET_VERSION_STR, requiredFacetVersion.getVersionString());
} else {
missingFacets.add(requiredFacetVersion);
}
}
}
dm.getDefaultOperation().execute(null, null);
createdProject = ProjectUtilities.getProject(projectName);
fproject = ProjectFacetsManager.create(createdProject);
//add any facets that were not added by the project creation data model
if (missingFacets.size() > 0) {
status = FacetUtils.addFacetsToProject(fproject, missingFacets);
if (status.getSeverity() == IStatus.ERROR) {
return status;
}
}
}
else {
//did not find a project creation data model. create the project and install facets manually
status = FacetUtils.createNewFacetedProject(projectName);
if (status.getSeverity() == IStatus.ERROR) {
return status;
}
createdProject = ProjectUtilities.getProject(projectName);
fproject = ProjectFacetsManager.create(createdProject);
//Install the facet versions
status = FacetUtils.addFacetsToProject(fproject, facetsToAdd);
if (status.getSeverity() == IStatus.ERROR) {
return status;
}
//Set the installed facet versions as fixed.
Set newFacetVersions = fproject.getProjectFacets();
Set fixedFacets = new HashSet();
for (Iterator iter = newFacetVersions.iterator(); iter.hasNext();) {
IProjectFacetVersion facetVersion = (IProjectFacetVersion) iter.next();
fixedFacets.add(facetVersion.getProjectFacet());
}
status = FacetUtils.setFixedFacetsOnProject(fproject, fixedFacets);
if (status.getSeverity() == IStatus.ERROR) {
return status;
}
}
//Set the runtime
if (facetRuntime != null) {
status = FacetUtils.setFacetRuntimeOnProject(fproject, facetRuntime);
}
// add facets required by Web service runtime
if (requiredFacetVersions.length != 0) {
status = FacetUtils.addRequiredFacetsToProject(project, requiredFacetVersions, monitor);
if (status.getSeverity() == Status.ERROR) {
return status;
}
}
if (facetRuntime != null) {
// add the default facets that's not in conflict with the existing facets
Set projectFacetVersionSet = fproject.getProjectFacets();
Set projectFacetSet = new HashSet();
// get the project facet from the project facet version we calculated
for (Iterator iter = projectFacetVersionSet.iterator(); iter.hasNext();) {
IProjectFacetVersion pfv = (IProjectFacetVersion) iter.next();
projectFacetSet.add(pfv.getProjectFacet());
}
try {
Set defaultProjectFacetVersionSet = facetRuntime.getDefaultFacets(projectFacetSet);
// The returned defaultFacetSet contains the original projectFacetSet passed into getDefaultFacets
// plus any default facets that are not in conflict with the original projectFacetSet.
// Add to facetsToAdd if the the default facet is not in the original set.
Set defaultFacetsToAdd = new HashSet();
for (Iterator iter = defaultProjectFacetVersionSet.iterator(); iter.hasNext();) {
IProjectFacetVersion defaultProjFacetVersion = (IProjectFacetVersion) iter.next();
if( ! projectFacetSet.contains( defaultProjFacetVersion.getProjectFacet() ) )
{
defaultFacetsToAdd.add(defaultProjFacetVersion);
}
}
if (!defaultFacetsToAdd.isEmpty()) {
status = FacetUtils.addFacetsToProject(fproject, defaultFacetsToAdd);
if (status.getSeverity() == IStatus.ERROR) {
return status;
}
}
} catch (CoreException e) {
// If there's any exception when trying to get the default facet, just ignore the default facet
// and return the original facetsToAdd.
}
}
}
catch (CoreException ce) {
return StatusUtils.errorStatus(NLS.bind(ConsumptionMessages.MSG_ERROR_PROJECT_CREATION, new String[] { projectName }));
}
catch (ExecutionException e) {
return StatusUtils.errorStatus(NLS.bind(ConsumptionMessages.MSG_ERROR_PROJECT_CREATION, new String[] { projectName }));
}
}
return status;
}
private IStatus checkDataReady()
{
if (projectName == null)
{
return StatusUtils.errorStatus(NLS.bind(ConsumptionMessages.MSG_ERROR_PROJECT_CREATION, new String[] {projectName}));
}
return Status.OK_STATUS;
}
/**
* Returns the set of facets to install on the new project. The set will consist
* of the highest version of each of the template's fixed facets that satisfies
* the required facet versions, the facet runtime, and the EAR project J2EE level.
* @return Set a Set containing elements of type IProjectFacetVersion.
*/
private Set getFacetsToAdd()
{
Set facets = null;
//Set the facet runtime.
setFacetRuntime();
//Get all facet version combinations for the template in order of ascending version numbers.
Set[] allCombinations = FacetSetsByTemplateCache.getInstance().getFacetVersionCombinationsFromTemplate(templateId);
int n = allCombinations.length;
if (facetRuntime != null)
{
//Walk the facet version combinations in order of descending version numbers.
for (int i=n-1; i>=0; i--)
{
//Check this template combination to see if it is compatible with the
//required facet versions, the server runtime, and the EAR. If it is, choose it.
Set combination = allCombinations[i];
FacetMatcher fm = FacetUtils.match(requiredFacetVersions, combination);
if (fm.isMatch())
{
//Check against Runtime & EAR
if (FacetUtils.doesRuntimeSupportFacets(facetRuntime, combination) && doesEARSupportFacets(combination) )
{
//We have a match. Use this combination of facet versions for project creation.
facets = combination;
break;
}
}
}
}
else
{
for (int i=n-1; i>=0; i--)
{
//Check this template combination to see if it is compatible with both the
//service/client runtime and the server runtime. If it is, choose it.
Set combination = allCombinations[i];
FacetMatcher fm = FacetUtils.match(requiredFacetVersions, combination);
if (fm.isMatch())
{
//We have a match. Use this combination of facet versions for project creation.
facets = combination;
break;
}
}
}
//Unlikely to get to this point in the code, but if we do, choose the highest version
//of each fixed facet in the template that is supported by the server runtime
if (facets == null)
{
facets = getHighestFacetVersionsFromTemplateAndServer();
}
return facets;
}
/**
* Sets the facetRuntime attribute based on the serverInstanceId or serverFactoryId
* Preference is given to non-stub facet runtimes.
*/
private void setFacetRuntime()
{
if (serverInstanceId != null && serverInstanceId.length()>0)
{
IServer server = ServerCore.findServer(serverInstanceId);
IRuntime sRuntime = server.getRuntime();
facetRuntime = FacetUtil.getRuntime(sRuntime);
}
else
{
if (serverFactoryId != null && serverFactoryId.length() > 0)
{
//Find a non Stub runtime that matches this server type
IRuntime serverRuntime = ServerUtils.getNonStubRuntime(serverFactoryId);
if (serverRuntime != null)
{
facetRuntime = FacetUtil.getRuntime(serverRuntime);
}
else
{
//Accept stub runtime.
IServerType st = ServerCore.findServerType(serverFactoryId);
String runtimeTypeId = st.getRuntimeType().getId();
//Find the facet runtime
IRuntime[] runtimes = ServerCore.getRuntimes();
for (int i=0; i<runtimes.length; i++)
{
IRuntime sRuntime = runtimes[i];
if (sRuntime.getRuntimeType().getId().equals(runtimeTypeId))
{
facetRuntime = FacetUtil.getRuntime(sRuntime);
}
}
}
}
}
}
public void setProjectName(String projectName)
{
this.projectName = projectName;
}
public void setTemplateId(String templateId)
{
this.templateId = templateId;
}
public void setRequiredFacetVersions(RequiredFacetVersion[] requiredFacetVersions)
{
this.requiredFacetVersions = requiredFacetVersions;
}
public void setServerFactoryId(String serverFactoryId)
{
this.serverFactoryId = serverFactoryId;
}
public void setServerInstanceId(String serverInstanceId)
{
this.serverInstanceId = serverInstanceId;
}
public void setEarProjectName(String earProject) {
this.earProjectName = earProject;
}
private RequiredFacetVersion[] getRequiredWebFacets() {
return new RequiredFacetVersion[] { getRequiredFacetVersion(
IModuleConstants.JST_WEB_MODULE,
J2EEUtils.getWebJ2EEVersionFromEARJ2EEVersion(ProjectUtilities.getProject(earProjectName))) };
}
private RequiredFacetVersion[] getRequiredAppClientFacets() {
return new RequiredFacetVersion[] { getRequiredFacetVersion(
IModuleConstants.JST_APPCLIENT_MODULE,
J2EEUtils.getAppClientJ2EEVersionFromEARJ2EEVersion(ProjectUtilities.getProject(earProjectName))) };
}
private RequiredFacetVersion[] getRequiredEJBFacets() {
return new RequiredFacetVersion[] { getRequiredFacetVersion(
IModuleConstants.JST_EJB_MODULE,
J2EEUtils.getEJBJ2EEVersionFromEARJ2EEVersion(ProjectUtilities.getProject(earProjectName))) };
}
private boolean doesEARSupportFacets(Set combination) {
try {
if (earProjectName == null || earProjectName.length() == 0
|| !ProjectUtilities.getProject(earProjectName).exists())
// the ear does not exist or the project type template is
// undefined
return true;
else {
if (combinationContainsFacet(combination, IModuleConstants.JST_WEB_MODULE))
return FacetUtils
.match(getRequiredWebFacets(), combination)
.isMatch();
else if (combinationContainsFacet(combination, IModuleConstants.JST_EJB_MODULE))
return FacetUtils
.match(getRequiredEJBFacets(), combination)
.isMatch();
else if (combinationContainsFacet(combination, IModuleConstants.JST_APPCLIENT_MODULE))
return FacetUtils.match(getRequiredAppClientFacets(),
combination).isMatch();
else
return true;
}
} catch (Exception e) {
return true;
}
}
private boolean combinationContainsFacet(Set combination, String facetName) {
if (combination == null || facetName == null || facetName.length() == 0)
return false;
for (Iterator iter = combination.iterator(); iter.hasNext();) {
IProjectFacetVersion nextFacetVersion = (IProjectFacetVersion) iter.next();
if (facetName.equals(nextFacetVersion.getProjectFacet().getId()))
return true;
}
return false;
}
private RequiredFacetVersion getRequiredFacetVersion(String facetName,
String facetVersion) {
IProjectFacet projectFacet = ProjectFacetsManager
.getProjectFacet(facetName);
IProjectFacetVersion projFacetVersion = projectFacet
.getVersion(facetVersion);
RequiredFacetVersion reqFacetVersion = new RequiredFacetVersion();
reqFacetVersion.setAllowNewer(false);
reqFacetVersion.setProjectFacetVersion(projFacetVersion);
return reqFacetVersion;
}
private Set getHighestFacetVersionsFromTemplateAndServer()
{
IFacetedProjectTemplate template = ProjectFacetsManager.getTemplate(templateId);
Set fixedFacets = template.getFixedProjectFacets();
HashSet initial = new HashSet();
for (Iterator itr = fixedFacets.iterator(); itr.hasNext(); )
{
IProjectFacet facet = (IProjectFacet) itr.next();
IProjectFacetVersion highestFacetVersion = null;
try {
highestFacetVersion = facet.getLatestSupportedVersion(facetRuntime);
} catch (CoreException e) {
try {
highestFacetVersion = facet.getLatestVersion();
} catch (CoreException e2) {
//not much we can do here
}
}
initial.add(highestFacetVersion);
}
return initial;
}
}