blob: 373b3b992c0985362d76f1f0be40ddd83e48d9cc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2008 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
*******************************************************************************/
package org.eclipse.jst.server.tomcat.core.internal;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.*;
import org.eclipse.debug.core.*;
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.osgi.util.NLS;
import org.eclipse.wst.server.core.*;
import org.eclipse.wst.server.core.internal.IModulePublishHelper;
import org.eclipse.wst.server.core.internal.Server;
import org.eclipse.wst.server.core.model.*;
import org.eclipse.wst.server.core.util.PublishHelper;
import org.eclipse.wst.server.core.util.SocketUtil;
/**
* Generic Tomcat server.
*/
public class TomcatServerBehaviour extends ServerBehaviourDelegate implements ITomcatServerBehaviour, 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;
/**
* TomcatServerBehaviour.
*/
public TomcatServerBehaviour() {
super();
}
public void initialize(IProgressMonitor monitor) {
// do nothing
}
public TomcatRuntime getTomcatRuntime() {
if (getServer().getRuntime() == null)
return null;
return (TomcatRuntime) getServer().getRuntime().loadAdapter(TomcatRuntime.class, null);
}
public ITomcatVersionHandler getTomcatVersionHandler() {
return getTomcatServer().getTomcatVersionHandler();
}
public TomcatConfiguration getTomcatConfiguration() throws CoreException {
return getTomcatServer().getTomcatConfiguration();
}
public TomcatServer getTomcatServer() {
return (TomcatServer) getServer().loadAdapter(TomcatServer.class, null);
}
/**
* Return the runtime class name.
*
* @return the class name
*/
public String getRuntimeClass() {
return getTomcatVersionHandler().getRuntimeClass();
}
/**
* Returns the runtime base path for relative paths in the server
* configuration.
*
* @return the base path
*/
public IPath getRuntimeBaseDirectory() {
return getTomcatServer().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 (getTomcatServer().isTestEnvironment())
configPath = getRuntimeBaseDirectory();
return getTomcatVersionHandler().getRuntimeProgramArguments(configPath, getTomcatServer().isDebug(), starting);
}
protected String[] getExcludedRuntimeProgramArguments(boolean starting) {
return getTomcatVersionHandler().getExcludedRuntimeProgramArguments(getTomcatServer().isDebug(), starting);
}
/**
* Return the runtime (VM) arguments.
*
* @return an array of runtime arguments
*/
protected String[] getRuntimeVMArguments() {
IPath installPath = getServer().getRuntime().getLocation();
IPath configPath = getRuntimeBaseDirectory();
IPath deployPath;
// If serving modules without publishing, use workspace path as the deploy path
if (getTomcatServer().isServeModulesWithoutPublish()) {
deployPath = ResourcesPlugin.getWorkspace().getRoot().getLocation();
}
// Else normal publishing for modules
else {
deployPath = getServerDeployDirectory();
}
return getTomcatVersionHandler().getRuntimeVMArguments(installPath, configPath,
deployPath, getTomcatServer().isTestEnvironment());
}
protected String getRuntimePolicyFile() {
IPath configPath = getRuntimeBaseDirectory();
return getTomcatVersionHandler().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();
}
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);
}
protected void publishServer(int kind, IProgressMonitor monitor) throws CoreException {
if (getServer().getRuntime() == null)
return;
IPath installDir = getServer().getRuntime().getLocation();
IPath confDir = null;
if (getTomcatServer().isTestEnvironment()) {
confDir = getRuntimeBaseDirectory();
IStatus status = getTomcatVersionHandler().prepareRuntimeDirectory(confDir);
if (status != null && !status.isOK())
throw new CoreException(status);
} else
confDir = installDir;
IStatus status = getTomcatVersionHandler().prepareDeployDirectory(getServerDeployDirectory());
if (status != null && !status.isOK())
throw new CoreException(status);
monitor = ProgressUtil.getMonitorFor(monitor);
monitor.beginTask(Messages.publishServerTask, 600);
status = getTomcatConfiguration().cleanupServer(confDir, installDir,
!getTomcatServer().isSaveSeparateContextFiles(), ProgressUtil.getSubMonitorFor(monitor, 100));
if (status != null && !status.isOK())
throw new CoreException(status);
status = getTomcatConfiguration().backupAndPublish(confDir, !getTomcatServer().isTestEnvironment(), ProgressUtil.getSubMonitorFor(monitor, 400));
if (status != null && !status.isOK())
throw new CoreException(status);
status = getTomcatConfiguration().localizeConfiguration(confDir, getServerDeployDirectory(),
getTomcatServer(), 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.
*/
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 (getTomcatServer().isTestEnvironment())
return;
IPath path = getTempDirectory().append("publish.txt");
Properties p = new Properties();
FileInputStream fin = null;
try {
fin = new FileInputStream(path.toFile());
p.load(fin);
} catch (Exception e) {
// ignore
} finally {
try {
fin.close();
} catch (Exception ex) {
// ignore
}
}
PublishHelper helper = new PublishHelper(getRuntimeBaseDirectory().append("temp").toFile());
if (moduleTree.length == 1) // web module
publishDir(deltaKind, p, moduleTree, helper, monitor);
else // utility jar
publishJar(kind, deltaKind, p, moduleTree, helper, monitor);
setModulePublishState(moduleTree, IServer.PUBLISH_STATE_NONE);
try {
p.store(new FileOutputStream(path.toFile()), "Tomcat publish data");
} catch (Exception e) {
// ignore
}
}
/**
* 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 || getTomcatServer().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, TomcatPlugin.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;
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++) {
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(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 || getTomcatServer().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, TomcatPlugin.PLUGIN_ID, 0, "Could not remove module", e));
}
} else {
IPath path = getModuleDeployDirectory(module[0]);
path = path.append("WEB-INF").append("lib");
IPath jarPath = path.append(module[1].getName() + ".jar");
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());
}
}
protected void publishFinish(IProgressMonitor monitor) throws CoreException {
IStatus status;
IPath baseDir = getRuntimeBaseDirectory();
TomcatServer ts = getTomcatServer();
ITomcatVersionHandler tvh = getTomcatVersionHandler();
// Include or remove loader jar depending on state of serving directly
status = tvh.prepareForServingDirectly(baseDir, getTomcatServer());
if (status.isOK()) {
// If serving modules directly, update server.xml accordingly (includes project context.xmls)
if (ts.isServeModulesWithoutPublish()) {
status = getTomcatConfiguration().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 = getTomcatConfiguration().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
TomcatVersionHelper.moveContextsToSeparateFiles(baseDir, noPath, serverStopped, null);
}
}
if (!status.isOK())
throw new CoreException(status);
}
/**
* 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 ("true".equals(launch.getLaunchConfiguration().getAttribute(ATTR_STOP, "false")))
return;
//if (getTomcatRuntime() == null)
// throw new CoreException();
IStatus status = getTomcatRuntime().validate();
if (status != null && status.getSeverity() == IStatus.ERROR)
throw new CoreException(status);
//setRestartNeeded(false);
TomcatConfiguration configuration = getTomcatConfiguration();
// 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, TomcatPlugin.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, TomcatPlugin.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, TomcatPlugin.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, TomcatPlugin.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://localhost";
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 Tomcat startup.");
}
}
/**
* Cleanly shuts down and terminates the server.
*
* @param force <code>true</code> to kill the server
*/
public void stop(boolean force) {
if (force) {
terminate();
return;
}
int state = getServer().getServerState();
if (state == IServer.STATE_STOPPED)
return;
else if (state == IServer.STATE_STARTING || state == IServer.STATE_STOPPING) {
terminate();
return;
}
try {
if (Trace.isTraceEnabled())
Trace.trace(Trace.FINER, "Stopping Tomcat");
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 Tomcat", 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 Tomcat 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();
}
/**
* Return a string representation of this object.
* @return java.lang.String
*/
public String toString() {
return "TomcatServer";
}
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 Tomcat
* 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 &quot;start&quot;.
* @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 && 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 && 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 && 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 && 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() && 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 && 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() && 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 && 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() && 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);
}
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 (getTomcatServer().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));
ITomcatRuntime runtime = getTomcatRuntime();
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]);
List cp2 = runtime.getRuntimeClasspath();
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 IModuleResource[] getResources(IModule[] module) {
return super.getResources(module);
}
protected IModuleResourceDelta[] getPublishedResourceDelta(IModule[] module) {
return super.getPublishedResourceDelta(module);
}
/**
* @see ServerBehaviourDelegate#handleResourceChange()
*/
public void handleResourceChange() {
if (getServer().getServerRestartState())
return;
Iterator iterator = getAllModules().iterator();
while (iterator.hasNext()) {
IModule[] module = (IModule[]) iterator.next();
IModuleResourceDelta[] delta = getPublishedResourceDelta(module);
if (delta == null || delta.length == 0)
continue;
if (containsNonResourceChange(delta)) {
setServerRestartState(true);
return;
}
}
}
protected boolean containsNonResourceChange(IModuleResourceDelta[] delta) {
int size = delta.length;
for (int i = 0; i < size; i++) {
IModuleResourceDelta d = delta[i];
if (d.getModuleRelativePath().segmentCount() == 0) {
if ("WEB-INF".equals(d.getModuleResource().getName())) {
return containsNonResourceChange(d.getAffectedChildren());
}
continue;
}
if (d.getModuleResource() instanceof IModuleFile)
return true;
boolean b = containsNonAddChange(d.getAffectedChildren());
if (b)
return true;
}
return false;
}
protected boolean containsNonAddChange(IModuleResourceDelta[] delta) {
if (delta == null)
return false;
int size = delta.length;
for (int i = 0; i < size; i++) {
IModuleResourceDelta d = delta[i];
if (d.getModuleResource() instanceof IModuleFile) {
if (d.getKind() != IModuleResourceDelta.ADDED)
return true;
}
boolean b = containsNonAddChange(d.getAffectedChildren());
if (b)
return true;
}
return false;
}
/**
* Cleans the entire work directory for this server. This involves
* deleting all subdirectories of the server's work directory.
*
* @param monitor a progress monitor
* @return results of the clean operation
* @throws CoreException
*/
public IStatus cleanServerWorkDir(IProgressMonitor monitor) throws CoreException {
IStatus result;
IPath basePath = getRuntimeBaseDirectory();
IPath workPath = getTomcatConfiguration().getServerWorkDirectory(basePath);
if (workPath != null) {
File workDir = workPath.toFile();
result = Status.OK_STATUS;
if (workDir.exists() && workDir.isDirectory()) {
// Delete subdirectories of the server's work dir
File[] files = workDir.listFiles();
if (files != null && files.length > 0) {
MultiStatus ms = new MultiStatus(TomcatPlugin.PLUGIN_ID, 0, "Problem occurred deleting work directory for module.", null);
int size = files.length;
monitor = ProgressUtil.getMonitorFor(monitor);
monitor.beginTask(NLS.bind("Cleaning Server Work Directory", new String[] { workDir.getAbsolutePath() }), size * 10);
for (int i = 0; i < size; i++) {
File current = files[i];
if (current.isDirectory()) {
IStatus [] results = PublishHelper.deleteDirectory(current, ProgressUtil.getSubMonitorFor(monitor, 10));
if (results != null && results.length > 0) {
for (int j = 0; j < results.length; j++) {
ms.add(results[j]);
}
}
}
}
monitor.done();
result = ms;
}
}
}
else {
result = new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, "Could not determine work directory for module", null);
}
return result;
}
/**
* Cleans the work directory associated with the specified module on this
* server.
*
* @param module module whose work directory should be cleaned
* @param monitor a progress monitor
* @return result of the clean operation
* @throws CoreException
*/
public IStatus cleanContextWorkDir(ITomcatWebModule module, IProgressMonitor monitor) throws CoreException {
IStatus result;
IPath basePath = getRuntimeBaseDirectory();
IPath workPath = getTomcatConfiguration().getContextWorkDirectory(basePath, module);
if (workPath != null) {
IStatus [] results = PublishHelper.deleteDirectory(workPath.toFile(), monitor);
MultiStatus ms = new MultiStatus(TomcatPlugin.PLUGIN_ID, 0, "Problem occurred deleting work directory for module.", null);
if (results != null && results.length > 0) {
for (int i = 0; i < results.length; i++) {
ms.add(results[i]);
}
}
result = ms;
}
else {
result = new Status(IStatus.ERROR, TomcatPlugin.PLUGIN_ID, 0, "Could not determine work directory for module", null);
}
return result;
}
/**
* 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 getTomcatServer().getServerDeployDirectory();
}
/**
* 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);
}
}