/*
* 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.ExecutionBundle;
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.runners.ProgramRunner;
import com.intellij.openapi.components.ServiceManager;
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.projectRoots.impl.JavaSdkImpl;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
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 java.util.*;
/**
* A run configuration for an OSGI server.
*
* @author <a href="mailto:janthomae@janthomae.de">Jan Thomä</a>
* @author Robert F. Beeger (robert@beeger.net)
* @version $Id$
*/
public class OsgiRunConfiguration extends RunConfigurationBase implements ModuleRunConfiguration {
@NonNls
private static final String BUNDLE_ELEMENT = "bundle";
@NonNls
private static final String NAME_ATTRIBUTE = "name";
@NonNls
private static final String VM_PARAMETERS_ATTRIBUTE = "vmParameters";
@NonNls
private static final String PROGRAM_PARAMETERS_ATTRIBUTE = "programParameters";
@NonNls
private static final String WORKING_DIR_ATTRIBUTE = "workingDir";
@NonNls
private static final String FRAMEWORK_ELEMENT = "framework";
@NonNls
private static final String INSTANCE_ATTRIBUTE = "instance";
@NonNls
private static final String URL_ATTRIBUTE = "url";
@NonNls
private static final String ADDITIONAL_PROPERTIES_ELEMENT = "additinalProperties";
@NonNls
private static final String TYPE_ATTRIBUTE = "type";
@NonNls
private static final String START_AFTER_INSTALLATION_ATTRIBUTE = "startAfterInstallation";
@NonNls
private static final String START_LEVEL_ATTRIBUTE = "startLevel";
@NonNls
private static final String INCLUDE_ALL_BUNDLES_IN_CLASS_PATH_ATTRIBUTE = "includeAllBundlesInClassPath";
@NonNls
private static final String USE_ALTERNATIVE_JRE_ATTRIBUTE = "useAlternativeJre";
@NonNls
private static final String ALTERNATIVE_JRE_PATH = "alternativeJrePath";
@NonNls
private static final String FRAMEWORK_START_LEVEL = "frameworkStartLevel";
@NonNls
private static final String DEFAULT_START_LEVEL = "defaultStartLevel";
@NonNls
public static final String GENERATE_WORKING_DIR_ATTRIBUTE = "generateWorkingDir";
@Nullable
private OsgiRunConfigurationChecker checker;
private LegacyOsgiRunConfigurationLoader legacyOsgiRunConfigurationLoader;
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<SelectedBundle>();
additionalProperties = new HashMap<String, String>();
additionalProperties.put(GenericRunProperties.START_CONSOLE, String.valueOf(true));
}
@Override
@Nullable
public RunConfiguration clone() {
OsgiRunConfiguration conf = (OsgiRunConfiguration)super.clone();
if (conf == null) {
return conf;
}
conf.bundlesToDeploy = new ArrayList<SelectedBundle>(bundlesToDeploy);
conf.additionalProperties = new HashMap<String, String>(additionalProperties);
return conf;
}
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));
String fwsl = element.getAttributeValue(FRAMEWORK_START_LEVEL);
if (fwsl != null) {
try {
frameworkStartLevel = Integer.parseInt(fwsl);
}
catch (NumberFormatException e) {
frameworkStartLevel = 1;
}
}
String dfsl = element.getAttributeValue(DEFAULT_START_LEVEL);
if ( dfsl != null ) {
try {
defaultStartLevel = Integer.parseInt(dfsl);
}
catch( NumberFormatException e) {
defaultStartLevel = 5;
}
}
// noinspection unchecked
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);
if ("legacyLoader".equals(name)) {
try {
legacyOsgiRunConfigurationLoader = (LegacyOsgiRunConfigurationLoader)Class.forName(url).newInstance();
}
catch (InstantiationException e) {
throw new InvalidDataException(e);
}
catch (IllegalAccessException e) {
throw new InvalidDataException(e);
}
catch (ClassNotFoundException e) {
throw new InvalidDataException(e);
}
break;
}
SelectedBundle.BundleType type;
try {
type = SelectedBundle.BundleType.valueOf(typeName);
}
catch (Exception e) {
// legacy settings should have modules, only so this is a safe guess.
type = SelectedBundle.BundleType.Module;
}
SelectedBundle selectedBundle = new SelectedBundle(name, url, type);
if (startLevel != null) { // avoid crashing on legacy settings.
try {
selectedBundle.setStartLevel(Integer.parseInt(startLevel));
}
catch (NumberFormatException e) {
// ok.
}
}
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 unchecked
List<Attribute> attributes = additionalProperties.getAttributes();
for (Attribute attribute : attributes) {
this.additionalProperties.put(attribute.getName(), attribute.getValue());
}
}
super.readExternal(element);
}
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()) {
bundle.setAttribute(URL_ATTRIBUTE, selectedBundle.getBundleUrl());
}
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);
}
public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
return new OsgiRunConfigurationEditor(getProject());
}
@SuppressWarnings({"deprecation"})
public JDOMExternalizable createRunnerSettings(final ConfigurationInfoProvider configurationInfoProvider) {
return null;
}
@SuppressWarnings({"deprecation"})
public SettingsEditor<JDOMExternalizable> getRunnerSettingsEditor(final ProgramRunner runner) {
return null;
}
public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException {
// prepare the state
return new OsgiRunState(executor, env, this, getProject(), ProjectRootManager.getInstance(getProject()).getProjectSdk());
}
public void checkConfiguration() throws RuntimeConfigurationException {
if (legacyOsgiRunConfigurationLoader != null) {
legacyOsgiRunConfigurationLoader.finishAfterModulesAreAvailable(this);
legacyOsgiRunConfigurationLoader = null;
}
if (instanceToUse == null) {
throw new RuntimeConfigurationError(OsmorcBundle.getTranslation("runconfiguration.no.instance.selected"));
}
if (isUseAlternativeJre()) {
final String jrePath = this.getAlternativeJrePath();
if (jrePath == null || jrePath.length() == 0 || !JavaSdkImpl.checkForJre(jrePath)) {
throw new RuntimeConfigurationWarning(ExecutionBundle.message("jre.not.valid.error.message", jrePath));
}
}
if (checker != null) {
checker.checkConfiguration(this);
}
}
@NotNull
public Module[] getModules() {
List<Module> modules = new ArrayList<Module>();
for (SelectedBundle selectedBundle : getBundlesToDeploy()) {
if (selectedBundle.isModule()) {
modules.add(ModuleManager.getInstance(getProject()).findModuleByName(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() {
return instanceToUse;
}
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 final 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(@NotNull final 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;
}
}