/*******************************************************************************
* Copyright (c) 2012 Pivotal Software, Inc.
* 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:
* Pivotal Software, Inc. - initial API and implementation
*******************************************************************************/
package org.springsource.ide.eclipse.commons.configurator;
import java.io.File;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IRuntime;
import org.eclipse.wst.server.core.IRuntimeWorkingCopy;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerListener;
import org.eclipse.wst.server.core.IServerType;
import org.eclipse.wst.server.core.IServerWorkingCopy;
import org.eclipse.wst.server.core.ServerCore;
import org.eclipse.wst.server.core.ServerEvent;
import org.eclipse.wst.server.core.ServerPort;
import org.eclipse.wst.server.core.ServerUtil;
import org.springsource.ide.eclipse.commons.core.Policy;
import org.springsource.ide.eclipse.commons.internal.configurator.Activator;
import org.springsource.ide.eclipse.commons.internal.configurator.server.ServerDescriptor;
/**
* @author Steffen Pingel
* @author Christian Dupuis
* @author Terry Denney
*/
public class ServerHandler {
public static final IOverwriteQuery ALWAYS_OVERWRITE = new IOverwriteQuery() {
public String queryOverwrite(String arg0) {
return IOverwriteQuery.YES;
}
};
public static final IOverwriteQuery NEVER_OVERWRITE = new IOverwriteQuery() {
public String queryOverwrite(String arg0) {
return IOverwriteQuery.NO;
}
};
private final String serverType;
private String runtimeName;
private String serverName;
/**
* Absolute path to the target directory for the server installation.
*/
private String serverPath;
private String verifyPath;
private boolean forceCreateRuntime;
public ServerHandler(ServerDescriptor descriptor) {
this(descriptor, null);
}
public ServerHandler(ServerDescriptor descriptor, File path) {
this(descriptor.getServerTypeId());
setRuntimeName(descriptor.getRuntimeName());
setServerName(descriptor.getServerName());
setForceCreateRuntime(descriptor.getForceCreateRuntime());
if (path != null) {
setServerPath(path.getAbsolutePath());
}
}
public ServerHandler(String serverType) {
this.serverType = serverType;
this.verifyPath = "conf";
}
public IServer getExistingServer() {
IProgressMonitor monitor = new NullProgressMonitor();
try {
IServerType st = ServerCore.findServerType(serverType);
if (st == null) {
return null;
}
IRuntime runtime;
if (serverPath != null || forceCreateRuntime) {
runtime = ServerCore.findRuntime(runtimeName);
if (runtime == null) {
return null;
}
}
else {
runtime = findRuntime(st, monitor);
}
if (serverName != null) {
return ServerCore.findServer(serverName);
}
else {
return findServer(st, runtime, monitor);
}
}
catch (CoreException e) {
return null;
}
}
public IServer createServer(IProgressMonitor monitor, IOverwriteQuery query) throws CoreException {
return createServer(monitor, query, null);
}
public IServer createServer(IProgressMonitor monitor, IOverwriteQuery query, ServerHandlerCallback callback)
throws CoreException {
try {
monitor.beginTask("Creating server configuration", 4);
IServerType st = ServerCore.findServerType(serverType);
if (st == null) {
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Could not find server type \""
+ serverType + "\""));
}
IRuntime runtime;
if (serverPath != null) {
runtime = createRuntime(st, new Path(serverPath), monitor, query);
}
else if (forceCreateRuntime) {
runtime = createRuntime(st, null, monitor, query);
}
else {
runtime = findRuntime(st, monitor);
}
if (serverName != null) {
return createServer(st, runtime, monitor, query, callback);
}
else {
return findServer(st, runtime, monitor);
}
}
finally {
monitor.done();
}
}
public void deleteServerAndRuntime(IProgressMonitor monitor) throws CoreException {
try {
monitor.beginTask("Deleting server configuration", 4);
IServer server = ServerCore.findServer(serverName);
if (server != null) {
IFolder serverConfiguration = server.getServerConfiguration();
server.delete();
if (serverConfiguration != null) {
serverConfiguration.delete(true, true, monitor);
}
}
IRuntime runtime = ServerCore.findRuntime(runtimeName);
if (runtime != null) {
runtime.delete();
}
}
finally {
monitor.done();
}
}
public int getHttpPort(IServer server, IProgressMonitor monitor) {
ServerPort[] ports = server.getServerPorts(monitor);
if (ports != null) {
for (ServerPort serverPort : ports) {
if ("http".equals(serverPort.getProtocol())) {
return serverPort.getPort();
}
}
}
return -1;
}
public String getRuntimeName() {
return runtimeName;
}
public String getVerifyPath() {
return verifyPath;
}
public IServer launch(IProject project, IProgressMonitor monitor) throws CoreException {
try {
monitor.beginTask("Launching " + project.getName(), IProgressMonitor.UNKNOWN);
IServer server = createServer(new SubProgressMonitor(monitor, 1), NEVER_OVERWRITE);
IServerWorkingCopy wc = server.createWorkingCopy();
IModule[] modules = ServerUtil.getModules(project);
if (modules == null || modules.length == 0) {
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
"Sample project does not contain web modules: " + project));
}
if (!Arrays.asList(wc.getModules()).contains(modules[0])) {
wc.modifyModules(modules, new IModule[0], monitor);
server = wc.save(true, monitor);
}
server.publish(IServer.PUBLISH_INCREMENTAL, monitor);
restartServer(server, monitor);
return server;
}
finally {
monitor.done();
}
}
public void setForceCreateRuntime(boolean forceCreateRuntime) {
this.forceCreateRuntime = forceCreateRuntime;
}
public void setRuntimeName(String runtimeName) {
this.runtimeName = runtimeName;
}
public void setServerName(String serverName) {
this.serverName = serverName;
}
public void setServerPath(String serverPath) {
this.serverPath = serverPath;
}
public void setVerifyPath(String verifyPath) {
this.verifyPath = verifyPath;
}
public String getServerName() {
return serverName;
}
public String getServerPath() {
return serverPath;
}
private IRuntime createRuntime(IServerType st, IPath path, IProgressMonitor monitor, IOverwriteQuery query)
throws CoreException {
IRuntime runtime = ServerCore.findRuntime(runtimeName);
if (runtime != null) {
if (!query(query, NLS.bind("A runtime with the name ''{0}'' already exists. Replace the existing runtime?",
runtimeName))) {
monitor.worked(1);
return runtime;
}
else {
runtime.delete();
}
}
IRuntimeWorkingCopy wc = st.getRuntimeType().createRuntime(runtimeName, new SubProgressMonitor(monitor, 1));
wc.setName(runtimeName);
if (path != null) {
wc.setLocation(path);
}
IStatus validationResult = wc.validate(monitor);
if (!validationResult.isOK()) {
throw new CoreException(validationResult);
}
runtime = wc.save(true, new SubProgressMonitor(monitor, 1));
return runtime;
}
private IServer createServer(IServerType st, IRuntime runtime, IProgressMonitor monitor, IOverwriteQuery query,
ServerHandlerCallback callback) throws CoreException {
IServer server = ServerCore.findServer(serverName);
if (server != null) {
if (!query(query,
NLS.bind("A server with the name ''{0}'' already exists. Replace the existing server?", serverName))) {
monitor.worked(1);
return server;
}
else {
IFolder serverConfiguration = server.getServerConfiguration();
server.delete();
if (serverConfiguration != null) {
serverConfiguration.delete(true, true, monitor);
}
}
}
IServerWorkingCopy wc = st.createServer(serverName, null, runtime, new SubProgressMonitor(monitor, 1));
wc.setName(serverName);
if (callback != null) {
callback.configureServer(wc);
}
server = wc.save(true, new SubProgressMonitor(monitor, 1));
return server;
}
private IRuntime findRuntime(IServerType st, IProgressMonitor monitor) throws CoreException {
IRuntime[] runtimes = ServerCore.getRuntimes();
if (runtimes != null) {
for (IRuntime runtime : runtimes) {
if (runtime.getRuntimeType().equals(st.getRuntimeType())) {
return runtime;
}
}
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "No matching runtime found"));
}
private IServer findServer(IServerType st, IRuntime runtime, IProgressMonitor monitor) throws CoreException {
IServer[] servers = ServerCore.getServers();
if (servers != null) {
for (IServer server : servers) {
if (server.getRuntime().getRuntimeType().equals(st.getRuntimeType())) {
return server;
}
}
}
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "No matching server found"));
}
private boolean query(IOverwriteQuery query, String message) {
String response = query.queryOverwrite(message);
if (IOverwriteQuery.CANCEL.equals(response)) {
throw new OperationCanceledException();
}
if (IOverwriteQuery.YES.equals(response)) {
return true;
}
return false;
}
private void restartServer(IServer server, IProgressMonitor monitor) throws CoreException {
monitor.subTask("Restarting server");
final CountDownLatch eventLatch = new CountDownLatch(1);
IServerListener serverListener = new IServerListener() {
public void serverChanged(ServerEvent event) {
if (event.getState() == IServer.STATE_STARTED) {
eventLatch.countDown();
}
}
};
try {
server.addServerListener(serverListener);
if (server.getServerState() != IServer.STATE_STARTED) {
server.start(ILaunchManager.DEBUG_MODE, monitor);
}
else if (server.getServerRestartState()) {
server.restart(ILaunchManager.DEBUG_MODE, monitor);
}
else {
return;
}
// wait 10 seconds
monitor.subTask("Waiting for server to start");
for (int i = 0; i < 50; i++) {
try {
if (eventLatch.await(200, TimeUnit.MILLISECONDS)) {
break;
}
}
catch (InterruptedException e) {
throw new OperationCanceledException();
}
Policy.checkCancelled(monitor);
}
}
finally {
server.removeServerListener(serverListener);
}
}
}