/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2005-2006, JBoss Inc.
*/
package org.jboss.tools.smooks.launch;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate;
import org.eclipse.jdt.launching.ExecutionArguments;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IVMRunner;
import org.eclipse.jdt.launching.VMRunnerConfiguration;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.jboss.tools.smooks.configuration.ProcessNodeType;
import org.jboss.tools.smooks.configuration.RuntimeDependency;
import org.jboss.tools.smooks.configuration.RuntimeMetadata;
import org.jboss.tools.smooks.core.SmooksInputType;
import org.jboss.tools.smooks.launch.serialize.MarshallingStrategy;
import org.jboss.tools.smooks.launch.serialize.ObjectSerializer;
import org.jboss.tools.smooks.launch.serialize.XPathMarshaller;
/**
* Smooks Launch Configuration Delegate.
*
* @author <a href="mailto:tom.fennelly@jboss.com">tom.fennelly@jboss.com</a>
*/
public class SmooksLaunchConfigurationDelegate extends JUnitLaunchConfigurationDelegate {
private static final String PLUGIN_ID = "org.jboss.tools.smooks.ui.smooksLauncher"; //$NON-NLS-1$
/* (non-Javadoc)
* @see org.eclipse.debug.core.model.ILaunchConfigurationDelegate#launch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor)
*/
public void launch(ILaunchConfiguration launchConfig, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
IJavaProject javaProject = getJavaProject(launchConfig);
IProject project = javaProject.getProject();
final String smooksConfigName = launchConfig.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, ""); //$NON-NLS-1$
String[] baseClasspath = getClasspath(launchConfig);
final RuntimeMetadata launchMetadata = new RuntimeMetadata();
launchMetadata.setSmooksConfig(project.findMember(smooksConfigName));
if(SmooksInputType.INPUT_TYPE_JAVA.equals(launchMetadata.getInputType())) {
// displayError(smooksConfigName, Messages.SmooksLaunchConfigurationDelegate_Error_Java_Unsupported);
// return;
} else if(!launchMetadata.isValidSmooksConfig()) {
displayError(smooksConfigName, launchMetadata.getErrorMessage());
return;
} else {
List<RuntimeDependency> dependencies = launchMetadata.getDependencies();
URLClassLoader projectClassLoader = toURLClassLoader(baseClasspath);
for(RuntimeDependency dependency : dependencies) {
if(!dependency.isOnProjectClasspath(projectClassLoader)) {
displayError(smooksConfigName, Messages.SmooksLaunchConfigurationDelegate_Error_missing_artifact + dependency.getGroupId() + ":" + dependency.getArtifactId() + Messages.SmooksLaunchConfigurationDelegate_Error_missing_artifact2); //$NON-NLS-1$
return;
}
}
}
IVMRunner runner= getVMRunner(launchConfig, mode);
VMRunnerConfiguration runConfig = buildRunnerConfig(launchConfig, baseClasspath);
// check for cancellation
if (monitor.isCanceled()) {
return;
}
String inputType = launchMetadata.getInputType();
String inputPath = launchMetadata.getInputFile().getAbsolutePath();
if(SmooksInputType.INPUT_TYPE_JAVA.equals(launchMetadata.getInputType())) {
inputPath = launchMetadata.getInputClassName();
}
String nodeTypes = launchMetadata.getNodeTypesString();
runConfig.setProgramArguments(new String[] {launchMetadata.getConfigFile().getAbsolutePath(), inputType, inputPath, nodeTypes});
runner.run(runConfig, launch, monitor);
}
private void displayError(final String smooksConfigName, final String errorMessage) {
final Display display = PlatformUI.getWorkbench().getDisplay();
display.syncExec(new Runnable() {
public void run(){
Shell shell = display.getActiveShell();
ErrorDialog.openError(shell, Messages.SmooksLaunchConfigurationDelegate_Error_Title, Messages.SmooksLaunchConfigurationDelegate_Error_launching + smooksConfigName + "'.", new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, errorMessage, new Exception())); //$NON-NLS-1$
}
});
}
private VMRunnerConfiguration buildRunnerConfig(ILaunchConfiguration launchConfig, String[] baseClasspath) throws CoreException {
List<String> classpath = new ArrayList<String>(Arrays.asList(baseClasspath));
// We need to add the SmooksLauncher to the launch classpath because it will not be part of the projects
// classpath. Bit of a hack... there's probably a nicer way of doing this!!!
File wsTempClasses = copyLauncherResourcesToFilesys();
classpath.add(wsTempClasses.getAbsolutePath());
VMRunnerConfiguration runConfig= new VMRunnerConfiguration(SmooksLauncher.class.getName(), classpath.toArray(new String[classpath.size()]));
String[] envp= getEnvironment(launchConfig);
ArrayList<String> vmArguments= new ArrayList<String>();
String vmArgs= getVMArguments(launchConfig);
ExecutionArguments execArgs= new ExecutionArguments(vmArgs, ""); //$NON-NLS-1$
File workingDir = verifyWorkingDirectory(launchConfig);
vmArguments.addAll(Arrays.asList(execArgs.getVMArgumentsArray()));
runConfig.setVMArguments((String[]) vmArguments.toArray(new String[vmArguments.size()]));
runConfig.setEnvironment(envp);
if(workingDir != null) {
runConfig.setWorkingDirectory(workingDir.getAbsolutePath());
}
runConfig.setVMSpecificAttributesMap(getVMSpecificAttributesMap(launchConfig));
runConfig.setBootClassPath(getBootpath(launchConfig));
return runConfig;
}
private File copyLauncherResourcesToFilesys() throws CoreException {
File wsRootDir = ResourcesPlugin.getWorkspace().getRoot().getRawLocation().toFile();
File wsTempClasses = new File(wsRootDir, "temp/launcher/classes"); //$NON-NLS-1$
writeClassToFilesys(JavaGraphBuilder.class, wsTempClasses);
writeClassToFilesys(SmooksLauncher.class, wsTempClasses);
writeClassToFilesys(SmooksInputType.class, wsTempClasses);
writeClassToFilesys(ProcessNodeType.class, wsTempClasses);
writeClassToFilesys(ObjectSerializer.class, wsTempClasses);
writeClassToFilesys(MarshallingStrategy.class, wsTempClasses);
writeClassToFilesys(XPathMarshaller.class, wsTempClasses);
// Need to send the localized message strings to the launcher...
Properties localizedMessages = new Properties();
localizedMessages.setProperty("SmooksLauncher_Error_Do_Not_Support_Java_Inputs", Messages.SmooksLauncher_Error_Do_Not_Support_Java_Inputs); //$NON-NLS-1$
localizedMessages.setProperty("SmooksLauncher_Error_Expected_Four_Args", Messages.SmooksLauncher_Error_Expected_Four_Args); //$NON-NLS-1$
localizedMessages.setProperty("SmooksLauncher_Java_Mapping_Results", Messages.SmooksLauncher_Java_Mapping_Results); //$NON-NLS-1$
localizedMessages.setProperty("SmooksLauncher_Templating_To_StreamResult", Messages.SmooksLauncher_Templating_To_StreamResult); //$NON-NLS-1$
localizedMessages.setProperty("SmooksLauncher_Nothing_To_Display", Messages.SmooksLauncher_Nothing_To_Display); //$NON-NLS-1$
try {
FileOutputStream messagesOutStream = getFilesysOutStream(SmooksLauncher.LOCALIZED_FILE_NAME, SmooksLauncher.class, wsTempClasses);
try {
localizedMessages.store(messagesOutStream, "Localized messages..."); //$NON-NLS-1$
} finally {
messagesOutStream.close();
}
} catch (IOException e) {
new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, Messages.SmooksLaunchConfigurationDelegate_Error_Copying_Smooks_Launcher, e));
}
return wsTempClasses;
}
private void writeClassToFilesys(Class<?> theClass, File toDir) throws CoreException {
String className = theClass.getSimpleName() + ".class"; //$NON-NLS-1$
writeResourceToFilesys(className, theClass, toDir);
}
private void writeResourceToFilesys(String resource, Class<?> refClass, File toDir) {
String packagePath = refClass.getPackage().getName().replace(".", "/"); //$NON-NLS-1$ //$NON-NLS-2$
String resourcePath = "/" + packagePath + Messages.SmooksLaunchConfigurationDelegate_11 + resource; //$NON-NLS-1$
URL resourceURI = refClass.getResource(resourcePath);
if(resourceURI != null) {
try {
InputStream resourceStream = resourceURI.openStream();
if(resourceStream != null) {
try {
File resourceOutFile = new File(toDir, resourcePath);
File resourcePackage = resourceOutFile.getParentFile();
resourcePackage.mkdirs();
if(resourcePackage.exists()) {
FileOutputStream resourceOutStream = new FileOutputStream(resourceOutFile);
try {
byte[] readBuf = new byte[100];
int readCount = 0;
while(readCount != -1) {
readCount = resourceStream.read(readBuf);
if(readCount != -1) {
resourceOutStream.write(readBuf, 0, readCount);
}
}
} finally {
try {
resourceOutStream.flush();
} finally {
resourceOutStream.close();
}
}
}
} finally {
resourceStream.close();
}
}
} catch (IOException e) {
new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, Messages.SmooksLaunchConfigurationDelegate_Error_Copying_Smooks_Launcher, e));
}
}
}
private FileOutputStream getFilesysOutStream(String resource, Class<?> refClass, File toDir) throws FileNotFoundException {
String packagePath = refClass.getPackage().getName().replace(".", "/"); //$NON-NLS-1$ //$NON-NLS-2$
String resourcePath = "/" + packagePath + "/" + resource; //$NON-NLS-1$ //$NON-NLS-2$
File resourceOutFile = new File(toDir, resourcePath);
File resourcePackage = resourceOutFile.getParentFile();
resourcePackage.mkdirs();
return new FileOutputStream(resourceOutFile);
}
private URLClassLoader toURLClassLoader(String[] baseClasspath) {
URL[] classPathURLs = new URL[baseClasspath.length];
for(int i = 0; i < baseClasspath.length; i++) {
try {
File cpEntry = new File(baseClasspath[i]);
classPathURLs[i] = cpEntry.toURL();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
return new URLClassLoader(classPathURLs);
}
}