blob: 6d8fa62d8701ef356a99ab395d76e72530978370 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 Angelo Zerr 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:
* Angelo Zerr <angelo.zerr@gmail.com> - Initial API and implementation
*******************************************************************************/
package org.eclipse.jst.server.jetty.core.internal;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.core.runtime.IPath;
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.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.Launch;
import org.eclipse.debug.core.model.IStreamsProxy;
import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMInstallType;
import org.eclipse.jdt.launching.IVMRunner;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.VMRunnerConfiguration;
import org.eclipse.jst.server.jetty.core.IJettyRuntimeWorkingCopy;
import org.eclipse.jst.server.jetty.core.JettyPlugin;
import org.eclipse.jst.server.jetty.core.internal.util.StringUtils;
import org.eclipse.wst.server.core.IRuntimeType;
import org.eclipse.wst.server.core.model.RuntimeDelegate;
/**
* Jetty Runtime.
*
*/
public class JettyRuntime extends RuntimeDelegate implements IJettyRuntime,
IJettyRuntimeWorkingCopy {
//private static final String TOOLS_JAR_PATH = "lib" + File.separator + "tools.jar";
private static final String JAVAC_MAIN = "com.sun.tools.javac.Main";
private static final String CLASS_DETECTOR = "org.eclipse.jst.server.Jetty.core.internal.ClassDetector";
protected static final String PROP_VM_INSTALL_TYPE_ID = "vm-install-type-id";
protected static final String PROP_VM_INSTALL_ID = "vm-install-id";
protected static Map<File, Boolean> sdkMap = new HashMap<File, Boolean>(2);
private static Map<String, Integer> javaVersionMap = new ConcurrentHashMap<String, Integer>();
public JettyRuntime() {
// do nothing
}
public IJettyVersionHandler getVersionHandler() {
IRuntimeType type = getRuntime().getRuntimeType();
return JettyPlugin.getJettyVersionHandler(type.getId());
}
protected String getVMInstallTypeId() {
return getAttribute(PROP_VM_INSTALL_TYPE_ID, (String) null);
}
protected String getVMInstallId() {
return getAttribute(PROP_VM_INSTALL_ID, (String) null);
}
public boolean isUsingDefaultJRE() {
return getVMInstallTypeId() == null;
}
public IVMInstall getVMInstall() {
if (getVMInstallTypeId() == null)
return JavaRuntime.getDefaultVMInstall();
try {
IVMInstallType vmInstallType = JavaRuntime
.getVMInstallType(getVMInstallTypeId());
IVMInstall[] vmInstalls = vmInstallType.getVMInstalls();
int size = vmInstalls.length;
String id = getVMInstallId();
for (int i = 0; i < size; i++) {
if (id.equals(vmInstalls[i].getId()))
return vmInstalls[i];
}
} catch (Exception e) {
// ignore
}
return null;
}
public Collection<IRuntimeClasspathEntry> getRuntimeClasspath(
IPath configPath) {
IPath installPath = getRuntime().getLocation();
// If installPath is relative, convert to canonical path and hope for
// the best
if (!installPath.isAbsolute()) {
try {
String installLoc = (new File(installPath.toOSString()))
.getCanonicalPath();
installPath = new Path(installLoc);
} catch (IOException e) {
// Ignore if there is a problem
}
}
return getVersionHandler().getRuntimeClasspath(installPath, configPath);
}
/**
* Verifies the Jetty installation directory. If it is correct, true is
* returned. Otherwise, the user is notified and false is returned.
*
* @return boolean
*/
public IStatus verifyLocation() {
return getVersionHandler()
.verifyInstallPath(getRuntime().getLocation());
}
/*
* Validate the runtime
*/
public IStatus validate() {
IStatus status = super.validate();
if (!status.isOK())
return status;
status = verifyLocation();
if (!status.isOK())
return status;
// don't accept trailing space since that can cause startup problems
if (getRuntime().getLocation().hasTrailingSeparator())
return new Status(IStatus.ERROR, JettyPlugin.PLUGIN_ID, 0,
Messages.errorInstallDirTrailingSlash, null);
if (getVMInstall() == null)
return new Status(IStatus.ERROR, JettyPlugin.PLUGIN_ID, 0,
Messages.errorJRE, null);
// check for tools.jar (contains the javac compiler on Windows & Linux)
// to see whether
// Jetty will be able to compile JSPs.
// boolean found = false;
// File file = getVMInstall().getInstallLocation();
// if (file != null) {
// File toolsJar = new File(file, TOOLS_JAR_PATH);
// if (toolsJar.exists())
// found = true;
// }
status = getVersionHandler().validate(getRuntime().getLocation(), getVMInstall());
if (status != null) {
return status;
}
return Status.OK_STATUS;
// // on Jetty 5.5 and 6.0, the Eclipse JDT compiler is used for JSP's
// String id = getRuntime().getRuntimeType().getId();
// if (!found) {
// if (id != null && (id.indexOf("55") > 0 || id.indexOf("60") > 0))
// found = true;
// }
//
// // on Mac, tools.jar is merged into classes.zip. if tools.jar wasn't
// // found,
// // try loading the javac class by running a check inside the VM
// if (!found) {
// String os = Platform.getOS();
// if (os != null && os.toLowerCase().indexOf("mac") >= 0)
// found = checkForCompiler();
// }
//
// if (!found)
// return new Status(IStatus.WARNING, JettyPlugin.PLUGIN_ID, 0,
// Messages.warningJRE, null);
//
// File f = getRuntime().getLocation().append("conf").toFile();
// File[] conf = f.listFiles();
// if (conf != null) {
// int size = conf.length;
// for (int i = 0; i < size; i++) {
// if (!f.canRead())
// return new Status(IStatus.WARNING, JettyPlugin.PLUGIN_ID,
// 0, Messages.warningCantReadConfig, null);
// }
// }
//
// // For Jetty 6.0, ensure we have J2SE 5.0
// if (id != null && id.indexOf("60") > 0) {
// IVMInstall vmInstall = getVMInstall();
// if (vmInstall instanceof IVMInstall2) {
// String javaVersion = ((IVMInstall2) vmInstall).getJavaVersion();
// if (javaVersion != null
// && !isVMMinimumVersion(javaVersion, 105)) {
// return new Status(IStatus.ERROR, JettyPlugin.PLUGIN_ID, 0,
// Messages.errorJREJetty60, null);
// }
// }
// }
// // Else for Jetty 7.0, ensure we have J2SE 6.0
// else if (id != null && id.indexOf("70") > 0) {
// IVMInstall vmInstall = getVMInstall();
// if (vmInstall instanceof IVMInstall2) {
// String javaVersion = ((IVMInstall2) vmInstall).getJavaVersion();
// if (javaVersion != null
// && !isVMMinimumVersion(javaVersion, 106)) {
// return new Status(IStatus.ERROR, JettyPlugin.PLUGIN_ID, 0,
// Messages.errorJREJetty70, null);
// }
// }
// }
// return Status.OK_STATUS;
}
/**
* @see RuntimeDelegate#setDefaults(IProgressMonitor)
*/
public void setDefaults(IProgressMonitor monitor) {
IRuntimeType type = getRuntimeWorkingCopy().getRuntimeType();
getRuntimeWorkingCopy().setLocation(
new Path(JettyPlugin.getPreference("location" + type.getId())));
}
public void setVMInstall(IVMInstall vmInstall) {
if (vmInstall == null) {
setVMInstall(null, null);
} else
setVMInstall(vmInstall.getVMInstallType().getId(),
vmInstall.getId());
}
protected void setVMInstall(String typeId, String id) {
if (typeId == null)
setAttribute(PROP_VM_INSTALL_TYPE_ID, (String) null);
else
setAttribute(PROP_VM_INSTALL_TYPE_ID, typeId);
if (id == null)
setAttribute(PROP_VM_INSTALL_ID, (String) null);
else
setAttribute(PROP_VM_INSTALL_ID, id);
}
/**
* Checks for the existence of the Java compiler in the given java
* executable. A main program is run (<code>org.eclipse.jst.Jetty.core.
* internal.ClassDetector</code>), that dumps a true or false value
* depending on whether the compiler is found. This output is then parsed
* and cached for future reference.
*
* @return true if the compiler was found
*/
protected boolean checkForCompiler() {
// first try the cache
File javaHome = getVMInstall().getInstallLocation();
try {
Boolean b = (Boolean) sdkMap.get(javaHome);
return b.booleanValue();
} catch (Exception e) {
// ignore
}
// locate Jettycore.jar - it contains the class detector main program
File file = JettyPlugin.getPlugin();
if (file != null && file.exists()) {
IVMRunner vmRunner = getVMInstall().getVMRunner(
ILaunchManager.RUN_MODE);
VMRunnerConfiguration config = new VMRunnerConfiguration(
CLASS_DETECTOR,
new String[] { file.getAbsolutePath() });
config.setProgramArguments(new String[] { JAVAC_MAIN });
ILaunch launch = new Launch(null, ILaunchManager.RUN_MODE, null);
try {
vmRunner.run(config, launch, null);
for (int i = 0; i < 600; i++) {
// wait no more than 30 seconds (600 * 50 mils)
if (launch.isTerminated()) {
break;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// ignore
}
}
IStreamsProxy streamsProxy = launch.getProcesses()[0]
.getStreamsProxy();
String text = null;
if (streamsProxy != null) {
text = streamsProxy.getOutputStreamMonitor().getContents();
if (text != null && text.length() > 0) {
boolean found = false;
if (StringUtils.isTrue(text))
found = true;
sdkMap.put(javaHome, new Boolean(found));
return found;
}
}
} catch (Exception e) {
Trace.trace(Trace.SEVERE, "Error checking for JDK", e);
} finally {
if (!launch.isTerminated()) {
try {
launch.terminate();
} catch (Exception ex) {
// ignore
}
}
}
}
// log error that we were unable to check for the compiler
JettyPlugin.log(MessageFormat.format("Failed compiler check for {0}",
javaHome.getAbsolutePath()));
return false;
}
private boolean isVMMinimumVersion(String javaVersion, int minimumVersion) {
Integer version = (Integer) javaVersionMap.get(javaVersion);
if (version == null) {
int index = javaVersion.indexOf('.');
if (index > 0) {
try {
int major = Integer.parseInt(javaVersion
.substring(0, index)) * 100;
index++;
int index2 = javaVersion.indexOf('.', index);
if (index2 > 0) {
int minor = Integer.parseInt(javaVersion.substring(
index, index2));
version = new Integer(major + minor);
javaVersionMap.put(javaVersion, version);
}
} catch (NumberFormatException e) {
// Ignore
}
}
}
// If we have a version, and it's less than the minimum, fail the check
if (version != null && version.intValue() < minimumVersion) {
return false;
}
return true;
}
}