/*******************************************************************************
* Copyright (c) 2007 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.seam.ui.wizard;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.tools.ant.types.FilterSetCollection;
import org.apache.tools.ant.util.FileUtils;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.AbstractOperation;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
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.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.internal.core.LaunchManager;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFile;
import org.jboss.tools.common.ui.widget.editor.INamedElement;
import org.jboss.tools.jst.web.WebUtils;
import org.jboss.tools.seam.core.SeamCorePlugin;
import org.jboss.tools.seam.core.SeamProjectsSet;
import org.jboss.tools.seam.core.project.facet.SeamRuntimeManager;
import org.jboss.tools.seam.internal.core.project.facet.ISeamFacetDataModelProperties;
import org.jboss.tools.seam.internal.core.project.facet.SeamFacetFilterSetFactory;
import org.jboss.tools.seam.internal.core.project.facet.SeamFacetInstallDataModelProvider;
import org.jboss.tools.seam.ui.SeamGuiPlugin;
import org.osgi.service.prefs.BackingStoreException;
/**
* @author eskimo
*
*/
public abstract class SeamBaseOperation extends AbstractOperation {
public static final String TESTNG_LAUNCH_CONFIG_TYPE_ID = "org.testng.eclipse.launchconfig";
/**
* @param label
*/
public SeamBaseOperation(String label) {
super(label);
}
private void putResourceLocationProperty(Map<String, Object> vars, String parameterName, IResource resource) {
if(resource!=null) {
vars.put(parameterName, resource.getLocation().toFile().toString());
} else {
vars.put(parameterName, "");
}
}
private void putResourceLocationProperty(Map<String, Object> vars, String parameterName, String resourcePath) {
if(resourcePath!=null) {
vars.put(parameterName, resourcePath);
} else {
vars.put(parameterName, "");
}
}
private void putPackageLocationProperty(Map<String, Object> vars, String parameterName, String packageName) {
if(packageName!=null) {
vars.put(parameterName, packageName.replace('.','/'));
} else {
vars.put(parameterName, "");
}
}
protected IAdaptable info;
/**
* @see AbstractOperation#execute(IProgressMonitor, IAdaptable)
*/
@Override
public IStatus execute(IProgressMonitor monitor, IAdaptable info)
throws ExecutionException {
IStatus result = Status.OK_STATUS;
this.info = info;
launchFiles = null;
final SeamProjectsSet seamPrjSet = new SeamProjectsSet(getProject(info));
try {
Map<String, Object> vars = loadParameters(info, seamPrjSet);
List<FileMapping> fileMapping = shouldCreateTestLaunch()?getFileMappingsWithTestLaunch(vars):getFileMappings(vars);
List<String[]> fileMappingCopy = applyVariables(fileMapping,vars);
FilterSetCollection filters = getFilterSetCollection(vars);
final File[] file = new File[fileMappingCopy.size()];
int index=0;
for (String[] mapping : fileMappingCopy) {
file[index] = new File(mapping[1]);
FileUtils.getFileUtils().copyFile(new File(mapping[0]), file[index],filters,false);
index++;
}
if(shouldTouchServer(seamPrjSet)) {
WebUtils.changeTimeStamp(seamPrjSet.getWarProject());
}
if(launchFiles!=null) {
for (File launchFile : launchFiles) {
if(launchFile.exists()) {
ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
if(manager instanceof LaunchManager) {
((LaunchManager)manager).importConfigurations(new File[]{launchFile}, monitor);
}
launchFile.delete();
}
}
}
} catch (BackingStoreException e) {
result = new Status(IStatus.ERROR,SeamGuiPlugin.PLUGIN_ID,e.getMessage(),e);
} catch (IOException e) {
result = new Status(IStatus.ERROR,SeamGuiPlugin.PLUGIN_ID,e.getMessage(),e);
} catch (CoreException e) {
result = new Status(IStatus.ERROR,SeamGuiPlugin.PLUGIN_ID,e.getMessage(),e);
}
finally {
try {
// ComponentCore is used to handle case when user changes
// default WebContent folder to another one in
// Web Facet configuration page
IContainer viewFolder = seamPrjSet.getViewsFolder();
if(viewFolder!=null) {
IProject prj = seamPrjSet.getWarProject();
IVirtualComponent webComp = ComponentCore.createComponent(prj);
if(webComp!=null) {
IVirtualFile manifest = webComp.getRootFolder().getFile("/META-INF/MANIFEST.MF");
if(manifest.exists()) {
manifest.getUnderlyingFile().getParent().touch(monitor);
manifest.getUnderlyingFile().touch(monitor);
}
}
}
// to keep workspace in sync
seamPrjSet.refreshLocal(monitor);
} catch (CoreException e) {
result = new Status(IStatus.ERROR,SeamGuiPlugin.PLUGIN_ID,e.getMessage(),e);
}
}
if (result.getSeverity()==IStatus.ERROR) {
SeamGuiPlugin.getDefault().getLog().log(result);
}
return result;
}
private Map<String, Object> loadParameters(IAdaptable info, SeamProjectsSet seamPrjSet) throws BackingStoreException {
Map<String, INamedElement> params = (Map<String, INamedElement>)info.getAdapter(Map.class);
IEclipsePreferences seamFacetPrefs = SeamCorePlugin.getSeamPreferences(seamPrjSet.getWarProject());
Map<String, Object> vars = new HashMap<String, Object>();
for (String key : seamFacetPrefs.keys()) {
vars.put(key, seamFacetPrefs.get(key, "")); //$NON-NLS-1$
}
for (Object valueHolder : params.values()) {
INamedElement elem = (INamedElement)valueHolder;
vars.put(elem.getName(),elem.getValue().toString());
}
loadCustomVariables(vars);
String actionFolder = getSessionBeanPackageName(seamFacetPrefs, params);
String entityFolder = getEntityBeanPackageName(seamFacetPrefs, params);
String testFolder = getTestCasesPackageName(seamFacetPrefs, params);
vars.put(ISeamParameter.SEAM_PROJECT_INSTANCE, seamPrjSet.getWarProject());
vars.put(ISeamParameter.JBOSS_SEAM_HOME, SeamRuntimeManager.getInstance().getRuntimeForProject(seamPrjSet.getWarProject()).getHomeDir());
putResourceLocationProperty(vars, ISeamParameter.SEAM_PROJECT_LOCATION_PATH, seamPrjSet.getWarProject());
putResourceLocationProperty(vars, ISeamParameter.SEAM_PROJECT_WEBCONTENT_PATH, seamPrjSet.getViewsFolder());
putResourceLocationProperty(vars, ISeamParameter.SEAM_PROJECT_SRC_ACTION, seamPrjSet.getActionFolder());
putResourceLocationProperty(vars, ISeamParameter.SEAM_PROJECT_SRC_MODEL, seamPrjSet.getModelFolder());
putResourceLocationProperty(vars, ISeamParameter.SEAM_EJB_PROJECT_LOCATION_PATH, seamPrjSet.getEjbProject());
putResourceLocationProperty(vars, ISeamParameter.SEAM_TEST_PROJECT_LOCATION_PATH, seamPrjSet.getTestProject());
putResourceLocationProperty(vars, ISeamParameter.TEST_SOURCE_FOLDER, seamPrjSet.getTestsFolder());
putPackageLocationProperty(vars, ISeamParameter.SESSION_BEAN_PACKAGE_PATH, actionFolder);
putResourceLocationProperty(vars, ISeamParameter.SESSION_BEAN_PACKAGE_NAME, actionFolder);
putPackageLocationProperty(vars, ISeamParameter.TEST_CASES_PACKAGE_PATH, testFolder);
putResourceLocationProperty(vars, ISeamParameter.TEST_CASES_PACKAGE_NAME, testFolder);
putPackageLocationProperty(vars, ISeamParameter.ENTITY_BEAN_PACKAGE_PATH, entityFolder);
putResourceLocationProperty(vars, ISeamParameter.ENTITY_BEAN_PACKAGE_NAME, entityFolder);
return vars;
}
public void openResultInEditor(final IAdaptable info) {
final IProject project = getProject(info);
final SeamProjectsSet seamPrjSet = new SeamProjectsSet(project);
Map<String, Object> parameters = null;
try {
parameters = loadParameters(info, seamPrjSet);
} catch (BackingStoreException e) {
SeamGuiPlugin.getPluginLog().logError(e);
return;
}
final Map<String, Object> vars = parameters;
final List<FileMapping> fileMappings = getFileMappings(parameters);
Display display = Display.getCurrent();
if(display!=null) {
display.asyncExec(new Runnable() {
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
public void run() {
openResultInEditorInCurrentThread(info, project, seamPrjSet, vars, fileMappings);
}
});
} else {
// If we run this methods from test environment then don't use asyncExec.
openResultInEditorInCurrentThread(info, project, seamPrjSet, parameters, fileMappings);
}
}
private static void openResultInEditorInCurrentThread(IAdaptable info, IProject project, SeamProjectsSet seamPrjSet, Map<String, Object> parameters, List<FileMapping> fileMappings) {
try {
if(!fileMappings.isEmpty()) {
List<String[]> fileMappingCopy = applyVariables(fileMappings, parameters);
IFile iFile = seamPrjSet.getWarProject().getWorkspace().getRoot().getFileForLocation(new Path(fileMappingCopy.get(0)[1]));
IDE.openEditor(SeamGuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage(), iFile);
}
} catch (PartInitException e) {
SeamGuiPlugin.getPluginLog().logError(e);
}
}
protected boolean shouldTouchServer(SeamProjectsSet seamPrjSet) {
return !seamPrjSet.isWarConfiguration();
}
protected String getSessionBeanPackageName(IEclipsePreferences seamFacetPrefs, Map<String, INamedElement> wizardParams) {
return seamFacetPrefs.get(ISeamParameter.SESSION_BEAN_PACKAGE_NAME, "");
}
protected String getEntityBeanPackageName(IEclipsePreferences seamFacetPrefs, Map<String, INamedElement> wizardParams) {
return seamFacetPrefs.get(ISeamParameter.ENTITY_BEAN_PACKAGE_NAME, "");
}
protected String getTestCasesPackageName(IEclipsePreferences seamFacetPrefs, Map<String, INamedElement> wizardParams) {
return seamFacetPrefs.get(ISeamParameter.TEST_CASES_PACKAGE_NAME, "");
}
protected IProject getProject(IAdaptable info) {
Map<String, INamedElement> params = (Map<String, INamedElement>)info.getAdapter(Map.class);
return ResourcesPlugin.getWorkspace().getRoot().getProject(
params.get(ISeamParameter.SEAM_PROJECT_NAME).getValueAsString());
}
/**
* @param fileMapping
* @param vars
* @return
*/
public static List<String[]> applyVariables(List<FileMapping> fileMapping, Map<String, Object> vars) {
List<String[]> result = new ArrayList<String[]>();
for (FileMapping filter : fileMapping) {
if(filter.getDeployType().equalsString((String)vars.get(ISeamFacetDataModelProperties.JBOSS_AS_DEPLOY_AS)) &&
(!filter.isTest() || Boolean.parseBoolean(vars.get(ISeamFacetDataModelProperties.TEST_CREATING).toString()))) { //$NON-NLS-1$
String source = filter.getSource();
for (Object property : vars.keySet()){
if(source.contains("${"+property.toString()+"}")) { //$NON-NLS-1$ //$NON-NLS-2$
source = source.replace("${"+property.toString()+"}",vars.get(property.toString()).toString()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
String dest = filter.getDestination();
for (Object property : vars.keySet()){
if(dest.contains("${"+property.toString()+"}")) { //$NON-NLS-1$ //$NON-NLS-2$
dest = dest.replace("${"+property.toString()+"}",vars.get(property.toString()).toString()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
result.add(new String[]{source, dest});
}
}
return result;
}
/**
* @param vars
* @return
*/
public abstract List<FileMapping> getFileMappings(Map<String, Object> vars);
protected abstract boolean shouldCreateTestLaunch();
private Set<File> launchFiles;
private String launchTemplatePath;
public static final String[] TEST_NAME_PREFIXES = {"Test, ....launch", "Test.launch"};
protected List<FileMapping> getFileMappingsWithTestLaunch(Map<String, Object> vars) {
List<FileMapping> mapping = new ArrayList<FileMapping>();
mapping.addAll(getFileMappings(vars));
launchFiles = new HashSet<File>();
// Uncomment following code if we shouldn't create TestNG launch in case TestNG plug-in is not installed.
// See https://jira.jboss.org/browse/JBIDE-7359
// ----------------->
// ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
// if(manager.getLaunchConfigurationType(SeamBaseOperation.TESTNG_LAUNCH_CONFIG_TYPE_ID)==null) {
// // TestNG plug-in is not install. Don't verify attributes of the launch.
// return mapping;
// }
// <-----------------
// String namePrefix = vars.get(ISeamParameter.SEAM_LOCAL_INTERFACE_NAME) + "Test-JDK16.launch"; //$NON-NLS-1$
// Different versions of TestNG plugins use different default names for launches. So we have to create two launches with different names.
for (String prefix : TEST_NAME_PREFIXES) {
String namePrefix = vars.get(ISeamParameter.SEAM_LOCAL_INTERFACE_NAME) + prefix; //$NON-NLS-1$
addTestLaunchToFileMapping(mapping, namePrefix);
}
return mapping;
}
protected List<FileMapping> addTestLaunchToFileMapping(List<FileMapping> mapping, String namePrefix) {
String launchName = DebugPlugin.getDefault().getLaunchManager().generateLaunchConfigurationName(namePrefix);
try {
File launchFile = new File(SeamCorePlugin.getDefault().getStateLocation().toFile(), ".testNGlaunches/" + launchName);
launchFiles.add(launchFile);
if(launchFile.exists()) {
launchFile.delete();
}
if(launchTemplatePath==null) {
launchTemplatePath = new File(SeamFacetInstallDataModelProvider.getTemplatesFolder(), "/testng/testng.launch").getAbsolutePath(); //$NON-NLS-1$
}
mapping.add(new FileMapping(
launchTemplatePath,
launchFile.getAbsolutePath(),
FileMapping.TYPE.EAR,
true));
mapping.add(new FileMapping(
launchTemplatePath,
launchFile.getAbsolutePath(),
FileMapping.TYPE.WAR,
true));
} catch (IOException e) {
SeamGuiPlugin.getDefault().logError(e);
}
return mapping;
}
/**
*
* @param vars
* @return
*/
public FilterSetCollection getFilterSetCollection(Map<String, Object> vars) {
return new FilterSetCollection(SeamFacetFilterSetFactory.createFiltersFilterSet(vars));
}
/* (non-Javadoc)
* @see org.eclipse.core.commands.operations.AbstractOperation#redo(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.runtime.IAdaptable)
*/
@Override
public IStatus redo(IProgressMonitor monitor, IAdaptable info)
throws ExecutionException {
return Status.OK_STATUS;
}
/* (non-Javadoc)
* @see org.eclipse.core.commands.operations.AbstractOperation#undo(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.core.runtime.IAdaptable)
*/
@Override
public IStatus undo(IProgressMonitor monitor, IAdaptable info)
throws ExecutionException {
return Status.OK_STATUS;
}
@Override
public boolean canRedo() {
return false;
}
@Override
public boolean canUndo() {
return false;
}
public File getSeamFolder(Map<String, Object> vars) {
return new File(vars.get(ISeamParameter.JBOSS_SEAM_HOME).toString(),"seam-gen"); //$NON-NLS-1$
}
protected void loadCustomVariables(Map<String, Object> vars) {
}
}