/******************************************************************************* | |
* Copyright (c) 2003, 2010 IBM Corporation 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: | |
* IBM Corporation - Initial API and implementation | |
* Angelo Zerr <angelo.zerr@gmail.com> - Jetty packages | |
*******************************************************************************/ | |
package org.eclipse.jst.server.jetty.core.internal; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.Properties; | |
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.IStatus; | |
import org.eclipse.core.runtime.NullProgressMonitor; | |
import org.eclipse.core.runtime.Path; | |
import org.eclipse.core.runtime.Status; | |
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.ILaunchConfigurationWorkingCopy; | |
import org.eclipse.debug.core.ILaunchManager; | |
import org.eclipse.debug.core.model.IProcess; | |
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; | |
import org.eclipse.jdt.launching.IRuntimeClasspathEntry; | |
import org.eclipse.jdt.launching.IVMInstall; | |
import org.eclipse.jdt.launching.JavaRuntime; | |
import org.eclipse.jst.server.core.IJ2EEModule; | |
import org.eclipse.jst.server.core.IWebModule; | |
import org.eclipse.jst.server.core.internal.ProgressUtil; | |
import org.eclipse.jst.server.jetty.core.IJettyConfiguration; | |
import org.eclipse.jst.server.jetty.core.JettyPlugin; | |
import org.eclipse.jst.server.jetty.core.WebModule; | |
import org.eclipse.jst.server.jetty.core.internal.util.JettyVersionHelper; | |
import org.eclipse.jst.server.jetty.core.internal.util.StringUtils; | |
import org.eclipse.osgi.util.NLS; | |
import org.eclipse.wst.server.core.IModule; | |
import org.eclipse.wst.server.core.IServer; | |
import org.eclipse.wst.server.core.ServerPort; | |
import org.eclipse.wst.server.core.internal.IModulePublishHelper; | |
import org.eclipse.wst.server.core.internal.Server; | |
import org.eclipse.wst.server.core.model.IModuleResource; | |
import org.eclipse.wst.server.core.model.IModuleResourceDelta; | |
import org.eclipse.wst.server.core.model.ServerBehaviourDelegate; | |
import org.eclipse.wst.server.core.util.PublishHelper; | |
import org.eclipse.wst.server.core.util.SocketUtil; | |
public class JettyServerBehaviour extends ServerBehaviourDelegate implements | |
IJettyServerBehaviour, IModulePublishHelper { | |
private static final String ATTR_STOP = "stop-server"; | |
private static final String[] JMX_EXCLUDE_ARGS = new String[] { | |
"-Dcom.sun.management.jmxremote", | |
"-Dcom.sun.management.jmxremote.port=", | |
"-Dcom.sun.management.jmxremote.ssl=", | |
"-Dcom.sun.management.jmxremote.authenticate=" }; | |
// the thread used to ping the server to check for startup | |
protected transient PingThread ping = null; | |
protected transient IDebugEventSetListener processListener; | |
/** | |
* JettyServerBehaviour. | |
*/ | |
public JettyServerBehaviour() { | |
super(); | |
} | |
public void initialize(IProgressMonitor monitor) { | |
// do nothing | |
} | |
public JettyRuntime getJettyRuntime() { | |
if (getServer().getRuntime() == null) | |
return null; | |
return (JettyRuntime) getServer().getRuntime().loadAdapter( | |
JettyRuntime.class, null); | |
} | |
public IJettyVersionHandler getJettyVersionHandler() { | |
return getJettyServer().getJettyVersionHandler(); | |
} | |
public IJettyConfiguration getJettyConfiguration() throws CoreException { | |
return getJettyServer().getJettyConfiguration(); | |
} | |
public JettyServer getJettyServer() { | |
return (JettyServer) getServer().loadAdapter(JettyServer.class, null); | |
} | |
/** | |
* Return the runtime class name. | |
* | |
* @return the class name | |
*/ | |
public String getRuntimeClass() { | |
return getJettyVersionHandler().getRuntimeClass(); | |
} | |
/** | |
* Returns the runtime base path for relative paths in the server | |
* configuration. | |
* | |
* @return the base path | |
*/ | |
public IPath getRuntimeBaseDirectory() { | |
return getJettyServer().getRuntimeBaseDirectory(); | |
} | |
/** | |
* Return the program's runtime arguments to start or stop. | |
* | |
* @param starting | |
* true if starting | |
* @return an array of runtime program arguments | |
*/ | |
protected String[] getRuntimeProgramArguments(boolean starting) { | |
IPath configPath = null; | |
if (getJettyServer().isTestEnvironment()) | |
configPath = getRuntimeBaseDirectory(); | |
return getJettyVersionHandler().getRuntimeProgramArguments(configPath, | |
getJettyServer().isDebug(), starting); | |
} | |
protected String[] getExcludedRuntimeProgramArguments(boolean starting) { | |
return getJettyVersionHandler().getExcludedRuntimeProgramArguments( | |
getJettyServer().isDebug(), starting); | |
} | |
/** | |
* Return the runtime (VM) arguments. | |
* | |
* @return an array of runtime arguments | |
*/ | |
protected String[] getRuntimeVMArguments() { | |
IPath installPath = getServer().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 | |
} | |
} | |
IPath configPath = getRuntimeBaseDirectory(); | |
IPath deployPath; | |
// If serving modules without publishing, use workspace path as the | |
// deploy path | |
if (getJettyServer().isServeModulesWithoutPublish()) { | |
deployPath = ResourcesPlugin.getWorkspace().getRoot().getLocation(); | |
} | |
// Else normal publishing for modules | |
else { | |
deployPath = getServerDeployDirectory(); | |
// If deployPath is relative, convert to canonical path and hope for | |
// the best | |
if (!deployPath.isAbsolute()) { | |
try { | |
String deployLoc = (new File(deployPath.toOSString())) | |
.getCanonicalPath(); | |
deployPath = new Path(deployLoc); | |
} catch (IOException e) { | |
// Ignore if there is a problem | |
} | |
} | |
} | |
return getJettyVersionHandler().getRuntimeVMArguments(installPath, | |
configPath, deployPath, getJettyServer().isTestEnvironment()); | |
} | |
protected String getRuntimePolicyFile() { | |
IPath configPath = getRuntimeBaseDirectory(); | |
return getJettyVersionHandler().getRuntimePolicyFile(configPath); | |
} | |
protected static String renderCommandLine(String[] commandLine, | |
String separator) { | |
if (commandLine == null || commandLine.length < 1) | |
return ""; | |
StringBuffer buf = new StringBuffer(commandLine[0]); | |
for (int i = 1; i < commandLine.length; i++) { | |
buf.append(separator); | |
buf.append(commandLine[i]); | |
} | |
return buf.toString(); | |
} | |
/** | |
* Setup for starting the server. | |
* | |
* @param launch | |
* ILaunch | |
* @param launchMode | |
* String | |
* @param monitor | |
* IProgressMonitor | |
* @throws CoreException | |
* if anything goes wrong | |
*/ | |
public void setupLaunch(ILaunch launch, String launchMode, | |
IProgressMonitor monitor) throws CoreException { | |
if (StringUtils.isTrue(launch.getLaunchConfiguration().getAttribute( | |
ATTR_STOP, StringUtils.FALSE))) | |
return; | |
// if (getJettyRuntime() == null) | |
// throw new CoreException(); | |
IStatus status = getJettyRuntime().validate(); | |
if (status != null && status.getSeverity() == IStatus.ERROR) | |
throw new CoreException(status); | |
// setRestartNeeded(false); | |
IJettyConfiguration configuration = getJettyConfiguration(); | |
// check that ports are free | |
Iterator iterator = configuration.getServerPorts().iterator(); | |
List usedPorts = new ArrayList(); | |
while (iterator.hasNext()) { | |
ServerPort sp = (ServerPort) iterator.next(); | |
if (sp.getPort() < 0) | |
throw new CoreException(new Status(IStatus.ERROR, | |
JettyPlugin.PLUGIN_ID, 0, Messages.errorPortInvalid, | |
null)); | |
if (SocketUtil.isPortInUse(sp.getPort(), 5)) { | |
usedPorts.add(sp); | |
} | |
} | |
if (usedPorts.size() == 1) { | |
ServerPort port = (ServerPort) usedPorts.get(0); | |
throw new CoreException(new Status(IStatus.ERROR, | |
JettyPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorPortInUse, | |
new String[] { port.getPort() + "", | |
getServer().getName() }), null)); | |
} else if (usedPorts.size() > 1) { | |
String portStr = ""; | |
iterator = usedPorts.iterator(); | |
boolean first = true; | |
while (iterator.hasNext()) { | |
if (!first) | |
portStr += ", "; | |
first = false; | |
ServerPort sp = (ServerPort) iterator.next(); | |
portStr += "" + sp.getPort(); | |
} | |
throw new CoreException(new Status(IStatus.ERROR, | |
JettyPlugin.PLUGIN_ID, 0, NLS.bind( | |
Messages.errorPortsInUse, new String[] { portStr, | |
getServer().getName() }), null)); | |
} | |
// check that there is only one app for each context root | |
iterator = configuration.getWebModules().iterator(); | |
List contextRoots = new ArrayList(); | |
while (iterator.hasNext()) { | |
WebModule module = (WebModule) iterator.next(); | |
String contextRoot = module.getPath(); | |
if (contextRoots.contains(contextRoot)) | |
throw new CoreException(new Status(IStatus.ERROR, | |
JettyPlugin.PLUGIN_ID, 0, NLS.bind( | |
Messages.errorDuplicateContextRoot, | |
new String[] { contextRoot }), null)); | |
contextRoots.add(contextRoot); | |
} | |
setServerRestartState(false); | |
setServerState(IServer.STATE_STARTING); | |
setMode(launchMode); | |
// ping server to check for startup | |
try { | |
String url = "http://" + getServer().getHost(); | |
int port = configuration.getMainPort().getPort(); | |
if (port != 80) | |
url += ":" + port; | |
ping = new PingThread(getServer(), url, -1, this); | |
} catch (Exception e) { | |
Trace.trace(Trace.SEVERE, "Can't ping for Jetty startup."); | |
} | |
} | |
/** | |
* Cleanly shuts down and terminates the server. | |
* | |
* @param force | |
* <code>true</code> to kill the server | |
*/ | |
@Override | |
public void stop(boolean force) { | |
if (force) { | |
terminate(); | |
return; | |
} | |
int state = getServer().getServerState(); | |
// If stopped or stopping, no need to run stop command again | |
if (state == IServer.STATE_STOPPED || state == IServer.STATE_STOPPING) | |
return; | |
else if (state == IServer.STATE_STARTING) { | |
terminate(); | |
return; | |
} | |
try { | |
if (Trace.isTraceEnabled()) | |
Trace.trace(Trace.FINER, "Stopping Jetty"); | |
if (state != IServer.STATE_STOPPED) | |
setServerState(IServer.STATE_STOPPING); | |
ILaunchConfiguration launchConfig = ((Server) getServer()) | |
.getLaunchConfiguration(true, null); | |
ILaunchConfigurationWorkingCopy wc = launchConfig.getWorkingCopy(); | |
String args = renderCommandLine(getRuntimeProgramArguments(false), | |
" "); | |
// Remove JMX arguments if present | |
String existingVMArgs = wc.getAttribute( | |
IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, | |
(String) null); | |
if (existingVMArgs.indexOf(JMX_EXCLUDE_ARGS[0]) >= 0) { | |
wc.setAttribute( | |
IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, | |
mergeArguments(existingVMArgs, new String[] {}, | |
JMX_EXCLUDE_ARGS, false)); | |
} | |
wc.setAttribute( | |
IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, | |
args); | |
wc.setAttribute("org.eclipse.debug.ui.private", true); | |
wc.setAttribute(ATTR_STOP, "true"); | |
wc.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor()); | |
} catch (Exception e) { | |
Trace.trace(Trace.SEVERE, "Error stopping Jetty", e); | |
} | |
} | |
/** | |
* Terminates the server. | |
*/ | |
protected void terminate() { | |
if (getServer().getServerState() == IServer.STATE_STOPPED) | |
return; | |
try { | |
setServerState(IServer.STATE_STOPPING); | |
if (Trace.isTraceEnabled()) | |
Trace.trace(Trace.FINER, "Killing the Jetty process"); | |
ILaunch launch = getServer().getLaunch(); | |
if (launch != null) { | |
launch.terminate(); | |
stopImpl(); | |
} | |
} catch (Exception e) { | |
Trace.trace(Trace.SEVERE, "Error killing the process", e); | |
} | |
} | |
public IPath getTempDirectory() { | |
return super.getTempDirectory(false); | |
} | |
protected static int getNextToken(String s, int start) { | |
int i = start; | |
int length = s.length(); | |
char lookFor = ' '; | |
while (i < length) { | |
char c = s.charAt(i); | |
if (lookFor == c) { | |
if (lookFor == '"') | |
return i + 1; | |
return i; | |
} | |
if (c == '"') | |
lookFor = '"'; | |
i++; | |
} | |
return -1; | |
} | |
/** | |
* Merge the given arguments into the original argument string, replacing | |
* invalid values if they have been changed. Special handling is provided if | |
* the keepActionLast argument is true and the last vmArg is a simple | |
* string. The vmArgs will be merged such that the last vmArg is guaranteed | |
* to be the last argument in the merged string. | |
* | |
* @param originalArg | |
* String of original arguments. | |
* @param vmArgs | |
* Arguments to merge into the original arguments string | |
* @param excludeArgs | |
* Arguments to exclude from the original arguments string | |
* @param keepActionLast | |
* If <b>true</b> the vmArguments are assumed to be Jetty program | |
* arguments, the last of which is the action to perform which | |
* must remain the last argument. This only has an impact if the | |
* last vmArg is a simple string argument, like | |
* "start". | |
* @return merged argument string | |
*/ | |
public static String mergeArguments(String originalArg, String[] vmArgs, | |
String[] excludeArgs, boolean keepActionLast) { | |
if (vmArgs == null) | |
return originalArg; | |
if (originalArg == null) | |
originalArg = ""; | |
// replace and null out all vmargs that already exist | |
int size = vmArgs.length; | |
for (int i = 0; i < size; i++) { | |
int ind = vmArgs[i].indexOf(" "); | |
int ind2 = vmArgs[i].indexOf("="); | |
if (ind >= 0 && (ind2 == -1 || ind < ind2)) { // -a bc style | |
int index = originalArg | |
.indexOf(vmArgs[i].substring(0, ind + 1)); | |
if (index == 0 | |
|| (index > 0 && Character.isWhitespace(originalArg | |
.charAt(index - 1)))) { | |
// replace | |
String s = originalArg.substring(0, index); | |
int index2 = getNextToken(originalArg, index + ind + 1); | |
if (index2 >= 0) | |
originalArg = s + vmArgs[i] | |
+ originalArg.substring(index2); | |
else | |
originalArg = s + vmArgs[i]; | |
vmArgs[i] = null; | |
} | |
} else if (ind2 >= 0) { // a=b style | |
int index = originalArg.indexOf(vmArgs[i] | |
.substring(0, ind2 + 1)); | |
if (index == 0 | |
|| (index > 0 && Character.isWhitespace(originalArg | |
.charAt(index - 1)))) { | |
// replace | |
String s = originalArg.substring(0, index); | |
int index2 = getNextToken(originalArg, index); | |
if (index2 >= 0) | |
originalArg = s + vmArgs[i] | |
+ originalArg.substring(index2); | |
else | |
originalArg = s + vmArgs[i]; | |
vmArgs[i] = null; | |
} | |
} else { // abc style | |
int index = originalArg.indexOf(vmArgs[i]); | |
if (index == 0 | |
|| (index > 0 && Character.isWhitespace(originalArg | |
.charAt(index - 1)))) { | |
// replace | |
String s = originalArg.substring(0, index); | |
int index2 = getNextToken(originalArg, index); | |
if (!keepActionLast || i < (size - 1)) { | |
if (index2 >= 0) | |
originalArg = s + vmArgs[i] | |
+ originalArg.substring(index2); | |
else | |
originalArg = s + vmArgs[i]; | |
vmArgs[i] = null; | |
} else { | |
// The last VM argument needs to remain last, | |
// remove original arg and append the vmArg later | |
if (index2 >= 0) | |
originalArg = s + originalArg.substring(index2); | |
else | |
originalArg = s; | |
} | |
} | |
} | |
} | |
// remove excluded arguments | |
if (excludeArgs != null && excludeArgs.length > 0) { | |
for (int i = 0; i < excludeArgs.length; i++) { | |
int ind = excludeArgs[i].indexOf(" "); | |
int ind2 = excludeArgs[i].indexOf("="); | |
if (ind >= 0 && (ind2 == -1 || ind < ind2)) { // -a bc style | |
int index = originalArg.indexOf(excludeArgs[i].substring(0, | |
ind + 1)); | |
if (index == 0 | |
|| (index > 0 && Character.isWhitespace(originalArg | |
.charAt(index - 1)))) { | |
// remove | |
String s = originalArg.substring(0, index); | |
int index2 = getNextToken(originalArg, index + ind + 1); | |
if (index2 >= 0) { | |
// If remainder will become the first argument, | |
// remove leading blanks | |
while (index2 < originalArg.length() | |
&& Character.isWhitespace(originalArg | |
.charAt(index2))) | |
index2 += 1; | |
originalArg = s + originalArg.substring(index2); | |
} else | |
originalArg = s; | |
} | |
} else if (ind2 >= 0) { // a=b style | |
int index = originalArg.indexOf(excludeArgs[i].substring(0, | |
ind2 + 1)); | |
if (index == 0 | |
|| (index > 0 && Character.isWhitespace(originalArg | |
.charAt(index - 1)))) { | |
// remove | |
String s = originalArg.substring(0, index); | |
int index2 = getNextToken(originalArg, index); | |
if (index2 >= 0) { | |
// If remainder will become the first argument, | |
// remove leading blanks | |
while (index2 < originalArg.length() | |
&& Character.isWhitespace(originalArg | |
.charAt(index2))) | |
index2 += 1; | |
originalArg = s + originalArg.substring(index2); | |
} else | |
originalArg = s; | |
} | |
} else { // abc style | |
int index = originalArg.indexOf(excludeArgs[i]); | |
if (index == 0 | |
|| (index > 0 && Character.isWhitespace(originalArg | |
.charAt(index - 1)))) { | |
// remove | |
String s = originalArg.substring(0, index); | |
int index2 = getNextToken(originalArg, index); | |
if (index2 >= 0) { | |
// Remove leading blanks | |
while (index2 < originalArg.length() | |
&& Character.isWhitespace(originalArg | |
.charAt(index2))) | |
index2 += 1; | |
originalArg = s + originalArg.substring(index2); | |
} else | |
originalArg = s; | |
} | |
} | |
} | |
} | |
// add remaining vmargs to the end | |
for (int i = 0; i < size; i++) { | |
if (vmArgs[i] != null) { | |
if (originalArg.length() > 0 && !originalArg.endsWith(" ")) | |
originalArg += " "; | |
originalArg += vmArgs[i]; | |
} | |
} | |
return originalArg; | |
} | |
/** | |
* Replace the current JRE container classpath with the given entry. | |
* | |
* @param cp | |
* @param entry | |
*/ | |
public static void replaceJREContainer(List cp, IRuntimeClasspathEntry entry) { | |
int size = cp.size(); | |
for (int i = 0; i < size; i++) { | |
IRuntimeClasspathEntry entry2 = (IRuntimeClasspathEntry) cp.get(i); | |
if (entry2.getPath().uptoSegment(2).isPrefixOf(entry.getPath())) { | |
cp.set(i, entry); | |
return; | |
} | |
} | |
cp.add(0, entry); | |
} | |
/** | |
* Merge a single classpath entry into the classpath list. | |
* | |
* @param cp | |
* @param entry | |
*/ | |
public static void mergeClasspath(List cp, IRuntimeClasspathEntry entry) { | |
Iterator iterator = cp.iterator(); | |
while (iterator.hasNext()) { | |
IRuntimeClasspathEntry entry2 = (IRuntimeClasspathEntry) iterator | |
.next(); | |
if (entry2.getPath().equals(entry.getPath())) | |
return; | |
} | |
cp.add(entry); | |
} | |
@Override | |
public void setupLaunchConfiguration( | |
ILaunchConfigurationWorkingCopy workingCopy, | |
IProgressMonitor monitor) throws CoreException { | |
String existingProgArgs = workingCopy.getAttribute( | |
IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, | |
(String) null); | |
workingCopy.setAttribute( | |
IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, | |
mergeArguments(existingProgArgs, | |
getRuntimeProgramArguments(true), | |
getExcludedRuntimeProgramArguments(true), true)); | |
String existingVMArgs = workingCopy.getAttribute( | |
IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, | |
(String) null); | |
String[] parsedVMArgs = null; | |
if (null != existingVMArgs) { | |
parsedVMArgs = DebugPlugin.parseArguments(existingVMArgs); | |
} | |
String[] configVMArgs = getRuntimeVMArguments(); | |
if (getJettyServer().isSecure()) { | |
boolean addSecurityArgs = true; | |
if (null != parsedVMArgs) { | |
for (int i = 0; i < parsedVMArgs.length; i++) { | |
if (parsedVMArgs[i].startsWith("wtp.configured.security")) { | |
addSecurityArgs = false; | |
break; | |
} | |
} | |
} | |
if (addSecurityArgs) { | |
String[] newVMArgs = new String[configVMArgs.length + 3]; | |
System.arraycopy(configVMArgs, 0, newVMArgs, 0, | |
configVMArgs.length); | |
newVMArgs[configVMArgs.length] = "-Djava.security.manager"; | |
newVMArgs[configVMArgs.length + 1] = "-Djava.security.policy=\"" | |
+ getRuntimePolicyFile() + "\""; | |
newVMArgs[configVMArgs.length + 2] = "-Dwtp.configured.security=true"; | |
configVMArgs = newVMArgs; | |
} | |
} else if (null != parsedVMArgs) { | |
boolean removeSecurityArgs = false; | |
for (int i = 0; i < parsedVMArgs.length; i++) { | |
if (parsedVMArgs[i].startsWith("-Dwtp.configured.security")) { | |
removeSecurityArgs = true; | |
break; | |
} | |
} | |
if (removeSecurityArgs) { | |
StringBuffer filteredVMArgs = new StringBuffer(); | |
for (int i = 0; i < parsedVMArgs.length; i++) { | |
String arg = parsedVMArgs[i]; | |
if (!arg.startsWith("-Djava.security.manager") | |
&& !arg.startsWith("-Djava.security.policy=") | |
&& !arg.startsWith("-Dwtp.configured.security=")) { | |
if (filteredVMArgs.length() > 0) { | |
filteredVMArgs.append(' '); | |
} | |
filteredVMArgs.append(arg); | |
} | |
} | |
existingVMArgs = filteredVMArgs.toString(); | |
} | |
} | |
workingCopy.setAttribute( | |
IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, | |
mergeArguments(existingVMArgs, configVMArgs, null, false)); | |
IJettyRuntime runtime = getJettyRuntime(); | |
IVMInstall vmInstall = runtime.getVMInstall(); | |
if (vmInstall != null) | |
workingCopy.setAttribute( | |
IJavaLaunchConfigurationConstants.ATTR_JRE_CONTAINER_PATH, | |
JavaRuntime.newJREContainerPath(vmInstall) | |
.toPortableString()); | |
// update classpath | |
IRuntimeClasspathEntry[] originalClasspath = JavaRuntime | |
.computeUnresolvedRuntimeClasspath(workingCopy); | |
int size = originalClasspath.length; | |
List oldCp = new ArrayList(originalClasspath.length + 2); | |
for (int i = 0; i < size; i++) | |
oldCp.add(originalClasspath[i]); | |
Collection cp2 = runtime.getRuntimeClasspath(getRuntimeBaseDirectory()); | |
Iterator iterator = cp2.iterator(); | |
while (iterator.hasNext()) { | |
IRuntimeClasspathEntry entry = (IRuntimeClasspathEntry) iterator | |
.next(); | |
mergeClasspath(oldCp, entry); | |
} | |
if (vmInstall != null) { | |
try { | |
String typeId = vmInstall.getVMInstallType().getId(); | |
replaceJREContainer(oldCp, | |
JavaRuntime.newRuntimeContainerClasspathEntry(new Path( | |
JavaRuntime.JRE_CONTAINER).append(typeId) | |
.append(vmInstall.getName()), | |
IRuntimeClasspathEntry.BOOTSTRAP_CLASSES)); | |
} catch (Exception e) { | |
// ignore | |
} | |
IPath jrePath = new Path(vmInstall.getInstallLocation() | |
.getAbsolutePath()); | |
if (jrePath != null) { | |
IPath toolsPath = jrePath.append("lib").append("tools.jar"); | |
if (toolsPath.toFile().exists()) { | |
IRuntimeClasspathEntry toolsJar = JavaRuntime | |
.newArchiveRuntimeClasspathEntry(toolsPath); | |
// Search for index to any existing tools.jar entry | |
int toolsIndex; | |
for (toolsIndex = 0; toolsIndex < oldCp.size(); toolsIndex++) { | |
IRuntimeClasspathEntry entry = (IRuntimeClasspathEntry) oldCp | |
.get(toolsIndex); | |
if (entry.getType() == IRuntimeClasspathEntry.ARCHIVE | |
&& entry.getPath().lastSegment() | |
.equals("tools.jar")) { | |
break; | |
} | |
} | |
// If existing tools.jar found, replace in case it's | |
// different. Otherwise add. | |
if (toolsIndex < oldCp.size()) | |
oldCp.set(toolsIndex, toolsJar); | |
else | |
mergeClasspath(oldCp, toolsJar); | |
} | |
} | |
} | |
iterator = oldCp.iterator(); | |
List list = new ArrayList(); | |
while (iterator.hasNext()) { | |
IRuntimeClasspathEntry entry = (IRuntimeClasspathEntry) iterator | |
.next(); | |
try { | |
list.add(entry.getMemento()); | |
} catch (Exception e) { | |
Trace.trace(Trace.SEVERE, "Could not resolve classpath entry: " | |
+ entry, e); | |
} | |
} | |
workingCopy.setAttribute( | |
IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, list); | |
workingCopy | |
.setAttribute( | |
IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, | |
false); | |
} | |
protected void addProcessListener(final IProcess newProcess) { | |
if (processListener != null || newProcess == null) | |
return; | |
processListener = new IDebugEventSetListener() { | |
public void handleDebugEvents(DebugEvent[] events) { | |
if (events != null) { | |
int size = events.length; | |
for (int i = 0; i < size; i++) { | |
if (newProcess != null | |
&& newProcess.equals(events[i].getSource()) | |
&& events[i].getKind() == DebugEvent.TERMINATE) { | |
stopImpl(); | |
} | |
} | |
} | |
} | |
}; | |
DebugPlugin.getDefault().addDebugEventListener(processListener); | |
} | |
protected void setServerStarted() { | |
setServerState(IServer.STATE_STARTED); | |
} | |
protected void stopImpl() { | |
if (ping != null) { | |
ping.stop(); | |
ping = null; | |
} | |
if (processListener != null) { | |
DebugPlugin.getDefault().removeDebugEventListener(processListener); | |
processListener = null; | |
} | |
setServerState(IServer.STATE_STOPPED); | |
} | |
@Override | |
protected void publishServer(int kind, IProgressMonitor monitor) | |
throws CoreException { | |
if (getServer().getRuntime() == null) | |
return; | |
IPath installDir = getServer().getRuntime().getLocation(); | |
IPath confDir = null; | |
if (getJettyServer().isTestEnvironment()) { | |
confDir = getRuntimeBaseDirectory(); | |
IStatus status = getJettyVersionHandler().prepareRuntimeDirectory( | |
confDir); | |
if (status != null && !status.isOK()) | |
throw new CoreException(status); | |
} else | |
confDir = installDir; | |
// IStatus status = | |
// getJettyVersionHandler().prepareDeployDirectory(getServerDeployDirectory()); | |
// if (status != null && !status.isOK()) | |
// throw new CoreException(status); | |
monitor = ProgressUtil.getMonitorFor(monitor); | |
monitor.beginTask(Messages.publishServerTask, 600); | |
IStatus status = getJettyConfiguration().cleanupServer(confDir, | |
installDir, ProgressUtil.getSubMonitorFor(monitor, 100)); | |
if (status != null && !status.isOK()) | |
throw new CoreException(status); | |
status = getJettyConfiguration().backupAndPublish(confDir, | |
!getJettyServer().isTestEnvironment(), | |
ProgressUtil.getSubMonitorFor(monitor, 400)); | |
if (status != null && !status.isOK()) | |
throw new CoreException(status); | |
status = getJettyConfiguration().localizeConfiguration(confDir, | |
getServerDeployDirectory(), getJettyServer(), | |
ProgressUtil.getSubMonitorFor(monitor, 100)); | |
if (status != null && !status.isOK()) | |
throw new CoreException(status); | |
monitor.done(); | |
setServerPublishState(IServer.PUBLISH_STATE_NONE); | |
} | |
/* | |
* Publishes the given module to the server. | |
*/ | |
@Override | |
protected void publishModule(int kind, int deltaKind, IModule[] moduleTree, | |
IProgressMonitor monitor) throws CoreException { | |
if (getServer().getServerState() != IServer.STATE_STOPPED) { | |
if (deltaKind == ServerBehaviourDelegate.ADDED | |
|| deltaKind == ServerBehaviourDelegate.REMOVED) | |
setServerRestartState(true); | |
} | |
if (getJettyServer().isTestEnvironment()) | |
return; | |
Properties p = loadModulePublishLocations(); | |
PublishHelper helper = new PublishHelper(getRuntimeBaseDirectory() | |
.append("temp").toFile()); | |
// If parent web module | |
if (moduleTree.length == 1) { | |
publishDir(deltaKind, p, moduleTree, helper, monitor); | |
} | |
// Else a child module | |
else { | |
// Try to determine the URI for the child module | |
IWebModule webModule = (IWebModule) moduleTree[0].loadAdapter( | |
IWebModule.class, monitor); | |
String childURI = null; | |
if (webModule != null) { | |
childURI = webModule.getURI(moduleTree[1]); | |
} | |
// Try to determine if child is binary | |
IJ2EEModule childModule = (IJ2EEModule) moduleTree[1].loadAdapter( | |
IJ2EEModule.class, monitor); | |
boolean isBinary = false; | |
if (childModule != null) { | |
isBinary = childModule.isBinary(); | |
} | |
if (isBinary) { | |
publishArchiveModule(childURI, kind, deltaKind, p, moduleTree, | |
helper, monitor); | |
} else { | |
publishJar(childURI, kind, deltaKind, p, moduleTree, helper, | |
monitor); | |
} | |
} | |
setModulePublishState(moduleTree, IServer.PUBLISH_STATE_NONE); | |
saveModulePublishLocations(p); | |
} | |
/** | |
* Publish a web module. | |
* | |
* @param deltaKind | |
* @param p | |
* @param module | |
* @param monitor | |
* @throws CoreException | |
*/ | |
private void publishDir(int deltaKind, Properties p, IModule module[], | |
PublishHelper helper, IProgressMonitor monitor) | |
throws CoreException { | |
List status = new ArrayList(); | |
// Remove if requested or if previously published and are now serving | |
// without publishing | |
if (deltaKind == REMOVED | |
|| getJettyServer().isServeModulesWithoutPublish()) { | |
String publishPath = (String) p.get(module[0].getId()); | |
if (publishPath != null) { | |
try { | |
File f = new File(publishPath); | |
if (f.exists()) { | |
IStatus[] stat = PublishHelper.deleteDirectory(f, | |
monitor); | |
PublishOperation2.addArrayToList(status, stat); | |
} | |
} catch (Exception e) { | |
throw new CoreException(new Status(IStatus.WARNING, | |
JettyPlugin.PLUGIN_ID, 0, NLS.bind( | |
Messages.errorPublishCouldNotRemoveModule, | |
module[0].getName()), e)); | |
} | |
p.remove(module[0].getId()); | |
} | |
} else { | |
IPath path = getModuleDeployDirectory(module[0]); | |
IModuleResource[] mr = getResources(module); | |
IPath[] jarPaths = null; | |
IWebModule webModule = (IWebModule) module[0].loadAdapter( | |
IWebModule.class, monitor); | |
IModule[] childModules = getServer().getChildModules(module, | |
monitor); | |
if (childModules != null && childModules.length > 0) { | |
jarPaths = new IPath[childModules.length]; | |
for (int i = 0; i < childModules.length; i++) { | |
if (webModule != null) { | |
jarPaths[i] = new Path( | |
webModule.getURI(childModules[i])); | |
} else { | |
IJ2EEModule childModule = (IJ2EEModule) childModules[i] | |
.loadAdapter(IJ2EEModule.class, monitor); | |
if (childModule != null && childModule.isBinary()) { | |
jarPaths[i] = new Path("WEB-INF/lib") | |
.append(childModules[i].getName()); | |
} else { | |
jarPaths[i] = new Path("WEB-INF/lib") | |
.append(childModules[i].getName() + ".jar"); | |
} | |
} | |
} | |
} | |
IStatus[] stat = helper.publishSmart(mr, path, jarPaths, monitor); | |
PublishOperation2.addArrayToList(status, stat); | |
p.put(module[0].getId(), path.toOSString()); | |
} | |
PublishOperation2.throwException(status); | |
} | |
/** | |
* Publish a jar file. | |
* | |
* @param deltaKind | |
* @param p | |
* @param module | |
* @param monitor | |
* @throws CoreException | |
*/ | |
private void publishJar(String jarURI, int kind, int deltaKind, | |
Properties p, IModule[] module, PublishHelper helper, | |
IProgressMonitor monitor) throws CoreException { | |
// Remove if requested or if previously published and are now serving | |
// without publishing | |
if (deltaKind == REMOVED | |
|| getJettyServer().isServeModulesWithoutPublish()) { | |
try { | |
String publishPath = (String) p.get(module[1].getId()); | |
if (publishPath != null) { | |
new File(publishPath).delete(); | |
p.remove(module[1].getId()); | |
} | |
} catch (Exception e) { | |
throw new CoreException(new Status(IStatus.WARNING, | |
JettyPlugin.PLUGIN_ID, 0, "Could not remove module", e)); | |
} | |
} else { | |
IPath path = getModuleDeployDirectory(module[0]); | |
if (jarURI == null) { | |
jarURI = "WEB-INF/lib" + module[1].getName() + ".jar"; | |
} | |
IPath jarPath = path.append(jarURI); | |
path = jarPath.removeLastSegments(1); | |
if (!path.toFile().exists()) { | |
path.toFile().mkdirs(); | |
} else { | |
// If file still exists and we are not forcing a new one to be | |
// built | |
if (jarPath.toFile().exists() && kind != IServer.PUBLISH_CLEAN | |
&& kind != IServer.PUBLISH_FULL) { | |
// avoid changes if no changes to module since last publish | |
IModuleResourceDelta[] delta = getPublishedResourceDelta(module); | |
if (delta == null || delta.length == 0) | |
return; | |
} | |
} | |
IModuleResource[] mr = getResources(module); | |
IStatus[] stat = helper.publishZip(mr, jarPath, monitor); | |
List status = new ArrayList(); | |
PublishOperation2.addArrayToList(status, stat); | |
PublishOperation2.throwException(status); | |
p.put(module[1].getId(), jarPath.toOSString()); | |
} | |
} | |
private void publishArchiveModule(String jarURI, int kind, int deltaKind, | |
Properties p, IModule[] module, PublishHelper helper, | |
IProgressMonitor monitor) throws CoreException { | |
// Remove if requested or if previously published and are now serving | |
// without publishing | |
if (deltaKind == REMOVED | |
|| getJettyServer().isServeModulesWithoutPublish()) { | |
try { | |
String publishPath = (String) p.get(module[1].getId()); | |
if (publishPath != null) { | |
new File(publishPath).delete(); | |
p.remove(module[1].getId()); | |
} | |
} catch (Exception e) { | |
throw new CoreException(new Status(IStatus.WARNING, | |
JettyPlugin.PLUGIN_ID, 0, | |
"Could not remove archive module", e)); | |
} | |
} else { | |
List status = new ArrayList(); | |
IPath path = getModuleDeployDirectory(module[0]); | |
if (jarURI == null) { | |
jarURI = "WEB-INF/lib" + module[1].getName(); | |
} | |
IPath jarPath = path.append(jarURI); | |
path = jarPath.removeLastSegments(1); | |
if (!path.toFile().exists()) { | |
path.toFile().mkdirs(); | |
} else { | |
// If file still exists and we are not forcing a new one to be | |
// built | |
if (jarPath.toFile().exists() && kind != IServer.PUBLISH_CLEAN | |
&& kind != IServer.PUBLISH_FULL) { | |
// avoid changes if no changes to module since last publish | |
IModuleResourceDelta[] delta = getPublishedResourceDelta(module); | |
if (delta == null || delta.length == 0) | |
return; | |
} | |
} | |
IModuleResource[] mr = getResources(module); | |
IStatus[] stat = helper.publishToPath(mr, jarPath, monitor); | |
PublishOperation2.addArrayToList(status, stat); | |
PublishOperation2.throwException(status); | |
p.put(module[1].getId(), jarPath.toOSString()); | |
} | |
} | |
// @Override | |
// protected void publishFinish(IProgressMonitor monitor) throws CoreException { | |
// IStatus status; | |
// IPath baseDir = getRuntimeBaseDirectory(); | |
// JettyServer ts = getJettyServer(); | |
// IJettyVersionHandler tvh = getJettyVersionHandler(); | |
// // Include or remove loader jar depending on state of serving directly | |
// status = tvh.prepareForServingDirectly(baseDir, getJettyServer()); | |
// if (status.isOK()) { | |
// // If serving modules directly, update server.xml accordingly | |
// // (includes project context.xmls) | |
// if (ts.isServeModulesWithoutPublish()) { | |
// status = getJettyConfiguration().updateContextsToServeDirectly( | |
// baseDir, tvh.getSharedLoader(baseDir), monitor); | |
// } | |
// // Else serving normally. Add project context.xmls to server.xml | |
// else { | |
// // Publish context configuration for servers that support | |
// // META-INF/context.xml | |
// status = getJettyConfiguration().publishContextConfig(baseDir, | |
// getServerDeployDirectory(), monitor); | |
// } | |
// if (status.isOK() && ts.isSaveSeparateContextFiles()) { | |
// // Determine if context's path attribute should be removed | |
// String id = getServer().getServerType().getId(); | |
// boolean noPath = id.indexOf("55") > 0 || id.indexOf("60") > 0; | |
// boolean serverStopped = getServer().getServerState() == IServer.STATE_STOPPED; | |
// // TODO Add a monitor | |
// JettyVersionHelper.moveContextsToSeparateFiles(baseDir, noPath, | |
// serverStopped, null); | |
// } | |
// } | |
// if (!status.isOK()) | |
// throw new CoreException(status); | |
// } | |
/** | |
* Gets the directory to which modules should be deployed for this server. | |
* | |
* @return full path to deployment directory for the server | |
*/ | |
public IPath getServerDeployDirectory() { | |
return getJettyServer().getServerDeployDirectory(); | |
} | |
protected IModuleResource[] getResources(IModule[] module) { | |
return super.getResources(module); | |
} | |
protected IModuleResourceDelta[] getPublishedResourceDelta(IModule[] module) { | |
return super.getPublishedResourceDelta(module); | |
} | |
/** | |
* Gets the directory to which to deploy a module's web application. | |
* | |
* @param module | |
* a module | |
* @return full path to deployment directory for the module | |
*/ | |
public IPath getModuleDeployDirectory(IModule module) { | |
return getServerDeployDirectory().append(module.getName()); | |
} | |
/** | |
* Temporary method to help web services team. Returns the path that the | |
* module is published to. | |
* | |
* @param module | |
* a module on the server | |
* @return the path that the module is published to when in test environment | |
* mode, or null if the module is not a web module | |
*/ | |
public IPath getPublishDirectory(IModule[] module) { | |
if (module == null || module.length != 1) | |
return null; | |
return getModuleDeployDirectory(module[0]); | |
} | |
public void setModulePublishState2(IModule[] module, int state) { | |
setModulePublishState(module, state); | |
} | |
public Properties loadModulePublishLocations() { | |
Properties p = new Properties(); | |
IPath path = getTempDirectory().append("publish.txt"); | |
FileInputStream fin = null; | |
try { | |
fin = new FileInputStream(path.toFile()); | |
p.load(fin); | |
} catch (Exception e) { | |
// ignore | |
} finally { | |
try { | |
fin.close(); | |
} catch (Exception ex) { | |
// ignore | |
} | |
} | |
return p; | |
} | |
public void saveModulePublishLocations(Properties p) { | |
IPath path = getTempDirectory().append("publish.txt"); | |
FileOutputStream fout = null; | |
try { | |
fout = new FileOutputStream(path.toFile()); | |
p.store(fout, "Jetty publish data"); | |
} catch (Exception e) { | |
// ignore | |
} finally { | |
try { | |
fout.close(); | |
} catch (Exception ex) { | |
// ignore | |
} | |
} | |
} | |
} |