blob: 79664fe5991a55c70dbd064f8d652897b8908d76 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.launching;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate;
import org.eclipse.jdt.launching.ExecutionArguments;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMRunner;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.VMRunnerConfiguration;
public class JavaAppletLaunchConfigurationDelegate extends AbstractJavaLaunchConfigurationDelegate
implements IDebugEventSetListener {
/**
* Mapping of ILaunch objects to File objects that represent the .html file
* used to initiate the applet launch. This is used to delete the .html
* file when the launch terminates.
*/
private static Map fgLaunchToFileMap = new HashMap();
/* (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 configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
if (configuration == null) {
abort(LaunchingMessages.getString("JavaAppletLaunchConfigurationDelegate.No_launch_configuration_specified_1"), null, IJavaLaunchConfigurationConstants.ERR_UNSPECIFIED_LAUNCH_CONFIG); //$NON-NLS-1$
}
monitor.beginTask(MessageFormat.format(LaunchingMessages.getString("JavaAppletLaunchConfigurationDelegate.Starting_Applet_{0}..._1"), new String[]{configuration.getName()}), 3); //$NON-NLS-1$
monitor.subTask(LaunchingMessages.getString("JavaAppletLaunchConfigurationDelegate.Verifying_launch_attributes..._1")); //$NON-NLS-1$
verifyMainTypeName(configuration);
IVMInstall vm = verifyVMInstall(configuration);
IVMRunner runner = vm.getVMRunner(mode);
if (runner == null) {
if (mode == ILaunchManager.DEBUG_MODE) {
abort(MessageFormat.format(LaunchingMessages.getString("JavaLocalApplicationLaunchConfigurationDelegate.0"), new String[]{vm.getName()}), null, IJavaLaunchConfigurationConstants.ERR_VM_RUNNER_DOES_NOT_EXIST); //$NON-NLS-1$
} else {
abort(MessageFormat.format(LaunchingMessages.getString("JavaLocalApplicationLaunchConfigurationDelegate.1"), new String[]{vm.getName()}), null, IJavaLaunchConfigurationConstants.ERR_VM_RUNNER_DOES_NOT_EXIST); //$NON-NLS-1$
}
}
File workingDir = verifyWorkingDirectory(configuration);
String workingDirName = workingDir.getAbsolutePath();
// Program & VM args
String javaPolicy = getJavaPolicyFile(workingDir);
ExecutionArguments execArgs = new ExecutionArguments(getVMArguments(configuration), ""); //$NON-NLS-1$
// Classpath
String[] classpath = getClasspath(configuration);
// Create VM config
String appletViewerClassName = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_APPLET_APPLETVIEWER_CLASS, IJavaLaunchConfigurationConstants.DEFAULT_APPLETVIEWER_CLASS);
VMRunnerConfiguration runConfig = new VMRunnerConfiguration(appletViewerClassName, classpath);
// Construct the HTML file and set its name as a program argument
File htmlFile = buildHTMLFile(configuration, workingDir);
if (htmlFile == null) {
abort(LaunchingMessages.getString("JavaAppletLaunchConfigurationDelegate.Could_not_build_HTML_file_for_applet_launch_1"), null, IJavaLaunchConfigurationConstants.ERR_COULD_NOT_BUILD_HTML); //$NON-NLS-1$
}
runConfig.setProgramArguments(new String[] {htmlFile.getName()});
// Retrieve & set the VM arguments
String[] vmArgs = execArgs.getVMArgumentsArray();
String[] realArgs = new String[vmArgs.length+1];
System.arraycopy(vmArgs, 0, realArgs, 1, vmArgs.length);
realArgs[0] = javaPolicy;
runConfig.setVMArguments(realArgs);
runConfig.setWorkingDirectory(workingDirName);
// Bootpath
runConfig.setBootClassPath(getBootpath(configuration));
// VM-specific attributes
Map vmAttributesMap = getVMSpecificAttributesMap(configuration);
runConfig.setVMSpecificAttributesMap(vmAttributesMap);
monitor.worked(1);
// Add a debug listener if necessary
if (fgLaunchToFileMap.isEmpty()) {
DebugPlugin.getDefault().addDebugEventListener(this);
}
// Add a mapping of the launch to the html file
fgLaunchToFileMap.put(launch, htmlFile);
monitor.subTask(LaunchingMessages.getString("JavaAppletLaunchConfigurationDelegate.Creating_source_locator..._2")); //$NON-NLS-1$
// Set default source locator if none specified
setDefaultSourceLocator(launch, configuration);
monitor.worked(1);
// Launch the configuration
try {
runner.run(runConfig, launch, monitor);
} catch (CoreException ce) {
htmlFile.delete();
throw ce;
}
monitor.done();
}
/**
* Returns the system property string for the policy file
*
* @param workingDir the working directory
* @return system property for the policy file
*/
public String getJavaPolicyFile(File workingDir) {
File file = new File(workingDir, "java.policy.applet");//$NON-NLS-1$
if (!file.exists()) {
// copy it to the working directory
File test = LaunchingPlugin.getFileInPlugin(new Path("java.policy.applet")); //$NON-NLS-1$
try {
byte[] bytes = getFileByteContent(test);
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file));
outputStream.write(bytes);
outputStream.close();
} catch (IOException e) {
return "";//$NON-NLS-1$
}
}
return "-Djava.security.policy=java.policy.applet";//$NON-NLS-1$
}
/**
* Using the specified launch configuration, build an HTML file that specifies the
* applet to launch. Return the name of the HTML file.
*
* @param dir the directoru in which to make the file
*/
private File buildHTMLFile(ILaunchConfiguration configuration, File dir) {
FileWriter writer = null;
File tempFile = null;
try {
String name = getMainTypeName(configuration);
tempFile = new File(dir, name + System.currentTimeMillis() + ".html"); //$NON-NLS-1$ //$NON-NLS-2$
writer = new FileWriter(tempFile);
writer.write("<html>\n"); //$NON-NLS-1$
writer.write("<body>\n"); //$NON-NLS-1$
writer.write("<applet code="); //$NON-NLS-1$
writer.write(name);
writer.write(".class "); //$NON-NLS-1$
String appletName = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_APPLET_NAME, ""); //$NON-NLS-1$
if (appletName.length() != 0) {
writer.write("NAME =\"" + appletName + "\" "); //$NON-NLS-1$ //$NON-NLS-2$
}
writer.write("width=\""); //$NON-NLS-1$
writer.write(Integer.toString(configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_APPLET_WIDTH, 200))); //$NON-NLS-1$
writer.write("\" height=\""); //$NON-NLS-1$
writer.write(Integer.toString(configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_APPLET_HEIGHT, 200))); //$NON-NLS-1$
writer.write("\" >\n"); //$NON-NLS-1$
Map parameters = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_APPLET_PARAMETERS, new HashMap());
if (parameters.size() != 0) {
Iterator iterator= parameters.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry next = (Map.Entry) iterator.next();
writer.write("<param name="); //$NON-NLS-1$
writer.write(getQuotedString((String)next.getKey()));
writer.write(" value="); //$NON-NLS-1$
writer.write(getQuotedString((String)next.getValue()));
writer.write(">\n"); //$NON-NLS-1$
}
}
writer.write("</applet>\n"); //$NON-NLS-1$
writer.write("</body>\n"); //$NON-NLS-1$
writer.write("</html>\n"); //$NON-NLS-1$
} catch(IOException e) {
} catch(CoreException e) {
} finally {
if (writer != null) {
try {
writer.close();
} catch(IOException e) {
}
}
}
if (tempFile == null) {
return null;
}
return tempFile;
}
private String getQuotedString(String string) {
if (string.indexOf('"') == -1) {
return '"' + string + '"';
}
return '\'' + string + '\'';
}
/* (non-Javadoc)
* @see org.eclipse.debug.core.IDebugEventSetListener#handleDebugEvents(org.eclipse.debug.core.DebugEvent[])
*/
public void handleDebugEvents(DebugEvent[] events) {
for (int i = 0; i < events.length; i++) {
DebugEvent event = events[i];
Object eventSource = event.getSource();
switch(event.getKind()) {
// Delete the HTML file used for the launch
case DebugEvent.TERMINATE :
if (eventSource != null) {
ILaunch launch = null;
if (eventSource instanceof IProcess) {
IProcess process = (IProcess) eventSource;
launch = process.getLaunch();
} else if (eventSource instanceof IDebugTarget) {
IDebugTarget debugTarget = (IDebugTarget) eventSource;
launch = debugTarget.getLaunch();
}
File temp = (File) fgLaunchToFileMap.get(launch);
if (temp != null) {
try {
fgLaunchToFileMap.remove(launch);
temp.delete();
} finally {
if (fgLaunchToFileMap.isEmpty()) {
DebugPlugin.getDefault().removeDebugEventListener(this);
}
}
}
}
break;
}
}
}
/**
* Returns the contents of the given file as a byte array.
* @throws IOException if a problem occured reading the file.
*/
protected static byte[] getFileByteContent(File file) throws IOException {
InputStream stream = null;
try {
stream = new BufferedInputStream(new FileInputStream(file));
return getInputStreamAsByteArray(stream, (int) file.length());
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
}
}
}
}
/**
* Returns the given input stream's contents as a byte array.
* If a length is specified (ie. if length != -1), only length bytes
* are returned. Otherwise all bytes in the stream are returned.
* Note this doesn't close the stream.
* @throws IOException if a problem occured reading the stream.
*/
protected static byte[] getInputStreamAsByteArray(InputStream stream, int length)
throws IOException {
byte[] contents;
if (length == -1) {
contents = new byte[0];
int contentsLength = 0;
int bytesRead = -1;
do {
int available = stream.available();
// resize contents if needed
if (contentsLength + available > contents.length) {
System.arraycopy(
contents,
0,
contents = new byte[contentsLength + available],
0,
contentsLength);
}
// read as many bytes as possible
bytesRead = stream.read(contents, contentsLength, available);
if (bytesRead > 0) {
// remember length of contents
contentsLength += bytesRead;
}
} while (bytesRead > 0);
// resize contents if necessary
if (contentsLength < contents.length) {
System.arraycopy(
contents,
0,
contents = new byte[contentsLength],
0,
contentsLength);
}
} else {
contents = new byte[length];
int len = 0;
int readSize = 0;
while ((readSize != -1) && (len != length)) {
// See PR 1FMS89U
// We record first the read size. In this case len is the actual read size.
len += readSize;
readSize = stream.read(contents, len, length - len);
}
}
return contents;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#verifyWorkingDirectory(org.eclipse.debug.core.ILaunchConfiguration)
*/
public File verifyWorkingDirectory(ILaunchConfiguration configuration) throws CoreException {
IPath path = getWorkingDirectoryPath(configuration);
if (path == null) {
// default working dir for applets is the project's output directory
String outputDir = JavaRuntime.getProjectOutputDirectory(configuration);
if (outputDir == null) {
// if no project attribute, default to eclipse directory
return new File(System.getProperty("user.dir")); //$NON-NLS-1$
}
IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(outputDir);
if (resource == null || !resource.exists()) {
//default to eclipse directory
return new File(System.getProperty("user.dir")); //$NON-NLS-1$
}
return resource.getLocation().toFile();
}
if (path.isAbsolute()) {
File dir = new File(path.toOSString());
if (dir.isDirectory()) {
return dir;
}
abort(MessageFormat.format(LaunchingMessages.getString("AbstractJavaLaunchConfigurationDelegate.Working_directory_does_not_exist__{0}_12"), new String[] {path.toString()}), null, IJavaLaunchConfigurationConstants.ERR_WORKING_DIRECTORY_DOES_NOT_EXIST); //$NON-NLS-1$
} else {
IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
if (res instanceof IContainer && res.exists()) {
return res.getLocation().toFile();
}
abort(MessageFormat.format(LaunchingMessages.getString("AbstractJavaLaunchConfigurationDelegate.Working_directory_does_not_exist__{0}_12"), new String[] {path.toString()}), null, IJavaLaunchConfigurationConstants.ERR_WORKING_DIRECTORY_DOES_NOT_EXIST); //$NON-NLS-1$
}
// cannot return null - an exception will be thrown
return null;
}
}