0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM - Initial API and implementation
0010: * G&H Softwareentwicklung GmbH - internationalization implementation (bug 150933)
0011: *******************************************************************************/package org.eclipse.pde.internal.build.builder;
0012:
0013: import java.io.*;
0014: import java.net.URL;
0015: import java.util.*;
0016: import java.util.jar.Attributes;
0017: import java.util.jar.Manifest;
0018: import org.eclipse.core.runtime.*;
0019: import org.eclipse.osgi.service.resolver.BundleDescription;
0020: import org.eclipse.osgi.util.NLS;
0021: import org.eclipse.pde.build.Constants;
0022: import org.eclipse.pde.internal.build.*;
0023: import org.eclipse.pde.internal.build.ant.AntScript;
0024: import org.eclipse.pde.internal.build.ant.FileSet;
0025: import org.eclipse.pde.internal.build.site.BuildTimeFeature;
0026: import org.eclipse.pde.internal.build.site.PDEState;
0027: import org.eclipse.update.core.*;
0028: import org.eclipse.update.core.model.IncludedFeatureReferenceModel;
0029: import org.eclipse.update.core.model.URLEntryModel;
0030: import org.osgi.framework.Version;
0031:
0032: /**
0033: * Generates build.xml script for features.
0034: */
0035: public class FeatureBuildScriptGenerator extends
0036: AbstractBuildScriptGenerator {
0037: private static final String COMMENT_START_TAG = "<!--"; //$NON-NLS-1$
0038: private static final String COMMENT_END_TAG = "-->"; //$NON-NLS-1$
0039: private static final String FEATURE_START_TAG = "<feature";//$NON-NLS-1$
0040: private static final String PLUGIN_START_TAG = "<plugin"; //$NON-NLS-1$
0041: private static final String FRAGMENT_START_TAG = "<fragment"; //$NON-NLS-1$
0042: private static final String VERSION = "version";//$NON-NLS-1$
0043: private static final String PLUGIN_VERSION = "plugin-version"; //$NON-NLS-1$
0044:
0045: // The 64 characters that are legal in a version qualifier, in lexicographical order.
0046: private static final String BASE_64_ENCODING = "-0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; //$NON-NLS-1$
0047:
0048: private static final int QUALIFIER_SUFFIX_VERSION = 1;
0049:
0050: // GENERATION FLAGS
0051: /**
0052: * Indicates whether scripts for this feature included features should be
0053: * generated.
0054: */
0055: protected boolean analyseIncludedFeatures = false;
0056: /**
0057: * Indicates whether scripts for this feature children' should be
0058: * generated.
0059: */
0060: protected boolean analysePlugins = true;
0061: /** Indicates whether a source feature should be generated for this feature */
0062: protected boolean sourceFeatureGeneration = false;
0063: /** Indicates whether the feature is binary */
0064: protected boolean binaryFeature = true;
0065: /** Indicates if the build scripts files should be produced or not */
0066: private boolean scriptGeneration = true;
0067:
0068: //FEATURE RELATED INFORMATION
0069: /** The identifier of the feature that the build script is being generated for. */
0070: protected String featureIdentifier;
0071: protected String searchedVersion;
0072: /** Target feature. */
0073: protected IFeature feature;
0074: /** The featurename with its version number */
0075: protected String featureFullName;
0076: protected String featureFolderName;
0077: protected String featureRootLocation;
0078: protected String featureTempFolder;
0079: protected Feature sourceFeature;
0080: protected PluginEntry sourcePlugin;
0081: protected String sourceFeatureFullName;
0082: protected String sourceFeatureFullNameVersionned;
0083: protected SourceFeatureInformation sourceToGather;
0084: protected boolean sourcePluginOnly = false;
0085: private String[] extraPlugins = new String[0];
0086: private boolean generateJnlp = false;
0087: private boolean signJars = false;
0088: private boolean generateVersionSuffix = false;
0089:
0090: //Cache the result of compteElements for performance
0091: private List computedElements = null;
0092: private String customFeatureCallbacks = null;
0093: private String customCallbacksBuildpath = null;
0094: private String customCallbacksFailOnError = null;
0095: private String customCallbacksInheritAll = null;
0096: private String product = null;
0097: private static final String TEMPLATE = "data"; //$NON-NLS-1$
0098:
0099: public FeatureBuildScriptGenerator() {
0100: super ();
0101: }
0102:
0103: /**
0104: * Constructor FeatureBuildScriptGenerator.
0105: */
0106: public FeatureBuildScriptGenerator(String featureId,
0107: String versionId, AssemblyInformation informationGathering)
0108: throws CoreException {
0109: if (featureId == null) {
0110: throw new CoreException(new Status(IStatus.ERROR,
0111: PI_PDEBUILD, EXCEPTION_FEATURE_MISSING,
0112: Messages.error_missingFeatureId, null));
0113: }
0114: this .featureIdentifier = featureId;
0115: this .searchedVersion = versionId;
0116: assemblyData = informationGathering;
0117: }
0118:
0119: /**
0120: * Returns a list of BundleDescription objects representing the elements delivered by the feature.
0121: *
0122: * @return List of BundleDescription
0123: * @throws CoreException
0124: */
0125: protected List computeElements() throws CoreException {
0126: if (computedElements != null)
0127: return computedElements;
0128:
0129: computedElements = new ArrayList(5);
0130: IPluginEntry[] pluginList = feature.getPluginEntries();
0131: for (int i = 0; i < pluginList.length; i++) {
0132: IPluginEntry entry = pluginList[i];
0133: VersionedIdentifier identifier = entry
0134: .getVersionedIdentifier();
0135: BundleDescription model;
0136: if (selectConfigs(entry).size() == 0)
0137: continue;
0138:
0139: String versionRequested = identifier.getVersion()
0140: .toString();
0141: model = getSite(false).getRegistry().getResolvedBundle(
0142: identifier.getIdentifier(), versionRequested);
0143: //we prefer a newly generated source plugin over a preexisting binary one.
0144: if ((model == null || Utils.isBinary(model))
0145: && getBuildProperties().containsKey(
0146: GENERATION_SOURCE_PLUGIN_PREFIX
0147: + identifier.getIdentifier())) {
0148: generateEmbeddedSource(identifier.getIdentifier());
0149: model = getSite(false).getRegistry().getResolvedBundle(
0150: identifier.getIdentifier(), versionRequested);
0151: }
0152: if (model == null) {
0153: String message = NLS.bind(
0154: Messages.exception_missingPlugin, entry
0155: .getVersionedIdentifier());
0156: throw new CoreException(new Status(IStatus.ERROR,
0157: PI_PDEBUILD, EXCEPTION_PLUGIN_MISSING, message,
0158: null));
0159: }
0160:
0161: associateModelAndEntry(model, entry);
0162:
0163: computedElements.add(model);
0164: collectElementToAssemble(pluginList[i]);
0165: collectSourcePlugins(pluginList[i], model);
0166: }
0167: return computedElements;
0168: }
0169:
0170: private void associateModelAndEntry(BundleDescription model,
0171: IPluginEntry entry) {
0172: Properties bundleProperties = ((Properties) model
0173: .getUserObject());
0174: if (bundleProperties == null) {
0175: bundleProperties = new Properties();
0176: model.setUserObject(bundleProperties);
0177: }
0178: Set entries = (Set) bundleProperties.get(PLUGIN_ENTRY);
0179: if (entries == null) {
0180: entries = new HashSet();
0181: bundleProperties.put(PLUGIN_ENTRY, entries);
0182: }
0183: entries.add(entry);
0184: }
0185:
0186: private void generateEmbeddedSource(String pluginId)
0187: throws CoreException {
0188: if (sourceFeatureGeneration)
0189: return;
0190: FeatureBuildScriptGenerator featureGenerator = new FeatureBuildScriptGenerator(
0191: Utils.getArrayFromString(getBuildProperties()
0192: .getProperty(
0193: GENERATION_SOURCE_PLUGIN_PREFIX
0194: + pluginId))[0], null,
0195: assemblyData);
0196: featureGenerator.setGenerateIncludedFeatures(false);
0197: featureGenerator.setAnalyseChildren(analysePlugins);
0198: featureGenerator.setSourceFeatureId(pluginId);
0199: featureGenerator.setSourceFeatureGeneration(true);
0200: featureGenerator.setExtraPlugins(Utils
0201: .getArrayFromString(getBuildProperties().getProperty(
0202: GENERATION_SOURCE_PLUGIN_PREFIX + pluginId)));
0203: featureGenerator.setBinaryFeatureGeneration(false);
0204: featureGenerator.setScriptGeneration(false);
0205: featureGenerator.setPluginPath(pluginPath);
0206: featureGenerator.setBuildSiteFactory(siteFactory);
0207: featureGenerator.setDevEntries(devEntries);
0208: featureGenerator.setCompiledElements(getCompiledElements());
0209: featureGenerator.setSourceToGather(sourceToGather);
0210: featureGenerator.setSourcePluginOnly(true);
0211: featureGenerator.setBuildingOSGi(isBuildingOSGi());
0212: featureGenerator
0213: .includePlatformIndependent(isPlatformIndependentIncluded());
0214: featureGenerator
0215: .setIgnoreMissingPropertiesFile(isIgnoreMissingPropertiesFile());
0216: featureGenerator
0217: .setGenerateVersionSuffix(generateVersionSuffix);
0218: featureGenerator.generate();
0219: }
0220:
0221: public void setSourcePluginOnly(boolean b) {
0222: sourcePluginOnly = b;
0223: }
0224:
0225: private void collectSourcePlugins(IPluginEntry pluginEntry,
0226: BundleDescription model) {
0227: if (!sourceFeatureGeneration)
0228: return;
0229: //Do not collect plug-ins for which we are not generating build.xml
0230: try {
0231: if (AbstractScriptGenerator.readProperties(model
0232: .getLocation(), PROPERTIES_FILE, IStatus.OK) == MissingProperties
0233: .getInstance())
0234: return;
0235: } catch (CoreException e) {
0236: return;
0237: }
0238: // The generic entry may not be part of the configuration we are building however,
0239: // the code for a non platform specific plugin still needs to go into a generic source plugin
0240: if (pluginEntry.getOS() == null && pluginEntry.getWS() == null
0241: && pluginEntry.getOSArch() == null) {
0242: sourceToGather.addElementEntry(Config.genericConfig(),
0243: model);
0244: return;
0245: }
0246: // Here we fan the plugins into the source fragment where they should go
0247: List correctConfigs = selectConfigs(pluginEntry);
0248: for (Iterator iter = correctConfigs.iterator(); iter.hasNext();) {
0249: sourceToGather.addElementEntry((Config) iter.next(), model);
0250: }
0251: }
0252:
0253: /**
0254: * Set the boolean for whether or not children scripts should be generated.
0255: *
0256: * @param generate
0257: * <code>true</code> if the children scripts should be
0258: * generated, <code>false</code> otherwise
0259: */
0260: public void setAnalyseChildren(boolean generate) {
0261: analysePlugins = generate;
0262: }
0263:
0264: /**
0265: * @see AbstractScriptGenerator#generate()
0266: */
0267: public void generate() throws CoreException {
0268: String message;
0269: if (workingDirectory == null) {
0270: throw new CoreException(new Status(IStatus.ERROR,
0271: PI_PDEBUILD,
0272: EXCEPTION_BUILDDIRECTORY_LOCATION_MISSING,
0273: Messages.error_missingInstallLocation, null));
0274: }
0275: initializeVariables();
0276:
0277: // if the feature defines its own custom script, we do not generate a
0278: // new one but we do try to update the version number
0279: boolean custom = TRUE
0280: .equalsIgnoreCase((String) getBuildProperties().get(
0281: PROPERTY_CUSTOM));
0282: File customBuildFile = null;
0283: if (custom) {
0284: customBuildFile = new File(featureRootLocation,
0285: DEFAULT_BUILD_SCRIPT_FILENAME);
0286: if (!customBuildFile.exists()) {
0287: message = NLS.bind(
0288: Messages.error_missingCustomBuildFile,
0289: customBuildFile);
0290: throw new CoreException(new Status(IStatus.ERROR,
0291: PI_PDEBUILD, EXCEPTION_WRITING_SCRIPT, message,
0292: null));
0293: }
0294:
0295: //turn off script generation so we don't overwrite the custom script
0296: scriptGeneration = false;
0297:
0298: /* need to do root files here because we won't be doing the gatherBinParts where it normally happens */
0299: List configs = getConfigInfos();
0300: for (Iterator iter = configs.iterator(); iter.hasNext();) {
0301: assemblyData.addRootFileProvider((Config) iter.next(),
0302: feature);
0303: }
0304: }
0305: if (analyseIncludedFeatures)
0306: generateIncludedFeatureBuildFile();
0307: if (sourceFeatureGeneration)
0308: generateSourceFeature();
0309: if (analysePlugins)
0310: generateChildrenScripts();
0311: if (sourceFeatureGeneration) {
0312: addSourceFragmentsToFeature();
0313: writeSourceFeature();
0314: }
0315: if (!sourcePluginOnly)
0316: collectElementToAssemble(feature);
0317:
0318: // Do the recursive generation of build files for the features required by the current feature
0319: if (sourceFeatureGeneration)
0320: generateSourceFeatureScripts();
0321:
0322: if (custom) {
0323: //Feature had a custom build script, we need to update the version in it.
0324: //Do it here after generateChildrenScripts since there may have been a suffix generated.
0325: try {
0326: updateVersion(customBuildFile,
0327: PROPERTY_FEATURE_VERSION_SUFFIX, feature
0328: .getVersionedIdentifier().getVersion()
0329: .toString());
0330: } catch (IOException e) {
0331: message = NLS.bind(Messages.exception_writeScript,
0332: customBuildFile);
0333: throw new CoreException(new Status(IStatus.ERROR,
0334: PI_PDEBUILD, EXCEPTION_WRITING_SCRIPT, message,
0335: e));
0336: }
0337: }
0338:
0339: if (scriptGeneration) {
0340: openScript(featureRootLocation,
0341: DEFAULT_BUILD_SCRIPT_FILENAME);
0342: try {
0343: generateBuildScript();
0344: } finally {
0345: closeScript();
0346: }
0347: }
0348: }
0349:
0350: protected void generateIncludedFeatureBuildFile()
0351: throws CoreException {
0352: IIncludedFeatureReference[] referencedFeatures = feature
0353: .getIncludedFeatureReferences();
0354: for (int i = 0; i < referencedFeatures.length; i++) {
0355: String featureId = ((IncludedFeatureReferenceModel) referencedFeatures[i])
0356: .getFeatureIdentifier();
0357: String featureVersion = ((IncludedFeatureReferenceModel) referencedFeatures[i])
0358: .getFeatureVersion();
0359: //If the feature which is included is a source feature, then instead of calling the generation of the featureID we are
0360: // calling the generation of the corresponding binary feature but without generating the scripts (set binaryFeatureGeneration to false)
0361: boolean doSourceFeatureGeneration = getBuildProperties()
0362: .containsKey(
0363: GENERATION_SOURCE_FEATURE_PREFIX
0364: + featureId);
0365: FeatureBuildScriptGenerator generator = new FeatureBuildScriptGenerator(
0366: doSourceFeatureGeneration == true ? Utils
0367: .getArrayFromString(getBuildProperties()
0368: .getProperty(
0369: GENERATION_SOURCE_FEATURE_PREFIX
0370: + featureId))[0]
0371: : featureId, featureVersion, assemblyData);
0372: //If we are generating a source feature we don't want to go recursively
0373: generator
0374: .setGenerateIncludedFeatures(doSourceFeatureGeneration ? false
0375: : true);
0376: generator.setAnalyseChildren(analysePlugins);
0377: generator
0378: .setSourceFeatureGeneration(doSourceFeatureGeneration);
0379: generator
0380: .setBinaryFeatureGeneration(!doSourceFeatureGeneration);
0381: //We don't want to regenerate the scripts for the binary feature we are reading to build the source feature
0382: generator
0383: .setScriptGeneration(doSourceFeatureGeneration ? false
0384: : true);
0385: if (doSourceFeatureGeneration) {
0386: generator.setSourceFeatureId(featureId);
0387: generator.setExtraPlugins(Utils
0388: .getArrayFromString(getBuildProperties()
0389: .getProperty(
0390: GENERATION_SOURCE_FEATURE_PREFIX
0391: + featureId)));
0392: }
0393: generator.setPluginPath(pluginPath);
0394: generator.setBuildSiteFactory(siteFactory);
0395: generator.setDevEntries(devEntries);
0396: generator.setCompiledElements(getCompiledElements());
0397: generator.setSourceToGather(new SourceFeatureInformation());
0398: generator.setBuildingOSGi(isBuildingOSGi());
0399: generator
0400: .includePlatformIndependent(isPlatformIndependentIncluded());
0401: generator
0402: .setIgnoreMissingPropertiesFile(isIgnoreMissingPropertiesFile());
0403: generator.setGenerateVersionSuffix(generateVersionSuffix);
0404: try {
0405: generator.generate();
0406: } catch (CoreException exception) {
0407: absorbExceptionIfOptionalFeature(referencedFeatures[i],
0408: exception);
0409: }
0410: }
0411: }
0412:
0413: private void absorbExceptionIfOptionalFeature(
0414: IIncludedFeatureReference feature, CoreException toAbsorb)
0415: throws CoreException {
0416: if (toAbsorb.getStatus().getCode() != EXCEPTION_FEATURE_MISSING
0417: || (toAbsorb.getStatus().getCode() == EXCEPTION_FEATURE_MISSING && !feature
0418: .isOptional()))
0419: throw toAbsorb;
0420: }
0421:
0422: protected void setExtraPlugins(String[] plugins) {
0423: extraPlugins = plugins;
0424: }
0425:
0426: /**
0427: * Main call for generating the script.
0428: *
0429: * @throws CoreException
0430: */
0431: private void generateBuildScript() throws CoreException {
0432: if (BundleHelper.getDefault().isDebugging())
0433: System.out.println("Generating feature " + featureFullName); //$NON-NLS-1$
0434: generatePrologue();
0435: generateAllPluginsTarget();
0436: generateAllFeaturesTarget();
0437: generateUpdateFeatureFile();
0438: generateAllChildrenTarget();
0439: generateChildrenTarget();
0440: generateBuildJarsTarget();
0441: generateBuildZipsTarget();
0442: generateBuildUpdateJarTarget();
0443: generateGatherBinPartsTarget();
0444: generateZipDistributionWholeTarget();
0445: generateZipSourcesTarget();
0446: generateZipLogsTarget();
0447: generateCleanTarget();
0448: generateRefreshTarget();
0449: generateGatherSourcesTarget();
0450: generateGatherLogsTarget();
0451: generateEpilogue();
0452: }
0453:
0454: /**
0455: * Method generateGatherSource. Used to enable the recursive call of
0456: * gathering the sources for the features
0457: */
0458: private void generateGatherSourcesTarget() {
0459: script.printTargetDeclaration(TARGET_GATHER_SOURCES, null,
0460: null, null, null);
0461: Map params = new HashMap(2);
0462: params.put(PROPERTY_DESTINATION_TEMP_FOLDER, Utils
0463: .getPropertyFormat(PROPERTY_FEATURE_TEMP_FOLDER)
0464: + '/'
0465: + DEFAULT_PLUGIN_LOCATION
0466: + '/'
0467: + sourceFeatureFullNameVersionned + '/' + "src"); //$NON-NLS-1$
0468: params.put(PROPERTY_TARGET, TARGET_GATHER_SOURCES);
0469: script.printAntCallTask(TARGET_CHILDREN, true, params);
0470: script.printTargetEnd();
0471: }
0472:
0473: /**
0474: * Method generateGatherSource. Used to enable the recursive call of
0475: * gathering the sources for the features
0476: */
0477: private void generateGatherLogsTarget() {
0478: script.println();
0479: script.printTargetDeclaration(TARGET_GATHER_LOGS, TARGET_INIT,
0480: null, null, null);
0481: script.printMkdirTask(featureTempFolder);
0482: Map params = new HashMap(1);
0483: params.put(PROPERTY_TARGET, TARGET_GATHER_LOGS);
0484: params.put(PROPERTY_DESTINATION_TEMP_FOLDER, new Path(
0485: featureTempFolder).append(DEFAULT_PLUGIN_LOCATION)
0486: .toString());
0487: script.printAntCallTask(TARGET_ALL_CHILDREN, false, params); //$NON-NLS-1$
0488: script.printTargetEnd();
0489: }
0490:
0491: private void generateUpdateFeatureFile() {
0492: script.printTargetDeclaration(TARGET_UPDATE_FEATURE_FILE,
0493: TARGET_INIT, null, null, null);
0494: script.printTargetEnd();
0495: }
0496:
0497: /**
0498: * Add the <code>build.zips</code> target to the given Ant script.
0499: *
0500: * @throws CoreException
0501: */
0502: private void generateBuildZipsTarget() throws CoreException {
0503: StringBuffer zips = new StringBuffer();
0504: Properties props = getBuildProperties();
0505: for (Iterator iterator = props.entrySet().iterator(); iterator
0506: .hasNext();) {
0507: Map.Entry entry = (Map.Entry) iterator.next();
0508: String key = (String) entry.getKey();
0509: if (key.startsWith(PROPERTY_SOURCE_PREFIX)
0510: && key.endsWith(PROPERTY_ZIP_SUFFIX)) {
0511: String zipName = key.substring(PROPERTY_SOURCE_PREFIX
0512: .length());
0513: zips.append(',');
0514: zips.append(zipName);
0515: generateZipIndividualTarget(zipName, (String) entry
0516: .getValue());
0517: }
0518: }
0519: script.println();
0520: script.printTargetDeclaration(TARGET_BUILD_ZIPS, TARGET_INIT
0521: + zips.toString(), null, null, null);
0522: Map params = new HashMap(2);
0523: params.put(PROPERTY_TARGET, TARGET_BUILD_ZIPS);
0524: script.printAntCallTask(TARGET_ALL_CHILDREN, true, params);
0525: script.printTargetEnd();
0526: }
0527:
0528: /**
0529: * Add a <code>zip</code> target to the given Ant script.
0530: *
0531: * @param zipName the name of the zip file to create
0532: * @param source the directory name to read the files from
0533: */
0534: private void generateZipIndividualTarget(String zipName,
0535: String source) {
0536: script.println();
0537: script.printTargetDeclaration(zipName, TARGET_INIT, null, null,
0538: null);
0539: script.printZipTask(Utils.getPropertyFormat(PROPERTY_BASEDIR)
0540: + '/' + zipName, Utils
0541: .getPropertyFormat(PROPERTY_BASEDIR)
0542: + '/' + source, false, false, null);
0543: script.printTargetEnd();
0544: }
0545:
0546: /**
0547: * Add the <code>clean</code> target to the given Ant script.
0548: */
0549: private void generateCleanTarget() {
0550: script.println();
0551: script.printTargetDeclaration(TARGET_CLEAN, TARGET_INIT, null,
0552: null, NLS.bind(Messages.build_feature_clean,
0553: featureIdentifier));
0554: script.printDeleteTask(null, Utils
0555: .getPropertyFormat(PROPERTY_FEATURE_DESTINATION)
0556: + '/' + featureFullName + ".jar", null); //$NON-NLS-1$
0557: script.printDeleteTask(null, Utils
0558: .getPropertyFormat(PROPERTY_FEATURE_DESTINATION)
0559: + '/' + featureFullName + ".bin.dist.zip", null); //$NON-NLS-1$
0560: script.printDeleteTask(null, Utils
0561: .getPropertyFormat(PROPERTY_FEATURE_DESTINATION)
0562: + '/' + featureFullName + ".log.zip", null); //$NON-NLS-1$
0563: script.printDeleteTask(null, Utils
0564: .getPropertyFormat(PROPERTY_FEATURE_DESTINATION)
0565: + '/' + featureFullName + ".src.zip", null); //$NON-NLS-1$
0566: script.printDeleteTask(featureTempFolder, null, null);
0567: Map params = new HashMap(2);
0568: params.put(PROPERTY_TARGET, TARGET_CLEAN);
0569: script.printAntCallTask(TARGET_ALL_CHILDREN, true, params);
0570: script.printTargetEnd();
0571: }
0572:
0573: /**
0574: * Add the <code>zip.logs</code> target to the given Ant script.
0575: */
0576: private void generateZipLogsTarget() {
0577: script.println();
0578: script.printTargetDeclaration(TARGET_ZIP_LOGS, TARGET_INIT,
0579: null, null, null);
0580: script.printDeleteTask(featureTempFolder, null, null);
0581: script.printMkdirTask(featureTempFolder);
0582: Map params = new HashMap(1);
0583: params.put(PROPERTY_INCLUDE_CHILDREN, "true"); //$NON-NLS-1$
0584: params.put(PROPERTY_TARGET, TARGET_GATHER_LOGS);
0585: params.put(PROPERTY_DESTINATION_TEMP_FOLDER, new Path(
0586: featureTempFolder).append(DEFAULT_PLUGIN_LOCATION)
0587: .toString());
0588: script.printAntCallTask(TARGET_ALL_CHILDREN, false, params); //$NON-NLS-1$
0589: IPath destination = new Path(Utils
0590: .getPropertyFormat(PROPERTY_FEATURE_DESTINATION))
0591: .append(featureFullName + ".log.zip"); //$NON-NLS-1$
0592: script.printZipTask(destination.toString(), featureTempFolder,
0593: true, false, null);
0594: script.printDeleteTask(featureTempFolder, null, null);
0595: script.printTargetEnd();
0596: }
0597:
0598: /**
0599: * Add the <code>zip.sources</code> target to the given Ant script.
0600: */
0601: protected void generateZipSourcesTarget() {
0602: script.println();
0603: script.printTargetDeclaration(TARGET_ZIP_SOURCES, TARGET_INIT,
0604: null, null, null);
0605: script.printDeleteTask(featureTempFolder, null, null);
0606: script.printMkdirTask(featureTempFolder);
0607: Map params = new HashMap(1);
0608: params.put(PROPERTY_INCLUDE_CHILDREN, "true"); //$NON-NLS-1$
0609: params.put(PROPERTY_TARGET, TARGET_GATHER_SOURCES);
0610: params.put(PROPERTY_DESTINATION_TEMP_FOLDER, featureTempFolder
0611: + '/' + DEFAULT_PLUGIN_LOCATION + '/'
0612: + sourceFeatureFullNameVersionned + '/' + "src"); //$NON-NLS-1$
0613: script.printAntCallTask(TARGET_ALL_CHILDREN, true, params);
0614: script
0615: .printZipTask(
0616: Utils
0617: .getPropertyFormat(PROPERTY_FEATURE_DESTINATION)
0618: + '/' + featureFullName + ".src.zip", featureTempFolder, true, false, null); //$NON-NLS-1$
0619: script.printDeleteTask(featureTempFolder, null, null);
0620: script.printTargetEnd();
0621: }
0622:
0623: /**
0624: * Add the <code>gather.bin.parts</code> target to the given Ant script
0625: *
0626: * @throws CoreException
0627: */
0628: private void generateGatherBinPartsTarget() throws CoreException {
0629: String include = (String) getBuildProperties().get(
0630: PROPERTY_BIN_INCLUDES);
0631: String exclude = (String) getBuildProperties().get(
0632: PROPERTY_BIN_EXCLUDES);
0633: String root = Utils.getPropertyFormat(PROPERTY_FEATURE_BASE)
0634: + '/' + featureFolderName;
0635:
0636: script.println();
0637: script.printTargetDeclaration(TARGET_GATHER_BIN_PARTS,
0638: TARGET_INIT, PROPERTY_FEATURE_BASE, null, null);
0639: if (include != null)
0640: script.printMkdirTask(root);
0641:
0642: Map callbackParams = null;
0643: if (customFeatureCallbacks != null) {
0644: callbackParams = new HashMap(1);
0645: callbackParams
0646: .put(
0647: PROPERTY_DESTINATION_TEMP_FOLDER,
0648: new Path(
0649: Utils
0650: .getPropertyFormat(PROPERTY_FEATURE_BASE))
0651: .append(DEFAULT_PLUGIN_LOCATION)
0652: .toString());
0653: callbackParams.put(PROPERTY_FEATURE_DIRECTORY, root);
0654: script
0655: .printSubantTask(
0656: Utils
0657: .getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS),
0658: PROPERTY_PRE + TARGET_GATHER_BIN_PARTS,
0659: customCallbacksBuildpath,
0660: customCallbacksFailOnError,
0661: customCallbacksInheritAll, callbackParams,
0662: null);
0663: }
0664:
0665: Map params = new HashMap(1);
0666: params.put(PROPERTY_TARGET, TARGET_GATHER_BIN_PARTS);
0667: params.put(PROPERTY_DESTINATION_TEMP_FOLDER, new Path(Utils
0668: .getPropertyFormat(PROPERTY_FEATURE_BASE)).append(
0669: DEFAULT_PLUGIN_LOCATION).toString());
0670: script.printAntCallTask(TARGET_CHILDREN, true, params);
0671:
0672: if (include != null) {
0673: if (include != null || exclude != null) {
0674: FileSet fileSet = new FileSet(Utils
0675: .getPropertyFormat(PROPERTY_BASEDIR), null,
0676: include, null, exclude, null, null);
0677: script.printCopyTask(null, root,
0678: new FileSet[] { fileSet }, true, false);
0679: }
0680: // Generate the parameters for the Id Replacer.
0681: String featureVersionInfo = ""; //$NON-NLS-1$
0682: // Here we get all the included features (independently of the config being built so the version numbers in the feature can be replaced)
0683: IIncludedFeatureReference[] includedFeatures = feature
0684: .getRawIncludedFeatureReferences();
0685: for (int i = 0; i < includedFeatures.length; i++) {
0686: String versionRequested = includedFeatures[i]
0687: .getVersionedIdentifier().getVersion()
0688: .toString();
0689: IFeature includedFeature = null;
0690: try {
0691: includedFeature = getSite(false).findFeature(
0692: includedFeatures[i]
0693: .getVersionedIdentifier()
0694: .getIdentifier(), versionRequested,
0695: true);
0696: } catch (CoreException e) {
0697: absorbExceptionIfOptionalFeature(
0698: includedFeatures[i], e);
0699: continue;
0700: }
0701: VersionedIdentifier includedFeatureVersionId = includedFeature
0702: .getVersionedIdentifier();
0703: if (needsReplacement(versionRequested))
0704: featureVersionInfo += (includedFeatureVersionId
0705: .getIdentifier()
0706: + ':'
0707: + extract3Segments(versionRequested)
0708: + ','
0709: + includedFeatureVersionId.getVersion()
0710: .toString() + ',');
0711: }
0712: String pluginVersionInfo = ""; //$NON-NLS-1$
0713: // Here we get all the included plugins (independently of the config being built so the version numbers in the feature can be replaced)
0714: IPluginEntry[] pluginsIncluded = feature
0715: .getRawPluginEntries();
0716: for (int i = 0; i < pluginsIncluded.length; i++) {
0717: VersionedIdentifier identifier = pluginsIncluded[i]
0718: .getVersionedIdentifier();
0719: BundleDescription model;
0720: // If we ask for 0.0.0, the call to the registry must have null as a parameter
0721: String versionRequested = identifier.getVersion()
0722: .toString();
0723: String entryIdentifier = identifier.getIdentifier();
0724: model = getSite(false).getRegistry().getResolvedBundle(
0725: entryIdentifier, versionRequested);
0726: if (model != null) {
0727: if (needsReplacement(versionRequested))
0728: pluginVersionInfo += (entryIdentifier + ':'
0729: + extract3Segments(versionRequested)
0730: + ',' + model.getVersion() + ',');
0731: }
0732: }
0733: script
0734: .println("<eclipse.idReplacer featureFilePath=\"" + AntScript.getEscaped(root) + '/' + Constants.FEATURE_FILENAME_DESCRIPTOR + "\" selfVersion=\"" + feature.getVersionedIdentifier().getVersion() + "\" featureIds=\"" + featureVersionInfo + "\" pluginIds=\"" + pluginVersionInfo + "\"/>"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
0735: }
0736: generateRootFilesAndPermissionsCalls();
0737: if (customFeatureCallbacks != null) {
0738: script
0739: .printSubantTask(
0740: Utils
0741: .getPropertyFormat(PROPERTY_CUSTOM_BUILD_CALLBACKS),
0742: PROPERTY_POST + TARGET_GATHER_BIN_PARTS,
0743: customCallbacksBuildpath,
0744: customCallbacksFailOnError,
0745: customCallbacksInheritAll, callbackParams,
0746: null);
0747: }
0748: script.printTargetEnd();
0749: generateRootFilesAndPermissions();
0750: }
0751:
0752: private boolean needsReplacement(String s) {
0753: if (s.equalsIgnoreCase(GENERIC_VERSION_NUMBER)
0754: || s.endsWith(PROPERTY_QUALIFIER))
0755: return true;
0756: return false;
0757: }
0758:
0759: private Version extract3Segments(String s) {
0760: Version tmp = new Version(s);
0761: return new Version(tmp.getMajor(), tmp.getMinor(), tmp
0762: .getMicro());
0763: }
0764:
0765: /**
0766: *
0767: */
0768: private void generateRootFilesAndPermissionsCalls() {
0769: script.printAntCallTask(TARGET_ROOTFILES_PREFIX
0770: + Utils.getPropertyFormat(PROPERTY_OS) + '_'
0771: + Utils.getPropertyFormat(PROPERTY_WS) + '_'
0772: + Utils.getPropertyFormat(PROPERTY_ARCH), true, null);
0773: }
0774:
0775: /**
0776: *
0777: */
0778: private void generateRootFilesAndPermissions() throws CoreException {
0779: if (product != null && !havePDEUIState()) {
0780: ProductGenerator generator = new ProductGenerator();
0781: generator.setProduct(product);
0782: generator.setBuildSiteFactory(siteFactory);
0783: generator.setBuildProperties(getBuildProperties());
0784: generator.setRoot(featureRootLocation);
0785: generator.setWorkingDirectory(getWorkingDirectory());
0786: try {
0787: generator.generate();
0788: } catch (CoreException e) {
0789: //problem with the .product file
0790: //TODO Log warning/error
0791: }
0792: }
0793: for (Iterator iter = getConfigInfos().iterator(); iter
0794: .hasNext();) {
0795: Config aConfig = (Config) iter.next();
0796: script.printTargetDeclaration(TARGET_ROOTFILES_PREFIX
0797: + aConfig.toString("_"), null, null, null, null); //$NON-NLS-1$
0798: generateCopyRootFiles(aConfig);
0799: Utils.generatePermissions(getBuildProperties(), aConfig,
0800: PROPERTY_FEATURE_BASE, script);
0801: script.printTargetEnd();
0802: }
0803: script.printTargetDeclaration(TARGET_ROOTFILES_PREFIX
0804: + "group_group_group", null, null, null, null); //$NON-NLS-1$
0805: for (Iterator iter = getConfigInfos().iterator(); iter
0806: .hasNext();) {
0807: Config aConfig = (Config) iter.next();
0808: script.printAntCallTask(TARGET_ROOTFILES_PREFIX
0809: + aConfig.toString("_"), true, null);//.getPropertyFormat(PROPERTY_OS) + '_' + Utils.getPropertyFormat(PROPERTY_WS) + '_' + Utils.getPropertyFormat(PROPERTY_ARCH))
0810: }
0811: script.printTargetEnd();
0812: }
0813:
0814: private void generateCopyRootFiles(Config aConfig)
0815: throws CoreException {
0816: Properties properties = getBuildProperties();
0817: Map foldersToCopy = new HashMap(2);
0818:
0819: /* normal root files */
0820: String baseList = getBuildProperties().getProperty(ROOT, ""); //$NON-NLS-1$
0821: String fileList = getBuildProperties().getProperty(
0822: ROOT_PREFIX + aConfig.toString("."), ""); //$NON-NLS-1$ //$NON-NLS-2$
0823: fileList = (fileList.length() == 0 ? "" : fileList + ',') + baseList; //$NON-NLS-1$
0824: if (fileList.length() > 0)
0825: foldersToCopy.put("", fileList); //$NON-NLS-1$
0826:
0827: /* root files going to subfolders */
0828: String configPrefix = ROOT_PREFIX
0829: + aConfig.toString(".") + FOLDER_INFIX; //$NON-NLS-1$
0830: for (Iterator it = properties.keySet().iterator(); it.hasNext();) {
0831: String key = (String) it.next();
0832: String folder = null;
0833: if (key.startsWith(ROOT_FOLDER_PREFIX)) {
0834: folder = key.substring(ROOT_FOLDER_PREFIX.length(), key
0835: .length());
0836: } else if (key.startsWith(configPrefix)) {
0837: folder = key.substring(configPrefix.length(), key
0838: .length());
0839: }
0840: if (folder != null) {
0841: String value = properties.getProperty(key);
0842: if (foldersToCopy.containsKey(folder)) {
0843: String set = (String) foldersToCopy.get(folder);
0844: set += "," + value; //$NON-NLS-1$
0845: foldersToCopy.put(folder, set);
0846: } else {
0847: foldersToCopy.put(folder, value);
0848: }
0849: }
0850: }
0851:
0852: if (foldersToCopy.isEmpty())
0853: return;
0854:
0855: String configName = aConfig.toStringReplacingAny(
0856: ".", ANY_STRING); //$NON-NLS-1$
0857: String shouldOverwrite = properties.getProperty(
0858: PROPERTY_OVERWRITE_ROOTFILES, "true"); //$NON-NLS-1$
0859: boolean overwrite = Boolean.valueOf(shouldOverwrite)
0860: .booleanValue();
0861:
0862: assemblyData.addRootFileProvider(aConfig, feature);
0863:
0864: Object[] folders = foldersToCopy.keySet().toArray();
0865: for (int i = 0; i < folders.length; i++) {
0866: String folder = (String) folders[i];
0867: fileList = (String) foldersToCopy.get(folder);
0868: String[] files = Utils.getArrayFromString(fileList, ","); //$NON-NLS-1$
0869: FileSet[] fileSet = new FileSet[files.length];
0870: for (int j = 0; j < files.length; j++) {
0871: String file = files[j];
0872: String fromDir = Utils
0873: .getPropertyFormat(PROPERTY_BASEDIR) + '/';
0874: if (file.startsWith("absolute:")) { //$NON-NLS-1$
0875: file = file.substring(9);
0876: fromDir = ""; //$NON-NLS-1$
0877: }
0878: if (file.startsWith("file:")) { //$NON-NLS-1$
0879: IPath target = new Path(file.substring(5));
0880: fileSet[j] = new FileSet(fromDir
0881: + target.removeLastSegments(1), null,
0882: target.lastSegment(), null, null, null,
0883: null);
0884: } else {
0885: fileSet[j] = new FileSet(fromDir + file, null,
0886: "**", null, null, null, null); //$NON-NLS-1$
0887: }
0888: }
0889: script
0890: .printMkdirTask(Utils
0891: .getPropertyFormat(PROPERTY_FEATURE_BASE)
0892: + '/'
0893: + configName
0894: + '/'
0895: + Utils
0896: .getPropertyFormat(PROPERTY_COLLECTING_FOLDER)
0897: + '/' + folder);
0898: script
0899: .printCopyTask(
0900: null,
0901: Utils
0902: .getPropertyFormat(PROPERTY_FEATURE_BASE)
0903: + '/'
0904: + configName
0905: + '/'
0906: + Utils
0907: .getPropertyFormat(PROPERTY_COLLECTING_FOLDER)
0908: + '/' + folder, fileSet, true,
0909: overwrite);
0910: }
0911: }
0912:
0913: /**
0914: * Add the <code>build.update.jar</code> target to the given script.
0915: */
0916: private void generateBuildUpdateJarTarget() {
0917: script.println();
0918: script.printTargetDeclaration(TARGET_BUILD_UPDATE_JAR,
0919: TARGET_INIT, null, null, NLS.bind(
0920: Messages.build_feature_buildUpdateJar,
0921: featureIdentifier));
0922: Map params = new HashMap(1);
0923: params.put(PROPERTY_TARGET, TARGET_BUILD_UPDATE_JAR);
0924: script.printAntCallTask(TARGET_ALL_CHILDREN, true, params);
0925: script.printProperty(PROPERTY_FEATURE_BASE, featureTempFolder);
0926: script.printDeleteTask(featureTempFolder, null, null);
0927: script.printMkdirTask(featureTempFolder);
0928: params.clear();
0929: params.put(PROPERTY_FEATURE_BASE, featureTempFolder);
0930: params.put(PROPERTY_OS, feature.getOS() == null ? Config.ANY
0931: : feature.getOS());
0932: params.put(PROPERTY_WS, feature.getWS() == null ? Config.ANY
0933: : feature.getWS());
0934: params.put(PROPERTY_ARCH,
0935: feature.getOSArch() == null ? Config.ANY : feature
0936: .getOSArch());
0937: params.put(PROPERTY_NL, feature.getNL() == null ? Config.ANY
0938: : feature.getNL());
0939: // Be sure to call the gather with children turned off. The only way to
0940: // do this is
0941: // to clear all inherited values. Must remember to setup anything that
0942: // is really expected.
0943: script.printAntCallTask(TARGET_GATHER_BIN_PARTS, false, params);
0944: String jar = Utils
0945: .getPropertyFormat(PROPERTY_FEATURE_DESTINATION)
0946: + '/' + featureFullName + ".jar"; //$NON-NLS-1$
0947: script.printJarTask(jar, featureTempFolder + '/'
0948: + featureFolderName, null);
0949: script.printDeleteTask(featureTempFolder, null, null);
0950: if (generateJnlp)
0951: script
0952: .println("<eclipse.jnlpGenerator feature=\"" + AntScript.getEscaped(jar) + "\" codebase=\"" + Utils.getPropertyFormat(IXMLConstants.PROPERTY_JNLP_CODEBASE) + "\" j2se=\"" + Utils.getPropertyFormat(IXMLConstants.PROPERTY_JNLP_J2SE) + "\" locale=\"" + Utils.getPropertyFormat(IXMLConstants.PROPERTY_JNLP_LOCALE) + "\" generateOfflineAllowed=\"" + Utils.getPropertyFormat(PROPERTY_JNLP_GENOFFLINE) + "\" configInfo=\"" + Utils.getPropertyFormat(PROPERTY_JNLP_CONFIGS) + "\"/>"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
0953: if (signJars) {
0954: if (generateJnlp) {
0955: script.printProperty(PROPERTY_UNSIGN, "true"); //$NON-NLS-1$
0956: }
0957: script
0958: .println("<eclipse.jarProcessor sign=\"" + Utils.getPropertyFormat(PROPERTY_SIGN) + "\" pack=\"" + Utils.getPropertyFormat(PROPERTY_PACK) + "\" unsign=\"" + Utils.getPropertyFormat(PROPERTY_UNSIGN) + "\" jar=\"" + AntScript.getEscaped(jar) + "\" alias=\"" + Utils.getPropertyFormat(PROPERTY_SIGN_ALIAS) + "\" keystore=\"" + Utils.getPropertyFormat(PROPERTY_SIGN_KEYSTORE) + "\" storepass=\"" + Utils.getPropertyFormat(PROPERTY_SIGN_STOREPASS) + "\"/>"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
0959: }
0960: script.printTargetEnd();
0961: }
0962:
0963: /**
0964: * Add the <code>zip.distribution</code> target to the given Ant script.
0965: * Zip up the whole feature.
0966: */
0967: protected void generateZipDistributionWholeTarget() {
0968: script.println();
0969: script
0970: .printTargetDeclaration(TARGET_ZIP_DISTRIBUTION,
0971: TARGET_INIT, null, null, NLS.bind(
0972: Messages.build_feature_zips,
0973: featureIdentifier));
0974: script.printDeleteTask(featureTempFolder, null, null);
0975: script.printMkdirTask(featureTempFolder);
0976: Map params = new HashMap(1);
0977: params.put(PROPERTY_FEATURE_BASE, featureTempFolder);
0978: params.put(PROPERTY_INCLUDE_CHILDREN, TRUE);
0979: params.put(PROPERTY_OS, feature.getOS() == null ? Config.ANY
0980: : feature.getOS());
0981: params.put(PROPERTY_WS, feature.getWS() == null ? Config.ANY
0982: : feature.getWS());
0983: params.put(PROPERTY_ARCH,
0984: feature.getOSArch() == null ? Config.ANY : feature
0985: .getOSArch());
0986: params.put(PROPERTY_NL, feature.getNL() == null ? Config.ANY
0987: : feature.getNL());
0988: script.printAntCallTask(TARGET_GATHER_BIN_PARTS, true, params);
0989: script
0990: .printZipTask(
0991: Utils
0992: .getPropertyFormat(PROPERTY_FEATURE_DESTINATION)
0993: + '/'
0994: + featureFullName
0995: + ".bin.dist.zip", featureTempFolder, false, false, null); //$NON-NLS-1$
0996: script.printDeleteTask(featureTempFolder, null, null);
0997: script.printTargetEnd();
0998: }
0999:
1000: /**
1001: * Executes a given target in all children's script files.
1002: */
1003: private void generateAllChildrenTarget() {
1004: StringBuffer depends = new StringBuffer();
1005: depends.append(TARGET_INIT);
1006: depends.append(',');
1007: depends.append(TARGET_ALL_FEATURES);
1008: depends.append(',');
1009: depends.append(TARGET_ALL_PLUGINS);
1010: depends.append(',');
1011: depends.append(TARGET_UPDATE_FEATURE_FILE);
1012: script.println();
1013: script.printTargetDeclaration(TARGET_ALL_CHILDREN, depends
1014: .toString(), null, null, null);
1015: script.printTargetEnd();
1016: }
1017:
1018: /**
1019: * Target responsible for delegating target calls to plug-in's build.xml
1020: * scripts. Plugins are sorted according to the requires chain. Fragments
1021: * are inserted afterward
1022: *
1023: * @throws CoreException
1024: */
1025: protected void generateAllPluginsTarget() throws CoreException {
1026: List plugins = computeElements();
1027: plugins = Utils.extractPlugins(getSite(false).getRegistry()
1028: .getSortedBundles(), plugins);
1029: script.println();
1030: script.printTargetDeclaration(TARGET_ALL_PLUGINS, TARGET_INIT,
1031: null, null, null);
1032: Set writtenCalls = new HashSet(plugins.size());
1033: for (Iterator iter = plugins.iterator(); iter.hasNext();) {
1034: BundleDescription current = (BundleDescription) iter.next();
1035: //If it is not a compiled element, then we don't generate a call
1036: Properties bundleProperties = (Properties) current
1037: .getUserObject();
1038: if (bundleProperties == null
1039: || bundleProperties.get(IS_COMPILED) == null
1040: || bundleProperties.get(IS_COMPILED) == Boolean.FALSE)
1041: continue;
1042: // Get the os / ws / arch to pass as a parameter to the plugin
1043: if (writtenCalls.contains(current))
1044: continue;
1045: writtenCalls.add(current);
1046: IPluginEntry[] entries = Utils.getPluginEntry(feature,
1047: current.getSymbolicName(), false); //TODO This can be improved to use the value from the user object in the bundleDescription
1048: for (int j = 0; j < entries.length; j++) {
1049: List list = selectConfigs(entries[j]);
1050: if (list.size() == 0)
1051: continue;
1052: Map params = null;
1053: Config aMatchingConfig = (Config) list.get(0);
1054: params = new HashMap(3);
1055: if (!aMatchingConfig.getOs().equals(Config.ANY))
1056: params.put(PROPERTY_OS, aMatchingConfig.getOs());
1057: if (!aMatchingConfig.getWs().equals(Config.ANY))
1058: params.put(PROPERTY_WS, aMatchingConfig.getWs());
1059: if (!aMatchingConfig.getArch().equals(Config.ANY))
1060: params
1061: .put(PROPERTY_ARCH, aMatchingConfig
1062: .getArch());
1063: IPath location = Utils.makeRelative(new Path(
1064: getLocation(current)), new Path(
1065: featureRootLocation));
1066: script.printAntTask(DEFAULT_BUILD_SCRIPT_FILENAME,
1067: location.toString(), Utils
1068: .getPropertyFormat(PROPERTY_TARGET),
1069: null, null, params);
1070: }
1071: }
1072: script.printTargetEnd();
1073: }
1074:
1075: private void generateAllFeaturesTarget() throws CoreException {
1076: script.printTargetDeclaration(TARGET_ALL_FEATURES, TARGET_INIT,
1077: null, null, null);
1078: if (analyseIncludedFeatures) {
1079: IIncludedFeatureReference[] features = feature
1080: .getIncludedFeatureReferences();
1081: for (int i = 0; i < features.length; i++) {
1082: String featureId = features[i].getVersionedIdentifier()
1083: .getIdentifier();
1084: String versionId = features[i].getVersionedIdentifier()
1085: .getVersion().toString();
1086: IFeature includedFeature = getSite(false).findFeature(
1087: featureId, versionId, false);
1088: if (includedFeature == null) {
1089: if (features[i].isOptional())
1090: continue;
1091: String message = NLS.bind(
1092: Messages.exception_missingFeature,
1093: featureId + ' ' + versionId);
1094: throw new CoreException(new Status(IStatus.ERROR,
1095: PI_PDEBUILD, EXCEPTION_FEATURE_MISSING,
1096: message, null));
1097: }
1098: if (includedFeature instanceof BuildTimeFeature) {
1099: if (((BuildTimeFeature) includedFeature).isBinary())
1100: continue;
1101: }
1102:
1103: String includedFeatureDirectory = includedFeature
1104: .getURL().getPath();
1105: int j = includedFeatureDirectory
1106: .lastIndexOf(Constants.FEATURE_FILENAME_DESCRIPTOR);
1107: if (j != -1)
1108: includedFeatureDirectory = includedFeatureDirectory
1109: .substring(0, j);
1110: IPath location;
1111: location = Utils.makeRelative(new Path(
1112: includedFeatureDirectory), new Path(
1113: featureRootLocation));
1114: script.printAntTask(DEFAULT_BUILD_SCRIPT_FILENAME,
1115: location.toString(), Utils
1116: .getPropertyFormat(PROPERTY_TARGET),
1117: null, null, null);
1118: }
1119: }
1120: script.printTargetEnd();
1121: }
1122:
1123: /**
1124: * Just ends the script.
1125: */
1126: private void generateEpilogue() {
1127: script.println();
1128: script.printProjectEnd();
1129: }
1130:
1131: /**
1132: * Defines, the XML declaration, Ant project and init target.
1133: */
1134: private void generatePrologue() {
1135: script.printProjectDeclaration(feature.getVersionedIdentifier()
1136: .getIdentifier(), TARGET_BUILD_UPDATE_JAR, "."); //$NON-NLS-1$
1137: script.println();
1138: script.printTargetDeclaration(TARGET_INIT, null, null, null,
1139: null);
1140: script.printProperty(PROPERTY_FEATURE_TEMP_FOLDER, Utils
1141: .getPropertyFormat(PROPERTY_BASEDIR)
1142: + '/' + PROPERTY_FEATURE_TEMP_FOLDER);
1143: script.printProperty(PROPERTY_FEATURE_DESTINATION, Utils
1144: .getPropertyFormat(PROPERTY_BASEDIR));
1145: if (customFeatureCallbacks != null) {
1146: script.printAvailableTask(PROPERTY_CUSTOM_BUILD_CALLBACKS,
1147: customCallbacksBuildpath + '/'
1148: + customFeatureCallbacks,
1149: customFeatureCallbacks);
1150: }
1151: script.printTargetEnd();
1152: }
1153:
1154: /**
1155: * @throws CoreException
1156: */
1157: private void generateChildrenScripts() throws CoreException {
1158: List plugins = computeElements();
1159: String suffix = generateFeatureVersionSuffix((BuildTimeFeature) feature);
1160: if (suffix != null) {
1161: PluginVersionIdentifier versionId = feature
1162: .getVersionedIdentifier().getVersion();
1163: String qualifier = versionId.getQualifierComponent();
1164: qualifier = qualifier.substring(0,
1165: ((BuildTimeFeature) feature)
1166: .getContextQualifierLength());
1167: qualifier = qualifier + '-' + suffix;
1168: versionId = new PluginVersionIdentifier(versionId
1169: .getMajorComponent(),
1170: versionId.getMinorComponent(), versionId
1171: .getServiceComponent(), qualifier);
1172: String newVersion = versionId.toString();
1173: ((BuildTimeFeature) feature).setFeatureVersion(newVersion);
1174: initializeFeatureNames(); //reset our variables
1175: }
1176: generateModels(Utils.extractPlugins(getSite(false)
1177: .getRegistry().getSortedBundles(), plugins));
1178: }
1179:
1180: // Integer to character conversion in our base-64 encoding scheme. If the
1181: // input is out of range, an illegal character will be returned.
1182: private static char base64Character(int number) {
1183: if (number < 0 || number > 63) {
1184: return ' ';
1185: }
1186: return BASE_64_ENCODING.charAt(number);
1187: }
1188:
1189: // Encode a non-negative number as a variable length string, with the
1190: // property that if X > Y then the encoding of X is lexicographically
1191: // greater than the enocding of Y. This is accomplished by encoding the
1192: // length of the string at the beginning of the string. The string is a
1193: // series of base 64 (6-bit) characters. The first three bits of the first
1194: // character indicate the number of additional characters in the string.
1195: // The last three bits of the first character and all of the rest of the
1196: // characters encode the actual value of the number. Examples:
1197: // 0 --> 000 000 --> "-"
1198: // 7 --> 000 111 --> "6"
1199: // 8 --> 001 000 001000 --> "77"
1200: // 63 --> 001 000 111111 --> "7z"
1201: // 64 --> 001 001 000000 --> "8-"
1202: // 511 --> 001 111 111111 --> "Dz"
1203: // 512 --> 010 000 001000 000000 --> "E7-"
1204: // 2^32 - 1 --> 101 011 111111 ... 111111 --> "fzzzzz"
1205: // 2^45 - 1 --> 111 111 111111 ... 111111 --> "zzzzzzzz"
1206: // (There are some wasted values in this encoding. For example,
1207: // "7-" through "76" and "E--" through "E6z" are not legal encodings of
1208: // any number. But the benefit of filling in those wasted ranges would not
1209: // be worth the added complexity.)
1210: private static String lengthPrefixBase64(long number) {
1211: int length = 7;
1212: for (int i = 0; i < 7; ++i) {
1213: if (number < (1L << ((i * 6) + 3))) {
1214: length = i;
1215: break;
1216: }
1217: }
1218: StringBuffer result = new StringBuffer(length + 1);
1219: result.append(base64Character((length << 3)
1220: + (int) ((number >> (6 * length)) & 0x7)));
1221: while (--length >= 0) {
1222: result
1223: .append(base64Character((int) ((number >> (6 * length)) & 0x3f)));
1224: }
1225: return result.toString();
1226: }
1227:
1228: private static int charValue(char c) {
1229: int index = BASE_64_ENCODING.indexOf(c);
1230: // The "+ 1" is very intentional. For a blank (or anything else that
1231: // is not a legal character), we want to return 0. For legal
1232: // characters, we want to return one greater than their position, so
1233: // that a blank is correctly distinguished from '-'.
1234: return index + 1;
1235: }
1236:
1237: private static void appendEncodedCharacter(StringBuffer buffer,
1238: int c) {
1239: while (c > 62) {
1240: buffer.append('z');
1241: c -= 63;
1242: }
1243: buffer.append(base64Character(c));
1244: }
1245:
1246: private static int getIntProperty(String property, int defaultValue) {
1247: int result = defaultValue;
1248: if (property != null) {
1249: try {
1250: result = Integer.parseInt(property);
1251: if (result < 1) {
1252: // It has to be a positive integer. Use the default.
1253: result = defaultValue;
1254: }
1255: } catch (NumberFormatException e) {
1256: // Leave as default value
1257: }
1258: }
1259: return result;
1260: }
1261:
1262: private String generateFeatureVersionSuffix(
1263: BuildTimeFeature buildFeature) throws CoreException {
1264: if (!generateVersionSuffix
1265: || buildFeature.getContextQualifierLength() == -1) {
1266: return null; // do nothing
1267: }
1268:
1269: Properties properties = getBuildProperties();
1270: int significantDigits = getIntProperty((String) properties
1271: .get(PROPERTY_SIGNIFICANT_VERSION_DIGITS), -1);
1272: if (significantDigits == -1)
1273: significantDigits = getIntProperty(
1274: AbstractScriptGenerator
1275: .getImmutableAntProperty(PROPERTY_SIGNIFICANT_VERSION_DIGITS),
1276: Integer.MAX_VALUE);
1277: int maxGeneratedLength = getIntProperty((String) properties
1278: .get(PROPERTY_GENERATED_VERSION_LENGTH), -1);
1279: if (maxGeneratedLength == -1)
1280: maxGeneratedLength = getIntProperty(
1281: AbstractScriptGenerator
1282: .getImmutableAntProperty(PROPERTY_GENERATED_VERSION_LENGTH),
1283: 28);
1284:
1285: long majorSum = 0L;
1286: long minorSum = 0L;
1287: long serviceSum = 0L;
1288:
1289: // Include the version of this algorithm as part of the suffix, so that
1290: // we have a way to make sure all suffixes increase when the algorithm
1291: // changes.
1292: majorSum += QUALIFIER_SUFFIX_VERSION;
1293:
1294: IIncludedFeatureReference[] referencedFeatures = buildFeature
1295: .getIncludedFeatureReferences();
1296: IPluginEntry[] pluginList = buildFeature.getRawPluginEntries();
1297: int numElements = pluginList.length + referencedFeatures.length;
1298: if (numElements == 0) {
1299: // Empty feature.
1300: return null;
1301: }
1302: String[] qualifiers = new String[numElements];
1303: int idx = -1;
1304:
1305: // Loop through the included features, adding the version number parts
1306: // to the running totals and storing the qualifier suffixes.
1307: for (int i = 0; i < referencedFeatures.length; i++) {
1308: BuildTimeFeature refFeature = (BuildTimeFeature) getSite(
1309: false).findFeature(
1310: referencedFeatures[i].getVersionedIdentifier()
1311: .getIdentifier(), null, false);
1312: if (refFeature == null) {
1313: qualifiers[++idx] = ""; //$NON-NLS-1$
1314: continue;
1315: }
1316: PluginVersionIdentifier version = refFeature
1317: .getVersionedIdentifier().getVersion();
1318: majorSum += version.getMajorComponent();
1319: minorSum += version.getMinorComponent();
1320: serviceSum += version.getServiceComponent();
1321: int contextLength = refFeature.getContextQualifierLength();
1322: ++contextLength; //account for the '-' separating the context qualifier and suffix
1323: String qualifier = version.getQualifierComponent();
1324: // The entire qualifier of the nested feature is often too long to
1325: // include in the suffix computation for the containing feature,
1326: // and using it would result in extremely long qualifiers for
1327: // umbrella features. So instead we want to use just the suffix
1328: // part of the qualifier, or just the context part (if there is no
1329: // suffix part). See bug #162022.
1330: if (qualifier.length() > contextLength) {
1331: // Use the suffix part
1332: qualifiers[++idx] = qualifier.substring(contextLength);
1333: } else {
1334: // Use the context part
1335: qualifiers[++idx] = qualifier;
1336: }
1337: }
1338:
1339: // Loop through the included plug-ins and fragments, adding the version
1340: // number parts to the running totals and storing the qualifiers.
1341:
1342: for (int i = 0; i < pluginList.length; i++) {
1343: IPluginEntry entry = pluginList[i];
1344: VersionedIdentifier identifier = entry
1345: .getVersionedIdentifier();
1346: String versionRequested = identifier.getVersion()
1347: .toString();
1348: BundleDescription model = getSite(false).getRegistry()
1349: .getBundle(identifier.getIdentifier(),
1350: versionRequested, false);
1351: Version version = null;
1352: if (model != null) {
1353: version = model.getVersion();
1354: } else {
1355: if (versionRequested.endsWith(PROPERTY_QUALIFIER)) {
1356: int resultingLength = versionRequested.length()
1357: - PROPERTY_QUALIFIER.length();
1358: if (versionRequested.charAt(resultingLength - 1) == '.')
1359: resultingLength--;
1360: versionRequested = versionRequested.substring(0,
1361: resultingLength);
1362: }
1363: version = new Version(versionRequested);
1364: }
1365:
1366: majorSum += version.getMajor();
1367: minorSum += version.getMinor();
1368: serviceSum += version.getMicro();
1369: qualifiers[++idx] = version.getQualifier();
1370: }
1371:
1372: // Limit the qualifiers to the specified number of significant digits,
1373: // and figure out what the longest qualifier is.
1374: int longestQualifier = 0;
1375: for (int i = 0; i < numElements; ++i) {
1376: if (qualifiers[i].length() > significantDigits) {
1377: qualifiers[i] = qualifiers[i].substring(0,
1378: significantDigits);
1379: }
1380: if (qualifiers[i].length() > longestQualifier) {
1381: longestQualifier = qualifiers[i].length();
1382: }
1383: }
1384:
1385: StringBuffer result = new StringBuffer();
1386:
1387: // Encode the sums of the first three parts of the version numbers.
1388: result.append(lengthPrefixBase64(majorSum));
1389: result.append(lengthPrefixBase64(minorSum));
1390: result.append(lengthPrefixBase64(serviceSum));
1391:
1392: if (longestQualifier > 0) {
1393: // Calculate the sum at each position of the qualifiers.
1394: int[] qualifierSums = new int[longestQualifier];
1395: for (int i = 0; i < numElements; ++i) {
1396: for (int j = 0; j < qualifiers[i].length(); ++j) {
1397: qualifierSums[j] += charValue(qualifiers[i]
1398: .charAt(j));
1399: }
1400: }
1401: // Normalize the sums to be base 65.
1402: int carry = 0;
1403: for (int k = longestQualifier - 1; k >= 1; --k) {
1404: qualifierSums[k] += carry;
1405: carry = qualifierSums[k] / 65;
1406: qualifierSums[k] = qualifierSums[k] % 65;
1407: }
1408: qualifierSums[0] += carry;
1409:
1410: // Always use one character for overflow. This will be handled
1411: // correctly even when the overflow character itself overflows.
1412: result.append(lengthPrefixBase64(qualifierSums[0]));
1413: for (int m = 1; m < longestQualifier; ++m) {
1414: appendEncodedCharacter(result, qualifierSums[m]);
1415: }
1416: }
1417: // It is safe to strip any '-' characters from the end of the suffix.
1418: // (This won't happen very often, but it will save us a character or
1419: // two when it does.)
1420: while (result.length() > 0
1421: && result.charAt(result.length() - 1) == '-') {
1422: result.deleteCharAt(result.length() - 1);
1423: }
1424:
1425: // If the resulting suffix is too long, shorten it to the designed length.
1426: if (maxGeneratedLength > result.length()) {
1427: return result.toString();
1428: }
1429: return result.substring(0, maxGeneratedLength);
1430: }
1431:
1432: /**
1433: * @param models
1434: * @throws CoreException
1435: */
1436: private void generateModels(List models) throws CoreException {
1437: if (scriptGeneration == false)
1438: return;
1439: if (binaryFeature == false || models.isEmpty())
1440: return;
1441:
1442: Set generatedScripts = new HashSet(models.size());
1443: for (Iterator iterator = models.iterator(); iterator.hasNext();) {
1444: BundleDescription model = (BundleDescription) iterator
1445: .next();
1446: if (generatedScripts.contains(model))
1447: continue;
1448: generatedScripts.add(model);
1449:
1450: //Get the corresponding plug-in entries (from a feature object) associated with the model
1451: //and generate the script if one the configuration is being built. The generated scripts
1452: //are configuration agnostic so we only generate once.
1453: Set matchingEntries = (Set) ((Properties) model
1454: .getUserObject()).get(PLUGIN_ENTRY);
1455: if (matchingEntries.isEmpty())
1456: return;
1457:
1458: Iterator entryIter = matchingEntries.iterator();
1459: IPluginEntry correspondingEntry = (IPluginEntry) entryIter
1460: .next();
1461: List list = selectConfigs(correspondingEntry);
1462: if (list.size() == 0)
1463: continue;
1464:
1465: ModelBuildScriptGenerator generator = new ModelBuildScriptGenerator();
1466: generator.setBuildSiteFactory(siteFactory);
1467: generator.setCompiledElements(getCompiledElements());
1468: generator
1469: .setIgnoreMissingPropertiesFile(isIgnoreMissingPropertiesFile());
1470: generator.setModel(model); // setModel has to be called before configurePersistentProperties because it reads the model's properties
1471: generator.setFeatureGenerator(this );
1472: generator.setPluginPath(getPluginPath());
1473: generator.setBuildingOSGi(isBuildingOSGi());
1474: generator.setDevEntries(devEntries);
1475: generator
1476: .includePlatformIndependent(isPlatformIndependentIncluded());
1477: generator.setSignJars(signJars);
1478: generator.setAssociatedEntry(correspondingEntry);
1479: generator.generate();
1480: }
1481:
1482: }
1483:
1484: /**
1485: * Set this object's feature id to be the given value.
1486: *
1487: * @param featureID the feature id
1488: * @throws CoreException if the given feature id is <code>null</code>
1489: */
1490: public void setFeature(String featureID) throws CoreException {
1491: if (featureID == null) {
1492: throw new CoreException(new Status(IStatus.ERROR,
1493: PI_PDEBUILD, EXCEPTION_FEATURE_MISSING,
1494: Messages.error_missingFeatureId, null));
1495: }
1496: this .featureIdentifier = featureID;
1497: }
1498:
1499: public static String getNormalizedName(IFeature feature) {
1500: return feature.getVersionedIdentifier().toString();
1501: }
1502:
1503: private void initializeVariables() throws CoreException {
1504: feature = getSite(false).findFeature(featureIdentifier,
1505: searchedVersion, true);
1506:
1507: if (featureRootLocation == null) {
1508: featureRootLocation = feature.getURL().getPath();
1509: int i = featureRootLocation
1510: .lastIndexOf(Constants.FEATURE_FILENAME_DESCRIPTOR);
1511: if (i != -1)
1512: featureRootLocation = featureRootLocation.substring(0,
1513: i);
1514: }
1515: initializeFeatureNames();
1516:
1517: if (feature instanceof BuildTimeFeature) {
1518: if (getBuildProperties() == MissingProperties.getInstance()
1519: || AbstractScriptGenerator
1520: .getPropertyAsBoolean(IBuildPropertiesConstants.PROPERTY_PACKAGER_MODE)) {
1521: BuildTimeFeature buildFeature = (BuildTimeFeature) feature;
1522: scriptGeneration = false;
1523: buildFeature.setBinary(true);
1524: }
1525: }
1526:
1527: Properties properties = getBuildProperties();
1528: customFeatureCallbacks = properties
1529: .getProperty(PROPERTY_CUSTOM_BUILD_CALLBACKS);
1530: if (TRUE.equalsIgnoreCase(customFeatureCallbacks))
1531: customFeatureCallbacks = DEFAULT_CUSTOM_BUILD_CALLBACKS_FILE;
1532: else if (FALSE.equalsIgnoreCase(customFeatureCallbacks))
1533: customFeatureCallbacks = null;
1534: customCallbacksBuildpath = properties.getProperty(
1535: PROPERTY_CUSTOM_CALLBACKS_BUILDPATH, "."); //$NON-NLS-1$
1536: customCallbacksFailOnError = properties.getProperty(
1537: PROPERTY_CUSTOM_CALLBACKS_FAILONERROR, FALSE);
1538: customCallbacksInheritAll = properties
1539: .getProperty(PROPERTY_CUSTOM_CALLBACKS_INHERITALL);
1540: }
1541:
1542: private void initializeFeatureNames() throws CoreException {
1543: featureFullName = getNormalizedName(feature);
1544: featureFolderName = DEFAULT_FEATURE_LOCATION + '/'
1545: + featureFullName;
1546: sourceFeatureFullName = computeSourceFeatureName(feature, false);
1547: sourceFeatureFullNameVersionned = computeSourceFeatureName(
1548: feature, true);
1549: featureTempFolder = Utils
1550: .getPropertyFormat(PROPERTY_FEATURE_TEMP_FOLDER);
1551: }
1552:
1553: public void setSourceFeatureId(String id) {
1554: sourceFeatureFullName = id;
1555: }
1556:
1557: private String computeSourceFeatureName(IFeature featureForName,
1558: boolean withNumber) throws CoreException {
1559: String sourceFeatureName = getBuildProperties().getProperty(
1560: PROPERTY_SOURCE_FEATURE_NAME);
1561: if (sourceFeatureName == null)
1562: sourceFeatureName = sourceFeatureFullName;
1563: if (sourceFeatureName == null)
1564: sourceFeatureName = featureForName.getVersionedIdentifier()
1565: .getIdentifier()
1566: + ".source"; //$NON-NLS-1$
1567: return sourceFeatureName
1568: + (withNumber ? "_" + featureForName.getVersionedIdentifier().getVersion().toString() : ""); //$NON-NLS-1$ //$NON-NLS-2$
1569: }
1570:
1571: /**
1572: * Return a properties object constructed from the build.properties file
1573: * for the given feature. If no file exists, then an empty properties
1574: * object is returned.
1575: *
1576: * @return Properties the feature's build.properties
1577: * @throws CoreException
1578: * @see Feature
1579: */
1580: protected Properties getBuildProperties() throws CoreException {
1581: if (buildProperties == null)
1582: buildProperties = readProperties(featureRootLocation,
1583: PROPERTIES_FILE,
1584: isIgnoreMissingPropertiesFile() ? IStatus.OK
1585: : IStatus.WARNING);
1586: return buildProperties;
1587: }
1588:
1589: /**
1590: * Add the <code>children</code> target to the given Ant script.
1591: * Delegates some target call to all-template only if the property
1592: * includeChildren is set.
1593: */
1594: private void generateChildrenTarget() {
1595: script.println();
1596: script.printTargetDeclaration(TARGET_CHILDREN, null,
1597: PROPERTY_INCLUDE_CHILDREN, null, null);
1598: script.printAntCallTask(TARGET_ALL_CHILDREN, true, null);
1599: script.printTargetEnd();
1600: }
1601:
1602: /**
1603: * Add the <code>build.jars</code> target to the given Ant script.
1604: */
1605: private void generateBuildJarsTarget() {
1606: script.println();
1607: script.printTargetDeclaration(TARGET_BUILD_JARS, TARGET_INIT,
1608: null, null, NLS.bind(Messages.build_feature_buildJars,
1609: featureIdentifier));
1610: Map params = new HashMap(1);
1611: params.put(PROPERTY_TARGET, TARGET_BUILD_JARS);
1612: script.printAntCallTask(TARGET_ALL_CHILDREN, true, params);
1613: script.printTargetEnd();
1614: script.println();
1615: script.printTargetDeclaration(TARGET_BUILD_SOURCES,
1616: TARGET_INIT, null, null, null);
1617: params.clear();
1618: params.put(PROPERTY_TARGET, TARGET_BUILD_SOURCES);
1619: script.printAntCallTask(TARGET_ALL_CHILDREN, true, params);
1620: script.printTargetEnd();
1621: }
1622:
1623: /**
1624: * Add the <code>refresh</code> target to the given Ant script.
1625: */
1626: private void generateRefreshTarget() {
1627: script.println();
1628: script.printTargetDeclaration(TARGET_REFRESH, TARGET_INIT,
1629: PROPERTY_ECLIPSE_RUNNING, null, NLS.bind(
1630: Messages.build_feature_refresh,
1631: featureIdentifier));
1632: script.printConvertPathTask(new Path(featureRootLocation)
1633: .removeLastSegments(0).toOSString().replace('\\', '/'),
1634: PROPERTY_RESOURCE_PATH, false);
1635: script.printRefreshLocalTask(Utils
1636: .getPropertyFormat(PROPERTY_RESOURCE_PATH), "infinite"); //$NON-NLS-1$
1637: Map params = new HashMap(2);
1638: params.put(PROPERTY_TARGET, TARGET_REFRESH);
1639: script.printAntCallTask(TARGET_ALL_CHILDREN, true, params);
1640: script.printTargetEnd();
1641: }
1642:
1643: public void setGenerateIncludedFeatures(boolean recursiveGeneration) {
1644: analyseIncludedFeatures = recursiveGeneration;
1645: }
1646:
1647: protected void collectElementToAssemble(IFeature featureToCollect)
1648: throws CoreException {
1649: if (assemblyData == null)
1650: return;
1651:
1652: /* collect binary features */
1653: if (featureToCollect instanceof BuildTimeFeature
1654: && ((BuildTimeFeature) featureToCollect).isBinary()) {
1655: basicCollectElementToAssemble(featureToCollect);
1656: return;
1657: }
1658:
1659: // don't collect if bin.includes is empty, or we are generating source;
1660: if (getBuildProperties().get(PROPERTY_BIN_INCLUDES) == null
1661: || sourceFeatureGeneration)
1662: return;
1663:
1664: basicCollectElementToAssemble(featureToCollect);
1665: }
1666:
1667: private void basicCollectElementToAssemble(IFeature featureToCollect) {
1668: if (assemblyData == null)
1669: return;
1670: List correctConfigs = selectConfigs(featureToCollect);
1671: // Here, we could sort if the feature is a common one or not by
1672: // comparing the size of correctConfigs
1673: for (Iterator iter = correctConfigs.iterator(); iter.hasNext();) {
1674: Config config = (Config) iter.next();
1675: assemblyData.addFeature(config, feature);
1676: }
1677: }
1678:
1679: /**
1680: * Method generateSourceFeature.
1681: */
1682: private void generateSourceFeature() throws CoreException {
1683: Feature featureExample = (Feature) feature;
1684: sourceFeature = createSourceFeature(featureExample);
1685: associateExtraPluginsAndFeatures();
1686: if (isBuildingOSGi())
1687: sourcePlugin = create30SourcePlugin();
1688: else
1689: sourcePlugin = createSourcePlugin();
1690:
1691: generateSourceFragment();
1692: }
1693:
1694: private void generateSourceFragment() throws CoreException {
1695: Map fragments = sourceToGather.getElementEntries();
1696: for (Iterator iter = fragments.entrySet().iterator(); iter
1697: .hasNext();) {
1698: Map.Entry fragmentInfo = (Map.Entry) iter.next();
1699: Config configInfo = (Config) fragmentInfo.getKey();
1700: if (configInfo.equals(Config.genericConfig()))
1701: continue;
1702: PluginEntry sourceFragment = new PluginEntry();
1703: String sourceFragmentId = sourceFeature
1704: .getFeatureIdentifier()
1705: + "." + configInfo.toString("."); //$NON-NLS-1$ //$NON-NLS-2$
1706: sourceFragment.setPluginIdentifier(sourceFragmentId);
1707: sourceFragment.setPluginVersion(sourceFeature
1708: .getFeatureVersion());
1709: sourceFragment.setOS(configInfo.getOs());
1710: sourceFragment.setWS(configInfo.getWs());
1711: sourceFragment.setArch(configInfo.getArch());
1712: sourceFragment.isFragment(true);
1713: //sourceFeature.addPluginEntryModel(sourceFragment);
1714: if (isBuildingOSGi())
1715: create30SourceFragment(sourceFragment, sourcePlugin);
1716: else
1717: createSourceFragment(sourceFragment, sourcePlugin);
1718: }
1719: }
1720:
1721: //Add the relevant source fragments to the source feature
1722: private void addSourceFragmentsToFeature() {
1723: Map fragments = sourceToGather.getElementEntries();
1724: for (Iterator iter = fragments.entrySet().iterator(); iter
1725: .hasNext();) {
1726: Map.Entry fragmentInfo = (Map.Entry) iter.next();
1727: Config configInfo = (Config) fragmentInfo.getKey();
1728: if (configInfo.equals(Config.genericConfig()))
1729: continue;
1730: Set sourceList = (Set) fragmentInfo.getValue();
1731: if (sourceList.size() == 0)
1732: continue;
1733: PluginEntry sourceFragment = new PluginEntry();
1734: String sourceFragmentId = sourceFeature
1735: .getFeatureIdentifier()
1736: + "." + configInfo.toString("."); //$NON-NLS-1$ //$NON-NLS-2$
1737: sourceFragment.setPluginIdentifier(sourceFragmentId);
1738: sourceFragment.setPluginVersion(sourceFeature
1739: .getFeatureVersion());
1740: sourceFragment.setOS(configInfo.getOs());
1741: sourceFragment.setWS(configInfo.getWs());
1742: sourceFragment.setArch(configInfo.getArch());
1743: sourceFragment.isFragment(true);
1744: sourceFeature.addPluginEntryModel(sourceFragment);
1745: //createSourceFragment(sourceFragment, sourcePlugin);
1746: }
1747: }
1748:
1749: private void generateSourceFeatureScripts() throws CoreException {
1750: FeatureBuildScriptGenerator sourceScriptGenerator = new FeatureBuildScriptGenerator(
1751: sourceFeatureFullName, sourceFeature
1752: .getFeatureVersion(), assemblyData);
1753: sourceScriptGenerator.setGenerateIncludedFeatures(true);
1754: sourceScriptGenerator.setAnalyseChildren(true);
1755: sourceScriptGenerator.setSourceToGather(sourceToGather);
1756: sourceScriptGenerator.setBinaryFeatureGeneration(true);
1757: sourceScriptGenerator.setSourceFeatureGeneration(false);
1758: sourceScriptGenerator.setScriptGeneration(true);
1759: sourceScriptGenerator.setPluginPath(pluginPath);
1760: sourceScriptGenerator.setBuildSiteFactory(siteFactory);
1761: sourceScriptGenerator.setDevEntries(devEntries);
1762: sourceScriptGenerator
1763: .setCompiledElements(getCompiledElements());
1764: sourceScriptGenerator.setSourcePluginOnly(sourcePluginOnly);
1765: sourceScriptGenerator.setBuildingOSGi(isBuildingOSGi());
1766: sourceScriptGenerator
1767: .includePlatformIndependent(isPlatformIndependentIncluded());
1768: sourceScriptGenerator
1769: .setIgnoreMissingPropertiesFile(isIgnoreMissingPropertiesFile());
1770: sourceScriptGenerator
1771: .setGenerateVersionSuffix(generateVersionSuffix);
1772: sourceScriptGenerator.generate();
1773: }
1774:
1775: // Add extra plugins into the given feature.
1776: private void associateExtraPluginsAndFeatures()
1777: throws CoreException {
1778: for (int i = 1; i < extraPlugins.length; i++) {
1779: BundleDescription model;
1780: // see if we have a plug-in or a fragment
1781: if (extraPlugins[i].startsWith("feature@")) { //$NON-NLS-1$
1782: String id = extraPlugins[i].substring(8);
1783: IncludedFeatureReference include = new IncludedFeatureReference();
1784: include.setFeatureIdentifier(id);
1785: include.setFeatureVersion(GENERIC_VERSION_NUMBER);
1786: sourceFeature.addIncludedFeatureReferenceModel(include);
1787: } else {
1788: Object[] items = Utils.parseExtraBundlesString(
1789: extraPlugins[i], true);
1790: model = getSite(false).getRegistry().getResolvedBundle(
1791: (String) items[0],
1792: ((Version) items[1]).toString());
1793: if (model == null) {
1794: String message = NLS.bind(
1795: Messages.exception_missingPlugin,
1796: extraPlugins[i]);
1797: BundleHelper.getDefault().getLog().log(
1798: new Status(IStatus.WARNING,
1799: extraPlugins[i],
1800: EXCEPTION_PLUGIN_MISSING, message,
1801: null));
1802: continue;
1803: }
1804: PluginEntry entry = new PluginEntry();
1805: entry.setPluginIdentifier(model.getSymbolicName());
1806: entry.setPluginVersion(model.getVersion().toString());
1807: entry.setUnpack(((Boolean) items[2]).booleanValue());
1808: sourceFeature.addPluginEntryModel(entry);
1809: }
1810: }
1811: }
1812:
1813: private PluginEntry create30SourcePlugin() throws CoreException {
1814: //Create an object representing the plugin
1815: PluginEntry result = new PluginEntry();
1816: String sourcePluginId = sourceFeature.getFeatureIdentifier();
1817: result.setPluginIdentifier(sourcePluginId);
1818: result.setPluginVersion(sourceFeature.getFeatureVersion());
1819: sourceFeature.addPluginEntryModel(result);
1820: // create the directory for the plugin
1821: IPath sourcePluginDirURL = new Path(workingDirectory + '/'
1822: + DEFAULT_PLUGIN_LOCATION + '/'
1823: + getSourcePluginName(result, false));
1824: File sourcePluginDir = sourcePluginDirURL.toFile();
1825: new File(sourcePluginDir, "META-INF").mkdirs(); //$NON-NLS-1$
1826:
1827: // Create the MANIFEST.MF
1828: StringBuffer buffer;
1829: Path templateManifest = new Path(TEMPLATE
1830: + "/30/plugin/" + Constants.BUNDLE_FILENAME_DESCRIPTOR); //$NON-NLS-1$
1831: URL templateManifestURL = BundleHelper.getDefault().find(
1832: templateManifest);
1833: if (templateManifestURL == null) {
1834: IStatus status = new Status(IStatus.WARNING, PI_PDEBUILD,
1835: IPDEBuildConstants.EXCEPTION_READING_FILE, NLS
1836: .bind(Messages.error_readingDirectory,
1837: templateManifest), null);
1838: BundleHelper.getDefault().getLog().log(status);
1839: return null;
1840: }
1841: try {
1842: buffer = readFile(templateManifestURL.openStream());
1843: } catch (IOException e1) {
1844: String message = NLS.bind(Messages.exception_readingFile,
1845: templateManifestURL.toExternalForm());
1846: throw new CoreException(new Status(IStatus.ERROR,
1847: PI_PDEBUILD, EXCEPTION_READING_FILE, message, e1));
1848: }
1849: int beginId = scan(buffer, 0, REPLACED_PLUGIN_ID);
1850: buffer.replace(beginId, beginId + REPLACED_PLUGIN_ID.length(),
1851: result.getPluginIdentifier());
1852: //set the version number
1853: beginId = scan(buffer, beginId, REPLACED_PLUGIN_VERSION);
1854: buffer.replace(beginId, beginId
1855: + REPLACED_PLUGIN_VERSION.length(), result
1856: .getPluginVersion());
1857: try {
1858: Utils.transferStreams(new ByteArrayInputStream(buffer
1859: .toString().getBytes()), new FileOutputStream(
1860: sourcePluginDirURL.append(
1861: Constants.BUNDLE_FILENAME_DESCRIPTOR)
1862: .toOSString()));
1863: } catch (IOException e1) {
1864: String message = NLS.bind(Messages.exception_writingFile,
1865: templateManifestURL.toExternalForm());
1866: throw new CoreException(new Status(IStatus.ERROR,
1867: PI_PDEBUILD, EXCEPTION_READING_FILE, message, e1));
1868: }
1869:
1870: //Copy the plugin.xml
1871: try {
1872: InputStream pluginXML = BundleHelper
1873: .getDefault()
1874: .getBundle()
1875: .getEntry(TEMPLATE + "/30/plugin/plugin.xml").openStream(); //$NON-NLS-1$
1876: Utils.transferStreams(pluginXML, new FileOutputStream(
1877: sourcePluginDirURL.append(
1878: Constants.PLUGIN_FILENAME_DESCRIPTOR)
1879: .toOSString()));
1880: } catch (IOException e1) {
1881: String message = NLS.bind(Messages.exception_readingFile,
1882: TEMPLATE + "/30/plugin/plugin.xml"); //$NON-NLS-1$
1883: throw new CoreException(new Status(IStatus.ERROR,
1884: PI_PDEBUILD, EXCEPTION_WRITING_FILE, message, e1));
1885: }
1886:
1887: //Copy the other files
1888: Collection copiedFiles = Utils
1889: .copyFiles(
1890: featureRootLocation + '/'
1891: + "sourceTemplatePlugin", sourcePluginDir.getAbsolutePath()); //$NON-NLS-1$
1892: if (copiedFiles.contains(Constants.BUNDLE_FILENAME_DESCRIPTOR)) {
1893: //make sure the manifest.mf has the version we want
1894: replaceManifestValue(sourcePluginDirURL.append(
1895: Constants.BUNDLE_FILENAME_DESCRIPTOR).toOSString(),
1896: org.osgi.framework.Constants.BUNDLE_VERSION, result
1897: .getPluginVersion()); //$NON-NLS-1$
1898: }
1899:
1900: // If a build.properties file already exist then we use it supposing it is correct.
1901: File buildProperty = sourcePluginDirURL.append(PROPERTIES_FILE)
1902: .toFile();
1903: if (!buildProperty.exists()) {
1904: copiedFiles.add(Constants.PLUGIN_FILENAME_DESCRIPTOR); //Because the plugin.xml is not copied, we need to add it to the file
1905: copiedFiles.add("src/**/*.zip"); //$NON-NLS-1$
1906: copiedFiles.add(Constants.BUNDLE_FILENAME_DESCRIPTOR);//Because the manifest.mf is not copied, we need to add it to the file
1907: Properties sourceBuildProperties = new Properties();
1908: sourceBuildProperties.put(PROPERTY_BIN_INCLUDES, Utils
1909: .getStringFromCollection(copiedFiles, ",")); //$NON-NLS-1$
1910: sourceBuildProperties.put(SOURCE_PLUGIN_ATTRIBUTE, "true"); //$NON-NLS-1$
1911: try {
1912: OutputStream buildFile = new BufferedOutputStream(
1913: new FileOutputStream(buildProperty));
1914: try {
1915: sourceBuildProperties.store(buildFile, null);
1916: } finally {
1917: buildFile.close();
1918: }
1919: } catch (FileNotFoundException e) {
1920: String message = NLS.bind(
1921: Messages.exception_writingFile, buildProperty
1922: .getAbsolutePath());
1923: throw new CoreException(
1924: new Status(IStatus.ERROR, PI_PDEBUILD,
1925: EXCEPTION_WRITING_FILE, message, e));
1926: } catch (IOException e) {
1927: String message = NLS.bind(
1928: Messages.exception_writingFile, buildProperty
1929: .getAbsolutePath());
1930: throw new CoreException(
1931: new Status(IStatus.ERROR, PI_PDEBUILD,
1932: EXCEPTION_WRITING_FILE, message, e));
1933: }
1934: }
1935:
1936: PDEState state = getSite(false).getRegistry();
1937: BundleDescription oldBundle = state.getResolvedBundle(result
1938: .getPluginIdentifier());
1939: if (oldBundle != null)
1940: state.getState().removeBundle(oldBundle);
1941: state.addBundle(sourcePluginDir);
1942:
1943: return result;
1944: }
1945:
1946: /**
1947: * Method createSourcePlugin.
1948: */
1949: private PluginEntry createSourcePlugin() throws CoreException {
1950: //Create an object representing the plugin
1951: PluginEntry result = new PluginEntry();
1952: String sourcePluginId = sourceFeature.getFeatureIdentifier();
1953: result.setPluginIdentifier(sourcePluginId);
1954: result.setPluginVersion(sourceFeature.getFeatureVersion());
1955: sourceFeature.addPluginEntryModel(result);
1956: // create the directory for the plugin
1957: IPath sourcePluginDirURL = new Path(workingDirectory + '/'
1958: + DEFAULT_PLUGIN_LOCATION + '/'
1959: + getSourcePluginName(result, false));
1960: File sourcePluginDir = sourcePluginDirURL.toFile();
1961: sourcePluginDir.mkdirs();
1962:
1963: // Create the plugin.xml
1964: StringBuffer buffer;
1965: Path templatePluginXML = new Path(TEMPLATE
1966: + "/21/plugin/" + Constants.PLUGIN_FILENAME_DESCRIPTOR); //$NON-NLS-1$
1967: URL templatePluginURL = BundleHelper.getDefault().find(
1968: templatePluginXML);
1969: if (templatePluginURL == null) {
1970: IStatus status = new Status(IStatus.WARNING, PI_PDEBUILD,
1971: IPDEBuildConstants.EXCEPTION_READING_FILE, NLS
1972: .bind(Messages.error_readingDirectory,
1973: templatePluginXML), null);
1974: BundleHelper.getDefault().getLog().log(status);
1975: return null;
1976: }
1977: try {
1978: buffer = readFile(templatePluginURL.openStream());
1979: } catch (IOException e1) {
1980: String message = NLS.bind(Messages.exception_readingFile,
1981: templatePluginURL.toExternalForm());
1982: throw new CoreException(new Status(IStatus.ERROR,
1983: PI_PDEBUILD, EXCEPTION_READING_FILE, message, e1));
1984: }
1985: int beginId = scan(buffer, 0, REPLACED_PLUGIN_ID);
1986: buffer.replace(beginId, beginId + REPLACED_PLUGIN_ID.length(),
1987: result.getPluginIdentifier());
1988: //set the version number
1989: beginId = scan(buffer, beginId, REPLACED_PLUGIN_VERSION);
1990: buffer.replace(beginId, beginId
1991: + REPLACED_PLUGIN_VERSION.length(), result
1992: .getPluginVersion());
1993: try {
1994: Utils.transferStreams(new ByteArrayInputStream(buffer
1995: .toString().getBytes()), new FileOutputStream(
1996: sourcePluginDirURL.append(
1997: Constants.PLUGIN_FILENAME_DESCRIPTOR)
1998: .toOSString()));
1999: } catch (IOException e1) {
2000: String message = NLS.bind(Messages.exception_writingFile,
2001: templatePluginURL.toExternalForm());
2002: throw new CoreException(new Status(IStatus.ERROR,
2003: PI_PDEBUILD, EXCEPTION_READING_FILE, message, e1));
2004: }
2005: Collection copiedFiles = Utils
2006: .copyFiles(
2007: featureRootLocation + '/'
2008: + "sourceTemplatePlugin", sourcePluginDir.getAbsolutePath()); //$NON-NLS-1$
2009: if (copiedFiles.contains(Constants.PLUGIN_FILENAME_DESCRIPTOR)) {
2010: replaceXMLAttribute(sourcePluginDirURL.append(
2011: Constants.PLUGIN_FILENAME_DESCRIPTOR).toOSString(),
2012: PLUGIN_START_TAG, VERSION, result
2013: .getPluginVersion());
2014: }
2015: // If a build.properties file already exist then we use it supposing it is correct.
2016: File buildProperty = sourcePluginDirURL.append(PROPERTIES_FILE)
2017: .toFile();
2018: if (!buildProperty.exists()) {
2019: copiedFiles.add(Constants.PLUGIN_FILENAME_DESCRIPTOR); //Because the plugin.xml is not copied, we need to add it to the file
2020: copiedFiles.add("src/**/*.zip"); //$NON-NLS-1$
2021: Properties sourceBuildProperties = new Properties();
2022: sourceBuildProperties.put(PROPERTY_BIN_INCLUDES, Utils
2023: .getStringFromCollection(copiedFiles, ",")); //$NON-NLS-1$
2024: sourceBuildProperties.put(SOURCE_PLUGIN_ATTRIBUTE, "true"); //$NON-NLS-1$
2025: try {
2026: OutputStream buildFile = new BufferedOutputStream(
2027: new FileOutputStream(buildProperty));
2028: try {
2029: sourceBuildProperties.store(buildFile, null);
2030: } finally {
2031: buildFile.close();
2032: }
2033: } catch (FileNotFoundException e) {
2034: String message = NLS.bind(
2035: Messages.exception_writingFile, buildProperty
2036: .getAbsolutePath());
2037: throw new CoreException(
2038: new Status(IStatus.ERROR, PI_PDEBUILD,
2039: EXCEPTION_WRITING_FILE, message, e));
2040: } catch (IOException e) {
2041: String message = NLS.bind(
2042: Messages.exception_writingFile, buildProperty
2043: .getAbsolutePath());
2044: throw new CoreException(
2045: new Status(IStatus.ERROR, PI_PDEBUILD,
2046: EXCEPTION_WRITING_FILE, message, e));
2047: }
2048: }
2049: PDEState state = getSite(false).getRegistry();
2050: BundleDescription oldBundle = state.getResolvedBundle(result
2051: .getPluginIdentifier());
2052: if (oldBundle != null)
2053: state.getState().removeBundle(oldBundle);
2054: state.addBundle(sourcePluginDir);
2055: return result;
2056: }
2057:
2058: private void create30SourceFragment(PluginEntry fragment,
2059: PluginEntry plugin) throws CoreException {
2060: // create the directory for the plugin
2061: Path sourceFragmentDirURL = new Path(workingDirectory + '/'
2062: + DEFAULT_PLUGIN_LOCATION + '/'
2063: + getSourcePluginName(fragment, false));
2064: File sourceFragmentDir = new File(sourceFragmentDirURL
2065: .toOSString());
2066: new File(sourceFragmentDir, "META-INF").mkdirs(); //$NON-NLS-1$
2067: try {
2068: // read the content of the template file
2069: Path fragmentPath = new Path(
2070: TEMPLATE
2071: + "/30/fragment/" + Constants.BUNDLE_FILENAME_DESCRIPTOR);//$NON-NLS-1$
2072: URL templateLocation = BundleHelper.getDefault().find(
2073: fragmentPath);
2074: if (templateLocation == null) {
2075: IStatus status = new Status(IStatus.WARNING,
2076: PI_PDEBUILD,
2077: IPDEBuildConstants.EXCEPTION_READING_FILE, NLS
2078: .bind(Messages.error_readingDirectory,
2079: fragmentPath), null);
2080: BundleHelper.getDefault().getLog().log(status);
2081: return;
2082: }
2083:
2084: //Copy the fragment.xml
2085: try {
2086: InputStream fragmentXML = BundleHelper
2087: .getDefault()
2088: .getBundle()
2089: .getEntry(
2090: TEMPLATE + "/30/fragment/fragment.xml").openStream(); //$NON-NLS-1$
2091: Utils
2092: .transferStreams(
2093: fragmentXML,
2094: new FileOutputStream(
2095: sourceFragmentDirURL
2096: .append(
2097: Constants.FRAGMENT_FILENAME_DESCRIPTOR)
2098: .toOSString()));
2099: } catch (IOException e1) {
2100: String message = NLS.bind(
2101: Messages.exception_readingFile, TEMPLATE
2102: + "/30/fragment/fragment.xml"); //$NON-NLS-1$
2103: throw new CoreException(new Status(IStatus.ERROR,
2104: PI_PDEBUILD, EXCEPTION_WRITING_FILE, message,
2105: e1));
2106: }
2107:
2108: StringBuffer buffer = readFile(templateLocation
2109: .openStream());
2110: //Set the Id of the fragment
2111: int beginId = scan(buffer, 0, REPLACED_FRAGMENT_ID);
2112: buffer.replace(beginId, beginId
2113: + REPLACED_FRAGMENT_ID.length(), fragment
2114: .getPluginIdentifier());
2115: // set the version number
2116: beginId = scan(buffer, beginId, REPLACED_FRAGMENT_VERSION);
2117: buffer.replace(beginId, beginId
2118: + REPLACED_FRAGMENT_VERSION.length(), fragment
2119: .getPluginVersion());
2120: // Set the Id of the plugin for the fragment
2121: beginId = scan(buffer, beginId, REPLACED_PLUGIN_ID);
2122: buffer.replace(beginId, beginId
2123: + REPLACED_PLUGIN_ID.length(), plugin
2124: .getPluginIdentifier());
2125: // set the version number of the plugin to which the fragment is attached to
2126: BundleDescription effectivePlugin = getSite(false)
2127: .getRegistry().getResolvedBundle(
2128: plugin.getVersionedIdentifier()
2129: .getIdentifier(),
2130: plugin.getPluginVersion());
2131: beginId = scan(buffer, beginId, REPLACED_PLUGIN_VERSION);
2132: buffer.replace(beginId, beginId
2133: + REPLACED_PLUGIN_VERSION.length(), effectivePlugin
2134: .getVersion().toString());
2135: // Set the platform filter of the fragment
2136: beginId = scan(buffer, beginId, REPLACED_PLATFORM_FILTER);
2137: buffer.replace(beginId, beginId
2138: + REPLACED_PLATFORM_FILTER.length(), "(& (osgi.ws="
2139: + fragment.getWS() + ") (osgi.os="
2140: + fragment.getOS() + ") (osgi.arch="
2141: + fragment.getOSArch() + "))");
2142:
2143: Utils.transferStreams(new ByteArrayInputStream(buffer
2144: .toString().getBytes()), new FileOutputStream(
2145: sourceFragmentDirURL.append(
2146: Constants.BUNDLE_FILENAME_DESCRIPTOR)
2147: .toOSString()));
2148: Collection copiedFiles = Utils
2149: .copyFiles(
2150: featureRootLocation + '/'
2151: + "sourceTemplateFragment", sourceFragmentDir.getAbsolutePath()); //$NON-NLS-1$
2152: if (copiedFiles
2153: .contains(Constants.BUNDLE_FILENAME_DESCRIPTOR)) {
2154: //make sure the manifest.mf has the versions we want
2155: replaceManifestValue(sourceFragmentDirURL.append(
2156: Constants.BUNDLE_FILENAME_DESCRIPTOR)
2157: .toOSString(),
2158: org.osgi.framework.Constants.BUNDLE_VERSION,
2159: fragment.getPluginVersion());
2160: String host = plugin.getPluginIdentifier() + ';'
2161: + org.osgi.framework.Constants.BUNDLE_VERSION
2162: + '=' + effectivePlugin.getVersion().toString();
2163: replaceManifestValue(sourceFragmentDirURL.append(
2164: Constants.BUNDLE_FILENAME_DESCRIPTOR)
2165: .toOSString(),
2166: org.osgi.framework.Constants.FRAGMENT_HOST,
2167: host);
2168: }
2169: File buildProperty = sourceFragmentDirURL.append(
2170: PROPERTIES_FILE).toFile();
2171: if (!buildProperty.exists()) { //If a build.properties file already exist then we don't override it.
2172: copiedFiles.add(Constants.FRAGMENT_FILENAME_DESCRIPTOR); //Because the fragment.xml is not copied, we need to add it to the file
2173: copiedFiles.add("src/**"); //$NON-NLS-1$
2174: copiedFiles.add(Constants.BUNDLE_FILENAME_DESCRIPTOR);
2175: Properties sourceBuildProperties = new Properties();
2176: sourceBuildProperties.put(PROPERTY_BIN_INCLUDES, Utils
2177: .getStringFromCollection(copiedFiles, ",")); //$NON-NLS-1$
2178: sourceBuildProperties.put("sourcePlugin", "true"); //$NON-NLS-1$ //$NON-NLS-2$
2179: try {
2180: OutputStream buildFile = new BufferedOutputStream(
2181: new FileOutputStream(buildProperty));
2182: try {
2183: sourceBuildProperties.store(buildFile, null);
2184: } finally {
2185: buildFile.close();
2186: }
2187: } catch (FileNotFoundException e) {
2188: String message = NLS.bind(
2189: Messages.exception_writingFile,
2190: buildProperty.getAbsolutePath());
2191: throw new CoreException(new Status(IStatus.ERROR,
2192: PI_PDEBUILD, EXCEPTION_WRITING_FILE,
2193: message, e));
2194: } catch (IOException e) {
2195: String message = NLS.bind(
2196: Messages.exception_writingFile,
2197: buildProperty.getAbsolutePath());
2198: throw new CoreException(new Status(IStatus.ERROR,
2199: PI_PDEBUILD, EXCEPTION_WRITING_FILE,
2200: message, e));
2201: }
2202: }
2203: } catch (IOException e) {
2204: String message = NLS.bind(Messages.exception_writingFile,
2205: sourceFragmentDir.getName());
2206: throw new CoreException(new Status(IStatus.ERROR,
2207: PI_PDEBUILD, EXCEPTION_WRITING_FILE, message, null));
2208: }
2209: PDEState state = getSite(false).getRegistry();
2210: BundleDescription oldBundle = state.getResolvedBundle(fragment
2211: .getPluginIdentifier());
2212: if (oldBundle != null)
2213: state.getState().removeBundle(oldBundle);
2214: state.addBundle(sourceFragmentDir);
2215: }
2216:
2217: private void createSourceFragment(PluginEntry fragment,
2218: PluginEntry plugin) throws CoreException {
2219: // create the directory for the plugin
2220: Path sourceFragmentDirURL = new Path(workingDirectory + '/'
2221: + DEFAULT_PLUGIN_LOCATION + '/'
2222: + getSourcePluginName(fragment, false));
2223: File sourceFragmentDir = new File(sourceFragmentDirURL
2224: .toOSString());
2225: sourceFragmentDir.mkdirs();
2226: try {
2227: // read the content of the template file
2228: Path fragmentPath = new Path(
2229: TEMPLATE
2230: + "/21/fragment/" + Constants.FRAGMENT_FILENAME_DESCRIPTOR);//$NON-NLS-1$
2231: URL templateLocation = BundleHelper.getDefault().find(
2232: fragmentPath);
2233: if (templateLocation == null) {
2234: IStatus status = new Status(IStatus.WARNING,
2235: PI_PDEBUILD,
2236: IPDEBuildConstants.EXCEPTION_READING_FILE, NLS
2237: .bind(Messages.error_readingDirectory,
2238: fragmentPath), null);
2239: BundleHelper.getDefault().getLog().log(status);
2240: return;
2241: }
2242:
2243: StringBuffer buffer = readFile(templateLocation
2244: .openStream());
2245: //Set the Id of the fragment
2246: int beginId = scan(buffer, 0, REPLACED_FRAGMENT_ID);
2247: buffer.replace(beginId, beginId
2248: + REPLACED_FRAGMENT_ID.length(), fragment
2249: .getPluginIdentifier());
2250: // set the version number
2251: beginId = scan(buffer, beginId, REPLACED_FRAGMENT_VERSION);
2252: buffer.replace(beginId, beginId
2253: + REPLACED_FRAGMENT_VERSION.length(), fragment
2254: .getPluginVersion());
2255: // Set the Id of the plugin for the fragment
2256: beginId = scan(buffer, beginId, REPLACED_PLUGIN_ID);
2257: buffer.replace(beginId, beginId
2258: + REPLACED_PLUGIN_ID.length(), plugin
2259: .getPluginIdentifier());
2260: // set the version number of the plugin to which the fragment is attached to
2261: beginId = scan(buffer, beginId, REPLACED_PLUGIN_VERSION);
2262: buffer.replace(beginId, beginId
2263: + REPLACED_PLUGIN_VERSION.length(), plugin
2264: .getPluginVersion());
2265: Utils.transferStreams(new ByteArrayInputStream(buffer
2266: .toString().getBytes()), new FileOutputStream(
2267: sourceFragmentDirURL.append(
2268: Constants.FRAGMENT_FILENAME_DESCRIPTOR)
2269: .toOSString()));
2270: Collection copiedFiles = Utils
2271: .copyFiles(
2272: featureRootLocation + '/'
2273: + "sourceTemplateFragment", sourceFragmentDir.getAbsolutePath()); //$NON-NLS-1$
2274: if (copiedFiles
2275: .contains(Constants.FRAGMENT_FILENAME_DESCRIPTOR)) {
2276: replaceXMLAttribute(sourceFragmentDirURL.append(
2277: Constants.FRAGMENT_FILENAME_DESCRIPTOR)
2278: .toOSString(), FRAGMENT_START_TAG, VERSION,
2279: fragment.getPluginVersion());
2280: replaceXMLAttribute(sourceFragmentDirURL.append(
2281: Constants.FRAGMENT_FILENAME_DESCRIPTOR)
2282: .toOSString(), FRAGMENT_START_TAG,
2283: PLUGIN_VERSION, plugin.getPluginVersion());
2284: }
2285: File buildProperty = sourceFragmentDirURL.append(
2286: PROPERTIES_FILE).toFile();
2287: if (!buildProperty.exists()) { //If a build.properties file already exist then we don't override it.
2288: copiedFiles.add(Constants.FRAGMENT_FILENAME_DESCRIPTOR); //Because the fragment.xml is not copied, we need to add it to the file
2289: copiedFiles.add("src/**"); //$NON-NLS-1$
2290: Properties sourceBuildProperties = new Properties();
2291: sourceBuildProperties.put(PROPERTY_BIN_INCLUDES, Utils
2292: .getStringFromCollection(copiedFiles, ",")); //$NON-NLS-1$
2293: sourceBuildProperties.put("sourcePlugin", "true"); //$NON-NLS-1$ //$NON-NLS-2$
2294: try {
2295: OutputStream buildFile = new BufferedOutputStream(
2296: new FileOutputStream(buildProperty));
2297: try {
2298: sourceBuildProperties.store(buildFile, null);
2299: } finally {
2300: buildFile.close();
2301: }
2302: } catch (FileNotFoundException e) {
2303: String message = NLS.bind(
2304: Messages.exception_writingFile,
2305: buildProperty.getAbsolutePath());
2306: throw new CoreException(new Status(IStatus.ERROR,
2307: PI_PDEBUILD, EXCEPTION_WRITING_FILE,
2308: message, e));
2309: } catch (IOException e) {
2310: String message = NLS.bind(
2311: Messages.exception_writingFile,
2312: buildProperty.getAbsolutePath());
2313: throw new CoreException(new Status(IStatus.ERROR,
2314: PI_PDEBUILD, EXCEPTION_WRITING_FILE,
2315: message, e));
2316: }
2317: }
2318: } catch (IOException e) {
2319: String message = NLS.bind(Messages.exception_writingFile,
2320: sourceFragmentDir.getName());
2321: throw new CoreException(new Status(IStatus.ERROR,
2322: PI_PDEBUILD, EXCEPTION_WRITING_FILE, message, null));
2323: }
2324: PDEState state = getSite(false).getRegistry();
2325: BundleDescription oldBundle = state.getResolvedBundle(fragment
2326: .getPluginIdentifier());
2327: if (oldBundle != null)
2328: state.getState().removeBundle(oldBundle);
2329: state.addBundle(sourceFragmentDir);
2330: }
2331:
2332: public String getSourcePluginName(PluginEntry plugin,
2333: boolean versionSuffix) {
2334: return plugin.getPluginIdentifier()
2335: + (versionSuffix ? "_" + plugin.getPluginVersion() : ""); //$NON-NLS-1$ //$NON-NLS-2$
2336: }
2337:
2338: public void setFeatureRootLocation(String featureLocation) {
2339: this .featureRootLocation = featureLocation;
2340: }
2341:
2342: /**
2343: * Method setSourceToGather.
2344: *
2345: * @param sourceToGather
2346: */
2347: public void setSourceToGather(
2348: SourceFeatureInformation sourceToGather) {
2349: this .sourceToGather = sourceToGather;
2350: }
2351:
2352: /**
2353: * Sets the sourceFeatureGeneration.
2354: *
2355: * @param sourceFeatureGeneration
2356: * The sourceFeatureGeneration to set
2357: */
2358: public void setSourceFeatureGeneration(
2359: boolean sourceFeatureGeneration) {
2360: this .sourceFeatureGeneration = sourceFeatureGeneration;
2361: }
2362:
2363: /**
2364: * Sets the binaryFeatureGeneration.
2365: *
2366: * @param binaryFeatureGeneration
2367: * The binaryFeatureGeneration to set
2368: */
2369: public void setBinaryFeatureGeneration(
2370: boolean binaryFeatureGeneration) {
2371: this .binaryFeature = binaryFeatureGeneration;
2372: }
2373:
2374: /**
2375: * Sets the scriptGeneration.
2376: *
2377: * @param scriptGeneration
2378: * The scriptGeneration to set
2379: */
2380: public void setScriptGeneration(boolean scriptGeneration) {
2381: this .scriptGeneration = scriptGeneration;
2382: }
2383:
2384: /**
2385: * Returns the sourceFeatureGeneration.
2386: *
2387: * @return boolean
2388: */
2389: public boolean isSourceFeatureGeneration() {
2390: return sourceFeatureGeneration;
2391: }
2392:
2393: /**
2394: * Sets whether or not to generate JNLP manifests
2395: *
2396: * @param value whether or not to generate JNLP manifests
2397: */
2398: public void setGenerateJnlp(boolean value) {
2399: generateJnlp = value;
2400: }
2401:
2402: /**
2403: * Sets whether or not to sign any constructed jars.
2404: *
2405: * @param value whether or not to sign any constructed JARs
2406: */
2407: public void setSignJars(boolean value) {
2408: signJars = value;
2409: }
2410:
2411: /**
2412: * Sets whether or not to generate the feature version suffix
2413: *
2414: * @param value whether or not to generate the feature version suffix
2415: */
2416: public void setGenerateVersionSuffix(boolean value) {
2417: generateVersionSuffix = value;
2418: }
2419:
2420: /**
2421: * Set the location of the .product file
2422: * @param product the location of the .product file
2423: */
2424: public void setProduct(String product) {
2425: this .product = product;
2426: }
2427:
2428: protected void collectElementToAssemble(IPluginEntry entryToCollect)
2429: throws CoreException {
2430: if (assemblyData == null || sourceFeatureGeneration)
2431: return;
2432: List correctConfigs = selectConfigs(entryToCollect);
2433: String versionRequested = entryToCollect
2434: .getVersionedIdentifier().getVersion().toString();
2435: BundleDescription effectivePlugin = null;
2436: effectivePlugin = getSite(false).getRegistry()
2437: .getResolvedBundle(
2438: entryToCollect.getVersionedIdentifier()
2439: .getIdentifier(), versionRequested);
2440: for (Iterator iter = correctConfigs.iterator(); iter.hasNext();) {
2441: assemblyData.addPlugin((Config) iter.next(),
2442: effectivePlugin);
2443: }
2444: }
2445:
2446: // Create a feature object representing a source feature based on the featureExample
2447: private Feature createSourceFeature(Feature featureExample)
2448: throws CoreException {
2449: BuildTimeFeature result = new BuildTimeFeature();
2450: result.setFeatureIdentifier(computeSourceFeatureName(
2451: featureExample, false));
2452: result.setFeatureVersion(featureExample
2453: .getVersionedIdentifier().getVersion().toString());
2454: result.setLabel(featureExample.getLabelNonLocalized());
2455: result.setProvider(featureExample.getProviderNonLocalized());
2456: result.setImageURLString(featureExample.getImageURLString());
2457: result.setInstallHandlerModel(featureExample
2458: .getInstallHandlerModel());
2459: result
2460: .setDescriptionModel(featureExample
2461: .getDescriptionModel());
2462: result.setCopyrightModel(featureExample.getCopyrightModel());
2463: result.setLicenseModel(featureExample.getLicenseModel());
2464: result.setUpdateSiteEntryModel(featureExample
2465: .getUpdateSiteEntryModel());
2466: URLEntryModel[] siteEntries = featureExample
2467: .getDiscoverySiteEntryModels();
2468: result
2469: .setDiscoverySiteEntryModels((siteEntries == null || siteEntries.length == 0) ? null
2470: : siteEntries);
2471: result.setOS(featureExample.getOS());
2472: result.setArch(featureExample.getOSArch());
2473: result.setWS(featureExample.getWS());
2474: int contextLength = featureExample instanceof BuildTimeFeature ? ((BuildTimeFeature) featureExample)
2475: .getContextQualifierLength()
2476: : -1;
2477: result.setContextQualifierLength(contextLength);
2478: return result;
2479: }
2480:
2481: private void writeSourceFeature() throws CoreException {
2482: String sourceFeatureDir = workingDirectory + '/'
2483: + DEFAULT_FEATURE_LOCATION + '/'
2484: + sourceFeatureFullName;
2485: File sourceDir = new File(sourceFeatureDir);
2486: sourceDir.mkdirs();
2487: // write the source feature to the feature.xml
2488: File file = new File(sourceFeatureDir + '/'
2489: + Constants.FEATURE_FILENAME_DESCRIPTOR);
2490: try {
2491: SourceFeatureWriter writer = new SourceFeatureWriter(
2492: new BufferedOutputStream(new FileOutputStream(file)),
2493: sourceFeature, this );
2494: try {
2495: writer.printFeature();
2496: } finally {
2497: writer.close();
2498: }
2499: } catch (IOException e) {
2500: String message = NLS.bind(Messages.error_creatingFeature,
2501: sourceFeature.getFeatureIdentifier());
2502: throw new CoreException(new Status(IStatus.OK, PI_PDEBUILD,
2503: EXCEPTION_WRITING_FILE, message, e));
2504: }
2505: Collection copiedFiles = Utils.copyFiles(featureRootLocation
2506: + '/' + "sourceTemplateFeature", sourceFeatureDir); //$NON-NLS-1$
2507: if (copiedFiles.contains(Constants.FEATURE_FILENAME_DESCRIPTOR)) {
2508: //we overwrote our feature.xml with a template, replace the version
2509: replaceXMLAttribute(sourceFeatureDir + '/'
2510: + Constants.FEATURE_FILENAME_DESCRIPTOR,
2511: FEATURE_START_TAG, VERSION, sourceFeature
2512: .getFeatureVersion());
2513: }
2514: File buildProperty = new File(sourceFeatureDir + '/'
2515: + PROPERTIES_FILE);
2516: if (buildProperty.exists()) {//If a build.properties file already exist then we don't override it.
2517: getSite(false).addFeatureReferenceModel(sourceDir);
2518: return;
2519: }
2520: copiedFiles.add(Constants.FEATURE_FILENAME_DESCRIPTOR); //Because the feature.xml is not copied, we need to add it to the file
2521: Properties sourceBuildProperties = new Properties();
2522: sourceBuildProperties.put(PROPERTY_BIN_INCLUDES, Utils
2523: .getStringFromCollection(copiedFiles, ",")); //$NON-NLS-1$
2524: OutputStream output = null;
2525: try {
2526: output = new BufferedOutputStream(new FileOutputStream(
2527: buildProperty));
2528: try {
2529: sourceBuildProperties.store(output, null);
2530: } finally {
2531: output.close();
2532: }
2533: } catch (FileNotFoundException e) {
2534: String message = NLS.bind(Messages.exception_writingFile,
2535: buildProperty.getAbsolutePath());
2536: throw new CoreException(new Status(IStatus.ERROR,
2537: PI_PDEBUILD, EXCEPTION_WRITING_FILE, message, e));
2538: } catch (IOException e) {
2539: String message = NLS.bind(Messages.exception_writingFile,
2540: buildProperty.getAbsolutePath());
2541: throw new CoreException(new Status(IStatus.ERROR,
2542: PI_PDEBUILD, EXCEPTION_WRITING_FILE, message, e));
2543: }
2544: getSite(false).addFeatureReferenceModel(sourceDir);
2545: }
2546:
2547: private void replaceManifestValue(String location,
2548: String attribute, String newVersion) {
2549: Manifest manifest = null;
2550: try {
2551: InputStream is = new BufferedInputStream(
2552: new FileInputStream(location));
2553: try {
2554: manifest = new Manifest(is);
2555: } finally {
2556: is.close();
2557: }
2558: } catch (IOException e) {
2559: return;
2560: }
2561:
2562: manifest.getMainAttributes().put(
2563: new Attributes.Name(attribute), newVersion);
2564:
2565: OutputStream os = null;
2566: try {
2567: os = new BufferedOutputStream(
2568: new FileOutputStream(location));
2569: try {
2570: manifest.write(os);
2571: } finally {
2572: os.close();
2573: }
2574: } catch (IOException e1) {
2575: //ignore
2576: }
2577: }
2578:
2579: private void replaceXMLAttribute(String location, String tag,
2580: String attr, String newValue) {
2581: File featureFile = new File(location);
2582: if (!featureFile.exists())
2583: return;
2584:
2585: StringBuffer buffer = null;
2586: try {
2587: buffer = readFile(featureFile);
2588: } catch (IOException e) {
2589: return;
2590: }
2591:
2592: int startComment = scan(buffer, 0, COMMENT_START_TAG);
2593: int endComment = startComment > -1 ? scan(buffer, startComment,
2594: COMMENT_END_TAG) : -1;
2595: int startTag = scan(buffer, 0, tag);
2596: while (startComment != -1 && startTag > startComment
2597: && startTag < endComment) {
2598: startTag = scan(buffer, endComment, tag);
2599: startComment = scan(buffer, endComment, COMMENT_START_TAG);
2600: endComment = startComment > -1 ? scan(buffer, startComment,
2601: COMMENT_END_TAG) : -1;
2602: }
2603: if (startTag == -1)
2604: return;
2605: int endTag = scan(buffer, startTag, ">"); //$NON-NLS-1$
2606: boolean attrFound = false;
2607: while (!attrFound) {
2608: int startAttributeWord = scan(buffer, startTag, attr);
2609: if (startAttributeWord == -1 || startAttributeWord > endTag)
2610: return;
2611: if (!Character.isWhitespace(buffer
2612: .charAt(startAttributeWord - 1))) {
2613: startTag = startAttributeWord + attr.length();
2614: continue;
2615: }
2616: //Verify that the word found is the actual attribute
2617: int endAttributeWord = startAttributeWord + attr.length();
2618: while (Character.isWhitespace(buffer
2619: .charAt(endAttributeWord))
2620: && endAttributeWord < endTag) {
2621: endAttributeWord++;
2622: }
2623: if (endAttributeWord > endTag) { //attribute has not been found
2624: return;
2625: }
2626:
2627: if (buffer.charAt(endAttributeWord) != '=') {
2628: startTag = endAttributeWord;
2629: continue;
2630: }
2631:
2632: int startVersionId = scan(buffer, startAttributeWord + 1,
2633: "\""); //$NON-NLS-1$
2634: int endVersionId = scan(buffer, startVersionId + 1, "\""); //$NON-NLS-1$
2635: buffer.replace(startVersionId + 1, endVersionId, newValue);
2636: attrFound = true;
2637: }
2638: if (attrFound) {
2639: try {
2640: Utils.transferStreams(new ByteArrayInputStream(buffer
2641: .toString().getBytes()), new FileOutputStream(
2642: featureFile));
2643: } catch (IOException e) {
2644: //ignore
2645: }
2646: }
2647: }
2648:
2649: }
|