blob: b98c591d6da59ee1a6c1ca5366f3b79db497901c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 Eteration Bilisim A.S.
* All rights reserved.   This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* Gorkem Ercan - initial API and implementation
* Naci M. Dai
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ETERATION A.S. OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Eteration Bilisim A.S. For more
* information on eteration, please see
* <http://www.eteration.com/>.
***************************************************************************/
package org.eclipse.jst.server.generic.internal.core;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
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.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jst.server.generic.core.CorePlugin;
import org.eclipse.jst.server.generic.internal.xml.ServerTypeDefinition;
import org.eclipse.jst.server.generic.modules.J2eeSpecModuleFactoryDelegate;
import org.eclipse.jst.server.j2ee.IWebModule;
import org.eclipse.wst.server.core.IServer;
import org.eclipse.wst.server.core.IServerConfiguration;
import org.eclipse.wst.server.core.IServerState;
import org.eclipse.wst.server.core.ITask;
import org.eclipse.wst.server.core.ServerCore;
import org.eclipse.wst.server.core.model.IModule;
import org.eclipse.wst.server.core.model.IModuleEvent;
import org.eclipse.wst.server.core.model.IModuleFactoryEvent;
import org.eclipse.wst.server.core.model.IMonitorableServer;
import org.eclipse.wst.server.core.model.IPublisher;
import org.eclipse.wst.server.core.model.IServerDelegate;
import org.eclipse.wst.server.core.model.IServerPort;
import org.eclipse.wst.server.core.model.IStartableServer;
import org.eclipse.wst.server.core.model.IURLProvider;
import org.eclipse.wst.server.core.resources.IModuleResourceDelta;
import org.eclipse.wst.server.core.util.ServerPort;
import org.eclipse.wst.server.core.util.SocketUtil;
/**
* Generic XML based server implementation.
*
* @author Gorkem Ercan
*/
public class GenericServer implements IServerDelegate, IStartableServer, IMonitorableServer,IURLProvider {
private IServerState fLiveServer;
private static final String ATTR_STOP = "stop-server";
// the thread used to ping the server to check for startup
protected transient PingThread ping = null;
protected transient IProcess process;
protected transient IDebugEventSetListener processListener;
private ServerTypeDefinition fServerDefinition;
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#initialize(org.eclipse.wst.server.core.IServerState)
*/
public void initialize(IServerState liveServer) {
this.fLiveServer = liveServer;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#dispose()
*/
public void dispose() {
this.fLiveServer = null;
}
/**
* Returns the project publisher that can be used to
* publish the given project.
*
* @param project org.eclipse.core.resources.IProject
* @return org.eclipse.wst.server.core.model.IProjectPublisher
*/
public IPublisher getPublisher(List parents, IModule module) {
return new AntPublisher(parents, module, this.getServerDefinition());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#updateConfiguration()
*/
public void updateConfiguration() {
Trace.trace(Trace.FINEST, "updateConfiguration" + this);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#updateModule(org.eclipse.wst.server.core.model.IModule,
* org.eclipse.wst.server.core.resources.IModuleResourceDelta)
*/
public void updateModule(IModule module, IModuleResourceDelta delta) {
// TODO Auto-generated method stub
Trace.trace(Trace.FINEST, "Configuration updated " + this);
//setConfigurationSyncState(SYNC_STATE_DIRTY);
//setRestartNeeded(true);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#publishStart(org.eclipse.core.runtime.IProgressMonitor)
*/
public IStatus publishStart(IProgressMonitor monitor) {
return new Status(IStatus.OK, CorePlugin.PLUGIN_ID, 0, "PublishingStarted", null);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#publishConfiguration(org.eclipse.core.runtime.IProgressMonitor)
*/
public IStatus publishConfiguration(IProgressMonitor monitor) {
return new Status(IStatus.OK, CorePlugin.PLUGIN_ID, 0, "Published Configuration", null);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#publishStop(org.eclipse.core.runtime.IProgressMonitor)
*/
public IStatus publishStop(IProgressMonitor monitor) {
fLiveServer.setConfigurationSyncState(IServer.SYNC_STATE_IN_SYNC);
return new Status(IStatus.OK, CorePlugin.PLUGIN_ID, 0, "Published Configuration", null);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#canModifyModules(org.eclipse.wst.server.core.model.IModule[],
* org.eclipse.wst.server.core.model.IModule[])
*/
public IStatus canModifyModules(IModule[] add, IModule[] remove) {
// TODO Auto-generated method stub
return new Status(IStatus.OK, CorePlugin.PLUGIN_ID, 0, "CanModifyModules", null);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#getModules()
*/
public IModule[] getModules() {
// TODO Auto-generated method stub
List list = J2eeSpecModuleFactoryDelegate.getInstance().getModules();
return (IModule[])list.toArray(new IModule[list.size()]);
}
protected IWebModule getWebModule(IProject project) throws CoreException {
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#getModuleState(org.eclipse.wst.server.core.model.IModule)
*/
public byte getModuleState(IModule module) {
// TODO Auto-generated method stub
return IServer.MODULE_STATE_STARTED;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#getRepairCommands(org.eclipse.wst.server.core.model.IModuleFactoryEvent[],
* org.eclipse.wst.server.core.model.IModuleEvent[])
*/
public ITask[] getRepairCommands(IModuleFactoryEvent[] factoryEvent,
IModuleEvent[] moduleEvent) {
// TODO Auto-generated method stub
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#getChildModules(org.eclipse.wst.server.core.model.IModule)
*/
public List getChildModules(IModule module) {
// TODO Auto-generated method stub
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#getParentModules(org.eclipse.wst.server.core.model.IModule)
*/
public List getParentModules(IModule module) throws CoreException {
//FIXME This is valid for only web modules. A generic server should support any
// kind of j2ee module. Fix this after the server architectures are determined.
if (module instanceof IWebModule) {
IWebModule webModule = (IWebModule) module;
IStatus status = canModifyModules(new IModule[] { module }, null);
if (status == null || !status.isOK())
throw new CoreException(status);
ArrayList l = new ArrayList();
l.add(webModule);
return l;
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IServerDelegate#setLaunchDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
*/
public void setLaunchDefaults(ILaunchConfigurationWorkingCopy workingCopy) {
fLiveServer.getRuntime().getDelegate();
workingCopy.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME,
getStartClassName());
GenericServerRuntime runtime = (GenericServerRuntime) fLiveServer
.getRuntime().getDelegate();
IVMInstall vmInstall = runtime.getVMInstall();
workingCopy.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE, runtime
.getVMInstallTypeId());
workingCopy.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_NAME,
vmInstall.getName());
setupLaunchClasspath(workingCopy, vmInstall);
workingCopy.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY,
getWorkingDirectory());
workingCopy.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,
getProgramArguments());
workingCopy.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS,
getVmArguments());
//workingCopy.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE_SPECIFIC_ATTRS_MAP,);
}
private List getClasspathMementos() {
return getServerDefinition().getServerClasspathMementos();
}
private String getVmArguments() {
return getServerDefinition().getStartVmParameters();
}
private String getProgramArguments() {
return getServerDefinition().getStartProgramArguments();
}
private String getWorkingDirectory() {
return getServerDefinition().getStartWorkingDirectory();
}
public String getStartClassName() {
return getServerDefinition().getStartClass();
}
/**
* @return
*/
private Map getServerInstanceProperties() {
Map instanceProperties = fLiveServer.getRuntime().getAttribute(
GenericServerRuntime.SERVER_INSTANCE_PROPERTIES, (Map) null);
return instanceProperties;
}
public ServerTypeDefinition getServerDefinition() {
if (fServerDefinition == null)
fServerDefinition = CorePlugin.getDefault()
.getServerTypeDefinitionManager()
.getServerRuntimeDefinition(
fLiveServer.getRuntime().getAttribute(
GenericServerRuntime.SERVER_DEFINITION_ID,
""), getServerInstanceProperties());
return fServerDefinition;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.wst.server.core.model.IMonitorableServer#getServerPorts()
*/
public List getServerPorts() {
List ports = new ArrayList();
try {
int port = Integer.parseInt(this.getServerDefinition().getPort());
ports.add(new ServerPort("server", "Server port", port, "TCPIP"));
} catch (Exception e) {
}
return ports;
}
/* (non-Javadoc)
* @see org.eclipse.wst.server.core.model.IStartableServer#isTerminateOnShutdown()
*/
public boolean isTerminateOnShutdown() {
// TODO Auto-generated method stub
return false;
}
/**
* Setup for starting the server.
*
* @param launch ILaunch
* @param launchMode String
* @param monitor IProgressMonitor
*/
public void setupLaunch(ILaunch launch, String launchMode, IProgressMonitor monitor) throws CoreException {
if ("true".equals(launch.getLaunchConfiguration().getAttribute(ATTR_STOP, "false")))
return;
// IStatus status = getRuntime().validate();
// if (status != null && !status.isOK())
// throw new CoreException(status);
Iterator iterator = this.getServerPorts().iterator();
IServerPort sp = null;
while (iterator.hasNext()) {
sp = (IServerPort) iterator.next();
if (SocketUtil.isPortInUse(sp.getPort(), 5))
throw new CoreException(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, 0, "Server Part In Use "+sp.getPort() + "- " +sp.getName() ,null));
}
fLiveServer.setServerState(IServer.SERVER_STARTING);
// ping server to check for startup
try {
String url = "http://localhost";
int port = sp.getPort();
if (port != 80)
url += ":" + port;
ping = new PingThread(this, fLiveServer, url, launchMode);
ping.start();
} catch (Exception e) {
Trace.trace(Trace.SEVERE, "Can't ping for server startup.");
}
}
/**
* Cleanly shuts down and terminates the server.
*/
public void stop() {
byte state = this.fLiveServer.getServerState();
if (state == IServer.SERVER_STOPPED)
return;
else if (state == IServer.SERVER_STARTING || state == IServer.SERVER_STOPPING) {
terminate();
return;
}
try {
Trace.trace(Trace.FINEST, "Stopping Server");
if (state != IServer.SERVER_STOPPED)
fLiveServer.setServerState(IServer.SERVER_STOPPING);
ILaunchManager mgr = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType type =
mgr.getLaunchConfigurationType(
IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);
String launchName = "GenericServerStopper";
String uniqueLaunchName =
mgr.generateUniqueLaunchConfigurationNameFrom(launchName);
ILaunchConfiguration conf = null;
ILaunchConfiguration[] lch = mgr.getLaunchConfigurations(type);
for (int i = 0; i < lch.length; i++) {
if (launchName.equals(lch[i].getName())) {
conf = lch[i];
break;
}
}
ILaunchConfigurationWorkingCopy wc = null;
if (conf != null) {
wc = conf.getWorkingCopy();
} else {
wc = type.newInstance(null, uniqueLaunchName);
}
//To stop from appearing in history lists
wc.setAttribute(IDebugUIConstants.ATTR_PRIVATE, true);
wc.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME,
this.getServerDefinition().getStopClass());
GenericServerRuntime runtime = (GenericServerRuntime) fLiveServer
.getRuntime().getDelegate();
IVMInstall vmInstall = runtime.getVMInstall();
wc.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_TYPE, runtime
.getVMInstallTypeId());
wc.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_VM_INSTALL_NAME,
vmInstall.getName());
setupLaunchClasspath(wc, vmInstall);
wc.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY,
getWorkingDirectory());
wc.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,
getServerDefinition().getStopProgramArguments());
wc.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS,
getServerDefinition().getStopVmParameters());
wc.setAttribute(ATTR_STOP, "true");
wc.launch(ILaunchManager.RUN_MODE, new NullProgressMonitor());
} catch (Exception e) {
Trace.trace(Trace.SEVERE, "Error stopping Server", e);
}
}
/**
* @param wc
* @param vmInstall
*/
private void setupLaunchClasspath(ILaunchConfigurationWorkingCopy wc, IVMInstall vmInstall) {
List cp = getClasspathMementos();
// add tools.jar to the path
if (vmInstall != null) {
try {
cp
.add(JavaRuntime
.newRuntimeContainerClasspathEntry(
new Path(JavaRuntime.JRE_CONTAINER)
.append(
"org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType")
.append(vmInstall.getName()),
IRuntimeClasspathEntry.BOOTSTRAP_CLASSES)
.getMemento());
} catch (Exception e) {
}
IPath jrePath = new Path(vmInstall.getInstallLocation()
.getAbsolutePath());
if (jrePath != null) {
IPath toolsPath = jrePath.append("lib").append("tools.jar");
if (toolsPath.toFile().exists()) {
try {
cp.add(JavaRuntime.newArchiveRuntimeClasspathEntry(
toolsPath).getMemento());
} catch (CoreException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
wc.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, cp);
wc.setAttribute(
IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH,
false);
}
/**
* Terminates the server.
*/
public void terminate() {
if (fLiveServer.getServerState() == IServer.SERVER_STOPPED)
return;
try {
fLiveServer.setServerState(IServer.SERVER_STOPPING);
Trace.trace(Trace.FINEST, "Killing the Server process");
if (process != null && !process.isTerminated()) {
process.terminate();
stopImpl();
}
} catch (Exception e) {
Trace.trace(Trace.SEVERE, "Error killing the process", e);
}
}
protected void stopImpl() {
if (ping != null) {
ping.stopPinging();
ping = null;
}
if (process != null) {
process = null;
DebugPlugin.getDefault().removeDebugEventListener(processListener);
processListener = null;
}
fLiveServer.setServerState(IServer.SERVER_STOPPED);
}
public void setProcess(final IProcess newProcess) {
if (process != null)
return;
process = newProcess;
processListener = new IDebugEventSetListener() {
public void handleDebugEvents(DebugEvent[] events) {
if (events != null) {
int size = events.length;
for (int i = 0; i < size; i++) {
if (process.equals(events[i].getSource()) && events[i].getKind() == DebugEvent.TERMINATE) {
DebugPlugin.getDefault().removeDebugEventListener(this);
stopImpl();
}
}
}
}
};
DebugPlugin.getDefault().addDebugEventListener(processListener);
}
public int getStartTimeout() {
return 300000;
}
public int getStopTimeout() {
return 300000;
}
/* (non-Javadoc)
* @see org.eclipse.wtp.server.core.model.IURLProvider#getModuleRootURL(org.eclipse.wtp.server.core.model.IModule)
*/
public URL getModuleRootURL(IModule module) {
try {
if (module == null || !(module instanceof IWebModule))
return null;
IServerConfiguration serverConfig = fLiveServer
.getServerConfiguration();
if (serverConfig == null)
return null;
String url = "http://localhost";
int port = Integer.parseInt(getServerDefinition().getPort());
port = ServerCore.getServerMonitorManager().getMonitoredPort(
fLiveServer, port, "web");
if (port != 80)
url += ":" + port;
url += "/"+module.getName();
if (!url.endsWith("/"))
url += "/";
return new URL(url);
} catch (Exception e) {
Trace.trace("Could not get root URL", e);
return null;
}
}
}