/*
* Copyright (c) 2007-2009, Osmorc Development Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
* * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS 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
* THE COPYRIGHT OWNER OR 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.
*/
package org.osmorc.run;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.*;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.util.JavaParametersUtil;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.vfs.VfsUtilCore;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osmorc.frameworkintegration.FrameworkInstanceDefinition;
import org.osmorc.frameworkintegration.impl.GenericRunProperties;
import org.osmorc.i18n.OsmorcBundle;
import org.osmorc.run.ui.OsgiRunConfigurationEditor;
import org.osmorc.run.ui.SelectedBundle;
import org.osmorc.settings.ApplicationSettings;
import org.osmorc.settings.ProjectSettings;
import java.util.*;
/**
* A run configuration for an OSGI server.
*
* @author <a href="mailto:janthomae@janthomae.de">Jan Thomä</a>
* @author <a href="mailto:robert@beeger.net">Robert F. Beeger</a>
*/
public class OsgiRunConfiguration extends RunConfigurationBase implements ModuleRunConfiguration {
private static final Logger LOG = Logger.getInstance("#org.osmorc.run.OsgiRunConfiguration");
private static final String BUNDLE_ELEMENT = "bundle";
private static final String NAME_ATTRIBUTE = "name";
private static final String VM_PARAMETERS_ATTRIBUTE = "vmParameters";
private static final String PROGRAM_PARAMETERS_ATTRIBUTE = "programParameters";
private static final String WORKING_DIR_ATTRIBUTE = "workingDir";
private static final String FRAMEWORK_ELEMENT = "framework";
private static final String INSTANCE_ATTRIBUTE = "instance";
private static final String URL_ATTRIBUTE = "url";
private static final String ADDITIONAL_PROPERTIES_ELEMENT = "additionalProperties";
private static final String TYPE_ATTRIBUTE = "type";
private static final String START_AFTER_INSTALLATION_ATTRIBUTE = "startAfterInstallation";
private static final String START_LEVEL_ATTRIBUTE = "startLevel";
private static final String INCLUDE_ALL_BUNDLES_IN_CLASS_PATH_ATTRIBUTE = "includeAllBundlesInClassPath";
private static final String USE_ALTERNATIVE_JRE_ATTRIBUTE = "useAlternativeJre";
private static final String ALTERNATIVE_JRE_PATH = "alternativeJrePath";
private static final String FRAMEWORK_START_LEVEL = "frameworkStartLevel";
private static final String DEFAULT_START_LEVEL = "defaultStartLevel";
private static final String GENERATE_WORKING_DIR_ATTRIBUTE = "generateWorkingDir";
private OsgiRunConfigurationChecker checker;
private List<SelectedBundle> bundlesToDeploy;
private int frameworkStartLevel = 1;
private int defaultStartLevel = 5;
private String programParameters;
private String vmParameters;
private String alternativeJrePath;
private boolean useAlternativeJre;
private FrameworkInstanceDefinition instanceToUse;
private Map<String, String> additionalProperties;
private boolean includeAllBundlesInClassPath;
private String workingDir;
private boolean generateWorkingDir;
public OsgiRunConfiguration(final Project project, final ConfigurationFactory configurationFactory, final String name) {
super(project, configurationFactory, name);
bundlesToDeploy = new ArrayList<>();
additionalProperties = new HashMap<>();
GenericRunProperties.setStartConsole(additionalProperties, true);
}
@Override
@Nullable
public RunConfiguration clone() {
OsgiRunConfiguration conf = (OsgiRunConfiguration)super.clone();
if (conf == null) return null;
conf.bundlesToDeploy = new ArrayList<>(bundlesToDeploy);
conf.additionalProperties = new HashMap<>(additionalProperties);
return conf;
}
@Override
public void readExternal(final Element element) throws InvalidDataException {
workingDir = element.getAttributeValue(WORKING_DIR_ATTRIBUTE);
vmParameters = element.getAttributeValue(VM_PARAMETERS_ATTRIBUTE);
programParameters = element.getAttributeValue(PROGRAM_PARAMETERS_ATTRIBUTE);
includeAllBundlesInClassPath = Boolean.valueOf(element.getAttributeValue(INCLUDE_ALL_BUNDLES_IN_CLASS_PATH_ATTRIBUTE, "false"));
useAlternativeJre = Boolean.valueOf(element.getAttributeValue(USE_ALTERNATIVE_JRE_ATTRIBUTE, "false"));
alternativeJrePath = element.getAttributeValue(ALTERNATIVE_JRE_PATH, "");
generateWorkingDir = Boolean.valueOf(element.getAttributeValue(GENERATE_WORKING_DIR_ATTRIBUTE));
try {
frameworkStartLevel = Integer.parseInt(element.getAttributeValue(FRAMEWORK_START_LEVEL, "1"));
}
catch (NumberFormatException e) {
frameworkStartLevel = 1;
}
try {
defaultStartLevel = Integer.parseInt(element.getAttributeValue(DEFAULT_START_LEVEL, "5"));
}
catch (NumberFormatException e) {
defaultStartLevel = 5;
}
List<Element> children = element.getChildren(BUNDLE_ELEMENT);
bundlesToDeploy.clear();
for (Element child : children) {
String name = child.getAttributeValue(NAME_ATTRIBUTE);
String url = child.getAttributeValue(URL_ATTRIBUTE);
String startLevel = child.getAttributeValue(START_LEVEL_ATTRIBUTE);
String typeName = child.getAttributeValue(TYPE_ATTRIBUTE);
SelectedBundle.BundleType type;
try {
type = SelectedBundle.BundleType.valueOf(typeName);
}
catch (IllegalArgumentException e) {
LOG.error("unexpected bundle type '" + typeName + "'");
type = SelectedBundle.BundleType.Module;
}
String path = url != null ? VfsUtilCore.urlToPath(url) : null;
SelectedBundle selectedBundle = new SelectedBundle(type, name, path);
if (startLevel != null) {
try {
selectedBundle.setStartLevel(Integer.parseInt(startLevel));
}
catch (NumberFormatException ignored) { }
}
String startAfterInstallationString = child.getAttributeValue(START_AFTER_INSTALLATION_ATTRIBUTE);
if (startAfterInstallationString != null) {
selectedBundle.setStartAfterInstallation(Boolean.parseBoolean(startAfterInstallationString));
}
bundlesToDeploy.add(selectedBundle);
}
// try to load the framework instance
Element framework = element.getChild(FRAMEWORK_ELEMENT);
if (framework != null) {
String name = framework.getAttributeValue(INSTANCE_ATTRIBUTE);
if (name != null) {
ApplicationSettings settings = ServiceManager.getService(ApplicationSettings.class);
instanceToUse = settings.getFrameworkInstance(name);
}
}
Element additionalProperties = element.getChild(ADDITIONAL_PROPERTIES_ELEMENT);
if (additionalProperties == null) {
//noinspection SpellCheckingInspection
additionalProperties = element.getChild("additinalProperties");
}
if (additionalProperties != null) {
List<Attribute> attributes = additionalProperties.getAttributes();
for (Attribute attribute : attributes) {
this.additionalProperties.put(attribute.getName(), attribute.getValue());
}
}
super.readExternal(element);
}
@Override
public void writeExternal(final Element element) throws WriteExternalException {
// store the vm parameters
element.setAttribute(VM_PARAMETERS_ATTRIBUTE, vmParameters == null ? "" : vmParameters);
element.setAttribute(PROGRAM_PARAMETERS_ATTRIBUTE, programParameters == null ? "" : programParameters);
element.setAttribute(INCLUDE_ALL_BUNDLES_IN_CLASS_PATH_ATTRIBUTE, Boolean.toString(includeAllBundlesInClassPath));
element.setAttribute(WORKING_DIR_ATTRIBUTE, workingDir == null ? "" : workingDir);
element.setAttribute(USE_ALTERNATIVE_JRE_ATTRIBUTE, String.valueOf(useAlternativeJre));
element.setAttribute(ALTERNATIVE_JRE_PATH, alternativeJrePath != null ? alternativeJrePath : "");
element.setAttribute(FRAMEWORK_START_LEVEL, String.valueOf(frameworkStartLevel));
element.setAttribute(DEFAULT_START_LEVEL, String.valueOf(defaultStartLevel));
element.setAttribute(GENERATE_WORKING_DIR_ATTRIBUTE, String.valueOf(generateWorkingDir));
// all module's names
for (SelectedBundle selectedBundle : bundlesToDeploy) {
Element bundle = new Element(BUNDLE_ELEMENT);
bundle.setAttribute(NAME_ATTRIBUTE, selectedBundle.getName());
if (!selectedBundle.isModule()) {
String path = selectedBundle.getBundlePath();
if (path != null) bundle.setAttribute(URL_ATTRIBUTE, VfsUtilCore.pathToUrl(path));
}
bundle.setAttribute(START_LEVEL_ATTRIBUTE, String.valueOf(selectedBundle.getStartLevel()));
bundle.setAttribute(TYPE_ATTRIBUTE, selectedBundle.getBundleType().name());
bundle.setAttribute(START_AFTER_INSTALLATION_ATTRIBUTE, Boolean.toString(selectedBundle.isStartAfterInstallation()));
element.addContent(bundle);
}
// and the instance to use
Element framework = new Element(FRAMEWORK_ELEMENT);
framework.setAttribute(INSTANCE_ATTRIBUTE, instanceToUse != null ? instanceToUse.getName() : "");
element.addContent(framework);
Element additionalProperties = new Element(ADDITIONAL_PROPERTIES_ELEMENT);
for (String additionalPropertyName : this.additionalProperties.keySet()) {
additionalProperties.setAttribute(additionalPropertyName, this.additionalProperties.get(additionalPropertyName));
}
element.addContent(additionalProperties);
super.writeExternal(element);
}
@NotNull
@Override
public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
return new OsgiRunConfigurationEditor(getProject());
}
@Override
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
return new OsgiRunState(env, this);
}
@Override
public void checkConfiguration() throws RuntimeConfigurationException {
if (getInstanceToUse() == null) {
throw new RuntimeConfigurationError(OsmorcBundle.message("run.configuration.no.instance"));
}
if (isUseAlternativeJre()) {
JavaParametersUtil.checkAlternativeJRE(getAlternativeJrePath());
}
if (checker != null) {
checker.checkConfiguration(this);
}
}
@NotNull
@Override
public Module[] getModules() {
List<Module> modules = new ArrayList<>();
ModuleManager moduleManager = ModuleManager.getInstance(getProject());
for (SelectedBundle selectedBundle : getBundlesToDeploy()) {
if (selectedBundle.isModule()) {
Module module = moduleManager.findModuleByName(selectedBundle.getName());
if (module != null) {
modules.add(module);
}
else {
LOG.error("no module [" + selectedBundle.getName() + "]");
}
}
}
return modules.toArray(new Module[modules.size()]);
}
@NotNull
public Map<String, String> getAdditionalProperties() {
return Collections.unmodifiableMap(additionalProperties);
}
public String getAlternativeJrePath() {
return alternativeJrePath;
}
@NotNull
public List<SelectedBundle> getBundlesToDeploy() {
return bundlesToDeploy;
}
public int getFrameworkStartLevel() {
return frameworkStartLevel;
}
@Nullable
public FrameworkInstanceDefinition getInstanceToUse() {
if (instanceToUse != null) return instanceToUse;
String projectInstanceName = ProjectSettings.getInstance(getProject()).getFrameworkInstanceName();
FrameworkInstanceDefinition projectInstance = ApplicationSettings.getInstance().getFrameworkInstance(projectInstanceName);
if (projectInstance != null) return projectInstance;
return null;
}
public String getProgramParameters() {
return programParameters != null ? programParameters : "";
}
@NotNull
public String getVmParameters() {
return vmParameters != null ? vmParameters : "";
}
public String getWorkingDir() {
return workingDir != null ? workingDir : "";
}
public boolean isAutoStartLevel() {
return frameworkStartLevel == 0;
}
public boolean isIncludeAllBundlesInClassPath() {
return includeAllBundlesInClassPath;
}
public boolean isUseAlternativeJre() {
return useAlternativeJre;
}
public void putAdditionalProperties(@NotNull Map<String, String> props) {
additionalProperties.putAll(props);
}
public void setAdditionalChecker(@Nullable OsgiRunConfigurationChecker checker) {
this.checker = checker;
}
public void setAlternativeJrePath(String alternativeJrePath) {
this.alternativeJrePath = alternativeJrePath;
}
public void setBundlesToDeploy(final List<SelectedBundle> bundlesToDeploy) {
this.bundlesToDeploy = bundlesToDeploy;
}
public void setFrameworkStartLevel(int frameworkStartLevel) {
this.frameworkStartLevel = frameworkStartLevel;
}
public void setIncludeAllBundlesInClassPath(final boolean includeAllBundlesInClassPath) {
this.includeAllBundlesInClassPath = includeAllBundlesInClassPath;
}
public void setInstanceToUse(@Nullable FrameworkInstanceDefinition instanceToUse) {
this.instanceToUse = instanceToUse;
}
public void setProgramParameters(final String programParameters) {
this.programParameters = programParameters;
}
public void setUseAlternativeJre(boolean useAlternativeJre) {
this.useAlternativeJre = useAlternativeJre;
}
public void setVmParameters(final String vmParameters) {
this.vmParameters = vmParameters;
}
public void setWorkingDir(final String workingDir) {
this.workingDir = workingDir;
}
public int getDefaultStartLevel() {
return defaultStartLevel;
}
public void setDefaultStartLevel(int defaultStartLevel) {
this.defaultStartLevel = defaultStartLevel;
}
/**
* Should the working directory be regenerated on run or not?
*/
public boolean isGenerateWorkingDir() {
return generateWorkingDir;
}
public void setGenerateWorkingDir(boolean generateWorkingDir) {
this.generateWorkingDir = generateWorkingDir;
}
}