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.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
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.model.IDebugTarget;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.JavaLaunchDelegate;
import org.eclipse.jdt.launching.JavaRuntime;
public class JavaAppletLaunchConfigurationDelegate extends JavaLaunchDelegate implements IDebugEventSetListener {
private static Map<ILaunch, File> fgLaunchToFileMap = new HashMap<>();
private ILaunch fLaunch;
@Override
public synchronized void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
try {
fLaunch = launch;
super.launch(configuration, mode, launch, monitor);
} catch (CoreException e) {
cleanup(launch);
throw e;
}
fLaunch = null;
}
public String getJavaPolicyFile(File workingDir) {
File file = new File(workingDir, "java.policy.applet");
if (!file.exists()) {
File test = LaunchingPlugin.getFileInPlugin(new Path("java.policy.applet"));
try (BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file))) {
byte[] bytes = getFileByteContent(test);
outputStream.write(bytes);
} catch (IOException e) {
return "";
}
}
return "-Djava.security.policy=java.policy.applet";
}
private File buildHTMLFile(ILaunchConfiguration configuration, File dir) throws CoreException {
String name = getAppletMainTypeName(configuration);
File tempFile = new File(dir, name + System.currentTimeMillis() + ".html");
try (FileOutputStream stream = new FileOutputStream(tempFile)) {
String encoding = getLaunchManager().getEncoding(configuration);
StringBuilder buf = new StringBuilder();
buf.append("<html>\n");
buf.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + encoding + "\"/>\n");
buf.append("<body>\n");
buf.append("<applet code=");
buf.append(name);
buf.append(".class ");
String appletName = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_APPLET_NAME, "");
if (appletName.length() != 0) {
buf.append("NAME =\"" + appletName + "\" ");
}
buf.append("width=\"");
buf.append(Integer.toString(configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_APPLET_WIDTH, 200)));
buf.append("\" height=\"");
buf.append(Integer.toString(configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_APPLET_HEIGHT, 200)));
buf.append("\" >\n");
Map<String, String> parameters = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_APPLET_PARAMETERS, new HashMap<String, String>());
if (parameters.size() != 0) {
Iterator<Entry<String, String>> iterator = parameters.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, String> next = iterator.next();
buf.append("<param name=");
buf.append(getQuotedString(next.getKey()));
buf.append(" value=");
buf.append(getQuotedString(next.getValue()));
buf.append(">\n");
}
}
buf.append("</applet>\n");
buf.append("</body>\n");
buf.append("</html>\n");
stream.write(buf.toString().getBytes(encoding));
} catch(IOException e) {
LaunchingPlugin.log(e);
}
return tempFile;
}
private String getQuotedString(String string) {
int singleQuotes = count(string, '\'');
int doubleQuotes = count(string, '"');
if (doubleQuotes == 0) {
return '"' + string + '"';
} else if (singleQuotes == 0) {
return '\'' + string + '\'';
} else {
return '"' + convertToHTMLContent(string) + '"';
}
}
private static int count(String string, char character) {
int count = 0;
for (int i = 0; i < string.length(); i++) {
if (string.charAt(i) == character) {
count++;
}
}
return count;
}
private static String convertToHTMLContent(String content) {
content = replace(content, '"', """);
content = replace(content, '\'', "'");
return content;
}
private static String replace(String text, char c, String s) {
int previous = 0;
int current = text.indexOf(c, previous);
if (current == -1) {
return text;
}
StringBuilder buffer = new StringBuilder();
while (current > -1) {
buffer.append(text.substring(previous, current));
buffer.append(s);
previous = current + 1;
current = text.indexOf(c, previous);
}
buffer.append(text.substring(previous));
return buffer.toString();
}
@Override
public void handleDebugEvents(DebugEvent[] events) {
for (int i = 0; i < events.length; i++) {
DebugEvent event = events[i];
Object eventSource = event.getSource();
switch(event.getKind()) {
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();
}
if (launch != null) {
cleanup(launch);
}
}
break;
}
}
}
private void cleanup(ILaunch launch) {
File temp = fgLaunchToFileMap.get(launch);
if (temp != null) {
try {
fgLaunchToFileMap.remove(launch);
temp.delete();
} finally {
if (fgLaunchToFileMap.isEmpty()) {
DebugPlugin.getDefault().removeDebugEventListener(this);
}
}
}
}
protected static byte[] getFileByteContent(File file) throws IOException {
try (InputStream stream = new BufferedInputStream(new FileInputStream(file))) {
return getInputStreamAsByteArray(stream, (int) file.length());
}
}
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();
if (contentsLength + available > contents.length) {
System.arraycopy(
contents,
0,
contents = new byte[contentsLength + available],
0,
contentsLength);
}
bytesRead = stream.read(contents, contentsLength, available);
if (bytesRead > 0) {
contentsLength += bytesRead;
}
} while (bytesRead > 0);
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)) {
len += readSize;
readSize = stream.read(contents, len, length - len);
}
}
return contents;
}
@Override
public String getProgramArguments(ILaunchConfiguration configuration) throws CoreException {
File workingDir = verifyWorkingDirectory(configuration);
File htmlFile = buildHTMLFile(configuration, workingDir);
if (htmlFile == null) {
abort(LaunchingMessages.JavaAppletLaunchConfigurationDelegate_Could_not_build_HTML_file_for_applet_launch_1, null, IJavaLaunchConfigurationConstants.ERR_COULD_NOT_BUILD_HTML);
}
if (fgLaunchToFileMap.isEmpty()) {
DebugPlugin.getDefault().addDebugEventListener(this);
}
fgLaunchToFileMap.put(fLaunch, htmlFile);
return htmlFile.getName();
}
@Override
public String getVMArguments(ILaunchConfiguration configuration) throws CoreException {
StringBuilder arguments = new StringBuilder(super.getVMArguments(configuration));
File workingDir = verifyWorkingDirectory(configuration);
String javaPolicyFile = getJavaPolicyFile(workingDir);
arguments.append(" ");
arguments.append(javaPolicyFile);
return arguments.toString();
}
@Override
public String getMainTypeName(ILaunchConfiguration configuration) throws CoreException {
return configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_APPLET_APPLETVIEWER_CLASS, IJavaLaunchConfigurationConstants.DEFAULT_APPLETVIEWER_CLASS);
}
protected String getAppletMainTypeName(ILaunchConfiguration configuration) throws CoreException {
return super.getMainTypeName(configuration);
}
@Override
protected File getDefaultWorkingDirectory(ILaunchConfiguration configuration) throws CoreException {
String outputDir = JavaRuntime.getProjectOutputDirectory(configuration);
if (outputDir == null) {
return new File(System.getProperty("user.dir"));
}
IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(outputDir);
if (resource == null || !resource.exists()) {
return new File(System.getProperty("user.dir"));
}
return resource.getLocation().toFile();
}
}