| /******************************************************************************* |
| * Copyright (c) 2000, 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: |
| * GmbH - internationalization implementation (bug 150933) |
| *******************************************************************************/ |
| package org.eclipse.pde.internal.build.builder; |
| |
| import java.io.File; |
| import java.util.*; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.equinox.p2.publisher.eclipse.Feature; |
| import org.eclipse.equinox.p2.publisher.eclipse.FeatureEntry; |
| import org.eclipse.osgi.service.resolver.BundleDescription; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.pde.internal.build.*; |
| import org.eclipse.pde.internal.build.builder.ClasspathComputer3_0.ClasspathElement; |
| import org.eclipse.pde.internal.build.site.BuildTimeFeature; |
| import org.osgi.framework.Version; |
| |
| /** |
| * Generates build.xml script for features. |
| */ |
| public class BuildDirector extends AbstractBuildScriptGenerator { |
| |
| private static final int QUALIFIER_SUFFIX_VERSION = 2; |
| |
| // GENERATION FLAGS |
| /** |
| * Indicates whether scripts for this feature included features should be |
| * generated. |
| */ |
| protected boolean analyseIncludedFeatures = false; |
| /** |
| * Indicates whether scripts for this feature children' should be |
| * generated. |
| */ |
| protected boolean analysePlugins = true; |
| /** Indicates whether the feature is binary */ |
| protected boolean binaryFeature = true; |
| /** Indicates if the build scripts files should be produced or not */ |
| private boolean scriptGeneration = true; |
| |
| //FEATURE RELATED INFORMATION |
| /** The identifier of the feature that the build script is being generated for. */ |
| protected String featureIdentifier; |
| protected String searchedVersion; |
| |
| protected SourceFeatureInformation sourceToGather = new SourceFeatureInformation(); |
| private boolean generateVersionSuffix = false; |
| protected boolean signJars = false; |
| protected String product = null; |
| protected boolean generateJnlp = false; |
| protected boolean workspaceBinaries = false; |
| private boolean sourceReferences = false; |
| |
| public static boolean p2Gathering = false; |
| |
| public BuildDirector() { |
| super(); |
| } |
| |
| /** |
| * Constructor FeatureBuildScriptGenerator. |
| */ |
| public BuildDirector(String featureId, String versionId, AssemblyInformation informationGathering) throws CoreException { |
| if (featureId == null) { |
| throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_FEATURE_MISSING, Messages.error_missingFeatureId, null)); |
| } |
| this.featureIdentifier = featureId; |
| this.searchedVersion = versionId; |
| assemblyData = informationGathering; |
| } |
| |
| public BuildDirector(AssemblyInformation assemblageInformation) { |
| this.assemblyData = assemblageInformation; |
| } |
| |
| private final Map<String, String> extractedLocations = new HashMap<String, String>(); |
| |
| public String getExtractedRoot(ClasspathElement element) { |
| if (element.getSubPath() == null) |
| return element.getPath(); |
| |
| String absolute = element.getAbsolutePath(); |
| if (extractedLocations.containsKey(absolute)) { |
| return extractedLocations.get(absolute); |
| } |
| |
| //Use the jar name, append a suffix if that name is already taken |
| String name = new File(absolute).getName(); |
| if (name.endsWith(".jar")) //$NON-NLS-1$ |
| name = name.substring(0, name.length() - 4); |
| String destination = name; |
| while (extractedLocations.containsValue(destination)) { |
| destination = name + '_' + Integer.toHexString(destination.hashCode()); |
| } |
| |
| extractedLocations.put(absolute, destination); |
| return destination; |
| } |
| |
| /** |
| * Returns a list of BundleDescription objects representing the elements delivered by the feature. |
| * |
| * @return List of BundleDescription |
| * @throws CoreException |
| */ |
| protected Set<BundleDescription> computeElements(BuildTimeFeature feature) throws CoreException { |
| Set<BundleDescription> computedElements = new LinkedHashSet<BundleDescription>(5); |
| Properties featureProperties = getBuildProperties(feature); |
| FeatureEntry[] pluginList = feature.getPluginEntries(); |
| for (int i = 0; i < pluginList.length; i++) { |
| FeatureEntry entry = pluginList[i]; |
| BundleDescription model; |
| if (selectConfigs(entry).size() == 0) |
| continue; |
| |
| String versionRequested = entry.getVersion(); |
| model = getSite(false).getRegistry().getResolvedBundle(entry.getId(), versionRequested); |
| //we prefer a newly generated source plugin over a preexisting binary one. |
| if ((model == null || Utils.isBinary(model)) && featureProperties.containsKey(GENERATION_SOURCE_PLUGIN_PREFIX + entry.getId())) { |
| boolean individual = useIndividualSource(featureProperties); |
| String[] extraEntries = Utils.getArrayFromString(featureProperties.getProperty(GENERATION_SOURCE_PLUGIN_PREFIX + entry.getId())); |
| if (individual) { |
| BundleDescription originalBundle = getSite(false).getRegistry().getResolvedBundle(extraEntries[0]); |
| if (originalBundle != null) { |
| if (!Utils.isBinary(originalBundle)) |
| generateEmbeddedSource(entry, extraEntries, individual); |
| else if (model == null) { |
| String message = NLS.bind(Messages.exception_unableToGenerateSourceFromBinary, entry.getId(), originalBundle.getSymbolicName() + "_" + originalBundle.getVersion()); //$NON-NLS-1$ |
| IStatus status = new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PLUGIN_MISSING, message, null); |
| throw new CoreException(status); |
| } |
| } |
| } else { |
| generateEmbeddedSource(entry, extraEntries, individual); |
| } |
| model = getSite(false).getRegistry().getResolvedBundle(entry.getId(), versionRequested); |
| } |
| if (model == null) { |
| getSite(false).missingPlugin(entry.getId(), versionRequested, feature, true); |
| } |
| |
| associateModelAndEntry(model, entry); |
| |
| computedElements.add(model); |
| collectElementToAssemble(pluginList[i]); |
| } |
| return computedElements; |
| } |
| |
| private boolean useIndividualSource(Properties featureProperties) { |
| boolean individual = Boolean.valueOf(featureProperties.getProperty(PROPERTY_INDIVIDUAL_SOURCE)).booleanValue(); |
| return individual || AbstractScriptGenerator.getPropertyAsBoolean(PROPERTY_INDIVIDUAL_SOURCE); |
| } |
| |
| // As properties can only contain strings, it isn't clear how this code worked, leaving as is but surpressing the warnings |
| @SuppressWarnings({"rawtypes", "unchecked"}) |
| private void associateModelAndEntry(BundleDescription model, FeatureEntry entry) { |
| Properties bundleProperties = ((Properties) model.getUserObject()); |
| if (bundleProperties == null) { |
| bundleProperties = new Properties(); |
| model.setUserObject(bundleProperties); |
| } |
| Set<FeatureEntry> entries = (Set) bundleProperties.get(PLUGIN_ENTRY); |
| if (entries == null) { |
| entries = new HashSet<FeatureEntry>(); |
| bundleProperties.put(PLUGIN_ENTRY, entries); |
| } |
| entries.add(entry); |
| } |
| |
| private void generateEmbeddedSource(FeatureEntry pluginEntry, String[] extraEntries, boolean individual) throws CoreException { |
| if (individual) { |
| BundleDescription originalBundle = getSite(false).getRegistry().getResolvedBundle(extraEntries[0]); |
| if (originalBundle != null) { |
| SourceGenerator sourceGenerator = new SourceGenerator(); |
| sourceGenerator.setExtraEntries(extraEntries); |
| sourceGenerator.setDirector(this); |
| sourceGenerator.setIndividual(individual); |
| sourceGenerator.generateSourcePlugin(pluginEntry, originalBundle); |
| return; |
| } |
| } |
| /* else do it the old way */ |
| BuildTimeFeature baseFeature = getSite(false).findFeature(extraEntries[0], null, true); |
| if (baseFeature != null) |
| generateSourceFeature(baseFeature, pluginEntry.getId(), extraEntries, false); |
| } |
| |
| /** |
| * Set the boolean for whether or not children scripts should be generated. |
| * |
| * @param generate |
| * <code>true</code> if the children scripts should be |
| * generated, <code>false</code> otherwise |
| */ |
| public void setAnalyseChildren(boolean generate) { |
| analysePlugins = generate; |
| } |
| |
| @Override |
| public void generate() throws CoreException { |
| if (workingDirectory == null) { |
| throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_BUILDDIRECTORY_LOCATION_MISSING, Messages.error_missingInstallLocation, null)); |
| } |
| |
| BuildTimeFeature feature = getSite(false).findFeature(featureIdentifier, searchedVersion, true); |
| generate(feature); |
| } |
| |
| /** |
| * @see AbstractScriptGenerator#generate() |
| */ |
| public void generate(BuildTimeFeature feature) throws CoreException { |
| generate(feature, true); |
| } |
| |
| protected void generate(BuildTimeFeature feature, boolean generateProductFiles) throws CoreException { |
| if (analyseIncludedFeatures) |
| generateIncludedFeatureBuildFile(feature); |
| if (analysePlugins) |
| generateChildrenScripts(feature); |
| |
| collectElementToAssemble(feature); |
| |
| if (scriptGeneration) { |
| FeatureBuildScriptGenerator featureScriptGenerator = new FeatureBuildScriptGenerator(feature); |
| featureScriptGenerator.setDirector(this); |
| featureScriptGenerator.setBuildSiteFactory(siteFactory); |
| featureScriptGenerator.setGenerateProductFiles(generateProductFiles); |
| featureScriptGenerator.generate(); |
| } |
| } |
| |
| protected void generateSourceFeature(BuildTimeFeature baseFeature, String sourceFeatureName, String[] extraEntries, boolean individual) throws CoreException { |
| SourceGenerator sourceGenerator = new SourceGenerator(); |
| sourceGenerator.setExtraEntries(extraEntries); |
| sourceGenerator.setDirector(this); |
| sourceGenerator.setIndividual(individual); |
| sourceGenerator.generateSourceFeature(baseFeature, sourceFeatureName); |
| } |
| |
| protected void generateIncludedFeatureBuildFile(BuildTimeFeature feature) throws CoreException { |
| FeatureEntry[] referencedFeatures = feature.getIncludedFeatureReferences(); |
| for (int i = 0; i < referencedFeatures.length; i++) { |
| String featureId = referencedFeatures[i].getId(); |
| String featureVersion = referencedFeatures[i].getVersion(); |
| |
| BuildTimeFeature nestedFeature = null; |
| Properties featureProperties = getBuildProperties(feature); |
| boolean doSourceFeatureGeneration = featureProperties.containsKey(GENERATION_SOURCE_FEATURE_PREFIX + featureId); |
| if (doSourceFeatureGeneration) { |
| String[] extraEntries = Utils.getArrayFromString(featureProperties.getProperty(GENERATION_SOURCE_FEATURE_PREFIX + featureId)); |
| nestedFeature = getSite(false).findFeature(extraEntries[0], featureVersion, true); |
| generateSourceFeature(nestedFeature, featureId, extraEntries, useIndividualSource(featureProperties)); |
| } |
| |
| try { |
| nestedFeature = getSite(false).findFeature(featureId, featureVersion, true); |
| generate(nestedFeature, false); |
| } catch (CoreException exception) { |
| absorbExceptionIfOptionalFeature(referencedFeatures[i], exception); |
| } |
| } |
| } |
| |
| private void absorbExceptionIfOptionalFeature(FeatureEntry entry, CoreException toAbsorb) throws CoreException { |
| if (toAbsorb.getStatus().getCode() != EXCEPTION_FEATURE_MISSING || (toAbsorb.getStatus().getCode() == EXCEPTION_FEATURE_MISSING && !entry.isOptional())) |
| throw toAbsorb; |
| } |
| |
| /** |
| * @throws CoreException |
| */ |
| private void generateChildrenScripts(BuildTimeFeature feature) throws CoreException { |
| Set<BundleDescription> plugins = computeElements(feature); |
| String suffix = generateFeatureVersionSuffix(feature); |
| if (suffix != null) { |
| Version versionId = new Version(feature.getVersion()); |
| String qualifier = versionId.getQualifier(); |
| qualifier = qualifier.substring(0, feature.getContextQualifierLength()); |
| qualifier = qualifier + '-' + suffix; |
| versionId = new Version(versionId.getMajor(), versionId.getMinor(), versionId.getMicro(), qualifier); |
| String newVersion = versionId.toString(); |
| feature.setVersion(newVersion); |
| //initializeFeatureNames(); //reset our variables |
| } |
| generateModels(Utils.extractPlugins(getSite(false).getRegistry().getSortedBundles(), plugins)); |
| } |
| |
| // Encode a non-negative number as a variable length string, with the |
| // property that if X > Y then the encoding of X is lexicographically |
| // greater than the enocding of Y. This is accomplished by encoding the |
| // length of the string at the beginning of the string. The string is a |
| // series of base 64 (6-bit) characters. The first three bits of the first |
| // character indicate the number of additional characters in the string. |
| // The last three bits of the first character and all of the rest of the |
| // characters encode the actual value of the number. Examples: |
| // 0 --> 000 000 --> "-" |
| // 7 --> 000 111 --> "6" |
| // 8 --> 001 000 001000 --> "77" |
| // 63 --> 001 000 111111 --> "7z" |
| // 64 --> 001 001 000000 --> "8-" |
| // 511 --> 001 111 111111 --> "Dz" |
| // 512 --> 010 000 001000 000000 --> "E7-" |
| // 2^32 - 1 --> 101 011 111111 ... 111111 --> "fzzzzz" |
| // 2^45 - 1 --> 111 111 111111 ... 111111 --> "zzzzzzzz" |
| // (There are some wasted values in this encoding. For example, |
| // "7-" through "76" and "E--" through "E6z" are not legal encodings of |
| // any number. But the benefit of filling in those wasted ranges would not |
| // be worth the added complexity.) |
| private static String lengthPrefixBase64(long number) { |
| int length = 7; |
| for (int i = 0; i < 7; ++i) { |
| if (number < (1L << ((i * 6) + 3))) { |
| length = i; |
| break; |
| } |
| } |
| StringBuffer result = new StringBuffer(length + 1); |
| result.append(Utils.base64Character((length << 3) + (int) ((number >> (6 * length)) & 0x7))); |
| while (--length >= 0) { |
| result.append(Utils.base64Character((int) ((number >> (6 * length)) & 0x3f))); |
| } |
| return result.toString(); |
| } |
| |
| private static void appendEncodedCharacter(StringBuffer buffer, int c) { |
| while (c > 62) { |
| buffer.append('z'); |
| c -= 63; |
| } |
| buffer.append(Utils.base64Character(c)); |
| } |
| |
| private static int getIntProperty(String property, int defaultValue) { |
| int result = defaultValue; |
| if (property != null) { |
| try { |
| result = Integer.parseInt(property); |
| if (result < 1) { |
| // It has to be a positive integer. Use the default. |
| result = defaultValue; |
| } |
| } catch (NumberFormatException e) { |
| // Leave as default value |
| } |
| } |
| return result; |
| } |
| |
| protected String generateFeatureVersionSuffix(BuildTimeFeature buildFeature) throws CoreException { |
| if (!generateVersionSuffix || buildFeature.getContextQualifierLength() == -1) { |
| return null; // do nothing |
| } |
| |
| Properties properties = getBuildProperties(buildFeature); |
| int significantDigits = getIntProperty((String) properties.get(PROPERTY_SIGNIFICANT_VERSION_DIGITS), -1); |
| if (significantDigits == -1) |
| significantDigits = getIntProperty(AbstractScriptGenerator.getImmutableAntProperty(PROPERTY_SIGNIFICANT_VERSION_DIGITS), Integer.MAX_VALUE); |
| int maxGeneratedLength = getIntProperty((String) properties.get(PROPERTY_GENERATED_VERSION_LENGTH), -1); |
| if (maxGeneratedLength == -1) |
| maxGeneratedLength = getIntProperty(AbstractScriptGenerator.getImmutableAntProperty(PROPERTY_GENERATED_VERSION_LENGTH), 28); |
| |
| long majorSum = 0L; |
| long minorSum = 0L; |
| long serviceSum = 0L; |
| |
| // Include the version of this algorithm as part of the suffix, so that |
| // we have a way to make sure all suffixes increase when the algorithm |
| // changes. |
| majorSum += QUALIFIER_SUFFIX_VERSION; |
| |
| FeatureEntry[] referencedFeatures = buildFeature.getIncludedFeatureReferences(); |
| FeatureEntry[] pluginList = buildFeature.getRawPluginEntries(); |
| int numElements = pluginList.length + referencedFeatures.length; |
| if (numElements == 0) { |
| // Empty feature. |
| return null; |
| } |
| String[] qualifiers = new String[numElements]; |
| int idx = -1; |
| |
| // Loop through the included features, adding the version number parts |
| // to the running totals and storing the qualifier suffixes. |
| for (int i = 0; i < referencedFeatures.length; i++) { |
| BuildTimeFeature refFeature = getSite(false).findFeature(referencedFeatures[i].getId(), null, false); |
| if (refFeature == null) { |
| qualifiers[++idx] = ""; //$NON-NLS-1$ |
| continue; |
| } |
| |
| Version version = new Version(refFeature.getVersion()); |
| //PluginVersionIdentifier version = refFeature.getVersion(); |
| majorSum += version.getMajor(); |
| minorSum += version.getMinor(); |
| serviceSum += version.getMicro(); |
| int contextLength = refFeature.getContextQualifierLength(); |
| ++contextLength; //account for the '-' separating the context qualifier and suffix |
| String qualifier = version.getQualifier(); |
| // The entire qualifier of the nested feature is often too long to |
| // include in the suffix computation for the containing feature, |
| // and using it would result in extremely long qualifiers for |
| // umbrella features. So instead we want to use just the suffix |
| // part of the qualifier, or just the context part (if there is no |
| // suffix part). See bug #162022. |
| if (qualifier.length() > contextLength) { |
| // Use the suffix part |
| qualifiers[++idx] = qualifier.substring(contextLength); |
| } else { |
| // Use the context part |
| qualifiers[++idx] = qualifier; |
| } |
| } |
| |
| // Loop through the included plug-ins and fragments, adding the version |
| // number parts to the running totals and storing the qualifiers. |
| |
| for (int i = 0; i < pluginList.length; i++) { |
| FeatureEntry entry = pluginList[i]; |
| |
| String versionRequested = entry.getVersion(); |
| BundleDescription model = getSite(false).getRegistry().getBundle(entry.getId(), versionRequested, false); |
| Version version = null; |
| if (model != null) { |
| version = model.getVersion(); |
| } else { |
| if (versionRequested.endsWith(PROPERTY_QUALIFIER)) { |
| int resultingLength = versionRequested.length() - PROPERTY_QUALIFIER.length(); |
| if (versionRequested.charAt(resultingLength - 1) == '.') |
| resultingLength--; |
| versionRequested = versionRequested.substring(0, resultingLength); |
| } |
| version = new Version(versionRequested); |
| } |
| |
| majorSum += version.getMajor(); |
| minorSum += version.getMinor(); |
| serviceSum += version.getMicro(); |
| qualifiers[++idx] = version.getQualifier(); |
| } |
| |
| // Limit the qualifiers to the specified number of significant digits, |
| // and figure out what the longest qualifier is. |
| int longestQualifier = 0; |
| for (int i = 0; i < numElements; ++i) { |
| if (qualifiers[i].length() > significantDigits) { |
| qualifiers[i] = qualifiers[i].substring(0, significantDigits); |
| } |
| if (qualifiers[i].length() > longestQualifier) { |
| longestQualifier = qualifiers[i].length(); |
| } |
| } |
| |
| StringBuffer result = new StringBuffer(); |
| |
| // Encode the sums of the first three parts of the version numbers. |
| result.append(lengthPrefixBase64(majorSum)); |
| result.append(lengthPrefixBase64(minorSum)); |
| result.append(lengthPrefixBase64(serviceSum)); |
| |
| if (longestQualifier > 0) { |
| // Calculate the sum at each position of the qualifiers. |
| int[] qualifierSums = new int[longestQualifier]; |
| for (int i = 0; i < numElements; ++i) { |
| for (int j = 0; j < qualifiers[i].length(); ++j) { |
| qualifierSums[j] += Utils.qualifierCharValue(qualifiers[i].charAt(j)); |
| } |
| } |
| // Normalize the sums to be base 65. |
| int carry = 0; |
| for (int k = longestQualifier - 1; k >= 1; --k) { |
| qualifierSums[k] += carry; |
| carry = qualifierSums[k] / 65; |
| qualifierSums[k] = qualifierSums[k] % 65; |
| } |
| qualifierSums[0] += carry; |
| |
| // Always use one character for overflow. This will be handled |
| // correctly even when the overflow character itself overflows. |
| result.append(lengthPrefixBase64(qualifierSums[0])); |
| for (int m = 1; m < longestQualifier; ++m) { |
| appendEncodedCharacter(result, qualifierSums[m]); |
| } |
| } |
| // It is safe to strip any '-' characters from the end of the suffix. |
| // (This won't happen very often, but it will save us a character or |
| // two when it does.) |
| while (result.length() > 0 && result.charAt(result.length() - 1) == '-') { |
| result.deleteCharAt(result.length() - 1); |
| } |
| |
| // If the resulting suffix is too long, shorten it to the designed length. |
| if (maxGeneratedLength > result.length()) { |
| return result.toString(); |
| } |
| return result.substring(0, maxGeneratedLength); |
| } |
| |
| /** |
| * @param models |
| * @throws CoreException |
| */ |
| private void generateModels(List<BundleDescription> models) throws CoreException { |
| if (scriptGeneration == false) |
| return; |
| if (binaryFeature == false || models.isEmpty()) |
| return; |
| |
| Set<BundleDescription> generatedScripts = new HashSet<BundleDescription>(models.size()); |
| for (Iterator<BundleDescription> iterator = models.iterator(); iterator.hasNext();) { |
| BundleDescription model = iterator.next(); |
| if (generatedScripts.contains(model)) |
| continue; |
| generatedScripts.add(model); |
| |
| //Get the corresponding plug-in entries (from a feature object) associated with the model |
| //and generate the script if one the configuration is being built. The generated scripts |
| //are configuration agnostic so we only generate once. |
| @SuppressWarnings("rawtypes") |
| Set matchingEntries = (Set) ((Properties) model.getUserObject()).get(PLUGIN_ENTRY); |
| if (matchingEntries == null || matchingEntries.isEmpty()) |
| return; |
| |
| @SuppressWarnings("rawtypes") |
| Iterator entryIter = matchingEntries.iterator(); |
| FeatureEntry correspondingEntry = (FeatureEntry) entryIter.next(); |
| List<Config> list = selectConfigs(correspondingEntry); |
| if (list.size() == 0) |
| continue; |
| |
| ModelBuildScriptGenerator generator = new ModelBuildScriptGenerator(); |
| generator.setBuildSiteFactory(siteFactory); |
| generator.setCompiledElements(getCompiledElements()); |
| generator.setIgnoreMissingPropertiesFile(isIgnoreMissingPropertiesFile()); |
| generator.setModel(model); // setModel has to be called before configurePersistentProperties because it reads the model's properties |
| generator.setFeatureGenerator(this); |
| generator.setPluginPath(getPluginPath()); |
| generator.setDevEntries(devEntries); |
| generator.includePlatformIndependent(isPlatformIndependentIncluded()); |
| generator.setSignJars(signJars); |
| generator.setAssociatedEntry(correspondingEntry); |
| generator.setGenerateSourceReferences(sourceReferences); |
| generator.generate(); |
| } |
| |
| } |
| |
| /** |
| * Set this object's feature id to be the given value. |
| * |
| * @param featureID the feature id |
| * @throws CoreException if the given feature id is <code>null</code> |
| */ |
| public void setFeature(String featureID) throws CoreException { |
| if (featureID == null) { |
| throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_FEATURE_MISSING, Messages.error_missingFeatureId, null)); |
| } |
| this.featureIdentifier = featureID; |
| } |
| |
| /** |
| * Return a properties object constructed from the build.properties file |
| * for the given feature. If no file exists, then an empty properties |
| * object is returned. |
| * |
| * @return Properties the feature's build.properties |
| * @see Feature |
| */ |
| @Override |
| protected Properties getBuildProperties() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| protected Properties getBuildProperties(BuildTimeFeature feature) throws CoreException { |
| return readProperties(feature.getRootLocation(), PROPERTIES_FILE, isIgnoreMissingPropertiesFile() ? IStatus.OK : IStatus.WARNING); |
| } |
| |
| public void setGenerateIncludedFeatures(boolean recursiveGeneration) { |
| analyseIncludedFeatures = recursiveGeneration; |
| } |
| |
| protected void collectElementToAssemble(BuildTimeFeature featureToCollect) throws CoreException { |
| if (assemblyData == null || featureToCollect == null) |
| return; |
| |
| String binIncludes = getBuildProperties(featureToCollect).getProperty(PROPERTY_BIN_INCLUDES); |
| |
| /* collect binary features, and any feature defining bin.includes */ |
| if (featureToCollect.isBinary() || (binIncludes != null && binIncludes.length() > 0)) { |
| basicCollectElementToAssemble(featureToCollect); |
| return; |
| } |
| |
| //at this point, we have a non-binary feature with empty bin includes |
| //when building p2, containers (features without bin.includes) need to be collected, |
| //with the exception of the pde generated containers. |
| if (!BuildDirector.p2Gathering) |
| return; |
| |
| if (featureToCollect.getId().equals(CONTAINER_FEATURE) || featureToCollect.getId().equals(UI_CONTAINER_FEATURE)) |
| return; |
| |
| basicCollectElementToAssemble(featureToCollect); |
| } |
| |
| private void basicCollectElementToAssemble(BuildTimeFeature featureToCollect) { |
| if (assemblyData == null) |
| return; |
| List<Config> correctConfigs = selectConfigs(featureToCollect); |
| // Here, we could sort if the feature is a common one or not by |
| // comparing the size of correctConfigs |
| for (Iterator<Config> iter = correctConfigs.iterator(); iter.hasNext();) { |
| Config config = iter.next(); |
| assemblyData.addFeature(config, featureToCollect); |
| } |
| } |
| |
| /** |
| * Method setSourceToGather. |
| * |
| * @param sourceToGather |
| */ |
| public void setSourceToGather(SourceFeatureInformation sourceToGather) { |
| this.sourceToGather = sourceToGather; |
| } |
| |
| /** |
| * Sets the binaryFeatureGeneration. |
| * |
| * @param binaryFeatureGeneration |
| * The binaryFeatureGeneration to set |
| */ |
| public void setBinaryFeatureGeneration(boolean binaryFeatureGeneration) { |
| this.binaryFeature = binaryFeatureGeneration; |
| } |
| |
| /** |
| * Sets the scriptGeneration. |
| * |
| * @param scriptGeneration |
| * The scriptGeneration to set |
| */ |
| public void setScriptGeneration(boolean scriptGeneration) { |
| this.scriptGeneration = scriptGeneration; |
| } |
| |
| /** |
| * Sets whether or not to generate JNLP manifests |
| * |
| * @param value whether or not to generate JNLP manifests |
| */ |
| public void setGenerateJnlp(boolean value) { |
| generateJnlp = value; |
| } |
| |
| /** |
| * Sets whether or not to sign any constructed jars. |
| * |
| * @param value whether or not to sign any constructed JARs |
| */ |
| public void setSignJars(boolean value) { |
| signJars = value; |
| } |
| |
| public void setGenerateSourceReferences(boolean generateSourceRef) { |
| this.sourceReferences = generateSourceRef; |
| } |
| |
| /** |
| * Sets whether or not to generate the feature version suffix |
| * |
| * @param value whether or not to generate the feature version suffix |
| */ |
| public void setGenerateVersionSuffix(boolean value) { |
| generateVersionSuffix = value; |
| } |
| |
| /** |
| * Set the location of the .product file |
| * @param product the location of the .product file |
| */ |
| public void setProduct(String product) { |
| this.product = product; |
| } |
| |
| protected void collectElementToAssemble(FeatureEntry entryToCollect) throws CoreException { |
| if (assemblyData == null) |
| return; |
| List<Config> correctConfigs = selectConfigs(entryToCollect); |
| String versionRequested = entryToCollect.getVersion(); |
| BundleDescription effectivePlugin = null; |
| effectivePlugin = getSite(false).getRegistry().getResolvedBundle(entryToCollect.getId(), versionRequested); |
| for (Iterator<Config> iter = correctConfigs.iterator(); iter.hasNext();) { |
| assemblyData.addPlugin(iter.next(), effectivePlugin); |
| } |
| } |
| |
| public String getProduct() { |
| return product; |
| } |
| |
| public boolean getSignJars() { |
| return signJars; |
| } |
| |
| public boolean getGenerateJnlp() { |
| return generateJnlp; |
| } |
| |
| public AssemblyInformation getAssemblyData() { |
| return assemblyData; |
| } |
| |
| public boolean useWorkspaceBinaries() { |
| return workspaceBinaries; |
| } |
| |
| public void setUseWorkspaceBinaries(boolean workspaceBinaries) { |
| this.workspaceBinaries = workspaceBinaries; |
| } |
| } |