This commit was manufactured by cvs2svn to create tag 'R3_0_2'.
diff --git a/features/org.eclipse.jst.server_adapters.feature/feature.xml b/features/org.eclipse.jst.server_adapters.feature/feature.xml
index c24a357..d36572c 100644
--- a/features/org.eclipse.jst.server_adapters.feature/feature.xml
+++ b/features/org.eclipse.jst.server_adapters.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.jst.server_adapters.feature"
label="%featureName"
- version="3.0.0.qualifier"
+ version="3.0.2.qualifier"
provider-name="%providerName">
<description>
diff --git a/features/org.eclipse.jst.server_adapters.sdk.feature/feature.xml b/features/org.eclipse.jst.server_adapters.sdk.feature/feature.xml
index e39f7ab..ee61073 100644
--- a/features/org.eclipse.jst.server_adapters.sdk.feature/feature.xml
+++ b/features/org.eclipse.jst.server_adapters.sdk.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.jst.server_adapters.sdk.feature"
label="%featureName"
- version="3.0.0.qualifier"
+ version="3.0.2.qualifier"
provider-name="%providerName">
<description>
@@ -28,5 +28,5 @@
<includes
id="org.eclipse.jst.server_adapters.feature.source"
version="0.0.0"/>
-
+
</feature>
diff --git a/features/org.eclipse.jst.server_core.feature/feature.xml b/features/org.eclipse.jst.server_core.feature/feature.xml
index e7323d6..a1526ea 100644
--- a/features/org.eclipse.jst.server_core.feature/feature.xml
+++ b/features/org.eclipse.jst.server_core.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.jst.server_core.feature"
label="%featureName"
- version="3.0.0.qualifier"
+ version="3.0.1.qualifier"
provider-name="%providerName">
<description>
diff --git a/features/org.eclipse.wst.server_ui.feature/feature.xml b/features/org.eclipse.wst.server_ui.feature/feature.xml
index ce2c6b6..61072a0 100644
--- a/features/org.eclipse.wst.server_ui.feature/feature.xml
+++ b/features/org.eclipse.wst.server_ui.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.wst.server_ui.feature"
label="%featureName"
- version="3.0.1.qualifier"
+ version="3.0.2.qualifier"
provider-name="%providerName">
<description>
diff --git a/plugins/org.eclipse.jst.server.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.jst.server.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..d51ba9e
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.core/META-INF/MANIFEST.MF
@@ -0,0 +1,22 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.jst.server.core; singleton:=true
+Bundle-Version: 1.1.1.qualifier
+Bundle-Activator: org.eclipse.jst.server.core.internal.JavaServerPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.jst.server.core,
+ org.eclipse.jst.server.core.internal;x-friends:="org.eclipse.jst.server.ui",
+ org.eclipse.jst.server.core.internal.cactus;x-friends:="org.eclipse.jst.server.ui"
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.debug.core;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.jdt.core;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.jdt.launching;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.wst.server.core;bundle-version="[1.0.304,2.0.0)",
+ org.eclipse.wst.common.project.facet.core;bundle-version="[1.1.0,2.0.0)",
+ org.eclipse.jst.common.project.facet.core;bundle-version="[1.1.0,2.0.0)"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/Trace.java b/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/Trace.java
new file mode 100644
index 0000000..fd470af
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/internal/Trace.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.core.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+/**
+ * Helper class to route trace output.
+ */
+public class Trace {
+ /**
+ * Config tracing
+ */
+ public static final byte CONFIG = 0;
+ /**
+ * Warning tracing
+ */
+ public static final byte WARNING = 1;
+ /**
+ * Severe tracing
+ */
+ public static final byte SEVERE = 2;
+ /**
+ * Finest tracing
+ */
+ public static final byte FINEST = 3;
+
+ public static final byte PUBLISHING = 4;
+
+ private static Set<String> logged = new HashSet<String>();
+
+ /**
+ * Trace constructor comment.
+ */
+ private Trace() {
+ super();
+ }
+
+ /**
+ * Trace the given text.
+ *
+ * @param level trace level
+ * @param s String
+ */
+ public static void trace(byte level, String s) {
+ Trace.trace(level, s, null);
+ }
+
+ /**
+ * Trace the given message and exception.
+ *
+ * @param level trace level
+ * @param s String
+ * @param t Throwable
+ */
+ public static void trace(byte level, String s, Throwable t) {
+ if (s == null)
+ return;
+
+ if (level == SEVERE) {
+ if (!logged.contains(s)) {
+ JavaServerPlugin.getInstance().getLog().log(new Status(IStatus.ERROR, JavaServerPlugin.PLUGIN_ID, s, t));
+ logged.add(s);
+ }
+ }
+
+ if (!JavaServerPlugin.getInstance().isDebugging())
+ return;
+
+ System.out.println(JavaServerPlugin.PLUGIN_ID + " " + s);
+ if (t != null)
+ t.printStackTrace();
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.jst.server.preview.adapter/META-INF/MANIFEST.MF b/plugins/org.eclipse.jst.server.preview.adapter/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5eccac1
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.preview.adapter/META-INF/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.jst.server.preview.adapter;singleton:=true
+Bundle-Version: 1.0.101.qualifier
+Bundle-Activator: org.eclipse.jst.server.preview.adapter.internal.PreviewPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.jst.server.preview.adapter.internal;x-friends:="org.eclipse.jst.server.ui"
+Require-Bundle: org.eclipse.jdt.core;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.jdt.launching;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.wst.server.core;bundle-version="[1.0.103,2.0.0)",
+ org.eclipse.jst.server.core;bundle-version="[1.0.204,2.0.0)",
+ org.eclipse.debug.ui;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.wst.server.ui;bundle-version="[1.0.103,2.0.0)",
+ org.eclipse.wst.common.project.facet.ui;bundle-version="[1.1.0,2.0.0)",
+ org.eclipse.jst.common.project.facet.core;bundle-version="[1.1.0,2.0.0)",
+ org.eclipse.jdt.debug.ui;bundle-version="[3.2.100,4.0.0)"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.jst.server.preview.adapter/src/org/eclipse/jst/server/preview/adapter/internal/core/PreviewServerBehaviour.java b/plugins/org.eclipse.jst.server.preview.adapter/src/org/eclipse/jst/server/preview/adapter/internal/core/PreviewServerBehaviour.java
new file mode 100644
index 0000000..5ef20cb
--- /dev/null
+++ b/plugins/org.eclipse.jst.server.preview.adapter/src/org/eclipse/jst/server/preview/adapter/internal/core/PreviewServerBehaviour.java
@@ -0,0 +1,316 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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.preview.adapter.internal.core;
+
+import java.io.IOException;
+
+import org.eclipse.core.resources.IContainer;
+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.MultiStatus;
+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.model.IProcess;
+import org.eclipse.jst.server.core.IWebModule;
+import org.eclipse.jst.server.preview.adapter.internal.IMemento;
+import org.eclipse.jst.server.preview.adapter.internal.Messages;
+import org.eclipse.jst.server.preview.adapter.internal.PreviewPlugin;
+import org.eclipse.jst.server.preview.adapter.internal.ProgressUtil;
+import org.eclipse.jst.server.preview.adapter.internal.Trace;
+import org.eclipse.jst.server.preview.adapter.internal.XMLMemento;
+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.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.IStaticWeb;
+import org.eclipse.wst.server.core.util.ProjectModule;
+import org.eclipse.wst.server.core.util.PublishUtil;
+import org.eclipse.wst.server.core.util.SocketUtil;
+/**
+ * Generic Http server.
+ */
+public class PreviewServerBehaviour extends ServerBehaviourDelegate {
+ // the thread used to ping the server to check for startup
+ protected transient PingThread ping = null;
+ protected transient IDebugEventSetListener processListener;
+
+ /**
+ * PreviewServer.
+ */
+ public PreviewServerBehaviour() {
+ super();
+ }
+
+ public void initialize(IProgressMonitor monitor) {
+ // do nothing
+ }
+
+ public PreviewRuntime getPreviewRuntime() {
+ if (getServer().getRuntime() == null)
+ return null;
+
+ return (PreviewRuntime) getServer().getRuntime().loadAdapter(PreviewRuntime.class, null);
+ }
+
+ public PreviewServer getPreviewServer() {
+ return (PreviewServer) getServer().getAdapter(PreviewServer.class);
+ }
+
+ /**
+ * Returns the runtime base path for relative paths in the server
+ * configuration.
+ *
+ * @return the base path
+ */
+ public IPath getRuntimeBaseDirectory() {
+ return getServer().getRuntime().getLocation();
+ }
+
+ /**
+ * Setup for starting the server.
+ *
+ * @param launch ILaunch
+ * @param launchMode String
+ * @param monitor IProgressMonitor
+ * @throws CoreException if anything goes wrong
+ */
+ protected void setupLaunch(ILaunch launch, String launchMode, IProgressMonitor monitor) throws CoreException {
+ // check that ports are free
+ ServerPort[] ports = getPreviewServer().getServerPorts();
+ int port = ports[0].getPort();
+
+ if (SocketUtil.isPortInUse(port, 5))
+ throw new CoreException(new Status(IStatus.ERROR, PreviewPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorPortInUse, new String[] {port + "", getServer().getName()}), null));
+
+ // generate preview config file
+ XMLMemento memento = XMLMemento.createWriteRoot("server");
+ memento.putInteger("port", port);
+
+ IModule[] modules = getServer().getModules();
+ for (IModule module : modules) {
+ IMemento mod = memento.createChild("module");
+ mod.putString("name", module.getName());
+ String type = module.getModuleType().getId();
+ if ("wst.web".equals(type)) {
+ IStaticWeb staticWeb = (IStaticWeb) module.loadAdapter(IStaticWeb.class, null);
+ if (staticWeb != null)
+ mod.putString("context", staticWeb.getContextRoot());
+ mod.putString("type", "static");
+ } else if ("jst.web".equals(type)) {
+ IWebModule webModule = (IWebModule) module.loadAdapter(IWebModule.class, null);
+ if (webModule != null)
+ mod.putString("context", webModule.getContextRoot());
+ mod.putString("type", "j2ee");
+ }
+ mod.putString("path", getModulePublishDirectory(module).toPortableString());
+ }
+ try {
+ memento.saveToFile(getTempDirectory().append("preview.xml").toOSString());
+ } catch (IOException e) {
+ Trace.trace(Trace.SEVERE, "Could not write preview config", e);
+ throw new CoreException(new Status(IStatus.ERROR, PreviewPlugin.PLUGIN_ID, 0, "Could not write preview configuration", null));
+ }
+
+ setServerRestartState(false);
+ setServerState(IServer.STATE_STARTING);
+ setMode(launchMode);
+
+ // ping server to check for startup
+ try {
+ String url = "http://localhost";
+ if (port != 80)
+ url += ":" + port;
+ ping = new PingThread(getServer(), url, this);
+ } catch (Exception e) {
+ Trace.trace(Trace.SEVERE, "Can't ping for Tomcat startup.");
+ }
+ }
+
+ protected void addProcessListener(final IProcess newProcess) {
+ if (processListener != null || newProcess == null)
+ return;
+
+ processListener = new IDebugEventSetListener() {
+ public void handleDebugEvents(DebugEvent[] events) {
+ if (events != null) {
+ for (DebugEvent event : events) {
+ if (newProcess != null && newProcess.equals(event.getSource()) && event.getKind() == DebugEvent.TERMINATE) {
+ stop(true);
+ }
+ }
+ }
+ }
+ };
+ DebugPlugin.getDefault().addDebugEventListener(processListener);
+ }
+
+ protected void setServerStarted() {
+ setServerState(IServer.STATE_STARTED);
+ }
+
+ protected void publishServer(int kind, IProgressMonitor monitor) throws CoreException {
+ monitor = ProgressUtil.getMonitorFor(monitor);
+ 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 {
+ IModule module = moduleTree[moduleTree.length - 1];
+ if (isSingleRootStructure(module))
+ return;
+
+ IPath to = getModulePublishDirectory(module);
+
+ if (kind == IServer.PUBLISH_CLEAN || deltaKind == ServerBehaviourDelegate.REMOVED) {
+ IStatus[] status = PublishUtil.deleteDirectory(to.toFile(), monitor);
+ throwException(status);
+ }
+
+ IModuleResource[] res = getResources(moduleTree);
+ IStatus[] status = PublishUtil.publishSmart(res, to, monitor);
+ throwException(status);
+
+ setModulePublishState(moduleTree, IServer.PUBLISH_STATE_NONE);
+ }
+
+ /**
+ * Utility method to throw a CoreException based on the contents of a list of
+ * error and warning status.
+ *
+ * @param status a List containing error and warning IStatus
+ * @throws CoreException
+ */
+ private static void throwException(IStatus[] status) throws CoreException {
+ if (status == null || status.length == 0)
+ return;
+
+ if (status.length == 1)
+ throw new CoreException(status[0]);
+
+ String message = Messages.errorPublish;
+ MultiStatus status2 = new MultiStatus(PreviewPlugin.PLUGIN_ID, 0, status, message, null);
+ throw new CoreException(status2);
+ }
+
+ public void restart(String launchMode) throws CoreException {
+ setServerState(IServer.STATE_STOPPED);
+ setServerState(IServer.STATE_STARTED);
+ }
+
+ /**
+ * Cleanly shuts down and terminates the server.
+ *
+ * @param force <code>true</code> to kill the server
+ */
+ public void stop(boolean force) {
+ int state = getServer().getServerState();
+ if (state == IServer.STATE_STOPPED)
+ return;
+
+ setServerState(IServer.STATE_STOPPING);
+
+ if (ping != null) {
+ ping.stop();
+ ping = null;
+ }
+
+ if (processListener != null) {
+ DebugPlugin.getDefault().removeDebugEventListener(processListener);
+ processListener = null;
+ }
+
+ try {
+ Trace.trace(Trace.FINEST, "Killing the process");
+ ILaunch launch = getServer().getLaunch();
+ if (launch != null)
+ launch.terminate();
+ } catch (Exception e) {
+ Trace.trace(Trace.SEVERE, "Error killing the process", e);
+ }
+
+ setServerState(IServer.STATE_STOPPED);
+ }
+
+ protected IPath getTempDirectory() {
+ return super.getTempDirectory();
+ }
+
+ /**
+ * Returns <code>true</code> if the module in the workspace has a single
+ * root structure - i.e. matches the spec disk layout - and <code>false</code>
+ * otherwise.
+ *
+ * @return <code>true</code> if the module in the workspace has a single
+ * root structure - i.e. matches the spec disk layout - and
+ * <code>false</code> otherwise
+ */
+ protected boolean isSingleRootStructure(IModule module) {
+ ProjectModule pm = (ProjectModule) module.loadAdapter(ProjectModule.class, null);
+ if (pm == null)
+ return false;
+
+ return pm.isSingleRootStructure();
+ }
+
+ /**
+ * Returns the module's publish path.
+ *
+ * @param module a module
+ * @return the publish directory for the module
+ */
+ protected IPath getModulePublishDirectory(IModule module) {
+ if (isSingleRootStructure(module)) {
+ String type = module.getModuleType().getId();
+ if ("wst.web".equals(type)) {
+ IStaticWeb webModule = (IStaticWeb) module.loadAdapter(IStaticWeb.class, null);
+ if (webModule != null) {
+ //IContainer[] moduleFolder = webModule.getResourceFolders();
+ //if (moduleFolder != null && moduleFolder.length > 0)
+ // return moduleFolder[0].getLocation();
+ }
+ } else if ("jst.web".equals(type)) {
+ IWebModule webModule = (IWebModule) module.loadAdapter(IWebModule.class, null);
+ if (webModule != null) {
+ IContainer[] moduleFolder = webModule.getResourceFolders();
+ if (moduleFolder != null && moduleFolder.length > 0)
+ return moduleFolder[0].getLocation();
+ }
+ }
+ }
+
+ return getTempDirectory().append(module.getName());
+ }
+
+ /**
+ * Return a string representation of this object.
+ *
+ * @return a string
+ */
+ public String toString() {
+ return "PreviewServer";
+ }
+
+ protected IModuleResourceDelta[] getPublishedResourceDelta(IModule[] module) {
+ return super.getPublishedResourceDelta(module);
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.wst.server.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..48472e4
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/META-INF/MANIFEST.MF
@@ -0,0 +1,22 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.wst.server.core; singleton:=true
+Bundle-Version: 1.1.1.qualifier
+Bundle-Activator: org.eclipse.wst.server.core.internal.ServerPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.wst.server.core,
+ org.eclipse.wst.server.core.internal;x-friends:="org.eclipse.wst.server.ui",
+ org.eclipse.wst.server.core.internal.facets;x-friends:="org.eclipse.wst.server.ui",
+ org.eclipse.wst.server.core.internal.provisional;x-internal:=true,
+ org.eclipse.wst.server.core.model,
+ org.eclipse.wst.server.core.util
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.core.resources;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.core.expressions;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.debug.core;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.update.core;bundle-version="[3.2.0,4.0.0)";resolution:=optional,
+ org.eclipse.wst.common.project.facet.core;bundle-version="[1.1.0,2.0.0)";resolution:=optional
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Trace.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Trace.java
new file mode 100644
index 0000000..ea2fd7f
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/internal/Trace.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.wst.server.core.internal;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+/**
+ * Helper class to route trace output.
+ */
+public class Trace {
+ public static final byte CONFIG = 0;
+ public static final byte INFO = 1;
+ public static final byte WARNING = 2;
+ public static final byte SEVERE = 3;
+ public static final byte FINER = 4;
+ public static final byte FINEST = 5;
+
+ public static final byte RESOURCES = 6;
+ public static final byte EXTENSION_POINT = 7;
+ public static final byte LISTENERS = 8;
+ public static final byte RUNTIME_TARGET = 9;
+ public static final byte PERFORMANCE = 10;
+ public static final byte PUBLISHING = 11;
+
+ private static final String[] levelNames = new String[] {
+ "CONFIG ", "INFO ", "WARNING ", "SEVERE ", "FINER ", "FINEST ",
+ "RESOURCES", "EXTENSION", "LISTENERS", "TARGET ", "PERF ", "PUBLISH "};
+
+ private static final SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy HH:mm.ss.SSS");
+
+ private static Set<String> logged = new HashSet<String>();
+
+ /**
+ * Trace constructor comment.
+ */
+ private Trace() {
+ super();
+ }
+
+ /**
+ * Trace the given text.
+ *
+ * @param level a trace level
+ * @param s a message
+ */
+ public static void trace(int level, String s) {
+ trace(level, s, null);
+ }
+
+ /**
+ * Trace the given message and exception.
+ *
+ * @param level a trace level
+ * @param s a message
+ * @param t a throwable
+ */
+ public static void trace(int level, String s, Throwable t) {
+ if (s == null)
+ return;
+
+ if (level == SEVERE) {
+ if (!logged.contains(s)) {
+ ServerPlugin.log(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, s, t));
+ logged.add(s);
+ }
+ }
+
+ if (!ServerPlugin.getInstance().isDebugging())
+ return;
+
+ StringBuffer sb = new StringBuffer(ServerPlugin.PLUGIN_ID);
+ sb.append(" ");
+ sb.append(levelNames[level]);
+ sb.append(" ");
+ sb.append(sdf.format(new Date()));
+ sb.append(" ");
+ sb.append(s);
+ //Platform.getDebugOption(ServerCore.PLUGIN_ID + "/" + "resources");
+
+ System.out.println(sb.toString());
+ if (t != null)
+ t.printStackTrace();
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/PublishHelper.java b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/PublishHelper.java
new file mode 100644
index 0000000..3b8d979
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.core/servercore/org/eclipse/wst/server/core/util/PublishHelper.java
@@ -0,0 +1,806 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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.wst.server.core.util;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.*;
+import org.eclipse.wst.server.core.internal.Messages;
+import org.eclipse.wst.server.core.internal.ProgressUtil;
+import org.eclipse.wst.server.core.internal.ServerPlugin;
+import org.eclipse.wst.server.core.internal.Trace;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.wst.server.core.model.IModuleFile;
+import org.eclipse.wst.server.core.model.IModuleFolder;
+import org.eclipse.wst.server.core.model.IModuleResource;
+import org.eclipse.wst.server.core.model.IModuleResourceDelta;
+/**
+ * Utility class with an assortment of useful publishing file methods.
+ *
+ * @since 3.0
+ */
+public final class PublishHelper {
+ // size of the buffer
+ private static final int BUFFER = 65536;
+
+ // the buffer
+ private static byte[] buf = new byte[BUFFER];
+
+ private static final IStatus[] EMPTY_STATUS = new IStatus[0];
+
+ private static final File defaultTempDir = ServerPlugin.getInstance().getStateLocation().toFile();
+
+ private static final String TEMPFILE_PREFIX = "tmp";
+
+ private File tempDir;
+
+ /**
+ * Create a new PublishHelper.
+ *
+ * @param tempDirectory a temporary directory to use during publishing, or <code>null</code>
+ * to use the default. If it does not exist, the folder will be created
+ */
+ public PublishHelper(File tempDirectory) {
+ this.tempDir = tempDirectory;
+ if (tempDir == null)
+ tempDir = defaultTempDir;
+ else if (!tempDir.exists())
+ tempDir.mkdirs();
+ }
+
+ /**
+ * Copy a file from a to b. Closes the input stream after use.
+ *
+ * @param in an input stream
+ * @param to a path to copy to. the directory must already exist
+ * @param ts timestamp
+ * @throws CoreException if anything goes wrong
+ */
+ private void copyFile(InputStream in, IPath to, long ts, IModuleFile mf) throws CoreException {
+ OutputStream out = null;
+
+ File tempFile = null;
+ try {
+ File file = to.toFile();
+ tempFile = File.createTempFile(TEMPFILE_PREFIX, "." + to.getFileExtension(), tempDir);
+
+ out = new FileOutputStream(tempFile);
+
+ int avail = in.read(buf);
+ while (avail > 0) {
+ out.write(buf, 0, avail);
+ avail = in.read(buf);
+ }
+
+ out.close();
+ out = null;
+
+ moveTempFile(tempFile, file);
+
+ if (ts != IResource.NULL_STAMP && ts != 0)
+ file.setLastModified(ts);
+ } catch (CoreException e) {
+ throw e;
+ } catch (Exception e) {
+ IPath path = mf.getModuleRelativePath().append(mf.getName());
+ Trace.trace(Trace.SEVERE, "Error copying file: " + path.toOSString() + " to " + to.toOSString(), e);
+ throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCopyingFile, path.toOSString(), e.getLocalizedMessage()), null));
+ } finally {
+ if (tempFile != null && tempFile.exists())
+ tempFile.deleteOnExit();
+ try {
+ if (in != null)
+ in.close();
+ } catch (Exception ex) {
+ // ignore
+ }
+ try {
+ if (out != null)
+ out.close();
+ } catch (Exception ex) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Utility method to recursively delete a directory.
+ *
+ * @param dir a directory
+ * @param monitor a progress monitor, or <code>null</code> if progress
+ * reporting and cancellation are not desired
+ * @return a possibly-empty array of error and warning status
+ */
+ public static IStatus[] deleteDirectory(File dir, IProgressMonitor monitor) {
+ if (!dir.exists() || !dir.isDirectory())
+ return new IStatus[] { new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorNotADirectory, dir.getAbsolutePath()), null) };
+
+ List<IStatus> status = new ArrayList<IStatus>(2);
+
+ try {
+ File[] files = dir.listFiles();
+ int size = files.length;
+ monitor = ProgressUtil.getMonitorFor(monitor);
+ monitor.beginTask(NLS.bind(Messages.deletingTask, new String[] { dir.getAbsolutePath() }), size * 10);
+
+ // cycle through files
+ boolean deleteCurrent = true;
+ for (int i = 0; i < size; i++) {
+ File current = files[i];
+ if (current.isFile()) {
+ if (!current.delete()) {
+ status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, files[i].getAbsolutePath()), null));
+ deleteCurrent = false;
+ }
+ monitor.worked(10);
+ } else if (current.isDirectory()) {
+ monitor.subTask(NLS.bind(Messages.deletingTask, new String[] {current.getAbsolutePath()}));
+ IStatus[] stat = deleteDirectory(current, ProgressUtil.getSubMonitorFor(monitor, 10));
+ if (stat != null && stat.length > 0) {
+ deleteCurrent = false;
+ addArrayToList(status, stat);
+ }
+ }
+ }
+ if (deleteCurrent && !dir.delete())
+ status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, dir.getAbsolutePath()), null));
+ monitor.done();
+ } catch (Exception e) {
+ Trace.trace(Trace.SEVERE, "Error deleting directory " + dir.getAbsolutePath(), e);
+ status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, e.getLocalizedMessage(), null));
+ }
+
+ IStatus[] stat = new IStatus[status.size()];
+ status.toArray(stat);
+ return stat;
+ }
+
+ /**
+ * Smart copy the given module resources to the given path.
+ *
+ * @param resources an array of module resources
+ * @param path an external path to copy to
+ * @param monitor a progress monitor, or <code>null</code> if progress
+ * reporting and cancellation are not desired
+ * @return a possibly-empty array of error and warning status
+ */
+ public IStatus[] publishSmart(IModuleResource[] resources, IPath path, IProgressMonitor monitor) {
+ return publishSmart(resources, path, null, monitor);
+ }
+
+ /**
+ * Smart copy the given module resources to the given path.
+ *
+ * @param resources an array of module resources
+ * @param path an external path to copy to
+ * @param ignore an array of paths relative to path to ignore, i.e. not delete or copy over
+ * @param monitor a progress monitor, or <code>null</code> if progress
+ * reporting and cancellation are not desired
+ * @return a possibly-empty array of error and warning status
+ */
+ public IStatus[] publishSmart(IModuleResource[] resources, IPath path, IPath[] ignore, IProgressMonitor monitor) {
+ if (resources == null)
+ return EMPTY_STATUS;
+
+ monitor = ProgressUtil.getMonitorFor(monitor);
+
+ List<IStatus> status = new ArrayList<IStatus>(2);
+ File toDir = path.toFile();
+ int fromSize = resources.length;
+ String[] fromFileNames = new String[fromSize];
+ for (int i = 0; i < fromSize; i++)
+ fromFileNames[i] = resources[i].getName();
+ List<String> ignoreFileNames = new ArrayList<String>();
+ if (ignore != null) {
+ for (int i = 0; i < ignore.length; i++) {
+ if (ignore[i].segmentCount() == 1) {
+ ignoreFileNames.add(ignore[i].toOSString());
+ }
+ }
+ }
+
+ // cache files and file names for performance
+ File[] toFiles = null;
+ String[] toFileNames = null;
+
+ boolean foundExistingDir = false;
+ if (toDir.exists()) {
+ if (toDir.isDirectory()) {
+ foundExistingDir = true;
+ toFiles = toDir.listFiles();
+ int toSize = toFiles.length;
+ toFileNames = new String[toSize];
+
+ // check if this exact file exists in the new directory
+ for (int i = 0; i < toSize; i++) {
+ toFileNames[i] = toFiles[i].getName();
+ boolean isDir = toFiles[i].isDirectory();
+ boolean found = false;
+ for (int j = 0; j < fromSize; j++) {
+ if (toFileNames[i].equals(fromFileNames[j]) && isDir == resources[j] instanceof IModuleFolder) {
+ found = true;
+ break;
+ }
+ }
+
+ // delete file if it can't be found or isn't the correct type
+ if (!found) {
+ boolean delete = true;
+ // if should be preserved, don't delete and don't try to copy
+ for (String preserveFileName : ignoreFileNames) {
+ if (toFileNames[i].equals(preserveFileName)) {
+ delete = false;
+ break;
+ }
+ }
+ if (delete) {
+ if (isDir) {
+ IStatus[] stat = deleteDirectory(toFiles[i], null);
+ addArrayToList(status, stat);
+ } else {
+ if (!toFiles[i].delete())
+ status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, toFiles[i].getAbsolutePath()), null));
+ }
+ }
+ toFiles[i] = null;
+ toFileNames[i] = null;
+ }
+ }
+ } else { //if (toDir.isFile())
+ if (!toDir.delete()) {
+ status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, toDir.getAbsolutePath()), null));
+ IStatus[] stat = new IStatus[status.size()];
+ status.toArray(stat);
+ return stat;
+ }
+ }
+ }
+ if (!foundExistingDir && !toDir.mkdirs()) {
+ status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorMkdir, toDir.getAbsolutePath()), null));
+ IStatus[] stat = new IStatus[status.size()];
+ status.toArray(stat);
+ return stat;
+ }
+
+ if (monitor.isCanceled())
+ return new IStatus[] { Status.CANCEL_STATUS };
+
+ monitor.worked(50);
+
+ // cycle through files and only copy when it doesn't exist
+ // or is newer
+ if (toFiles == null) {
+ toFiles = toDir.listFiles();
+ if (toFiles == null)
+ toFiles = new File[0];
+ }
+ int toSize = toFiles.length;
+
+ int dw = 0;
+ if (toSize > 0)
+ dw = 500 / toSize;
+
+ // cache file names and last modified dates for performance
+ if (toFileNames == null)
+ toFileNames = new String[toSize];
+ long[] toFileMod = new long[toSize];
+ for (int i = 0; i < toSize; i++) {
+ if (toFiles[i] != null) {
+ if (toFileNames[i] != null)
+ toFileNames[i] = toFiles[i].getName();
+ toFileMod[i] = toFiles[i].lastModified();
+ }
+ }
+
+ for (int i = 0; i < fromSize; i++) {
+ IModuleResource current = resources[i];
+ String name = fromFileNames[i];
+ boolean currentIsDir = current instanceof IModuleFolder;
+
+ if (!currentIsDir) {
+ // check if this is a new or newer file
+ boolean copy = true;
+ IModuleFile mf = (IModuleFile) current;
+
+ long mod = -1;
+ IFile file = (IFile) mf.getAdapter(IFile.class);
+ if (file != null) {
+ mod = file.getLocalTimeStamp();
+ } else {
+ File file2 = (File) mf.getAdapter(File.class);
+ mod = file2.lastModified();
+ }
+
+ for (int j = 0; j < toSize; j++) {
+ if (name.equals(toFileNames[j]) && mod == toFileMod[j]) {
+ copy = false;
+ break;
+ }
+ }
+
+ if (copy) {
+ try {
+ copyFile(mf, path.append(name));
+ } catch (CoreException ce) {
+ status.add(ce.getStatus());
+ }
+ }
+ monitor.worked(dw);
+ } else { //if (currentIsDir) {
+ IModuleFolder folder = (IModuleFolder) current;
+ IModuleResource[] children = folder.members();
+
+ // build array of ignored Paths that apply to this folder
+ IPath[] ignoreChildren = null;
+ if (ignore != null) {
+ List<IPath> ignoreChildPaths = new ArrayList<IPath>();
+ for (int j = 0; j < ignore.length; j++) {
+ IPath preservePath = ignore[j];
+ if (preservePath.segment(0).equals(name)) {
+ ignoreChildPaths.add(preservePath.removeFirstSegments(1));
+ }
+ }
+ if (ignoreChildPaths.size() > 0)
+ ignoreChildren = ignoreChildPaths.toArray(new Path[ignoreChildPaths.size()]);
+ }
+ monitor.subTask(NLS.bind(Messages.copyingTask, new String[] {name, name}));
+ IStatus[] stat = publishSmart(children, path.append(name), ignoreChildren, ProgressUtil.getSubMonitorFor(monitor, dw));
+ addArrayToList(status, stat);
+ }
+ }
+ if (monitor.isCanceled())
+ return new IStatus[] { Status.CANCEL_STATUS };
+
+ monitor.worked(500 - dw * toSize);
+ monitor.done();
+
+ IStatus[] stat = new IStatus[status.size()];
+ status.toArray(stat);
+ return stat;
+ }
+
+ /**
+ * Handle a delta publish.
+ *
+ * @param delta a module resource delta
+ * @param path the path to publish to
+ * @param monitor a progress monitor, or <code>null</code> if progress
+ * reporting and cancellation are not desired
+ * @return a possibly-empty array of error and warning status
+ */
+ public IStatus[] publishDelta(IModuleResourceDelta[] delta, IPath path, IProgressMonitor monitor) {
+ if (delta == null)
+ return EMPTY_STATUS;
+
+ monitor = ProgressUtil.getMonitorFor(monitor);
+
+ List<IStatus> status = new ArrayList<IStatus>(2);
+ int size2 = delta.length;
+ for (int i = 0; i < size2; i++) {
+ IStatus[] stat = publishDelta(delta[i], path, monitor);
+ addArrayToList(status, stat);
+ }
+
+ IStatus[] stat = new IStatus[status.size()];
+ status.toArray(stat);
+ return stat;
+ }
+
+ /**
+ * Handle a delta publish.
+ *
+ * @param delta a module resource delta
+ * @param path the path to publish to
+ * @param monitor a progress monitor, or <code>null</code> if progress
+ * reporting and cancellation are not desired
+ * @return a possibly-empty array of error and warning status
+ */
+ public IStatus[] publishDelta(IModuleResourceDelta delta, IPath path, IProgressMonitor monitor) {
+ List<IStatus> status = new ArrayList<IStatus>(2);
+
+ IModuleResource resource = delta.getModuleResource();
+ int kind2 = delta.getKind();
+
+ if (resource instanceof IModuleFile) {
+ IModuleFile file = (IModuleFile) resource;
+ try {
+ if (kind2 == IModuleResourceDelta.REMOVED)
+ deleteFile(path, file);
+ else {
+ IPath path2 = path.append(file.getModuleRelativePath()).append(file.getName());
+ File f = path2.toFile().getParentFile();
+ if (!f.exists())
+ f.mkdirs();
+
+ copyFile(file, path2);
+ }
+ } catch (CoreException ce) {
+ status.add(ce.getStatus());
+ }
+ IStatus[] stat = new IStatus[status.size()];
+ status.toArray(stat);
+ return stat;
+ }
+
+ if (kind2 == IModuleResourceDelta.ADDED) {
+ IPath path2 = path.append(resource.getModuleRelativePath()).append(resource.getName());
+ File file = path2.toFile();
+ if (!file.exists() && !file.mkdirs()) {
+ status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorMkdir, path2), null));
+ IStatus[] stat = new IStatus[status.size()];
+ status.toArray(stat);
+ return stat;
+ }
+ }
+
+ IModuleResourceDelta[] childDeltas = delta.getAffectedChildren();
+ int size = childDeltas.length;
+ for (int i = 0; i < size; i++) {
+ IStatus[] stat = publishDelta(childDeltas[i], path, monitor);
+ addArrayToList(status, stat);
+ }
+
+ if (kind2 == IModuleResourceDelta.REMOVED) {
+ IPath path2 = path.append(resource.getModuleRelativePath()).append(resource.getName());
+ File file = path2.toFile();
+ if (file.exists() && !file.delete()) {
+ status.add(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, path2), null));
+ }
+ }
+
+ IStatus[] stat = new IStatus[status.size()];
+ status.toArray(stat);
+ return stat;
+ }
+
+ private static void deleteFile(IPath path, IModuleFile file) throws CoreException {
+ Trace.trace(Trace.PUBLISHING, "Deleting: " + file.getName() + " from " + path.toString());
+ IPath path2 = path.append(file.getModuleRelativePath()).append(file.getName());
+ if (path2.toFile().exists() && !path2.toFile().delete())
+ throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, path2), null));
+ }
+
+ private void copyFile(IModuleFile mf, IPath path) throws CoreException {
+ Trace.trace(Trace.PUBLISHING, "Copying: " + mf.getName() + " to " + path.toString());
+
+ IFile file = (IFile) mf.getAdapter(IFile.class);
+ if (file != null)
+ copyFile(file.getContents(), path, file.getLocalTimeStamp(), mf);
+ else {
+ File file2 = (File) mf.getAdapter(File.class);
+ InputStream in = null;
+ try {
+ in = new FileInputStream(file2);
+ } catch (IOException e) {
+ throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorReading, file2.getAbsolutePath()), e));
+ }
+ copyFile(in, path, file2.lastModified(), mf);
+ }
+ }
+
+ /**
+ * Publish the given module resources to the given path.
+ *
+ * @param resources an array of module resources
+ * @param path a path to publish to
+ * @param monitor a progress monitor, or <code>null</code> if progress
+ * reporting and cancellation are not desired
+ * @return a possibly-empty array of error and warning status
+ */
+ public IStatus[] publishFull(IModuleResource[] resources, IPath path, IProgressMonitor monitor) {
+ if (resources == null)
+ return EMPTY_STATUS;
+
+ monitor = ProgressUtil.getMonitorFor(monitor);
+
+ List<IStatus> status = new ArrayList<IStatus>(2);
+ int size = resources.length;
+ for (int i = 0; i < size; i++) {
+ IStatus[] stat = copy(resources[i], path, monitor);
+ addArrayToList(status, stat);
+ }
+
+ IStatus[] stat = new IStatus[status.size()];
+ status.toArray(stat);
+ return stat;
+ }
+
+ private IStatus[] copy(IModuleResource resource, IPath path, IProgressMonitor monitor) {
+ String name = resource.getName();
+ Trace.trace(Trace.PUBLISHING, "Copying: " + name + " to " + path.toString());
+ List<IStatus> status = new ArrayList<IStatus>(2);
+ if (resource instanceof IModuleFolder) {
+ IModuleFolder folder = (IModuleFolder) resource;
+ IStatus[] stat = publishFull(folder.members(), path, monitor);
+ addArrayToList(status, stat);
+ } else {
+ IModuleFile mf = (IModuleFile) resource;
+ path = path.append(mf.getModuleRelativePath()).append(name);
+ File f = path.toFile().getParentFile();
+ if (!f.exists())
+ f.mkdirs();
+ try {
+ copyFile(mf, path);
+ } catch (CoreException ce) {
+ status.add(ce.getStatus());
+ }
+ }
+ IStatus[] stat = new IStatus[status.size()];
+ status.toArray(stat);
+ return stat;
+ }
+
+ /**
+ * Creates a new zip file containing the given module resources. Deletes the existing file
+ * (and doesn't create a new one) if resources is null or empty.
+ *
+ * @param resources an array of module resources
+ * @param path the path where the zip file should be created
+ * @param monitor a progress monitor, or <code>null</code> if progress
+ * reporting and cancellation are not desired
+ * @return a possibly-empty array of error and warning status
+ */
+ public IStatus[] publishZip(IModuleResource[] resources, IPath path, IProgressMonitor monitor) {
+ if (resources == null || resources.length == 0) {
+ // should also check if resources consists of all empty directories
+ File file = path.toFile();
+ if (file.exists())
+ file.delete();
+ return EMPTY_STATUS;
+ }
+
+ monitor = ProgressUtil.getMonitorFor(monitor);
+
+ File tempFile = null;
+ try {
+ File file = path.toFile();
+ tempFile = File.createTempFile(TEMPFILE_PREFIX, "." + path.getFileExtension(), tempDir);
+
+ BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(tempFile));
+ ZipOutputStream zout = new ZipOutputStream(bout);
+ addZipEntries(zout, resources);
+ zout.close();
+
+ moveTempFile(tempFile, file);
+ } catch (CoreException e) {
+ return new IStatus[] { e.getStatus() };
+ } catch (Exception e) {
+ Trace.trace(Trace.SEVERE, "Error zipping", e);
+ return new Status[] { new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCreatingZipFile, path.lastSegment(), e.getLocalizedMessage()), e) };
+ } finally {
+ if (tempFile != null && tempFile.exists())
+ tempFile.deleteOnExit();
+ }
+ return EMPTY_STATUS;
+ }
+
+ private static void addZipEntries(ZipOutputStream zout, IModuleResource[] resources) throws Exception {
+ if (resources == null)
+ return;
+
+ int size = resources.length;
+ for (int i = 0; i < size; i++) {
+ if (resources[i] instanceof IModuleFolder) {
+ IModuleFolder mf = (IModuleFolder) resources[i];
+ IModuleResource[] res = mf.members();
+
+ IPath path = mf.getModuleRelativePath().append(mf.getName());
+ String entryPath = path.toPortableString();
+ if (!entryPath.endsWith("/"))
+ entryPath += '/';
+
+ ZipEntry ze = new ZipEntry(entryPath);
+
+ long ts = 0;
+ IContainer folder = (IContainer) mf.getAdapter(IContainer.class);
+ if (folder != null)
+ ts = folder.getLocalTimeStamp();
+
+ if (ts != IResource.NULL_STAMP && ts != 0)
+ ze.setTime(ts);
+
+ zout.putNextEntry(ze);
+ zout.closeEntry();
+
+ addZipEntries(zout, res);
+ continue;
+ }
+
+ IModuleFile mf = (IModuleFile) resources[i];
+ IPath path = mf.getModuleRelativePath().append(mf.getName());
+
+ ZipEntry ze = new ZipEntry(path.toPortableString());
+
+ InputStream in = null;
+ long ts = 0;
+ IFile file = (IFile) mf.getAdapter(IFile.class);
+ if (file != null) {
+ ts = file.getLocalTimeStamp();
+ in = file.getContents();
+ } else {
+ File file2 = (File) mf.getAdapter(File.class);
+ ts = file2.lastModified();
+ in = new FileInputStream(file2);
+ }
+
+ if (ts != IResource.NULL_STAMP && ts != 0)
+ ze.setTime(ts);
+
+ zout.putNextEntry(ze);
+
+ try {
+ int n = 0;
+ while (n > -1) {
+ n = in.read(buf);
+ if (n > 0)
+ zout.write(buf, 0, n);
+ }
+ } finally {
+ in.close();
+ }
+
+ zout.closeEntry();
+ }
+ }
+
+ /**
+ * Utility method to move a temp file into position by deleting the original and
+ * swapping in a new copy.
+ *
+ * @param tempFile
+ * @param file
+ * @throws CoreException
+ */
+ private void moveTempFile(File tempFile, File file) throws CoreException {
+ if (file.exists()) {
+ if (!safeDelete(file, 2)) {
+ // attempt to rewrite an existing file with the tempFile contents if
+ // the existing file can't be deleted to permit the move
+ try {
+ InputStream in = new FileInputStream(tempFile);
+ IStatus status = copyFile(in, file.getPath());
+ if (!status.isOK()) {
+ MultiStatus status2 = new MultiStatus(ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, file.toString()), null);
+ status2.add(status);
+ throw new CoreException(status2);
+ }
+ return;
+ } catch (FileNotFoundException e) {
+ // shouldn't occur
+ } finally {
+ tempFile.delete();
+ }
+ /*if (!safeDelete(file, 8)) {
+ tempFile.delete();
+ throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorDeleting, file.toString()), null));
+ }*/
+ }
+ }
+ if (!safeRename(tempFile, file, 10))
+ throw new CoreException(new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorRename, tempFile.toString()), null));
+ }
+
+ /**
+ * Copy a file from a to b. Closes the input stream after use.
+ *
+ * @param in an InputStream
+ * @param to the file to copy to
+ * @return a status
+ */
+ private IStatus copyFile(InputStream in, String to) {
+ OutputStream out = null;
+
+ try {
+ out = new FileOutputStream(to);
+
+ int avail = in.read(buf);
+ while (avail > 0) {
+ out.write(buf, 0, avail);
+ avail = in.read(buf);
+ }
+ return Status.OK_STATUS;
+ } catch (Exception e) {
+ Trace.trace(Trace.SEVERE, "Error copying file", e);
+ return new Status(IStatus.ERROR, ServerPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorCopyingFile, new String[] {to, e.getLocalizedMessage()}), e);
+ } finally {
+ try {
+ if (in != null)
+ in.close();
+ } catch (Exception ex) {
+ // ignore
+ }
+ try {
+ if (out != null)
+ out.close();
+ } catch (Exception ex) {
+ // ignore
+ }
+ }
+ }
+
+ /**
+ * Safe delete. Tries to delete multiple times before giving up.
+ *
+ * @param f
+ * @return <code>true</code> if it succeeds, <code>false</code> otherwise
+ */
+ private static boolean safeDelete(File f, int retrys) {
+ int count = 0;
+ while (count < retrys) {
+ if (!f.exists())
+ return true;
+
+ f.delete();
+
+ if (!f.exists())
+ return true;
+
+ count++;
+ // delay if we are going to try again
+ if (count < retrys) {
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Safe rename. Will try multiple times before giving up.
+ *
+ * @param from
+ * @param to
+ * @param retrys number of times to retry
+ * @return <code>true</code> if it succeeds, <code>false</code> otherwise
+ */
+ private static boolean safeRename(File from, File to, int retrys) {
+ // make sure parent dir exists
+ File dir = to.getParentFile();
+ if (dir != null && !dir.exists())
+ dir.mkdirs();
+
+ int count = 0;
+ while (count < retrys) {
+ if (from.renameTo(to))
+ return true;
+
+ count++;
+ // delay if we are going to try again
+ if (count < retrys) {
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+ return false;
+ }
+
+ private static void addArrayToList(List<IStatus> list, IStatus[] a) {
+ if (list == null || a == null || a.length == 0)
+ return;
+
+ int size = a.length;
+ for (int i = 0; i < size; i++)
+ list.add(a[i]);
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.preview.adapter/META-INF/MANIFEST.MF b/plugins/org.eclipse.wst.server.preview.adapter/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..487f18a
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.preview.adapter/META-INF/MANIFEST.MF
@@ -0,0 +1,14 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.wst.server.preview.adapter;singleton:=true
+Bundle-Version: 1.0.101.qualifier
+Bundle-Activator: org.eclipse.wst.server.preview.adapter.internal.core.PreviewPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.wst.server.core;bundle-version="[1.0.204,2.0.0)",
+ org.eclipse.wst.server.ui;bundle-version="[1.0.103,2.0.0)",
+ org.eclipse.debug.ui;bundle-version="[3.3.0,4.0.0)",
+ org.eclipse.wst.common.project.facet.ui;bundle-version="[1.2.0,2.0.0)"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.wst.server.preview.adapter/src/org/eclipse/wst/server/preview/adapter/internal/core/PreviewServerBehaviour.java b/plugins/org.eclipse.wst.server.preview.adapter/src/org/eclipse/wst/server/preview/adapter/internal/core/PreviewServerBehaviour.java
new file mode 100644
index 0000000..ea0f5ec
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.preview.adapter/src/org/eclipse/wst/server/preview/adapter/internal/core/PreviewServerBehaviour.java
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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.wst.server.preview.adapter.internal.core;
+
+import java.io.IOException;
+
+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.MultiStatus;
+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.model.IProcess;
+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.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.IStaticWeb;
+import org.eclipse.wst.server.core.util.ProjectModule;
+import org.eclipse.wst.server.core.util.PublishUtil;
+import org.eclipse.wst.server.core.util.SocketUtil;
+/**
+ * Preview server.
+ */
+public class PreviewServerBehaviour extends ServerBehaviourDelegate {
+ // the thread used to ping the server to check for startup
+ protected transient PingThread ping = null;
+ protected transient IDebugEventSetListener processListener;
+
+ /**
+ * PreviewServer.
+ */
+ public PreviewServerBehaviour() {
+ super();
+ }
+
+ public void initialize(IProgressMonitor monitor) {
+ // do nothing
+ }
+
+ public PreviewRuntime getPreviewRuntime() {
+ if (getServer().getRuntime() == null)
+ return null;
+
+ return (PreviewRuntime) getServer().getRuntime().loadAdapter(PreviewRuntime.class, null);
+ }
+
+ public PreviewServer getPreviewServer() {
+ return (PreviewServer) getServer().getAdapter(PreviewServer.class);
+ }
+
+ /**
+ * Returns the runtime base path for relative paths in the server
+ * configuration.
+ *
+ * @return the base path
+ */
+ public IPath getRuntimeBaseDirectory() {
+ return getServer().getRuntime().getLocation();
+ }
+
+ /**
+ * Setup for starting the server.
+ *
+ * @param launch ILaunch
+ * @param launchMode String
+ * @param monitor IProgressMonitor
+ * @throws CoreException if anything goes wrong
+ */
+ protected void setupLaunch(ILaunch launch, String launchMode, IProgressMonitor monitor) throws CoreException {
+ // check that ports are free
+ ServerPort[] ports = getPreviewServer().getServerPorts();
+ int port = ports[0].getPort();
+
+ if (SocketUtil.isPortInUse(port, 5))
+ throw new CoreException(new Status(IStatus.ERROR, PreviewPlugin.PLUGIN_ID, 0, NLS.bind(Messages.errorPortInUse, new String[] {port + "", getServer().getName()}), null));
+
+ // generate preview config file
+ XMLMemento memento = XMLMemento.createWriteRoot("server");
+ memento.putInteger("port", port);
+
+ IModule[] modules = getServer().getModules();
+ for (IModule module : modules) {
+ IMemento mod = memento.createChild("module");
+ mod.putString("name", module.getName());
+ String type = module.getModuleType().getId();
+ if ("wst.web".equals(type)) {
+ IStaticWeb staticWeb = (IStaticWeb) module.loadAdapter(IStaticWeb.class, null);
+ if (staticWeb != null)
+ mod.putString("context", staticWeb.getContextRoot());
+ mod.putString("type", "static");
+ }
+ mod.putString("path", getModulePublishDirectory(module).toPortableString());
+ }
+ try {
+ memento.saveToFile(getTempDirectory().append("preview.xml").toOSString());
+ } catch (IOException e) {
+ Trace.trace(Trace.SEVERE, "Could not write preview config", e);
+ throw new CoreException(new Status(IStatus.ERROR, PreviewPlugin.PLUGIN_ID, 0, "Could not write preview configuration", null));
+ }
+
+ setServerRestartState(false);
+ setServerState(IServer.STATE_STARTING);
+ setMode(launchMode);
+
+ // ping server to check for startup
+ try {
+ String url = "http://localhost";
+ if (port != 80)
+ url += ":" + port;
+ ping = new PingThread(getServer(), url, this);
+ } catch (Exception e) {
+ Trace.trace(Trace.SEVERE, "Can't ping for Tomcat startup.");
+ }
+ }
+
+ protected void addProcessListener(final IProcess newProcess) {
+ if (processListener != null || newProcess == null)
+ return;
+
+ processListener = new IDebugEventSetListener() {
+ public void handleDebugEvents(DebugEvent[] events) {
+ if (events != null) {
+ for (DebugEvent event : events) {
+ if (newProcess != null && newProcess.equals(event.getSource()) && event.getKind() == DebugEvent.TERMINATE) {
+ stop(true);
+ }
+ }
+ }
+ }
+ };
+ DebugPlugin.getDefault().addDebugEventListener(processListener);
+ }
+
+ protected void setServerStarted() {
+ setServerState(IServer.STATE_STARTED);
+ }
+
+ protected void publishServer(int kind, IProgressMonitor monitor) throws CoreException {
+ monitor = ProgressUtil.getMonitorFor(monitor);
+ 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 {
+ IModule module = moduleTree[moduleTree.length - 1];
+ if (isSingleRootStructure(module))
+ return;
+
+ IPath to = getModulePublishDirectory(module);
+
+ if (kind == IServer.PUBLISH_CLEAN || deltaKind == ServerBehaviourDelegate.REMOVED) {
+ IStatus[] status = PublishUtil.deleteDirectory(to.toFile(), monitor);
+ throwException(status);
+ }
+
+ IModuleResource[] res = getResources(moduleTree);
+ IStatus[] status = PublishUtil.publishSmart(res, to, monitor);
+ throwException(status);
+
+ setModulePublishState(moduleTree, IServer.PUBLISH_STATE_NONE);
+ }
+
+ /**
+ * Utility method to throw a CoreException based on the contents of a list of
+ * error and warning status.
+ *
+ * @param status a List containing error and warning IStatus
+ * @throws CoreException
+ */
+ private static void throwException(IStatus[] status) throws CoreException {
+ if (status == null || status.length == 0)
+ return;
+
+ if (status.length == 1)
+ throw new CoreException(status[0]);
+
+ String message = Messages.errorPublish;
+ MultiStatus status2 = new MultiStatus(PreviewPlugin.PLUGIN_ID, 0, status, message, null);
+ throw new CoreException(status2);
+ }
+
+ public void restart(String launchMode) throws CoreException {
+ setServerState(IServer.STATE_STOPPED);
+ setServerState(IServer.STATE_STARTED);
+ }
+
+ /**
+ * Cleanly shuts down and terminates the server.
+ *
+ * @param force <code>true</code> to kill the server
+ */
+ public void stop(boolean force) {
+ int state = getServer().getServerState();
+ if (state == IServer.STATE_STOPPED)
+ return;
+
+ setServerState(IServer.STATE_STOPPING);
+
+ if (ping != null) {
+ ping.stop();
+ ping = null;
+ }
+
+ if (processListener != null) {
+ DebugPlugin.getDefault().removeDebugEventListener(processListener);
+ processListener = null;
+ }
+
+ try {
+ Trace.trace(Trace.FINEST, "Killing the process");
+ ILaunch launch = getServer().getLaunch();
+ if (launch != null)
+ launch.terminate();
+ } catch (Exception e) {
+ Trace.trace(Trace.SEVERE, "Error killing the process", e);
+ }
+
+ setServerState(IServer.STATE_STOPPED);
+ }
+
+ protected IPath getTempDirectory() {
+ return super.getTempDirectory();
+ }
+
+ /**
+ * Returns <code>true</code> if the module in the workspace has a single
+ * root structure - i.e. matches the spec disk layout - and <code>false</code>
+ * otherwise.
+ *
+ * @return <code>true</code> if the module in the workspace has a single
+ * root structure - i.e. matches the spec disk layout - and
+ * <code>false</code> otherwise
+ */
+ protected boolean isSingleRootStructure(IModule module) {
+ ProjectModule pm = (ProjectModule) module.loadAdapter(ProjectModule.class, null);
+ if (pm == null)
+ return false;
+
+ return pm.isSingleRootStructure();
+ }
+
+ /**
+ * Returns the module's publish path.
+ *
+ * @param module a module
+ * @return the publish directory for the module
+ */
+ protected IPath getModulePublishDirectory(IModule module) {
+ if (isSingleRootStructure(module)) {
+ IStaticWeb webModule = (IStaticWeb) module.loadAdapter(IStaticWeb.class, null);
+ if (webModule != null) {
+ //IContainer[] moduleFolder = webModule.getResourceFolders();
+ //if (moduleFolder != null && moduleFolder.length > 0)
+ // return moduleFolder[0].getLocation();
+ }
+ }
+
+ return getTempDirectory().append(module.getName());
+ }
+
+ /**
+ * Return a string representation of this object.
+ *
+ * @return java.lang.String
+ */
+ public String toString() {
+ return "PreviewServer";
+ }
+
+ protected IModuleResourceDelta[] getPublishedResourceDelta(IModule[] module) {
+ return super.getPublishedResourceDelta(module);
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.wst.server.ui/META-INF/MANIFEST.MF
index 8815a61..71f3f04 100644
--- a/plugins/org.eclipse.wst.server.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.wst.server.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.wst.server.ui; singleton:=true
-Bundle-Version: 1.1.1.qualifier
+Bundle-Version: 1.1.2.qualifier
Bundle-Activator: org.eclipse.wst.server.ui.internal.ServerUIPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.wst.server.ui/serverAdapterSites.xml b/plugins/org.eclipse.wst.server.ui/serverAdapterSites.xml
new file mode 100644
index 0000000..54ec5e0
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverAdapterSites.xml
@@ -0,0 +1,10 @@
+<extensions>
+ <site url="http://www.apache.org/dist/geronimo/eclipse/updates/"/>
+ <site url="http://download.boulder.ibm.com/ibmdl/pub/software/websphere/wasce/updates/"/>
+ <site url="http://www.pramati.com/downloads/eclipse/updates/"/>
+ <site url="http://update.eclipse.org/updates/3.3/"/>
+ <site url="http://download.oracle.com/otn_software/oepe/ganymede/wls-adapter/"/>
+ <site url="https://ajax.dev.java.net/eclipse"/>
+ <site url="https://www.sdn.sap.com/downloads/updates/netweaver/nwds/sapnwserver/"/>
+ <site url="http://www.webtide.com/eclipse"/>
+</extensions>
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.java
index 48a4403..79f2f7a 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.java
@@ -183,6 +183,7 @@
public static String wizModuleRemoveAll;
public static String wizModuleRequiredModule;
public static String wizModuleRequiredModules;
+ public static String wizModulePublishImmediately;
public static String wizTaskTitle;
public static String wizTaskDescription;
public static String wizErrorInvalidFolder;
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.properties b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.properties
index f768261..08b92ba 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.properties
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Messages.properties
@@ -85,6 +85,7 @@
wizModuleRemoveAll=<< Re&move All
wizModuleRequiredModule={0} is required and cannot be removed from the server
wizModuleRequiredModules=One of the required modules ({0}) must be added to the server
+wizModulePublishImmediately=If server is started, publish changes &immediately
# Wizard info and error messages
wizErrorInvalidFolder=The folder must be a server project or a folder within a server project
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerPropertyPage.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerPropertyPage.java
new file mode 100644
index 0000000..53a7147
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerPropertyPage.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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.wst.server.ui.internal;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PropertyPage;
+import org.eclipse.ui.help.IWorkbenchHelpSystem;
+import org.eclipse.wst.server.core.IRuntimeType;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.IServerType;
+import org.eclipse.wst.server.core.internal.Server;
+/**
+ * PropertyPage for servers.
+ */
+public class ServerPropertyPage extends PropertyPage {
+ protected IServer server;
+
+ protected IServer defaultServer;
+
+ /**
+ * ServerPropertyPage constructor comment.
+ */
+ public ServerPropertyPage() {
+ super();
+ }
+
+ /**
+ * Create the body of the page.
+ *
+ * @param parent org.eclipse.swt.widgets.Composite
+ * @return org.eclipse.swt.widgets.Control
+ */
+ protected Control createContents(Composite parent) {
+ try {
+ IAdaptable element = getElement();
+ server = (IServer) element.getAdapter(IServer.class);
+
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.numColumns = 3;
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ IWorkbenchHelpSystem whs = PlatformUI.getWorkbench().getHelpSystem();
+ whs.setHelp(composite, ContextIds.SERVER_PROPERTY_PAGE);
+
+ // name
+ Label label = new Label(composite, SWT.NONE);
+ label.setText(Messages.propServerInfoName);
+
+ label = new Label(composite, SWT.NONE);
+ label.setText(server.getName());
+ GridData data = new GridData(GridData.FILL_HORIZONTAL);
+ data.horizontalSpan = 2;
+ label.setLayoutData(data);
+
+ // type
+ label = new Label(composite, SWT.NONE);
+ label.setText(Messages.propServerInfoType);
+
+ IServerType serverType = server.getServerType();
+ label = new Label(composite, SWT.NONE);
+ if (serverType != null)
+ label.setText(serverType.getName());
+ else
+ label.setText(Messages.elementUnknownName);
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ data.horizontalSpan = 2;
+ label.setLayoutData(data);
+
+ // vendor
+ label = new Label(composite, SWT.NONE);
+ label.setText(Messages.propServerInfoVendor);
+
+ IRuntimeType runtimeType = null;
+ if (serverType != null)
+ runtimeType = serverType.getRuntimeType();
+ label = new Label(composite, SWT.NONE);
+ if (runtimeType != null)
+ label.setText(runtimeType.getVendor());
+ else
+ label.setText(Messages.elementUnknownName);
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ data.horizontalSpan = 2;
+ label.setLayoutData(data);
+
+ // location
+ label = new Label(composite, SWT.NONE);
+ label.setText(Messages.switchServerLocation);
+ label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING));
+
+ final Label serverLocation = new Label(composite, SWT.NONE);
+ final Server svr = (Server) server;
+ if (svr.getFile() != null)
+ serverLocation.setText(svr.getFile().getFullPath().toPortableString());
+ else
+ serverLocation.setText(Messages.switchServerLocationMetadata);
+
+ serverLocation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING));
+
+ Button switchLocation = new Button(composite, SWT.PUSH);
+ switchLocation.setText(Messages.actionSwitchServerLocation);
+ switchLocation.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
+ switchLocation.setEnabled(!server.isReadOnly());
+ switchLocation.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ try {
+ Server.switchLocation(svr, null);
+ } catch (CoreException ce) {
+ Trace.trace(Trace.SEVERE, "Error switching server location", ce);
+ }
+ if (svr.getFile() != null)
+ serverLocation.setText(svr.getFile().getFullPath().toPortableString());
+ else
+ serverLocation.setText(Messages.switchServerLocationMetadata);
+ }
+ });
+
+ Dialog.applyDialogFont(composite);
+
+ return composite;
+ } catch (Exception e) {
+ Trace.trace(Trace.SEVERE, "Error creating property page", e);
+ return null;
+ }
+ }
+
+ protected void performDefaults() {
+ super.performDefaults();
+ }
+
+ /**
+ * @see org.eclipse.jface.preference.PreferencePage#performOk()
+ */
+ public boolean performOk() {
+ return super.performOk();
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerToolTip.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerToolTip.java
new file mode 100644
index 0000000..83501e1
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerToolTip.java
@@ -0,0 +1,296 @@
+/**********************************************************************
+ * Copyright (c) 2007 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.wst.server.ui.internal;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.internal.text.html.HTML2TextReader;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.window.ToolTip;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.internal.Trace;
+import org.eclipse.wst.server.ui.IServerModule;
+import org.eclipse.wst.server.ui.internal.provisional.IServerToolTip;
+
+public class ServerToolTip extends ToolTip {
+ protected Hashtable<String,ArrayList<IServerToolTip>> toolTipProviders = new Hashtable<String,ArrayList<IServerToolTip>>();
+ protected static Shell CURRENT_TOOLTIP;
+ protected Label hintLabel;
+ protected Tree tree;
+ protected int x;
+ protected int y;
+
+ public ServerToolTip(final Tree tree) {
+ super(tree);
+
+ this.tree = tree;
+
+ tree.addMouseMoveListener(new MouseMoveListener() {
+ public void mouseMove(MouseEvent e) {
+ x = e.x;
+ y = e.y;
+ }
+ });
+
+ tree.addKeyListener(new KeyListener() {
+ public void keyPressed(KeyEvent e) {
+ if (e.keyCode == SWT.ESC) {
+ if (CURRENT_TOOLTIP != null) {
+ CURRENT_TOOLTIP.dispose();
+ CURRENT_TOOLTIP = null;
+ }
+ activate();
+ }
+ if (e.keyCode == SWT.F6) {
+ if (CURRENT_TOOLTIP == null) {
+ deactivate();
+ hide();
+ createFocusedTooltip(tree);
+ }
+ }
+ }
+ public void keyReleased(KeyEvent e){
+ // nothing to do
+ }
+ });
+
+ loadExtensions();
+ }
+
+ public void createFocusedTooltip(final Control control) {
+ final Shell stickyTooltip = new Shell(control.getShell(), SWT.ON_TOP | SWT.TOOL
+ | SWT.NO_FOCUS);
+ stickyTooltip.setLayout(new FillLayout());
+ stickyTooltip.setBackground(stickyTooltip.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+
+ control.getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ Event event = new Event();
+ event.x = x;
+ event.y = y;
+ event.widget = tree;
+
+ createToolTipContentArea(event, stickyTooltip);
+ stickyTooltip.pack();
+
+ stickyTooltip.setLocation(stickyTooltip.getDisplay().getCursorLocation());
+ hintLabel.setText(Messages.toolTipDisableFocus);
+ stickyTooltip.setVisible(true);
+// Eventually we want to add a listener that checks if
+// the mouseDown event is occurring outside of the bounds of the tooltip
+// if it is, then hide the tooltip
+// addListener(stickyTooltip);
+ }
+ });
+ CURRENT_TOOLTIP = stickyTooltip;
+ }
+
+// read the createFocusedTooltip method for information on why this is commented out
+//
+// private void addListener(Control control){
+// control.addMouseListener(new StickyTipMouseListener());
+// if (control instanceof Composite){
+// Control[] childrens = ((Composite)control).getChildren();
+// for (Control child :childrens){
+// addListener(child);
+// }
+// }
+//
+// }
+
+
+ @Override
+ protected Object getToolTipArea(Event event) {
+ Object o = tree.getItem(new Point(event.x,event.y));
+ return o;
+ }
+
+ protected final boolean shouldCreateToolTip(Event event) {
+ if (tree.getItem(new Point(event.x, event.y)) == null)
+ return false;
+ return super.shouldCreateToolTip(event);
+ }
+
+ protected Composite createToolTipContentArea(Event event, Composite parent) {
+ Object o = tree.getItem(new Point(event.x, event.y));
+ if (o == null)
+ return null;
+
+ IServer server = null;
+ IServerModule module = null;
+ if (o instanceof TreeItem) {
+ Object obj = ((TreeItem)o).getData();
+ if (obj instanceof IServer)
+ server = (IServer) obj;
+ if (obj instanceof IServerModule)
+ module = (IServerModule) obj;
+ }
+
+ FillLayout layout = (FillLayout)parent.getLayout();
+ layout.type = SWT.VERTICAL;
+ parent.setLayout(layout);
+
+ // set the default text for the tooltip
+ StyledText sText = new StyledText(parent, SWT.NONE);
+ sText.setEditable(false);
+ sText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+
+ if (module != null) {
+ IModule[] modules = module.getModule();
+ IModule m = modules[modules.length - 1];
+ sText.setText("<b>" + m.getName() + "</b>");
+ //sText.setText("<b>" + m.getName() + "</b></p>" + m.getModuleType().getName());
+
+ StyledText sText2 = new StyledText(parent, SWT.NONE);
+ sText2.setEditable(false);
+ sText2.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ sText2.setText(m.getModuleType().getName());
+ }
+
+ if (server != null) {
+ sText.setText("<b>" + server.getName() + "</b>");
+
+ // add adopters content
+ if (server.getServerType() != null) {
+ ArrayList<IServerToolTip> listOfProviders = toolTipProviders.get(server.getServerType().getId());
+
+ final Composite adoptersComposite = new Composite(parent,SWT.NONE);
+ adoptersComposite.setLayout(new FillLayout());
+ adoptersComposite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+
+ if (listOfProviders != null) {
+ for (IServerToolTip tipProvider : listOfProviders) {
+ tipProvider.createContent(adoptersComposite,server);
+ }
+ }
+ }
+ }
+
+ // add the F3 text
+ hintLabel = new Label(parent,SWT.BORDER);
+ hintLabel.setAlignment(SWT.RIGHT);
+ hintLabel.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ hintLabel.setText(Messages.toolTipEnableFocus);
+ hintLabel.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
+
+ final Font font;
+ Display display = parent.getDisplay();
+ FontData[] fd = parent.getFont().getFontData();
+ int size2 = fd.length;
+ for (int i = 0; i < size2; i++)
+ fd[i].setHeight(7);
+ font = new Font(display, fd);
+ parent.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ font.dispose();
+ }
+ });
+ hintLabel.setFont(font);
+
+ parseText(sText.getText(),sText);
+
+ return parent;
+ }
+
+ protected void parseText(String htmlText,StyledText sText) {
+ TextPresentation presentation = new TextPresentation();
+ HTML2TextReader reader = new HTML2TextReader(new StringReader(htmlText), presentation);
+ String text;
+
+ try {
+ text = reader.getString();
+ } catch (IOException e) {
+ text= ""; //$NON-NLS-1$
+ }
+
+ sText.setText(text);
+ Iterator iter = presentation.getAllStyleRangeIterator();
+ while (iter.hasNext()) {
+ StyleRange sr = (StyleRange)iter.next();
+ sText.setStyleRange(sr);
+ }
+ }
+
+ private void loadExtensions() {
+ Trace.trace(Trace.EXTENSION_POINT, "->- Loading serverToolTip extension point ->-");
+
+ // search for extension points
+ IExtensionRegistry reg = Platform.getExtensionRegistry();
+ IConfigurationElement[] extensions = reg.getConfigurationElementsFor(ServerUIPlugin.PLUGIN_ID + ".serverToolTip");
+
+ IServerType[] serverTypes = ServerCore.getServerTypes();
+
+ for (int i=0; i < extensions.length; i++){
+ IConfigurationElement exElement = extensions[i];
+
+ // Sort the extensions based on serverType
+ String exServerType = exElement.getAttribute("serverTypes");
+
+ for (IServerType serverType : serverTypes) {
+ if (exServerType.compareTo("*") == 0 ||
+ exServerType.startsWith(serverType.getId()) == true) {
+ try {
+ IServerToolTip exTooltip = (IServerToolTip) exElement.createExecutableExtension("class");
+ ArrayList<IServerToolTip> listOfProviders = new ArrayList<IServerToolTip>();
+ if (toolTipProviders.containsKey(serverType)) {
+ listOfProviders = toolTipProviders.get(serverType);
+ }
+ listOfProviders.add(exTooltip);
+ toolTipProviders.put(serverType.getId(), listOfProviders);
+ } catch (CoreException e) {
+ Trace.trace(Trace.SEVERE, "Tooltip failed to load" + extensions[i].toString(), e);
+ }
+ Trace.trace(Trace.EXTENSION_POINT, " Loaded serverToolTip: " + extensions[i].getAttribute("id"));
+ }
+ }
+ }
+ }
+
+// read the createFocusedTooltip method for information on why this is commented out
+//
+// protected class StickyTipMouseListener implements MouseListener{
+//
+// public void mouseDoubleClick(MouseEvent e) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+// public void mouseDown(MouseEvent e) {
+// //System.out.println("mouseDown");
+// if (CURRENT_TOOLTIP.getBounds().contains(new Point(e.x,e.y)) == true){
+// CURRENT_TOOLTIP.setVisible(false);
+// CURRENT_TOOLTIP.dispose();
+// activate();
+// CURRENT_TOOLTIP.removeMouseListener(this);
+// }
+// }
+//
+// public void mouseUp(MouseEvent e) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+// }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerUIPreferences.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerUIPreferences.java
index a66d68b..e9c6e3a 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerUIPreferences.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/ServerUIPreferences.java
@@ -29,6 +29,7 @@
private static final String PREF_ENABLE_BREAKPOINTS = "enable-breakpoints";
private static final String PREF_RESTART = "restart";
private static final String PREF_CREATE_SERVER_WITH_RUNTIME = "create-server";
+ private static final String PREF_PUBLISH_ON_ADD_REMOVE = "publish-on-add-remove";
public static final byte SAVE_EDITORS_ALWAYS = 2;
public static final byte SAVE_EDITORS_NEVER = 0;
@@ -72,6 +73,7 @@
preferences.setDefault(PREF_HOST_NAMES, "localhost");
preferences.setDefault(PREF_SHOW_ON_ACTIVITY, true);
preferences.setDefault(PREF_CREATE_SERVER_WITH_RUNTIME, false);
+ preferences.setDefault(PREF_PUBLISH_ON_ADD_REMOVE, true);
}
/**
@@ -340,4 +342,23 @@
preferences.setValue(PREF_CREATE_SERVER_WITH_RUNTIME, b);
ServerUIPlugin.getInstance().savePluginPreferences();
}
+
+ /**
+ * Returns the setting for publishing when modules are added or removed.
+ *
+ * @return boolean
+ */
+ public boolean getPublishOnAddRemoveModule() {
+ return preferences.getBoolean(PREF_PUBLISH_ON_ADD_REMOVE);
+ }
+
+ /**
+ * Sets the value for publishing when modules are added or removed.
+ *
+ * @param b
+ */
+ public void setPublishOnAddRemoveModule(boolean b) {
+ preferences.setValue(PREF_PUBLISH_ON_ADD_REMOVE, b);
+ ServerUIPlugin.getInstance().savePluginPreferences();
+ }
}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Trace.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Trace.java
new file mode 100644
index 0000000..c8513f7
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/Trace.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.wst.server.ui.internal;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+/**
+ * Helper class to route trace output.
+ */
+public class Trace {
+ public static final byte CONFIG = 0;
+ public static final byte INFO = 1;
+ public static final byte WARNING = 2;
+ public static final byte SEVERE = 3;
+ public static final byte FINEST = 4;
+ public static final byte FINER = 5;
+ public static final byte PERFORMANCE = 6;
+ public static final byte EXTENSION_POINT = 7;
+
+ private static final String[] levelNames = new String[] {
+ "CONFIG ", "INFO ", "WARNING", "SEVERE ", "FINER ", "FINEST ", "PERF ", "EXTENSION"};
+
+ private static final SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy HH:mm.ss.SSS");
+
+ private static Set<String> logged = new HashSet<String>();
+
+ /**
+ * Trace constructor comment.
+ */
+ private Trace() {
+ super();
+ }
+
+ /**
+ * Trace the given text.
+ *
+ * @param level a trace level
+ * @param s a message
+ */
+ public static void trace(byte level, String s) {
+ trace(level, s, null);
+ }
+
+ /**
+ * Trace the given message and exception.
+ *
+ * @param level a trace level
+ * @param s a message
+ * @param t a throwable
+ */
+ public static void trace(byte level, String s, Throwable t) {
+ if (s == null)
+ return;
+
+ if (level == SEVERE) {
+ if (!logged.contains(s)) {
+ ServerUIPlugin.getInstance().getLog().log(new Status(IStatus.ERROR, ServerUIPlugin.PLUGIN_ID, s, t));
+ logged.add(s);
+ }
+ }
+
+ if (!ServerUIPlugin.getInstance().isDebugging())
+ return;
+
+ StringBuffer sb = new StringBuffer(ServerUIPlugin.PLUGIN_ID);
+ sb.append(" ");
+ sb.append(levelNames[level]);
+ sb.append(" ");
+ sb.append(sdf.format(new Date()));
+ sb.append(" ");
+ sb.append(s);
+ System.out.println(sb.toString());
+ if (t != null)
+ t.printStackTrace();
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/DeleteAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/DeleteAction.java
new file mode 100644
index 0000000..43bf11e
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/DeleteAction.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.wst.server.ui.internal.view.servers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.core.ServerCore;
+import org.eclipse.wst.server.ui.internal.DeleteServerDialog;
+import org.eclipse.wst.server.ui.internal.Messages;
+import org.eclipse.swt.widgets.Shell;
+/**
+ * Action for deleting server resources.
+ */
+public class DeleteAction extends AbstractServerAction {
+ protected IServer[] servers;
+ protected IFolder[] configs;
+
+ /**
+ * DeleteAction constructor.
+ *
+ * @param shell a shell
+ * @param sp a selection provider
+ */
+ public DeleteAction(Shell shell, ISelectionProvider sp) {
+ super(shell, sp, Messages.actionDelete);
+ ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
+ setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE));
+ setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE_DISABLED));
+ setActionDefinitionId(IWorkbenchActionDefinitionIds.DELETE);
+ }
+
+ public boolean accept(IServer server) {
+ servers = new IServer[] { server };
+ List<IFolder> list = new ArrayList<IFolder>();
+
+ int size = servers.length;
+ for (int i = 0; i < size; i++) {
+ if (servers[i].isReadOnly())
+ return false;
+
+ if (servers[i].getServerConfiguration() != null)
+ list.add(servers[i].getServerConfiguration());
+ }
+
+ // remove configurations that are still referenced by other servers
+ IServer[] servers2 = ServerCore.getServers();
+ if (servers2 != null) {
+ int size2 = servers2.length;
+ for (int j = 0; j < size2; j++) {
+ boolean found = false;
+ for (int i = 0; i < size; i++) {
+ if (servers[i].equals(servers2[j]))
+ found = true;
+ }
+ if (!found) {
+ IFolder folder = servers2[j].getServerConfiguration();
+ if (folder != null && list.contains(folder))
+ list.remove(folder);
+ }
+ }
+ }
+
+ configs = new IFolder[list.size()];
+ list.toArray(configs);
+ return true;
+ }
+
+ public void perform(IServer server) {
+ DeleteServerDialog dsd = new DeleteServerDialog(shell, servers, configs);
+ dsd.open();
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RemoveModuleAction.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RemoveModuleAction.java
index b198af0..756ba36 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RemoveModuleAction.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/RemoveModuleAction.java
@@ -16,8 +16,8 @@
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerWorkingCopy;
-import org.eclipse.wst.server.core.internal.Server;
import org.eclipse.wst.server.ui.internal.Messages;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
import org.eclipse.wst.server.ui.internal.Trace;
import org.eclipse.swt.widgets.Shell;
/**
@@ -53,7 +53,8 @@
wc.modifyModules(null, new IModule[] { module }, null);
server = wc.save(true, null);
- if (server.getServerState() != IServer.STATE_STOPPED && ((Server)server).getAutoPublishSetting() != Server.AUTO_PUBLISH_DISABLE) {
+ if (server.getServerState() != IServer.STATE_STOPPED &&
+ ServerUIPlugin.getPreferences().getPublishOnAddRemoveModule()) {
final IAdaptable info = new IAdaptable() {
public Object getAdapter(Class adapter) {
if (Shell.class.equals(adapter))
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServersView.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServersView.java
new file mode 100644
index 0000000..5d754ad
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/view/servers/ServersView.java
@@ -0,0 +1,460 @@
+/*******************************************************************************
+ * 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.wst.server.ui.internal.view.servers;
+
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.jface.action.*;
+import org.eclipse.jface.bindings.TriggerSequence;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.internal.Server;
+import org.eclipse.wst.server.core.internal.UpdateServerJob;
+import org.eclipse.wst.server.core.model.ServerDelegate;
+import org.eclipse.wst.server.ui.internal.*;
+import org.eclipse.wst.server.ui.internal.actions.NewServerWizardAction;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.*;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.contexts.IContextService;
+import org.eclipse.ui.keys.IBindingService;
+import org.eclipse.ui.part.ResourceTransfer;
+import org.eclipse.ui.part.ViewPart;
+import org.eclipse.ui.views.navigator.LocalSelectionTransfer;
+/**
+ * A view of servers, their modules, and status.
+ */
+public class ServersView extends ViewPart {
+ private static final String TAG_COLUMN_WIDTH = "columnWidth";
+ private static final String SERVERS_VIEW_CONTEXT = "org.eclipse.ui.serverViewScope";
+
+ protected Action noneAction = new Action(Messages.dialogMonitorNone) {
+ // dummy action
+ };
+
+ protected int[] cols;
+
+ protected Tree treeTable;
+ protected ServerTableViewer tableViewer;
+
+ // actions on a server
+ protected Action[] actions;
+ protected Action actionModifyModules;
+ protected Action openAction, showInConsoleAction, showInDebugAction, propertiesAction, monitorPropertiesAction;
+ protected Action copyAction, pasteAction, deleteAction, renameAction;
+
+ /**
+ * ServersView constructor comment.
+ */
+ public ServersView() {
+ super();
+ }
+
+ protected SelectionListener getHeaderListener(final int col) {
+ return new SelectionAdapter() {
+ /**
+ * Handles the case of user selecting the header area.
+ */
+ public void widgetSelected(SelectionEvent e) {
+ if (tableViewer == null)
+ return;
+ TreeColumn column = (TreeColumn) e.widget;
+ tableViewer.resortTable(column, col);
+ }
+ };
+ }
+
+ /**
+ * createPartControl method comment.
+ *
+ * @param parent a parent composite
+ */
+ public void createPartControl(Composite parent) {
+ treeTable = new Tree(parent, SWT.SINGLE | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL);
+ treeTable.setHeaderVisible(true);
+ treeTable.setLinesVisible(false);
+ treeTable.setLayoutData(new GridData(GridData.FILL_BOTH));
+ treeTable.setFont(parent.getFont());
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(treeTable, ContextIds.VIEW_SERVERS);
+
+ // add columns
+ TreeColumn column = new TreeColumn(treeTable, SWT.SINGLE);
+ column.setText(Messages.viewServer);
+ column.setWidth(cols[0]);
+ column.addSelectionListener(getHeaderListener(0));
+ treeTable.setSortColumn(column);
+ treeTable.setSortDirection(SWT.UP);
+
+ TreeColumn column2 = new TreeColumn(treeTable, SWT.SINGLE);
+ column2.setText(Messages.viewState);
+ column2.setWidth(cols[1]);
+ column2.addSelectionListener(getHeaderListener(1));
+
+ TreeColumn column3 = new TreeColumn(treeTable, SWT.SINGLE);
+ column3.setText(Messages.viewStatus);
+ column3.setWidth(cols[2]);
+ column3.addSelectionListener(getHeaderListener(2));
+
+ IContextService contextSupport = (IContextService)getSite().getService(IContextService.class);
+ contextSupport.activateContext(SERVERS_VIEW_CONTEXT);
+
+ deferInitialization();
+ }
+
+ private void deferInitialization() {
+ TreeItem item = new TreeItem(treeTable, SWT.NONE);
+ item.setText(Messages.viewInitializing);
+
+ tableViewer = new ServerTableViewer(this, treeTable);
+ initializeActions(tableViewer);
+
+ Job job = new Job(Messages.jobInitializingServersView) {
+ public IStatus run(IProgressMonitor monitor) {
+ IServer[] servers = ServerCore.getServers();
+ int size = servers.length;
+ for (int i = 0; i < size; i++) {
+ ((Server)servers[i]).getAllModules().iterator();
+ /*while (iterator.hasNext()) {
+ Module module = (Module) iterator.next();
+ module.g
+ }*/
+ }
+
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ try {
+ deferredInitialize();
+ } catch (Exception e) {
+ // ignore - view has already been closed
+ }
+ }
+ });
+ return Status.OK_STATUS;
+ }
+ };
+
+ job.setSystem(true);
+ job.setPriority(Job.SHORT);
+ job.schedule();
+ }
+
+ protected void deferredInitialize() {
+ tableViewer.initialize();
+ tableViewer.addOpenListener(new IOpenListener() {
+ public void open(OpenEvent event) {
+ try {
+ IStructuredSelection sel = (IStructuredSelection) event.getSelection();
+ Object data = sel.getFirstElement();
+ if (!(data instanceof IServer))
+ return;
+ IServer server = (IServer) data;
+ ServerUIPlugin.editServer(server);
+ } catch (Exception e) {
+ Trace.trace(Trace.SEVERE, "Could not open server", e);
+ }
+ }
+ });
+
+ MenuManager menuManager = new MenuManager("#PopupMenu");
+ menuManager.setRemoveAllWhenShown(true);
+ final Shell shell = treeTable.getShell();
+ menuManager.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager mgr) {
+ fillContextMenu(shell, mgr);
+ }
+ });
+ Menu menu = menuManager.createContextMenu(treeTable);
+ treeTable.setMenu(menu);
+ getSite().registerContextMenu(menuManager, tableViewer);
+ getSite().setSelectionProvider(tableViewer);
+
+ initDragAndDrop();
+
+ // init the tooltip
+ ServerToolTip toolTip = new ServerToolTip(treeTable);
+ toolTip.setShift(new Point(10, 3));
+ toolTip.setPopupDelay(400); // in ms
+ toolTip.setHideOnMouseDown(true);
+ toolTip.activate();
+
+ if (tableViewer.getTree().getItemCount() > 0) {
+ Object obj = tableViewer.getTree().getItem(0).getData();
+ tableViewer.setSelection(new StructuredSelection(obj));
+ }
+
+ Thread thread = new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(5000);
+ } catch (Exception e) {
+ // ignore
+ }
+ IServer[] servers = ServerCore.getServers();
+ int size = servers.length;
+ for (int i = 0; i < size; i++) {
+ IServer server = servers[i];
+ if (server.getServerType() != null && server.getServerState() == IServer.STATE_UNKNOWN) {
+ UpdateServerJob job = new UpdateServerJob(server);
+ job.schedule();
+ }
+ }
+ }
+ };
+ thread.setDaemon(true);
+ thread.setPriority(Thread.MIN_PRIORITY + 1);
+ thread.start();
+ }
+
+ public void init(IViewSite site, IMemento memento) throws PartInitException {
+ super.init(site, memento);
+ cols = new int[3];
+ for (int i = 0; i < 3; i++) {
+ cols[i] = 200;
+ if (memento != null) {
+ Integer in = memento.getInteger(TAG_COLUMN_WIDTH + i);
+ if (in != null && in.intValue() > 5)
+ cols[i] = in.intValue();
+ }
+ }
+ }
+
+ public void saveState(IMemento memento) {
+ TreeColumn[] tc = treeTable.getColumns();
+ for (int i = 0; i < 3; i++) {
+ int width = tc[i].getWidth();
+ if (width != 0)
+ memento.putInteger(TAG_COLUMN_WIDTH + i, width);
+ }
+ }
+
+ /**
+ * Initialize actions
+ *
+ * @param provider a selection provider
+ */
+ public void initializeActions(ISelectionProvider provider) {
+ Shell shell = getSite().getShell();
+ IActionBars actionBars = getViewSite().getActionBars();
+
+ actions = new Action[6];
+ // create the start actions
+ actions[0] = new StartAction(shell, provider, ILaunchManager.DEBUG_MODE);
+ actionBars.setGlobalActionHandler("org.eclipse.wst.server.debug", actions[0]);
+ actions[1] = new StartAction(shell, provider, ILaunchManager.RUN_MODE);
+ actionBars.setGlobalActionHandler("org.eclipse.wst.server.run", actions[1]);
+ actions[2] = new StartAction(shell, provider, ILaunchManager.PROFILE_MODE);
+
+ // create the stop action
+ actions[3] = new StopAction(shell, provider);
+ actionBars.setGlobalActionHandler("org.eclipse.wst.server.stop", actions[3]);
+
+ // create the publish actions
+ actions[4] = new PublishAction(shell, provider);
+ actionBars.setGlobalActionHandler("org.eclipse.wst.server.publish", actions[4]);
+ actions[5] = new PublishCleanAction(shell, provider);
+
+ // create the open action
+ openAction = new OpenAction(provider);
+ actionBars.setGlobalActionHandler("org.eclipse.ui.navigator.Open", openAction);
+
+ // create copy, paste, and delete actions
+ pasteAction = new PasteAction(shell, provider, tableViewer.clipboard);
+ copyAction = new CopyAction(provider, tableViewer.clipboard, pasteAction);
+ deleteAction = new DeleteAction(shell, provider);
+ renameAction = new RenameAction(shell, tableViewer, provider);
+ actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
+ actionBars.setGlobalActionHandler(ActionFactory.PASTE.getId(), pasteAction);
+ actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), deleteAction);
+ actionBars.setGlobalActionHandler(ActionFactory.RENAME.getId(), renameAction);
+
+ // create the other actions
+ actionModifyModules = new ModuleSloshAction(shell, provider);
+ showInConsoleAction = new ShowInConsoleAction(provider);
+ showInDebugAction = new ShowInDebugAction(provider);
+
+ // create the properties action
+ propertiesAction = new PropertiesAction(shell, provider);
+ actionBars.setGlobalActionHandler(ActionFactory.PROPERTIES.getId(), propertiesAction);
+ monitorPropertiesAction = new PropertiesAction(shell, "org.eclipse.wst.server.ui.properties.monitor", provider);
+
+ // add toolbar buttons
+ IContributionManager cm = actionBars.getToolBarManager();
+ for (int i = 0; i < actions.length - 1; i++)
+ cm.add(actions[i]);
+
+ cm.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+ }
+
+ private static void fillNewContextMenu(Shell shell, ISelection selection, IMenuManager menu) {
+ IAction newServerAction = new NewServerWizardAction();
+ newServerAction.setText(Messages.actionNewServer);
+ menu.add(newServerAction);
+ }
+
+ protected void fillContextMenu(Shell shell, IMenuManager menu) {
+ // get selection but avoid no selection or multiple selection
+ IServer server = null;
+ IModule[] module = null;
+ IStructuredSelection selection = (IStructuredSelection) tableViewer.getSelection();
+ if (!selection.isEmpty()) {
+ Iterator iterator = selection.iterator();
+ Object obj = iterator.next();
+ if (obj instanceof IServer)
+ server = (IServer) obj;
+ if (obj instanceof ModuleServer) {
+ ModuleServer ms = (ModuleServer) obj;
+ server = ms.server;
+ module = ms.module;
+ }
+ if (iterator.hasNext()) {
+ server = null;
+ module = null;
+ }
+ }
+
+ // new action
+ MenuManager newMenu = new MenuManager(Messages.actionNew);
+ fillNewContextMenu(null, selection, newMenu);
+ menu.add(newMenu);
+
+ // open action
+ if (server != null && module == null) {
+ menu.add(openAction);
+
+ String text = Messages.actionShowIn;
+ final IWorkbench workbench = PlatformUI.getWorkbench();
+ final IBindingService bindingService = (IBindingService) workbench
+ .getAdapter(IBindingService.class);
+ final TriggerSequence[] activeBindings = bindingService
+ .getActiveBindingsFor("org.eclipse.ui.navigate.showInQuickMenu");
+ if (activeBindings.length > 0) {
+ text += "\t" + activeBindings[0].format();
+ }
+
+ MenuManager showInMenu = new MenuManager(text);
+ showInMenu.add(showInConsoleAction);
+ showInMenu.add(showInDebugAction);
+ //IActionBars actionBars = getViewSite().getActionBars();
+ //actionBars.setGlobalActionHandler("group.show", showInMenu);
+ menu.add(showInMenu);
+ menu.add(new Separator());
+ } else
+ menu.add(new Separator());
+
+ if (server != null) {
+ if (module == null) {
+ menu.add(copyAction);
+ menu.add(pasteAction);
+ menu.add(deleteAction);
+ menu.add(renameAction);
+ } else if (module.length == 1)
+ menu.add(new RemoveModuleAction(shell, server, module[0]));
+ menu.add(new Separator());
+ }
+
+ if (server != null && module == null) {
+ // server actions
+ for (int i = 0; i < actions.length; i++)
+ menu.add(actions[i]);
+
+ menu.add(new Separator());
+ menu.add(actionModifyModules);
+
+ // monitor
+ if (server.getServerType() != null) {
+ final MenuManager menuManager = new MenuManager(Messages.actionMonitor);
+
+ final IServer server2 = server;
+ final Shell shell2 = shell;
+ menuManager.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ menuManager.removeAll();
+ if (server2.getAdapter(ServerDelegate.class) != null) {
+ ServerPort[] ports = server2.getServerPorts(null);
+ if (ports != null) {
+ int size = ports.length;
+ for (int i = 0; i < size; i++) {
+ if (!ports[i].isAdvanced())
+ menuManager.add(new MonitorServerPortAction(shell2, server2, ports[i]));
+ }
+ }
+ }
+
+ if (menuManager.isEmpty())
+ menuManager.add(noneAction);
+
+ menuManager.add(new Separator());
+ menuManager.add(monitorPropertiesAction);
+ }
+ });
+
+ // add an initial menu item so that the menu appears correctly
+ noneAction.setEnabled(false);
+ menuManager.add(noneAction);
+ menu.add(menuManager);
+ }
+ }
+
+ if (server != null && module != null) {
+ menu.add(new Separator());
+ menu.add(new StartModuleAction(server, module));
+ menu.add(new StopModuleAction(server, module));
+ menu.add(new RestartModuleAction(server, module));
+ }
+
+ menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+ menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS+"-end"));
+
+ if (server != null) {
+ menu.add(new Separator());
+ menu.add(propertiesAction);
+ }
+ }
+
+ /**
+ *
+ */
+ public void setFocus() {
+ if (treeTable != null)
+ treeTable.setFocus();
+ }
+
+ /**
+ * Adds drag and drop support to the Servers view.
+ */
+ protected void initDragAndDrop() {
+ int ops = DND.DROP_COPY;
+ Transfer[] transfers = new Transfer[] { LocalSelectionTransfer.getInstance(),
+ ResourceTransfer.getInstance(), FileTransfer.getInstance() };
+ //tableViewer.addDragSupport(ops, transfers, new ServersViewDragAdapter(viewer));
+ tableViewer.addDropSupport(ops | DND.DROP_DEFAULT, transfers, new ServersViewDropAdapter(tableViewer));
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTreeContentProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTreeContentProvider.java
new file mode 100644
index 0000000..3e5e096
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/AbstractTreeContentProvider.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.wst.server.ui.internal.viewers;
+
+import java.util.*;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+/**
+ * Runtime type content provider.
+ */
+public abstract class AbstractTreeContentProvider implements ITreeContentProvider {
+ public static final String ROOT = "root";
+
+ protected Object initialSelection;
+
+ public class TreeElement {
+ public String text;
+ public List<Object> contents;
+ }
+
+ protected Object[] elements;
+ protected Map<Object, TreeElement> elementToParentMap = new HashMap<Object, TreeElement>(2);
+ protected Map<String, TreeElement> textMap = new HashMap<String, TreeElement>(2);
+
+ /**
+ * AbstractTreeContentProvider constructor comment.
+ */
+ public AbstractTreeContentProvider() {
+ super();
+
+ fillTree();
+ }
+
+ public AbstractTreeContentProvider(boolean init) {
+ super();
+ }
+
+ protected abstract void fillTree();
+
+ protected void clean() {
+ elements = null;
+ elementToParentMap = new HashMap<Object, TreeElement>(2);
+ textMap = new HashMap<String, TreeElement>(2);
+
+ initialSelection = null;
+ }
+
+ protected TreeElement getOrCreate(List<TreeElement> list, String text) {
+ try {
+ Object obj = textMap.get(text);
+ if (obj != null)
+ return (TreeElement) obj;
+ } catch (Exception e) {
+ return null;
+ }
+
+ TreeElement element = new TreeElement();
+ element.text = text;
+ element.contents = new ArrayList<Object>();
+ textMap.put(text, element);
+ list.add(element);
+ return element;
+ }
+
+ protected TreeElement getOrCreate(List<TreeElement> list, String id, String text) {
+ try {
+ Object obj = textMap.get(id);
+ if (obj != null)
+ return (TreeElement) obj;
+ } catch (Exception e) {
+ return null;
+ }
+
+ TreeElement element = new TreeElement();
+ element.text = text;
+ element.contents = new ArrayList<Object>();
+ textMap.put(id, element);
+ list.add(element);
+ return element;
+ }
+
+ protected TreeElement getByText(String text) {
+ try {
+ return textMap.get(text);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ protected TreeElement getParentImpl(Object obj) {
+ try {
+ return elementToParentMap.get(obj);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Disposes of this content provider.
+ * This is called by the viewer when it is disposed.
+ */
+ public void dispose() {
+ // do nothing
+ }
+
+ /**
+ * Returns the elements to display in the viewer
+ * when its input is set to the given element.
+ * These elements can be presented as rows in a table, items in a list, etc.
+ * The result is not modified by the viewer.
+ *
+ * @param element the input element
+ * @return the array of elements to display in the viewer
+ */
+ public Object[] getElements(Object element) {
+ return elements;
+ }
+
+ public Object[] getChildren(Object element) {
+ if (!(element instanceof TreeElement))
+ return null;
+
+ TreeElement rte = (TreeElement) element;
+ return rte.contents.toArray();
+ }
+
+ public Object getParent(Object element) {
+ return getParentImpl(element);
+ }
+
+ public boolean hasChildren(Object element) {
+ Object[] children = getChildren(element);
+ return children != null && children.length > 0;
+ }
+
+ /**
+ * Notifies this content provider that the given viewer's input
+ * has been switched to a different element.
+ * <p>
+ * A typical use for this method is registering the content provider as a listener
+ * to changes on the new input (using model-specific means), and deregistering the viewer
+ * from the old input. In response to these change notifications, the content provider
+ * propagates the changes to the viewer.
+ * </p>
+ *
+ * @param viewer the viewer
+ * @param oldInput the old input element, or <code>null</code> if the viewer
+ * did not previously have an input
+ * @param newInput the new input element, or <code>null</code> if the viewer
+ * does not have an input
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // do nothing
+ }
+
+ private Object[] getAllObjects() {
+ List<Object> list = new ArrayList<Object>();
+ Object[] obj = getElements(null);
+ if (obj != null) {
+ int size = obj.length;
+ for (int i = 0; i < size; i++) {
+ if (!(obj[i] instanceof AbstractTreeContentProvider.TreeElement))
+ list.add(obj[i]);
+ getAllChildren(list, obj[i]);
+ }
+ }
+ return list.toArray();
+ }
+
+ private void getAllChildren(List<Object> list, Object element) {
+ Object[] obj = getChildren(element);
+ if (obj != null) {
+ int size = obj.length;
+ for (int i = 0; i < size; i++) {
+ if (!(obj[i] instanceof AbstractTreeContentProvider.TreeElement))
+ list.add(obj[i]);
+ getAllChildren(list, obj[i]);
+ }
+ }
+ }
+
+ public Object getInitialSelection() {
+ if (initialSelection == null) {
+ InitialSelectionProvider isp = ServerUIPlugin.getInitialSelectionProvider();
+ initialSelection = isp.getInitialSelection(getAllObjects());
+ }
+ return initialSelection;
+ }
+
+ public Object getInitialSelection(IProject project){
+ if (initialSelection == null) {
+ InitialSelectionProvider isp = ServerUIPlugin.getInitialSelectionProvider();
+ initialSelection = isp.getInitialSelection(getAllObjects(),project);
+ }
+ return initialSelection;
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/InitialSelectionProvider.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/InitialSelectionProvider.java
new file mode 100644
index 0000000..248fad9
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/InitialSelectionProvider.java
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * Copyright (c) 2005 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.wst.server.ui.internal.viewers;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.wst.common.project.facet.core.IFacetedProject;
+import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.internal.ResourceManager;
+import org.eclipse.wst.server.core.internal.facets.FacetUtil;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.Trace;
+/**
+ * Class used to sort categories, runtime types, and server types in the
+ * New wizards.
+ */
+public class InitialSelectionProvider extends ViewerSorter {
+
+ public Object getInitialSelection(Object[] obj) {
+ if (obj == null || obj.length == 0)
+ return null;
+
+ if (obj[0] instanceof IRuntimeType) {
+ int size = obj.length;
+ IRuntimeType[] rt = new IRuntimeType[size];
+ for (int i = 0; i < size; i++)
+ rt[i] = (IRuntimeType) obj[i];
+ return getInitialSelection(rt);
+ }
+
+ if (obj[0] instanceof IServerType) {
+ int size = obj.length;
+ IServerType[] st = new IServerType[size];
+ for (int i = 0; i < size; i++)
+ st[i] = (IServerType) obj[i];
+ return getInitialSelection(st);
+ }
+
+ if (obj[0] instanceof IServer) {
+ int size = obj.length;
+ IServer[] st = new IServer[size];
+ for (int i = 0; i < size; i++)
+ st[i] = (IServer) obj[i];
+ return getInitialSelection(st);
+ }
+
+ return null;
+ }
+
+ /**
+ *
+ * @param serverTypes
+ * @return the initial selection
+ */
+ public IServerType getInitialSelection(IServerType[] serverTypes) {
+ if (serverTypes == null)
+ return null;
+
+ int size = serverTypes.length;
+ for (int i = 0; i < size; i++) {
+ if (hasRuntime(serverTypes[i]))
+ return serverTypes[i];
+ }
+ return getDefaultServerType(serverTypes);
+ }
+
+ /**
+ *
+ * @param servers
+ * @return the initial selection
+ */
+ public IServer getInitialSelection(IServer[] servers) {
+ return getInitialSelection(servers,null);
+ }
+
+ /**
+ * Allows adopters to provide an initial selection out of a list of items.
+ * <p>
+ * The <code>IProject</code> can be null, in cases where a project selection was not available (ie: New Server Wizard)
+ * </p><p>
+ * Returning <code>null</code> means no object is applicable to be selected.
+ * </p>
+ *
+ * @param servers
+ * @param project
+ * @return
+ */
+ public IServer getInitialSelection(IServer[] servers, IProject project){
+ if (servers == null)
+ return null;
+
+ IServer rval = servers[0];
+
+ if (project != null){
+ try{
+ // check for the targeted runtime of the project
+ IFacetedProject facetedProject = ProjectFacetsManager.create(project);
+ if (facetedProject != null){
+ org.eclipse.wst.common.project.facet.core.runtime.IRuntime facetedRuntime = facetedProject.getPrimaryRuntime();
+ if (facetedRuntime != null){
+ IRuntime runtime = FacetUtil.getRuntime(facetedRuntime);
+ IServer server = findServerFromRuntime(runtime.getId());
+ if (server != null){
+ rval = server;
+ }
+ }
+ }
+ }
+ catch (CoreException ce){
+ Trace.trace(Trace.WARNING,"Could not create a faceted project",ce);
+ }
+ }
+ return rval;
+ }
+
+ /**
+ *
+ * @param runtimeTypes
+ * @return the initial selection
+ */
+ public IRuntimeType getInitialSelection(IRuntimeType[] runtimeTypes) {
+ if (runtimeTypes == null)
+ return null;
+
+ int size = runtimeTypes.length;
+ for (int i = 0; i < size; i++) {
+ if (hasRuntime(runtimeTypes[i]))
+ return runtimeTypes[i];
+ }
+ return getDefaultRuntimeType(runtimeTypes);
+ }
+
+ protected boolean hasRuntime(IServerType serverType) {
+ return hasRuntime(serverType.getRuntimeType());
+ }
+
+ protected boolean hasRuntime(IRuntimeType runtimeType) {
+ if (runtimeType == null)
+ return false;
+ IRuntime[] runtimes = ServerUIPlugin.getRuntimes(runtimeType);
+ return runtimes != null && runtimes.length > 0;
+ }
+
+ /**
+ * Returns a default server type, typically the 'first' one sorted
+ * alphabetically by name.
+ *
+ * @param serverTypes
+ * @return the default server type
+ */
+ protected IServerType getDefaultServerType(IServerType[] serverTypes) {
+ if (serverTypes == null)
+ return null;
+
+ int size = serverTypes.length;
+ if (size == 1)
+ return serverTypes[0];
+
+ IServerType first = serverTypes[0];
+ for (int i = 1; i < size; i++) {
+ if (DefaultViewerSorter.compareServerTypes(first, serverTypes[i]) > 0)
+ first = serverTypes[i];
+ }
+ return first;
+ }
+
+ /**
+ * Returns a default runtime type, typically the 'first' one sorted
+ * alphabetically by name.
+ *
+ * @param runtimeTypes
+ * @return the default runtime type
+ */
+ protected IRuntimeType getDefaultRuntimeType(IRuntimeType[] runtimeTypes) {
+ if (runtimeTypes == null)
+ return null;
+
+ int size = runtimeTypes.length;
+ if (size == 1)
+ return runtimeTypes[0];
+
+ IRuntimeType first = runtimeTypes[0];
+ for (int i = 1; i < size; i++) {
+ if (DefaultViewerSorter.compareRuntimeTypes(first, runtimeTypes[i]) > 0)
+ first = runtimeTypes[i];
+ }
+ return first;
+ }
+
+ /**
+ * Allows adopters to provide an initial selection out of a list of items.
+ * <p>
+ * The <code>IProject</code> can be null, in cases where a project selection was not available (ie: New Server Wizard)
+ * </p><p>
+ * Returning <code>null</code> means no object is applicable to be selected.
+ * </p>
+ *
+ * @param obj Contains an array of all the possible object to be selected.
+ * @param project
+ * @return The object to be selected from the <code>obj[]</code>
+ */
+ public Object getInitialSelection(Object [] obj, IProject project){
+ if (obj == null || obj.length == 0)
+ return null;
+
+ if (obj[0] instanceof IRuntimeType) {
+ int size = obj.length;
+ IRuntimeType[] rt = new IRuntimeType[size];
+ for (int i = 0; i < size; i++)
+ rt[i] = (IRuntimeType) obj[i];
+ return getInitialSelection(rt);
+ }
+
+ if (obj[0] instanceof IServerType) {
+ int size = obj.length;
+ IServerType[] st = new IServerType[size];
+ for (int i = 0; i < size; i++)
+ st[i] = (IServerType) obj[i];
+ return getInitialSelection(st);
+ }
+
+ if (obj[0] instanceof IServer) {
+ int size = obj.length;
+ IServer[] st = new IServer[size];
+ for (int i = 0; i < size; i++)
+ st[i] = (IServer) obj[i];
+ return getInitialSelection(st,project);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the server with the given runtime id, or <code>null</code>
+ * if none. This convenience method searches the list of registered servers
+ * for the matching runtime id. The id may not be null.
+ *
+ * @param runtimeId
+ * @return
+ */
+ private static IServer findServerFromRuntime(String runtimeId){
+ if (runtimeId == null)
+ throw new IllegalArgumentException();
+
+ IServer [] servers = ResourceManager.getInstance().getServers();
+ for (IServer server:servers){
+ if (runtimeId == server.getRuntime().getId()){
+ return server;
+ }
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerComposite.java
new file mode 100644
index 0000000..2588b10
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/viewers/ServerComposite.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.wst.server.ui.internal.viewers;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.ui.dialogs.FilteredTree;
+
+import org.eclipse.wst.server.core.IModule;
+import org.eclipse.wst.server.core.IServer;
+import org.eclipse.wst.server.ui.internal.Messages;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
+import org.eclipse.wst.server.ui.internal.view.servers.ServerTableLabelProvider;
+/**
+ *
+ */
+public class ServerComposite extends AbstractTreeComposite {
+ protected IServer selection;
+ protected ServerSelectionListener listener;
+ protected ServerTreeContentProvider contentProvider;
+ protected boolean initialSelection = true;
+
+ protected IModule module;
+ protected String launchMode;
+ protected boolean includeIncompatibleVersions;
+
+ public interface ServerSelectionListener {
+ public void serverSelected(IServer server);
+ }
+
+ public ServerComposite(Composite parent, ServerSelectionListener listener2, IModule module, String launchMode) {
+ super(parent);
+ this.module = module;
+ this.launchMode = launchMode;
+
+ this.listener = listener2;
+
+ Tree tree2 = treeViewer.getTree();
+ TreeColumn column = new TreeColumn(tree2, SWT.SINGLE);
+ column.setText(Messages.viewServer);
+ column.setWidth(325);
+
+ TreeColumn column2 = new TreeColumn(tree2, SWT.SINGLE);
+ column2.setText(Messages.viewState);
+ column2.setWidth(100);
+
+ contentProvider = new ServerTreeContentProvider(module, launchMode);
+ treeViewer.setContentProvider(contentProvider);
+
+ //ILabelProvider labelProvider = new ServerTreeLabelProvider();
+ ILabelProvider labelProvider = new ServerTableLabelProvider();
+ labelProvider.addListener(new ILabelProviderListener() {
+ public void labelProviderChanged(LabelProviderChangedEvent event) {
+ Object[] obj = event.getElements();
+ if (obj == null)
+ treeViewer.refresh(true);
+ else {
+ obj = ServerUIPlugin.adaptLabelChangeObjects(obj);
+ int size = obj.length;
+ for (int i = 0; i < size; i++)
+ treeViewer.refresh(obj[i], true);
+ }
+ }
+ });
+ treeViewer.setLabelProvider(labelProvider);
+ treeViewer.setInput(AbstractTreeContentProvider.ROOT);
+ treeViewer.expandToLevel(1);
+
+ treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ Object obj = getSelection(event.getSelection());
+ if (obj instanceof IServer) {
+ selection = (IServer) obj;
+ setDescription(selection.getServerType().getRuntimeType().getDescription());
+ } else {
+ selection = null;
+ setDescription("");
+ }
+ listener.serverSelected(selection);
+ }
+ });
+ }
+
+ protected void createTree() {
+ tree = new FilteredTree(this, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION, new ServerPatternFilter());
+ }
+
+ public void setIncludeIncompatibleVersions(boolean b) {
+ includeIncompatibleVersions = b;
+ ISelection sel = treeViewer.getSelection();
+ contentProvider.setIncludeIncompatibleVersions(b);
+ treeViewer.refresh();
+ treeViewer.setSelection(sel, true);
+ }
+
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if (visible && initialSelection) {
+ initialSelection = false;
+ deferInitialization();
+ }
+ }
+
+ public void refreshAll() {
+ ISelection sel = treeViewer.getSelection();
+ contentProvider = new ServerTreeContentProvider(module, launchMode);
+ contentProvider.setIncludeIncompatibleVersions(includeIncompatibleVersions);
+ treeViewer.setContentProvider(contentProvider);
+ treeViewer.setSelection(sel);
+ }
+
+ protected String getDescriptionLabel() {
+ return null;
+ }
+
+ protected String getTitleLabel() {
+ return Messages.wizNewServerSelectExisting;
+ }
+
+ public IServer getSelectedServer() {
+ return selection;
+ }
+
+ public void setSelection(IServer server) {
+ if (server != null)
+ treeViewer.setSelection(new StructuredSelection(server), true);
+ else
+ treeViewer.setSelection(null);
+ }
+
+ protected void deferInitialization() {
+ Job job = new Job(Messages.jobInitializingServersView) {
+ public IStatus run(IProgressMonitor monitor) {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ try {
+ if (contentProvider.getInitialSelection(module.getProject()) != null)
+ treeViewer.setSelection(new StructuredSelection(contentProvider.getInitialSelection(module.getProject())), true);
+ } catch (Exception e) {
+ // ignore - wizard has already been closed
+ }
+ }
+ });
+ return Status.OK_STATUS;
+ }
+ };
+
+ job.setSystem(true);
+ job.setPriority(Job.SHORT);
+ job.schedule();
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ModifyModulesWizard.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ModifyModulesWizard.java
index 1c6b776..9cdc191 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ModifyModulesWizard.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/ModifyModulesWizard.java
@@ -16,8 +16,8 @@
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.wst.server.core.*;
-import org.eclipse.wst.server.core.internal.Server;
import org.eclipse.wst.server.ui.internal.Messages;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
import org.eclipse.wst.server.ui.internal.wizard.fragment.ModifyModulesWizardFragment;
import org.eclipse.wst.server.ui.wizard.WizardFragment;
/**
@@ -26,7 +26,7 @@
public class ModifyModulesWizard extends TaskWizard {
static class ModifyModulesWizard2 extends WizardFragment {
protected void createChildFragments(List<WizardFragment> list) {
- list.add(new ModifyModulesWizardFragment());
+ list.add(new ModifyModulesWizardFragment(true));
list.add(WizardTaskUtil.SaveServerFragment);
list.add(new WizardFragment() {
@@ -34,7 +34,8 @@
IServerAttributes svr = (IServerAttributes) getTaskModel().getObject(TaskModel.TASK_SERVER);
if (svr instanceof IServer) {
IServer server = (IServer) svr;
- if (server.getServerState() != IServer.STATE_STOPPED && ((Server)server).getAutoPublishSetting() != Server.AUTO_PUBLISH_DISABLE) {
+ if (server.getServerState() != IServer.STATE_STOPPED &&
+ ServerUIPlugin.getPreferences().getPublishOnAddRemoveModule()) {
IAdaptable info = null;
/*IAdaptable info = new IAdaptable() {
public Object getAdapter(Class adapter) {
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/ModifyModulesWizardFragment.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/ModifyModulesWizardFragment.java
index 02b9e09..498555d 100644
--- a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/ModifyModulesWizardFragment.java
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/ModifyModulesWizardFragment.java
@@ -19,6 +19,7 @@
import org.eclipse.wst.server.core.*;
import org.eclipse.wst.server.core.internal.IModuleVisitor;
import org.eclipse.wst.server.core.internal.Server;
+import org.eclipse.wst.server.ui.internal.ServerUIPlugin;
import org.eclipse.wst.server.ui.internal.Trace;
import org.eclipse.wst.server.ui.internal.wizard.WizardTaskUtil;
import org.eclipse.wst.server.ui.internal.wizard.page.ModifyModulesComposite;
@@ -31,11 +32,16 @@
protected ModifyModulesComposite comp;
protected IModule module;
+ protected boolean showPublishOption;
public ModifyModulesWizardFragment() {
// do nothing
}
+ public ModifyModulesWizardFragment(boolean showPublishOption) {
+ this.showPublishOption = showPublishOption;
+ }
+
public ModifyModulesWizardFragment(IModule module) {
this.module = module;
}
@@ -48,7 +54,7 @@
* @see org.eclipse.wst.server.ui.internal.task.WizardTask#getWizardPage()
*/
public Composite createComposite(Composite parent, IWizardHandle handle) {
- comp = new ModifyModulesComposite(parent, handle, module);
+ comp = new ModifyModulesComposite(parent, handle, module, showPublishOption);
return comp;
}
@@ -120,7 +126,10 @@
}
public void performFinish(IProgressMonitor monitor) throws CoreException {
- if (comp != null)
+ if (comp != null) {
WizardTaskUtil.modifyModules(comp.getModulesToAdd(), comp.getModulesToRemove(), getTaskModel(), monitor);
+ if (showPublishOption)
+ ServerUIPlugin.getPreferences().setPublishOnAddRemoveModule(comp.shouldPublishImmediately());
+ }
}
}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/TasksWizardFragment.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/TasksWizardFragment.java
new file mode 100644
index 0000000..5bc5f47
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/fragment/TasksWizardFragment.java
@@ -0,0 +1,305 @@
+/*******************************************************************************
+ * 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.wst.server.ui.internal.wizard.fragment;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.core.internal.*;
+import org.eclipse.wst.server.core.model.PublishOperation;
+import org.eclipse.wst.server.ui.internal.editor.IOrdered;
+import org.eclipse.wst.server.ui.internal.wizard.WizardTaskUtil;
+import org.eclipse.wst.server.ui.wizard.WizardFragment;
+/**
+ *
+ */
+public class TasksWizardFragment extends WizardFragment {
+ private static final int TASKS_PER_PAGE = 5;
+
+ public class TaskInfo implements IOrdered {
+ public int kind;
+ public String id;
+ public PublishOperation task2;
+
+ private static final String DEFAULT = "default:";
+
+ public boolean isSelected() {
+ if (id == null)
+ return false;
+
+ if (selectedTaskMap.containsKey(id))
+ return (selectedTaskMap.get(id)).booleanValue();
+
+ if (selectedTaskMap.containsKey(DEFAULT + id))
+ return (selectedTaskMap.get(DEFAULT + id)).booleanValue();
+
+ return false;
+ }
+
+ public void setDefaultSelected(boolean sel) {
+ selectedTaskMap.put(DEFAULT + getId(), new Boolean(sel));
+ }
+
+ public boolean getDefaultSelected() {
+ return (selectedTaskMap.get(DEFAULT + id)).booleanValue();
+ }
+
+ public void setSelected(boolean sel) {
+ selectedTaskMap.put(getId(), new Boolean(sel));
+ }
+
+ public int getOrder() {
+ return task2.getOrder();
+ }
+
+ protected String getId() {
+ return id;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof TaskInfo))
+ return false;
+
+ TaskInfo ti = (TaskInfo) obj;
+ if (kind != ti.kind)
+ return false;
+
+ if (id == null || !id.equals(ti.id))
+ return false;
+
+ if (task2 == null && ti.task2 != null)
+ return false;
+
+ if (task2 != null && ti.task2 == null)
+ return false;
+
+ try {
+ if (task2 != null && ti.task2 != null) {
+ if (task2.getKind() != ti.task2.getKind())
+ return false;
+ if (task2.getOrder() != ti.task2.getOrder())
+ return false;
+ if (!task2.getLabel().equals(ti.task2.getLabel()))
+ return false;
+ if (!task2.getDescription().equals(ti.task2.getDescription()))
+ return false;
+ }
+ } catch (Exception e) {
+ // ignore
+ }
+ return true;
+ }
+ }
+
+ protected List<TaskInfo> tasks;
+ protected boolean hasOptionalTasks;
+ protected boolean hasPreferredTasks;
+
+ protected Map<String, Boolean> selectedTaskMap = new HashMap<String, Boolean>();
+
+ public TasksWizardFragment() {
+ // do nothing
+ }
+
+ protected void createChildFragments(List<WizardFragment> list) {
+ if (tasks == null || tasks.isEmpty())
+ return;
+
+ int size = tasks.size();
+ int pages = (size - 1) / TASKS_PER_PAGE + 1;
+ for (int i = 0; i < pages; i++) {
+ SubTasksWizardFragment fragment = new SubTasksWizardFragment();
+ List list2 = tasks.subList(TASKS_PER_PAGE * i, Math.min(size, TASKS_PER_PAGE * (i+1)));
+ fragment.updateTasks(list2);
+ list.add(fragment);
+ }
+ }
+
+ public void enter() {
+ updateTasks();
+ }
+
+ public List getChildFragments() {
+ updateTasks();
+ return super.getChildFragments();
+ }
+
+ public void setTaskModel(TaskModel taskModel) {
+ super.setTaskModel(taskModel);
+ updateTasks();
+ }
+
+ public void updateTasks() {
+ if (getTaskModel() == null) {
+ tasks = null;
+ return;
+ }
+
+ IServerAttributes server = (IServerAttributes) getTaskModel().getObject(TaskModel.TASK_SERVER);
+ List modules = (List) getTaskModel().getObject(TaskModel.TASK_MODULES);
+
+ if (server != null && modules == null) {
+ final List<IModule[]> moduleList = new ArrayList<IModule[]>();
+ ((Server) server).visit(new IModuleVisitor() {
+ public boolean visit(IModule[] module2) {
+ moduleList.add(module2);
+ return true;
+ }
+ }, null);
+
+ modules = moduleList;
+ }
+
+ if (server != null && modules != null) {
+ hasOptionalTasks = false;
+ hasPreferredTasks = false;
+ List<TaskInfo> taskList = new ArrayList<TaskInfo>(5);
+ createTasks(taskList, server, modules);
+
+ if (tasks == null || !tasks.equals(taskList)) {
+ tasks = taskList;
+ updateChildFragments();
+
+ boolean b = hasOptionalTasks || hasPreferredTasks;
+ getTaskModel().putObject(WizardTaskUtil.TASK_HAS_TASKS, new Boolean(b));
+ }
+ }
+ }
+
+ protected void createTasks(List<TaskInfo> taskList, IServerAttributes server, List modules) {
+ if (server == null)
+ return;
+
+ List<String> enabledTasks = ((Server)server).getEnabledOptionalPublishOperationIds();
+ List<String> disabledTasks = ((Server)server).getDisabledPreferredPublishOperationIds();
+ PublishOperation[] tasks2 = ((Server)server).getAllTasks(modules);
+ for (int j = 0; j < tasks2.length; j++) {
+ int kind = tasks2[j].getKind();
+ String id = ((Server)server).getPublishOperationId(tasks2[j]);
+ if (kind == PublishOperation.OPTIONAL || kind == PublishOperation.PREFERRED)
+ hasOptionalTasks = true;
+ if (kind == PublishOperation.PREFERRED)
+ hasPreferredTasks = true;
+ tasks2[j].setTaskModel(getTaskModel());
+
+ boolean selected = true;
+ if (kind == PublishOperation.OPTIONAL) {
+ if (!enabledTasks.contains(id))
+ selected = false;
+ } else if (kind == PublishOperation.PREFERRED) {
+ if (disabledTasks.contains(id))
+ selected = false;
+ }
+ taskList.add(getServerTask(server, tasks2[j], selected));
+ }
+ }
+
+ public TaskInfo getServerTask(IServerAttributes server, PublishOperation task2, boolean selected) {
+ TaskInfo sti = new TaskInfo();
+ sti.task2 = task2;
+ sti.kind = task2.getKind();
+ sti.id = ((Server)server).getPublishOperationId(task2);
+ sti.setDefaultSelected(selected);
+
+ return sti;
+ }
+
+ /**
+ * @see WizardFragment#performFinish(IProgressMonitor)
+ */
+ public void performFinish(IProgressMonitor monitor) throws CoreException {
+ if (!hasOptionalTasks)
+ return;
+
+ if (tasks == null || tasks.isEmpty())
+ return;
+
+ TaskModel taskModel = getTaskModel();
+ IServer server = (IServer)taskModel.getObject(TaskModel.TASK_SERVER);
+ if (server == null)
+ return;
+
+ boolean createdWC = false;
+ ServerWorkingCopy wc = null;
+ if (server instanceof ServerWorkingCopy)
+ wc = (ServerWorkingCopy)server;
+ else {
+ wc = (ServerWorkingCopy)server.createWorkingCopy();
+ createdWC = true;
+ }
+
+ // compare lists
+ List<String> disabled = new ArrayList<String>();
+ List<String> enabled = new ArrayList<String>();
+ Iterator iterator = tasks.iterator();
+ while (iterator.hasNext()) {
+ TaskInfo task = (TaskInfo)iterator.next();
+ if (PublishOperation.REQUIRED == task.kind)
+ continue;
+
+ String id = wc.getPublishOperationId(task.task2);
+ if (PublishOperation.PREFERRED == task.kind) {
+ if (!task.isSelected())
+ disabled.add(id);
+ } else if (PublishOperation.OPTIONAL == task.kind) {
+ if (task.isSelected())
+ enabled.add(id);
+ }
+ }
+
+ List<String> curDisabled = wc.getDisabledPreferredPublishOperationIds();
+ List<String> curEnabled = wc.getEnabledOptionalPublishOperationIds();
+
+ boolean different = false;
+ if (curEnabled.size() != enabled.size() || curDisabled.size() != disabled.size()) {
+ different = true;
+ } else {
+ for (String id : curDisabled) {
+ if (!disabled.contains(id))
+ different = true;
+ }
+ for (String id : curEnabled) {
+ if (!enabled.contains(id))
+ different = true;
+ }
+ }
+
+ if (different) {
+ wc.resetPreferredPublishOperations();
+ wc.resetOptionalPublishOperations();
+
+ Iterator<TaskInfo> iterator2 = tasks.iterator();
+ while (iterator2.hasNext()) {
+ TaskInfo task = iterator2.next();
+ if (PublishOperation.REQUIRED == task.kind)
+ continue;
+
+ if (PublishOperation.PREFERRED == task.kind) {
+ if (!task.isSelected())
+ wc.disablePreferredPublishOperations(task.task2);
+ } else if (PublishOperation.OPTIONAL == task.kind) {
+ if (task.isSelected())
+ wc.enableOptionalPublishOperations(task.task2);
+ }
+ }
+ }
+
+ if (createdWC && wc.isDirty())
+ wc.save(true, monitor);
+ monitor.done();
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ModifyModulesComposite.java b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ModifyModulesComposite.java
new file mode 100644
index 0000000..454ad8b
--- /dev/null
+++ b/plugins/org.eclipse.wst.server.ui/serverui/org/eclipse/wst/server/ui/internal/wizard/page/ModifyModulesComposite.java
@@ -0,0 +1,946 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2007 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.wst.server.ui.internal.wizard.page;
+
+import java.util.*;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.server.core.*;
+import org.eclipse.wst.server.ui.ServerUICore;
+import org.eclipse.wst.server.ui.internal.*;
+import org.eclipse.wst.server.ui.internal.view.servers.ModuleServer;
+import org.eclipse.wst.server.ui.wizard.IWizardHandle;
+/**
+ * A wizard page used to add and remove modules.
+ */
+public class ModifyModulesComposite extends Composite {
+ public static final String TASK_REFRESH_MODULES = "refresh-modules";
+
+ private static final String ROOT = "root";
+ protected static Color color;
+ protected static Font font;
+
+ protected IWizardHandle wizard;
+
+ protected IServerAttributes server;
+ protected IRuntime runtime;
+ protected boolean runtimeDirty;
+ protected Object refreshModules;
+ protected boolean showPublishOption;
+ protected boolean publishImmediately;
+
+ protected Map<ChildModuleMapKey, IModule[]> childModuleMap = new HashMap<ChildModuleMapKey, IModule[]>();
+ protected Map<IModule, IModule[]> parentModuleMap = new HashMap<IModule, IModule[]>();
+
+ // original modules on the server
+ protected List<IModule> originalModules = new ArrayList<IModule>();
+
+ // modules available to be added to the server
+ protected List<IModule> modules = new ArrayList<IModule>();
+
+ // current modules on the server
+ protected List<IModule> deployed = new ArrayList<IModule>();
+
+ protected TreeViewer availableTreeViewer;
+ protected TreeViewer deployedTreeViewer;
+
+ protected Button add, addAll;
+ protected Button remove, removeAll;
+
+ protected TaskModel taskModel;
+
+ // a module that must be kept on the server
+ protected IModule requiredModule;
+ protected boolean isComplete = true;
+
+ // the parent modules of the above modules. at least one of these modules
+ // must be kept on the server
+ protected IModule[] requiredModules;
+
+ protected Map<IModule, IStatus> errorMap;
+
+ abstract class TreeContentProvider implements ITreeContentProvider {
+ public void dispose() {
+ // do nothing
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // do nothing
+ }
+
+ public Object[] getChildren(Object parentElement) {
+ ModuleServer ms = (ModuleServer) parentElement;
+ IModule[] parent = ms.module;
+ IModule[] children = childModuleMap.get(new ChildModuleMapKey(parent));
+
+ List<ModuleServer> list = new ArrayList<ModuleServer>();
+ if (children != null) {
+ int size = children.length;
+ for (int i = 0; i < size; i++) {
+ IModule child = children[i];
+
+ parentModuleMap.put(child, parent);
+
+ int size2 = parent.length;
+ IModule[] module2 = new IModule[size2 + 1];
+ System.arraycopy(parent, 0, module2, 0, size2);
+ module2[size2] = child;
+ list.add(new ModuleServer(null, module2));
+ }
+ }
+ return list.toArray();
+ }
+
+ public Object getParent(Object element) {
+ ModuleServer ms = (ModuleServer) element;
+ IModule[] child = ms.module;
+ IModule[] modules2 = parentModuleMap.get(child);
+ if (modules2 == null)
+ return null;
+ return new ModuleServer(null, modules2);
+ }
+
+ public boolean hasChildren(Object element) {
+ ModuleServer ms = (ModuleServer) element;
+ IModule[] parent = ms.module;
+ IModule[] children = childModuleMap.get(new ChildModuleMapKey(parent));
+ return (children != null && children.length > 0);
+ }
+ }
+
+ class AvailableContentProvider extends TreeContentProvider {
+ public Object[] getElements(Object inputElement) {
+ List<ModuleServer> list = new ArrayList<ModuleServer>();
+ Iterator iterator = modules.iterator();
+ while (iterator.hasNext()) {
+ IModule module = (IModule) iterator.next();
+ list.add(new ModuleServer(null, new IModule[] { module }));
+ }
+ return list.toArray();
+ }
+ }
+
+ class DeployedContentProvider extends TreeContentProvider {
+ public Object[] getElements(Object inputElement) {
+ List<ModuleServer> list = new ArrayList<ModuleServer>();
+ Iterator iterator = deployed.iterator();
+ while (iterator.hasNext()) {
+ IModule module = (IModule) iterator.next();
+ list.add(new ModuleServer(null, new IModule[] { module }));
+ }
+ return list.toArray();
+ }
+ }
+
+ /**
+ * The key element for the child module map
+ * ChildMapModuleKey
+ */
+ protected class ChildModuleMapKey {
+ protected IModule[] moduleTree;
+
+ protected ChildModuleMapKey(IModule curModule) {
+ if (curModule != null) {
+ moduleTree = new IModule[] { curModule };
+ }
+ }
+
+ protected ChildModuleMapKey(IModule[] curModuleTree) {
+ moduleTree = curModuleTree;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this) // same object
+ return true;
+
+ if (!(obj instanceof ChildModuleMapKey))
+ return false;
+
+ IModule[] curCompareModule = ((ChildModuleMapKey) obj).moduleTree;
+ if (curCompareModule == moduleTree) {
+ // the module tree is the same
+ return true;
+ } else if (moduleTree == null || curCompareModule == null || moduleTree.length != curCompareModule.length){
+ return false;
+ } else {
+ // compare each module
+ for (int i = 0; i < curCompareModule.length; i++) {
+ if (!curCompareModule[i].equals(moduleTree[i]))
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public int hashCode() {
+ // force the same hash code on all the instances to makes sure the
+ // equals(Object) method is being used for comparing the objects
+ return 12345;
+ }
+ }
+
+ /**
+ * Create a new ModifyModulesComposite.
+ *
+ * @param parent a parent composite
+ * @param wizard a wizard
+ * @param module the module that is being added
+ */
+ public ModifyModulesComposite(Composite parent, IWizardHandle wizard, IModule module) {
+ super(parent, SWT.NONE);
+ this.wizard = wizard;
+ requiredModule = module;
+
+ wizard.setTitle(Messages.wizModuleTitle);
+ wizard.setDescription(Messages.wizModuleDescription);
+ wizard.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_WIZBAN_SELECT_SERVER));
+
+ createControl();
+ }
+
+ /**
+ * Create a new ModifyModulesComposite.
+ *
+ * @param parent a parent composite
+ * @param wizard a wizard
+ * @param module the module that is being added
+ * @param showPublishOption show the publishing options
+ */
+ public ModifyModulesComposite(Composite parent, IWizardHandle wizard, IModule module, boolean showPublishOption) {
+ super(parent, SWT.NONE);
+ this.wizard = wizard;
+ requiredModule = module;
+ this.showPublishOption = showPublishOption;
+
+ wizard.setTitle(Messages.wizModuleTitle);
+ wizard.setDescription(Messages.wizModuleDescription);
+ wizard.setImageDescriptor(ImageResource.getImageDescriptor(ImageResource.IMG_WIZBAN_SELECT_SERVER));
+
+ createControl();
+ }
+
+ public void setServer(IServerAttributes server) {
+ if (isVisible())
+ return;
+
+ // see bug 185875, 205869
+ if (refreshModules == taskModel.getObject(TASK_REFRESH_MODULES) && server == this.server) {
+ if (server == null)
+ return;
+ if (runtime == server.getRuntime()) {
+ if (runtime == null)
+ return;
+ if (runtime instanceof IRuntimeWorkingCopy) {
+ IRuntimeWorkingCopy wc = (IRuntimeWorkingCopy) runtime;
+ if (wc.isDirty() == runtimeDirty)
+ return;
+ } else
+ return;
+ }
+ }
+
+ refreshModules = taskModel.getObject(TASK_REFRESH_MODULES);
+ this.server = server;
+ if (server == null)
+ runtime = null;
+ else
+ runtime = server.getRuntime();
+ runtimeDirty = false;
+ if (runtime != null) {
+ if (runtime instanceof IRuntimeWorkingCopy) {
+ IRuntimeWorkingCopy wc = (IRuntimeWorkingCopy) runtime;
+ if (wc.isDirty())
+ runtimeDirty = true;
+ }
+ }
+
+ originalModules = new ArrayList<IModule>();
+ deployed = new ArrayList<IModule>();
+ modules = new ArrayList<IModule>();
+
+ childModuleMap = new HashMap<ChildModuleMapKey, IModule[]>();
+
+ if (server == null)
+ return;
+
+ System.setProperty("J2EEcache", "" + Math.random());
+
+ // get currently deployed modules
+ IModule[] currentModules = server.getModules();
+ if (currentModules != null) {
+ int size = currentModules.length;
+ for (int i = 0; i < size; i++) {
+ originalModules.add(currentModules[i]);
+ deployed.add(currentModules[i]);
+ }
+ }
+
+ // add new module
+ requiredModules = null;
+ errorMap = new HashMap<IModule, IStatus>();
+ if (requiredModule != null) {
+ try {
+ IModule[] parents = server.getRootModules(requiredModule, null);
+ if (parents != null && parents.length > 0)
+ requiredModules = parents;
+ else
+ requiredModules = new IModule[] { requiredModule };
+ } catch (CoreException ce) {
+ // ignore
+ //errorMap.put(newModule, ce.getStatus());
+ Trace.trace(Trace.INFO, "A possible server implementation error", ce);
+ } catch (Exception e) {
+ Trace.trace(Trace.WARNING, "Could not find root module", e);
+ }
+ }
+ if (requiredModules != null && !deployed.contains(requiredModules[0]))
+ deployed.add(requiredModules[0]);
+
+ // get remaining modules
+ IModule[] modules2 = ServerUtil.getModules(server.getServerType().getRuntimeType().getModuleTypes());
+ if (modules2 != null) {
+ int size = modules2.length;
+ for (int i = 0; i < size; i++) {
+ IModule module = modules2[i];
+ if (!deployed.contains(module)) {
+ try {
+ IModule[] parents = server.getRootModules(module, null);
+ if (parents != null) {
+ int size2 = parents.length;
+ for (int j = 0; j < size2; j++) {
+ if (parents[j].equals(module)) {
+ IStatus status = server.canModifyModules(new IModule[] { module }, null, null);
+ if (status != null && !status.isOK())
+ errorMap.put(module, status);
+ modules.add(module);
+ }
+ }
+ }
+ } catch (CoreException ce) {
+ errorMap.put(module, ce.getStatus());
+ modules.add(module);
+ }
+ }
+ }
+ }
+
+ // build child map
+ Iterator iterator = deployed.iterator();
+ while (iterator.hasNext()) {
+ IModule module = (IModule) iterator.next();
+ try {
+ IModule[] children = server.getChildModules(new IModule[] { module }, null);
+ if (children != null && children.length > 0)
+ childModuleMap.put(new ChildModuleMapKey(module), children);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ iterator = modules.iterator();
+ while (iterator.hasNext()) {
+ IModule module = (IModule) iterator.next();
+ try {
+ IModule[] children = server.getChildModules(new IModule[] { module }, null);
+ if (children != null && children.length > 0)
+ childModuleMap.put(new ChildModuleMapKey(module), children);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+
+ // get children recursively one level
+ // put child elements into a different list to avoid concurrent modifications
+ Iterator<ChildModuleMapKey> iterator2 = childModuleMap.keySet().iterator();
+ List<ChildModuleMapKey> list = new ArrayList<ChildModuleMapKey>();
+ while (iterator2.hasNext()) {
+ list.add(iterator2.next());
+ }
+
+ iterator = list.iterator();
+ while (iterator.hasNext()) {
+ ChildModuleMapKey key = (ChildModuleMapKey) iterator.next();
+ IModule[] children0 = childModuleMap.get(key);
+ if (children0 != null) {
+ int size = children0.length;
+ for (int i = 0; i < size; i++) {
+ int size2 = key.moduleTree.length;
+ IModule[] module2 = new IModule[size2 + 1];
+ System.arraycopy(key.moduleTree, 0, module2, 0, size2);
+ module2[size2] = children0[i];
+
+ try {
+ IModule[] children = server.getChildModules(module2, null);
+ if (children != null && children.length > 0)
+ childModuleMap.put(new ChildModuleMapKey(module2), children);
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+ }
+
+ System.setProperty("J2EEcache", "");
+
+ updateTaskModel();
+ }
+
+ public void setVisible(boolean b) {
+ if (b) {
+ Display.getDefault().syncExec(new Runnable() {
+ public void run() {
+ if (availableTreeViewer == null || availableTreeViewer.getControl().isDisposed())
+ return;
+ try { // update trees if we can
+ availableTreeViewer.refresh();
+ deployedTreeViewer.refresh();
+ setEnablement();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ });
+ }
+ super.setVisible(b);
+ }
+
+ public void setTaskModel(TaskModel model) {
+ this.taskModel = model;
+ }
+
+ /**
+ * Creates the UI of the page.
+ */
+ protected void createControl() {
+ GridLayout layout = new GridLayout();
+ layout.horizontalSpacing = SWTUtil.convertHorizontalDLUsToPixels(this, 4);
+ layout.verticalSpacing = SWTUtil.convertVerticalDLUsToPixels(this, 4);
+ layout.numColumns = 3;
+ setLayout(layout);
+ setFont(getParent().getFont());
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(this, ContextIds.MODIFY_MODULES_COMPOSITE);
+
+ Display display = getDisplay();
+ color = display.getSystemColor(SWT.COLOR_DARK_GRAY);
+ FontData[] fd = getFont().getFontData();
+ int size2 = fd.length;
+ for (int i = 0; i < size2; i++)
+ fd[i].setStyle(SWT.ITALIC);
+ font = new Font(display, fd);
+ addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ font.dispose();
+ }
+ });
+
+ Label label = new Label(this, SWT.NONE);
+ GridData data = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING);
+ data.horizontalSpan = 3;
+ label.setLayoutData(data);
+ label.setText(Messages.wizModuleMessage);
+
+ label = new Label(this, SWT.NONE);
+ label.setText(Messages.wizModuleAvailableList);
+
+ label = new Label(this, SWT.NONE);
+ label.setText("");
+
+ label = new Label(this, SWT.NONE);
+ label.setText(Messages.wizModuleDeployedList);
+
+ Tree availableTree = new Tree(this, SWT.BORDER | SWT.MULTI);
+ data = new GridData(GridData.FILL_BOTH);
+ data.heightHint = 200;
+ data.widthHint = 150;
+ availableTree.setLayoutData(data);
+
+ availableTreeViewer = new TreeViewer(availableTree);
+ ILabelProvider labelProvider = ServerUICore.getLabelProvider();
+ labelProvider.addListener(new ILabelProviderListener() {
+ public void labelProviderChanged(LabelProviderChangedEvent event) {
+ Object[] obj = event.getElements();
+ if (obj == null)
+ availableTreeViewer.refresh(true);
+ else {
+ obj = ServerUIPlugin.adaptLabelChangeObjects(obj);
+ int size = obj.length;
+ for (int i = 0; i < size; i++)
+ availableTreeViewer.refresh(obj[i], true);
+ }
+ }
+ });
+ availableTreeViewer.setLabelProvider(labelProvider);
+ availableTreeViewer.setContentProvider(new AvailableContentProvider());
+ availableTreeViewer.setComparator(new ViewerComparator() {
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ if (e1 instanceof ModuleServer && e2 instanceof ModuleServer) {
+ ModuleServer s1 = (ModuleServer) e1;
+ ModuleServer s2 = (ModuleServer) e2;
+ return (s1.module[s1.module.length - 1].getName().compareToIgnoreCase(s2.module[s2.module.length - 1].getName()));
+ }
+
+ return super.compare(viewer, e1, e2);
+ }
+ });
+ availableTreeViewer.setInput(ROOT);
+
+ availableTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ setEnablement();
+ }
+ });
+ availableTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+ setEnablement();
+ if (add.isEnabled())
+ add(false);
+ }
+ });
+
+ // slosh buttons
+ Composite comp = new Composite(this, SWT.NONE);
+ data = new GridData(GridData.FILL_BOTH);
+ data.widthHint = 120;
+ comp.setLayoutData(data);
+
+ layout = new GridLayout();
+ layout.marginWidth = 5;
+ layout.marginHeight = 25;
+ layout.verticalSpacing = 20;
+ comp.setLayout(layout);
+
+ add = new Button(comp, SWT.PUSH);
+ add.setText(Messages.wizModuleAdd);
+ add.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ add.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ add(false);
+ }
+ });
+
+ remove = new Button(comp, SWT.PUSH);
+ remove.setText(Messages.wizModuleRemove);
+ remove.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ remove.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ remove(false);
+ }
+ });
+
+ label = new Label(comp, SWT.NONE);
+ label.setText("");
+
+ addAll = new Button(comp, SWT.PUSH);
+ addAll.setText(Messages.wizModuleAddAll);
+ addAll.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ addAll.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ add(true);
+ }
+ });
+
+ removeAll = new Button(comp, SWT.PUSH);
+ removeAll.setText(Messages.wizModuleRemoveAll);
+ removeAll.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ removeAll.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ remove(true);
+ }
+ });
+
+ Tree deployedTree = new Tree(this, SWT.BORDER | SWT.MULTI);
+ data = new GridData(GridData.FILL_BOTH);
+ data.widthHint = 150;
+ deployedTree.setLayoutData(data);
+
+ deployedTreeViewer = new TreeViewer(deployedTree) {
+ public void doUpdateItem(Widget widget, Object element, boolean fullMap) {
+ if (widget instanceof TreeItem && color != null) {
+ TreeItem item = (TreeItem) widget;
+ if (element instanceof ModuleServer) {
+ ModuleServer ms = (ModuleServer) element;
+ IModule m = ms.module[ms.module.length-1];
+ if (m.isExternal())
+ item.setForeground(color);
+ else
+ item.setForeground(null);
+ if (!(server instanceof IServer) || ((IServer)server).getModulePublishState(ms.module) != IServer.PUBLISH_STATE_NONE)
+ item.setFont(font);
+ else
+ item.setFont(null);
+ }
+ }
+ super.doUpdateItem(widget, element, fullMap);
+ }
+ };
+ labelProvider = ServerUICore.getLabelProvider();
+ labelProvider.addListener(new ILabelProviderListener() {
+ public void labelProviderChanged(LabelProviderChangedEvent event) {
+ Object[] obj = event.getElements();
+ if (obj == null)
+ deployedTreeViewer.refresh(true);
+ else {
+ int size = obj.length;
+ for (int i = 0; i < size; i++)
+ deployedTreeViewer.refresh(obj[i], true);
+ }
+ }
+ });
+ deployedTreeViewer.setLabelProvider(labelProvider);
+ deployedTreeViewer.setContentProvider(new DeployedContentProvider());
+ deployedTreeViewer.setComparator(new ViewerComparator() {
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ if (e1 instanceof ModuleServer && e2 instanceof ModuleServer) {
+ ModuleServer s1 = (ModuleServer) e1;
+ ModuleServer s2 = (ModuleServer) e2;
+ return (s1.module[s1.module.length - 1].getName().compareToIgnoreCase(s2.module[s2.module.length - 1].getName()));
+ }
+
+ return super.compare(viewer, e1, e2);
+ }
+ });
+ deployedTreeViewer.setInput(ROOT);
+
+ deployedTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ setEnablement();
+ }
+ });
+ deployedTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
+ public void doubleClick(DoubleClickEvent event) {
+ setEnablement();
+ if (remove.isEnabled())
+ remove(false);
+ }
+ });
+
+ if (showPublishOption) {
+ final Button publish = new Button(this, SWT.CHECK);
+ publish.setText(Messages.wizModulePublishImmediately);
+ data = new GridData(GridData.FILL_HORIZONTAL);
+ data.horizontalSpan = 3;
+ publish.setLayoutData(data);
+
+ publishImmediately = ServerUIPlugin.getPreferences().getPublishOnAddRemoveModule();
+ publish.setSelection(publishImmediately);
+ publish.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent event) {
+ publishImmediately = publish.getSelection();
+ }
+ });
+ }
+
+ setEnablement();
+ availableTree.setFocus();
+
+ Dialog.applyDialogFont(this);
+ }
+
+ protected ModuleServer[] getAvailableSelection() {
+ IStructuredSelection sel = (IStructuredSelection) availableTreeViewer.getSelection();
+ if (sel.isEmpty())
+ return new ModuleServer[0];
+
+ ModuleServer [] mss = new ModuleServer[sel.size()];
+ System.arraycopy(sel.toArray(), 0, mss, 0, sel.size());
+ return mss;
+ }
+
+ protected ModuleServer[] getDeployedSelection() {
+ IStructuredSelection sel = (IStructuredSelection) deployedTreeViewer.getSelection();
+ if (sel.isEmpty())
+ return new ModuleServer[0];
+
+ ModuleServer [] mss = new ModuleServer[sel.size()];
+ System.arraycopy(sel.toArray(), 0, mss, 0, sel.size());
+ return mss;
+ }
+
+ protected static IModule getModule(ModuleServer ms) {
+ if (ms == null)
+ return null;
+ IModule[] modules2 = ms.module;
+ return modules2[modules2.length - 1];
+ }
+
+ protected static IModule[] getModules(ModuleServer[] ms) {
+ if (ms == null)
+ return null;
+ IModule[] modules2 = new IModule[ms.length];
+ for (int i = 0; i < ms.length; i++)
+ modules2[i] = getModule(ms[i]);
+
+ return modules2;
+ }
+
+ protected void setEnablement() {
+ wizard.setMessage(null, IMessageProvider.NONE);
+
+ int count = 0;
+ if (requiredModules != null) {
+ // count how many of requiredModules are deployed
+ int size = requiredModules.length;
+ for (int i = 0; i < size; i++) {
+ if (deployed.contains(requiredModules[i]))
+ count++;
+ }
+ }
+
+ // give error if there are more than one possible required modules and none are
+ // added to the server
+ isComplete = true;
+ if (requiredModules != null && requiredModules.length > 1 && count == 0) {
+ String s = "";
+ int size = requiredModules.length;
+ for (int i = 0; i < size; i++) {
+ if (i > 0)
+ s += " | ";
+ s += requiredModules[i].getName();
+ }
+ wizard.setMessage(NLS.bind(Messages.wizModuleRequiredModules, s), IMessageProvider.ERROR);
+ isComplete = false;
+ }
+
+ // selection specific messages
+ ModuleServer[] ms = getAvailableSelection();
+ if (ms == null || ms.length == 0) {
+ add.setEnabled(false);
+ } else {
+ boolean enabled = false;
+ // iterate through selection, if we find at least ONE module that can't be added, exit the loop
+ for (int i = 0; i < ms.length; i++) {
+ IModule module = getModule(ms[i]);
+ if (module != null) {
+ try {
+ IStatus status = errorMap.get(module);
+ if (modules.contains(module)) {
+ if (status == null )
+ enabled = true;
+ else if (status.getSeverity() == IStatus.ERROR) {
+ // this module can't be added because has errors, exit the loop
+ enabled = false;
+ wizard.setMessage(status.getMessage(), IMessageProvider.ERROR);
+ break;
+ } else if (status.getSeverity() == IStatus.WARNING){
+ enabled = true;
+ wizard.setMessage(status.getMessage(), IMessageProvider.WARNING);
+ }
+ else if (status.getSeverity() == IStatus.INFO){
+ enabled = true;
+ wizard.setMessage(status.getMessage(), IMessageProvider.INFORMATION);
+ }
+ }
+ else{
+ // at least ONE module from the selection can't be added, exit the loop
+ enabled = false;
+ break;
+ }
+ } catch (Exception e) {
+ Trace.trace(Trace.INFO,"Unable to handle error map for module:" + module);
+ }
+ }
+ }
+ add.setEnabled(enabled);
+ }
+ addAll.setEnabled(modules.size() > 0);
+
+ ms = getDeployedSelection();
+ if (ms == null || ms.length == 0) {
+ remove.setEnabled(false);
+ } else {
+ boolean enabled = false;
+ // iterate through selection, if we find at least ONE module that can't be added, exit the loop
+ for (int i = 0; i < ms.length; i++) {
+ IModule module = getModule(ms[i]);
+ if (module != null && deployed.contains(module)) {
+ // provide error about removing required single module
+ // required modules can't be removed
+ if (requiredModules != null){
+ if (requiredModules.length == 1 && requiredModules[0].equals(module)) {
+ // this is a required module and can't be removed, exit the loop
+ wizard.setMessage(NLS.bind(Messages.wizModuleRequiredModule, module.getName()), IMessageProvider.ERROR);
+ enabled = false;
+ break;
+ }
+ }
+ else
+ enabled = true;
+ }
+ else{
+ // this module is not found in the 'deployed' array, the module might be a child
+ // at least ONE module from the selection can't be removed, exit the loop
+ enabled = false;
+ break;
+ }
+ }
+ remove.setEnabled(enabled);
+ }
+
+ if (requiredModules == null)
+ removeAll.setEnabled(deployed.size() > 0);
+ else
+ removeAll.setEnabled(deployed.size() > 1);
+ }
+
+ protected void add(boolean all) {
+ if (all) {
+ IModule[] modules2 = new IModule[modules.size()];
+ modules.toArray(modules2);
+ moveAll(modules2, true);
+ } else
+ moveAll(getModules(getAvailableSelection()), true);
+ updateTaskModel();
+ }
+
+ protected void remove(boolean all) {
+ if (all) {
+ // pick one of the required modules to keep
+ IModule keep = null;
+ if (requiredModules != null) {
+ int size2 = requiredModules.length;
+ for (int i = 0; i < size2; i++) {
+ if (keep == null && deployed.contains(requiredModules[i]))
+ keep = requiredModules[i];
+ }
+ }
+
+ List<IModule> list = new ArrayList<IModule>();
+ list.addAll(deployed);
+ list.remove(keep);
+
+ IModule[] modules2 = new IModule[list.size()];
+ list.toArray(modules2);
+
+ moveAll(modules2, false);
+ } else
+ moveAll(getModules(getDeployedSelection()), false);
+ updateTaskModel();
+ }
+
+ protected void moveAll(IModule[] mods, boolean add2) {
+ int size = mods.length;
+ List<IModule> list = new ArrayList<IModule>();
+ for (int i = 0; i < size; i++) {
+ IStatus status = errorMap.get(mods[i]);
+
+ if (status == null && !list.contains(mods[i]))
+ list.add(mods[i]);
+ }
+
+ Iterator iterator = list.iterator();
+ while (iterator.hasNext()) {
+ IModule module = (IModule) iterator.next();
+ ModuleServer ms = new ModuleServer(null, new IModule[] { module });
+ if (add2) {
+ modules.remove(module);
+ deployed.add(module);
+ availableTreeViewer.remove(ms);
+ deployedTreeViewer.add(ROOT, ms);
+ } else {
+ modules.add(module);
+ deployed.remove(module);
+ availableTreeViewer.add(ROOT, ms);
+ deployedTreeViewer.remove(ms);
+ }
+ }
+
+ setEnablement();
+ }
+
+ protected void updateTaskModel() {
+ if (taskModel == null)
+ return;
+
+ taskModel.putObject(TaskModel.TASK_MODULES, getModuleMap());
+ wizard.update();
+ }
+
+ public List<IModule> getModulesToRemove() {
+ List<IModule> list = new ArrayList<IModule>();
+ Iterator iterator = originalModules.iterator();
+ while (iterator.hasNext()) {
+ IModule module = (IModule) iterator.next();
+ if (!deployed.contains(module))
+ list.add(module);
+ }
+ return list;
+ }
+
+ public List<IModule> getModulesToAdd() {
+ List<IModule> list = new ArrayList<IModule>();
+ Iterator iterator = deployed.iterator();
+ while (iterator.hasNext()) {
+ IModule module = (IModule) iterator.next();
+ if (!originalModules.contains(module))
+ list.add(module);
+ }
+ return list;
+ }
+
+ private void addChildMap(List<IModule[]> map, IModule[] parents, IModule[] children) {
+ if (children == null)
+ return;
+
+ int size = children.length;
+ for (int i = 0; i < size; i++) {
+ IModule module = children[i];
+
+ int size2 = parents.length;
+ IModule[] modules2 = new IModule[size2 + 1];
+ System.arraycopy(parents, 0, modules2, 0, size2);
+ modules2[size2] = module;
+ map.add(modules2);
+
+ IModule[] children2 = childModuleMap.get(new ChildModuleMapKey(module));
+ if (children2 != null)
+ addChildMap(map, modules2, children2);
+ }
+ }
+
+ public List getModuleMap() {
+ final List<IModule[]> map = new ArrayList<IModule[]>();
+
+ Iterator iterator = deployed.iterator();
+ while (iterator.hasNext()) {
+ IModule module = (IModule) iterator.next();
+ IModule[] moduleTree = new IModule[] { module };
+ map.add(moduleTree);
+ IModule[] children = childModuleMap.get(new ChildModuleMapKey(module));
+ if (children != null)
+ addChildMap(map, moduleTree, children);
+ }
+
+ return map;
+ }
+
+ public boolean isComplete() {
+ return isComplete;
+ }
+
+ public boolean shouldPublishImmediately() {
+ return publishImmediately;
+ }
+}
\ No newline at end of file