blob: b650904a29fba43d76c9f528530cf1c7bb7642be [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2009 - 2013 SpringSource, a division of VMware, Inc. and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.virgo.ide.runtime.internal.core;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
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.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jst.server.core.FacetUtil;
import org.eclipse.jst.server.core.IWebModule;
import org.eclipse.virgo.ide.facet.core.FacetCorePlugin;
import org.eclipse.virgo.ide.facet.core.FacetUtils;
import org.eclipse.virgo.ide.module.core.ServerModuleDelegate;
import org.eclipse.virgo.ide.runtime.core.IServer;
import org.eclipse.virgo.ide.runtime.core.IServerConfiguration;
import org.eclipse.virgo.ide.runtime.core.IServerRuntimeProvider;
import org.eclipse.virgo.ide.runtime.core.IServerWorkingCopy;
import org.eclipse.virgo.ide.runtime.core.ServerCorePlugin;
import org.eclipse.wst.common.project.facet.core.FacetedProjectFramework;
import org.eclipse.wst.common.project.facet.core.IFacetedProject;
import org.eclipse.wst.common.project.facet.core.ProjectFacetsManager;
import org.eclipse.wst.common.project.facet.core.runtime.IRuntime;
import org.eclipse.wst.common.project.facet.core.runtime.RuntimeManager;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.core.IModuleType;
import org.eclipse.wst.server.core.model.ServerDelegate;
/**
* Default dm server implementation.
*
* @author Christian Dupuis
* @author Leo Dos Santos
* @author GianMaria Romanato
* @since 1.0.0
*/
public class Server extends ServerDelegate implements IServer, IServerWorkingCopy {
private ServerConfiguration configuration;
protected transient List<PropertyChangeListener> listeners = new ArrayList<PropertyChangeListener>();
protected transient IServerRuntimeProvider versionHandler;
public void addConfigurationChangeListener(PropertyChangeListener listener) {
if (!this.listeners.contains(listener)) {
this.listeners.add(listener);
}
}
protected String getServerName() {
return "SpringSource dm Server";
}
@Override
public IStatus canModifyModules(IModule[] add, IModule[] remove) {
if (add != null) {
int size = add.length;
for (int i = 0; i < size; i++) {
IModule module = add[i];
if (!FacetCorePlugin.WEB_FACET_ID.equals(module.getModuleType().getId())
&& !FacetCorePlugin.BUNDLE_FACET_ID.equals(module.getModuleType().getId())
&& !FacetCorePlugin.PAR_FACET_ID.equals(module.getModuleType().getId())
&& !FacetCorePlugin.PLAN_FACET_ID.equals(module.getModuleType().getId())) {
return new Status(IStatus.ERROR, ServerCorePlugin.PLUGIN_ID, 0, "SpringSource par or bundle projects only", null);
}
IProject project = module.getProject();
// Check that nested par module is not displayed
if (module.getId().endsWith("$" + project.getName())) {
return new Status(IStatus.ERROR, ServerCorePlugin.PLUGIN_ID, 0, "No nested par modules allowed", null);
}
// Check that shared war is only deployed as WAR
try {
if (FacetUtils.hasNature(project, JavaCore.NATURE_ID)
&& FacetedProjectFramework.hasProjectFacet(project, FacetCorePlugin.WEB_FACET_ID) && FacetUtils.isBundleProject(project)
&& FacetCorePlugin.BUNDLE_FACET_ID.equals(module.getModuleType().getId())) {
return new Status(IStatus.ERROR, ServerCorePlugin.PLUGIN_ID, 0, "Shared WAR deploy only as jst.web modules", null);
}
} catch (CoreException e) {
return new Status(IStatus.ERROR, ServerCorePlugin.PLUGIN_ID, 0, "Core Exception when resolving project: ", e);
}
if (getVersionHandler() == null) {
return new Status(IStatus.ERROR, ServerCorePlugin.PLUGIN_ID, 0, "No " + getServerName() + " runtime configured", null);
}
IStatus status = getVersionHandler().canAddModule(module);
if (status != null && !status.isOK()) {
return status;
}
if (module.getProject() == null || !module.getProject().isAccessible()) {
return new Status(IStatus.ERROR, ServerCorePlugin.PLUGIN_ID, 0, "Project not accessible", null);
}
status = FacetUtil.verifyFacets(module.getProject(), getServer());
if (status != null && !status.isOK()) {
return status;
}
}
}
return Status.OK_STATUS;
}
@Override
public void configurationChanged() {
this.configuration = null;
}
@Override
public IModule[] getChildModules(IModule[] module) {
if (module == null) {
return null;
}
IModuleType moduleType = module[0].getModuleType();
if (module.length > 0 && moduleType != null) {
if (FacetCorePlugin.WEB_FACET_ID.equals(moduleType.getId())) {
IWebModule webModule = (IWebModule) module[0].loadAdapter(IWebModule.class, null);
if (webModule != null) {
IModule[] modules = webModule.getModules();
return modules;
}
} else if (FacetCorePlugin.PAR_FACET_ID.equals(moduleType.getId())) {
ServerModuleDelegate parModule = (ServerModuleDelegate) module[0].loadAdapter(ServerModuleDelegate.class, null);
if (parModule != null) {
return parModule.getChildModules();
}
} else if (FacetCorePlugin.PLAN_FACET_ID.equals(moduleType.getId())) {
/*
* To support nested plans now the tooling creates an IModule tree where top level plans have nested
* plans or bundles as children. WTP is passing back the path from the root to a given module as a
* parameter to this method to get the children, so here children are computed only for the last item in
* the list (module.length -1)
**/
ServerModuleDelegate planModule = (ServerModuleDelegate) module[module.length - 1].loadAdapter(ServerModuleDelegate.class, null);
if (planModule != null) {
return planModule.getChildModules();
}
}
}
return new IModule[0];
}
public synchronized IServerConfiguration getConfiguration() {
if (this.configuration == null) {
try {
this.configuration = new ServerConfiguration(getServer().getServerConfiguration());
} catch (IOException e) {
}
}
return this.configuration;
}
public String getDeployDirectory() {
return getAttribute(PROPERTY_DEPLOY_DIR, DEFAULT_DEPLOYDIR);
}
public int getDeployTimeout() {
return getAttribute(PROPERTY_DEPLOY_TIMEOUT, DEFAULT_DEPLOY_TIMEOUT);
}
public String getMBeanServerPassword() {
return getAttribute(PROPERTY_MBEAN_SERVER_PASSWORD, DEFAULT_MBEAN_SERVER_PASSWORD);
}
public int getMBeanServerPort() {
return Integer.valueOf(getAttribute(PROPERTY_MBEAN_SERVER_PORT, DEFAULT_MBEAN_SERVER_PORT));
}
public String getMBeanServerUsername() {
return getAttribute(PROPERTY_MBEAN_SERVER_USERNAME, DEFAULT_MBEAN_SERVER_USERNAME);
}
public String getMaxPermSize() {
return getAttribute(PROPERTY_MAX_PERM_SIZE, DEFAULT_MAX_PERM_SIZE);
}
public IPath getModuleDeployDirectory(IModule module) {
if (FacetCorePlugin.BUNDLE_FACET_ID.equals(module.getModuleType().getId())) {
return getServerDeployDirectory().append(module.getName() + ".jar");
} else if (FacetCorePlugin.PAR_FACET_ID.equals(module.getModuleType().getId())) {
return getServerDeployDirectory().append(module.getName() + ".par");
} else if (FacetCorePlugin.PLAN_FACET_ID.equals(module.getModuleType().getId())) {
return getServerDeployDirectory();
} else {
return getServerDeployDirectory().append(module.getName() + ".war");
}
}
@Override
public IModule[] getRootModules(IModule module) throws CoreException {
if (FacetCorePlugin.WEB_FACET_ID.equals(module.getModuleType().getId())
|| FacetCorePlugin.BUNDLE_FACET_ID.equals(module.getModuleType().getId())
|| FacetCorePlugin.PAR_FACET_ID.equals(module.getModuleType().getId())
|| FacetCorePlugin.PLAN_FACET_ID.equals(module.getModuleType().getId())) {
IStatus status = canModifyModules(new IModule[] { module }, null);
if (status == null || !status.isOK()) {
return new IModule[0];
}
return new IModule[] { module };
}
return new IModule[0];
}
public VirgoServerRuntime getRuntime() {
if (getServer().getRuntime() == null) {
return null;
}
return (VirgoServerRuntime) getServer().getRuntime().loadAdapter(VirgoServerRuntime.class, null);
}
public IPath getRuntimeBaseDirectory() {
IServerRuntimeProvider tvh = getVersionHandler();
if (tvh != null) {
return tvh.getRuntimeBaseDirectory(this.getServer());
}
return null;
}
public IPath getServerDeployDirectory() {
String deployDir = getDeployDirectory();
IPath deployPath = new Path(deployDir);
if (!deployPath.isAbsolute()) {
IPath base = getRuntimeBaseDirectory();
deployPath = base.append(deployPath);
}
// Make sure that stage directory is accessible and we can write into
// it; if we can't the stage will be in the
// plugin's statelocation
File deployPathFile = deployPath.toFile();
if (!deployPathFile.exists() && !deployPathFile.getParentFile().canWrite()) {
deployPath = ServerCorePlugin.getDefault().getStateLocation().append(deployDir);
} else if (deployPathFile.exists() && !deployPathFile.canWrite()) {
deployPath = ServerCorePlugin.getDefault().getStateLocation().append(deployDir);
}
return deployPath;
}
public IServerRuntimeProvider getVersionHandler() {
if (this.versionHandler == null) {
if (getServer().getRuntime() == null || getRuntime() == null) {
return null;
}
this.versionHandler = getRuntime().getVirgoVersion();
}
return this.versionHandler;
}
@Override
public void modifyModules(IModule[] add, IModule[] remove, IProgressMonitor monitor) throws CoreException {
// Add target runtime to new projects in order to refresh their
// classpath based on the
// manifest
if (add != null && add.length > 0) {
// Get the facet runtime which is != the server runtime
IRuntime runtime = RuntimeManager.getRuntime(getRuntime().getRuntime().getName());
if (runtime != null) {
for (IModule addedModule : add) {
IFacetedProject project = ProjectFacetsManager.create(addedModule.getProject(), false, monitor);
if (project != null) {
Set<IRuntime> runtimes = new HashSet<IRuntime>(project.getTargetedRuntimes());
// Add this server's runtime to the target runtime
if (!runtimes.contains(runtime)) {
runtimes.add(runtime);
project.setTargetedRuntimes(runtimes, new SubProgressMonitor(monitor, 1));
if (runtimes.size() > 1) {
project.setPrimaryRuntime(runtime, new SubProgressMonitor(monitor, 1));
}
}
}
}
}
}
// Remove and add the modules to the ordered list
if (remove != null && remove.length > 0) {
for (IModule module : remove) {
getConfiguration().removeArtefact(module.getId());
}
}
if (add != null && add.length > 0) {
for (IModule module : add) {
getConfiguration().addArtefact(module.getId());
}
}
}
public void removeConfigurationChangeListener(PropertyChangeListener listener) {
this.listeners.remove(listener);
}
@Override
public void saveConfiguration(IProgressMonitor monitor) throws CoreException {
if (this.configuration == null) {
return;
}
}
@Override
public void setDefaults(IProgressMonitor monitor) {
setAttribute(PROPERTY_AUTO_PUBLISH_TIME, 2);
}
public void setDeployDirectory(String deployDir) {
setAttribute(PROPERTY_DEPLOY_DIR, deployDir);
}
public void setMBeanServerPassword(String password) {
String oldPassword = getMBeanServerPassword();
setAttribute(PROPERTY_MBEAN_SERVER_PASSWORD, password);
fireConfigurationChanged(PROPERTY_MBEAN_SERVER_PASSWORD, oldPassword, password);
}
public void setMBeanServerPort(int port) {
int oldPort = getMBeanServerPort();
setAttribute(PROPERTY_MBEAN_SERVER_PORT, port);
fireConfigurationChanged(PROPERTY_MBEAN_SERVER_PORT, oldPort, port);
}
public void setDeployTimeout(int timeout) {
int oldTimeout = getDeployTimeout();
setAttribute(PROPERTY_DEPLOY_TIMEOUT, timeout);
fireConfigurationChanged(PROPERTY_DEPLOY_TIMEOUT, oldTimeout, timeout);
}
public void setMBeanServerUsername(String username) {
String oldPassword = getMBeanServerUsername();
setAttribute(PROPERTY_MBEAN_SERVER_USERNAME, username);
fireConfigurationChanged(PROPERTY_MBEAN_SERVER_USERNAME, oldPassword, username);
}
public void setMaxPermSize(String maxPermSize) {
String oldMaxPermSize = getMaxPermSize();
setAttribute(PROPERTY_MAX_PERM_SIZE, maxPermSize);
fireConfigurationChanged(PROPERTY_MAX_PERM_SIZE, oldMaxPermSize, maxPermSize);
}
public boolean shouldTailTraceFiles() {
return getAttribute(PROPERTY_TAIL_LOG_FILES, DEFAULT_TAIL_LOG_FILES);
}
public void shouldTailTraceFiles(boolean shouldTailTraceFiles) {
boolean oldValue = shouldTailTraceFiles();
setAttribute(PROPERTY_TAIL_LOG_FILES, shouldTailTraceFiles);
fireConfigurationChanged(PROPERTY_TAIL_LOG_FILES, oldValue, shouldTailTraceFiles);
}
public boolean shouldCleanStartup() {
return getAttribute(PROPERTY_CLEAN_STARTUP, DEFAULT_CLEAN_STARTUP);
}
public void shouldCleanStartup(boolean shouldCleanStartup) {
boolean oldValue = shouldCleanStartup();
setAttribute(PROPERTY_CLEAN_STARTUP, shouldCleanStartup);
fireConfigurationChanged(PROPERTY_CLEAN_STARTUP, oldValue, shouldCleanStartup);
}
public List<String> getArtefactOrder() {
return getConfiguration().getArtefactOrder();
}
public void setArtefactOrder(List<String> artefactOrder) {
List<String> oldOrder = getArtefactOrder();
getConfiguration().setArtefactOrder(artefactOrder);
fireConfigurationChanged(PROPERTY_ARTEFACT_ORDER, oldOrder, artefactOrder);
}
@Override
public String toString() {
return getServerName();
}
protected void fireConfigurationChanged(String key, Object oldValue, Object newValue) {
PropertyChangeEvent event = new PropertyChangeEvent(this, key, oldValue, newValue);
for (PropertyChangeListener listener : this.listeners) {
listener.propertyChange(event);
}
}
protected String renderCommandLine(String[] commandLine, String separator) {
if (commandLine == null || commandLine.length < 1) {
return "";
}
StringBuffer buf = new StringBuffer(commandLine[0]);
for (int i = 1; i < commandLine.length; i++) {
buf.append(separator);
buf.append(commandLine[i]);
}
return buf.toString();
}
public void setStaticFilenamePatterns(String filenamePatterns) {
String old = getStaticFilenamePatterns();
setAttribute(PROPERTY_STATIC_FILENAMES, filenamePatterns);
fireConfigurationChanged(PROPERTY_STATIC_FILENAMES, old, filenamePatterns);
}
public String getStaticFilenamePatterns() {
return getAttribute(PROPERTY_STATIC_FILENAMES, DEFAULT_STATIC_FILENAMES);
}
}