blob: b33b0d73a39ce706cc6737e50b9b30fa6a40cc76 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2015 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
* Manumitting Technologies Inc - bug 437726: wrong error messages opening target definition
*******************************************************************************/
package org.eclipse.pde.internal.core.target;
import java.io.File;
import java.io.IOException;
import org.eclipse.core.runtime.*;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.equinox.internal.provisional.frameworkadmin.*;
import org.eclipse.pde.core.target.*;
import org.eclipse.pde.internal.core.PDECore;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
/**
* Common function for bundle containers.
*
* @since 3.5
*/
public abstract class AbstractBundleContainer extends PlatformObject implements ITargetLocation {
/**
* Resolved bundles or <code>null</code> if unresolved
*/
protected TargetBundle[] fBundles;
/**
* List of target features contained in this bundle container or <code>null</code> if unresolved
*/
protected TargetFeature[] fFeatures;
/**
* Status generated when this container was resolved, possibly <code>null</code>
*/
protected IStatus fResolutionStatus;
/**
* The Java VM Arguments specified by this bundle container
*/
private String[] fVMArgs;
/**
* Resolves any string substitution variables in the given text returning
* the result.
*
* @param text text to resolve
* @return result of the resolution
* @throws CoreException if unable to resolve
*/
protected String resolveVariables(String text) throws CoreException {
IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
return manager.performStringSubstitution(text);
}
/* (non-Javadoc)
* @see org.eclipse.pde.core.target.ITargetLocation#isResolved()
*/
public final boolean isResolved() {
return fResolutionStatus != null && fResolutionStatus.getSeverity() != IStatus.CANCEL;
}
/* (non-Javadoc)
* @see org.eclipse.pde.core.target.ITargetLocation#resolve(org.eclipse.pde.core.target.ITargetDefinition, org.eclipse.core.runtime.IProgressMonitor)
*/
public final IStatus resolve(ITargetDefinition definition, IProgressMonitor monitor) {
int resolveBundlesWork = getResolveBundlesWork();
int resolveFeaturesWork = getResolveFeaturesWork();
SubMonitor subMonitor = SubMonitor.convert(monitor, resolveBundlesWork + resolveFeaturesWork);
try {
fResolutionStatus = Status.OK_STATUS;
fBundles = resolveBundles(definition, subMonitor.newChild(resolveBundlesWork));
fFeatures = resolveFeatures(definition, subMonitor.newChild(resolveFeaturesWork));
if (subMonitor.isCanceled()) {
fBundles = null;
fResolutionStatus = Status.CANCEL_STATUS;
}
} catch (CoreException e) {
fBundles = new TargetBundle[0];
fFeatures = new TargetFeature[0];
fResolutionStatus = e.getStatus();
} finally {
subMonitor.done();
if (monitor != null) {
monitor.done();
}
}
return fResolutionStatus;
}
/**
* Can be overridden in subclasses to redistribute the work between {@link #resolveBundles(ITargetDefinition, IProgressMonitor)}
* and {@link #resolveFeatures(ITargetDefinition, IProgressMonitor)}.
*
* @return the value 100, making {@link #resolveFeatures(ITargetDefinition, IProgressMonitor)} consume two thirds of
* the overall work being done in {@link #resolve(ITargetDefinition, IProgressMonitor)}.
* @see #getResolveFeaturesWork()
*/
protected int getResolveBundlesWork() {
return 100;
}
/**
* Can be overridden in subclasses to redistribute the work between {@link #resolveBundles(ITargetDefinition, IProgressMonitor)}
* and {@link #resolveFeatures(ITargetDefinition, IProgressMonitor)}.
*
* @return the value 50, making {@link #resolveFeatures(ITargetDefinition, IProgressMonitor)} consume one third of
* the overall work being done in {@link #resolve(ITargetDefinition, IProgressMonitor)}.
* @see #getResolveBundlesWork()
*/
protected int getResolveFeaturesWork() {
return 50;
}
/* (non-Javadoc)
* @see org.eclipse.pde.core.target.ITargetLocation#getStatus()
*/
public IStatus getStatus() {
if (!isResolved()) {
return null;
}
return fResolutionStatus;
}
/* (non-Javadoc)
* @see org.eclipse.pde.core.target.ITargetLocation#getBundles()
*/
public final TargetBundle[] getBundles() {
if (isResolved()) {
return fBundles;
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.pde.core.target.ITargetLocation#getFeatures()
*/
public TargetFeature[] getFeatures() {
if (isResolved()) {
return fFeatures;
}
return null;
}
/**
* Resolves all source and executable bundles in this container
* <p>
* Subclasses must implement this method.
* </p><p>
* <code>beginTask()</code> and <code>done()</code> will be called on the given monitor by the caller.
* </p>
* @param definition target context
* @param monitor progress monitor
* @return all source and executable bundles in this container
* @throws CoreException if an error occurs
*/
protected abstract TargetBundle[] resolveBundles(ITargetDefinition definition, IProgressMonitor monitor) throws CoreException;
/**
* Collects all of the features in this container. May return an empty array if {@link #resolveBundles(ITargetDefinition, IProgressMonitor)}
* has not been called previously.
* <p>
* Subclasses must implement this method.
* </p><p>
* <code>beginTask()</code> and <code>done()</code> will be called on the given monitor by the caller.
* </p>
* @param definition target context
* @param monitor progress monitor
* @return all features in this container
* @throws CoreException if an error occurs
*/
protected abstract TargetFeature[] resolveFeatures(ITargetDefinition definition, IProgressMonitor monitor) throws CoreException;
/**
* Returns a string that identifies the type of bundle container. This type is persisted to xml
* so that the correct bundle container is created when deserializing the xml. This type is also
* used to alter how the containers are presented to the user in the UI.
*
* @return string identifier for the type of bundle container.
*/
public abstract String getType();
/**
* Returns a path in the local file system to the root of the bundle container.
* <p>
* TODO: Ideally we won't need this method. Currently the PDE target platform preferences are
* based on a home location and additional locations, so we need the information.
* </p>
* @param resolve whether to resolve variables in the path
* @return home location
* @exception CoreException if unable to resolve the location
*/
public abstract String getLocation(boolean resolve) throws CoreException;
/**
* Sets the resolution status to null. This container will be considered unresolved.
*/
protected void clearResolutionStatus() {
fResolutionStatus = null;
}
/* (non-Javadoc)
* @see org.eclipse.pde.core.target.ITargetLocation#getVMArguments()
*/
public String[] getVMArguments() {
String FWK_ADMIN_EQ = "org.eclipse.equinox.frameworkadmin.equinox"; //$NON-NLS-1$
if (fVMArgs == null) {
try {
FrameworkAdmin fwAdmin = (FrameworkAdmin) PDECore.getDefault().acquireService(FrameworkAdmin.class.getName());
if (fwAdmin == null) {
Bundle fwAdminBundle = Platform.getBundle(FWK_ADMIN_EQ);
if (fwAdminBundle != null) {
fwAdminBundle.start();
fwAdmin = (FrameworkAdmin) PDECore.getDefault().acquireService(FrameworkAdmin.class.getName());
}
}
if (fwAdmin != null) {
Manipulator manipulator = fwAdmin.getManipulator();
ConfigData configData = new ConfigData(null, null, null, null);
String home = getLocation(true);
manipulator.getLauncherData().setLauncher(new File(home, "eclipse")); //$NON-NLS-1$
File installDirectory = new File(home);
// if (Platform.getOS().equals(Platform.OS_MACOSX))
// installDirectory = new File(installDirectory, "Eclipse.app/Contents/MacOS"); //$NON-NLS-1$
manipulator.getLauncherData().setLauncherConfigLocation(new File(installDirectory, "eclipse.ini")); //$NON-NLS-1$
manipulator.getLauncherData().setHome(new File(home));
manipulator.setConfigData(configData);
manipulator.load();
fVMArgs = manipulator.getLauncherData().getJvmArgs();
}
} catch (BundleException e) {
PDECore.log(e);
} catch (CoreException e) {
PDECore.log(e);
} catch (IOException e) {
PDECore.log(e);
}
}
if (fVMArgs == null || fVMArgs.length == 0) {
return null;
}
return fVMArgs;
}
/**
* Associate this bundle container with the given target. This allows for the container and
* the target to share configuration information etc.
*
* @param target the target to which this container is being added.
*/
protected void associateWithTarget(ITargetDefinition target) {
// Do nothing by default
}
/* (non-Javadoc)
* @see org.eclipse.pde.core.target.ITargetLocation#serialize()
*/
public String serialize() {
// The default implementation returns null as most containers do not use the new UI
return null;
}
}