001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM - Initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.build;
011:
012: import java.io.*;
013: import java.util.*;
014: import org.eclipse.core.runtime.*;
015: import org.eclipse.osgi.service.resolver.BundleDescription;
016: import org.eclipse.osgi.service.resolver.State;
017: import org.eclipse.osgi.util.NLS;
018: import org.eclipse.pde.internal.build.ant.AntScript;
019: import org.eclipse.pde.internal.build.site.*;
020: import org.eclipse.update.core.*;
021:
022: /**
023: * Generic super-class for all script generator classes.
024: * It contains basic informations like the script, the configurations, and a location
025: */
026: public abstract class AbstractScriptGenerator implements IXMLConstants,
027: IPDEBuildConstants, IBuildPropertiesConstants {
028: private static Properties immutableAntProperties = null;
029: protected static boolean embeddedSource = false;
030: protected static boolean forceUpdateJarFormat = false;
031: private static List configInfos;
032: protected static String workingDirectory;
033: protected static boolean buildingOSGi = true;
034: protected AntScript script;
035: protected Properties platformProperties;
036:
037: private static PDEUIStateWrapper pdeUIState;
038:
039: /** Location of the plug-ins and fragments. */
040: protected String[] sitePaths;
041: protected String[] pluginPath;
042: protected BuildTimeSiteFactory siteFactory;
043:
044: /**
045: * Indicate whether the content of the pdestate should only contain the plugins that are in the transitive closure of the features being built
046: */
047: protected boolean filterState = false;
048: protected List featuresForFilterRoots = new ArrayList();
049: protected List pluginsForFilterRoots = new ArrayList();
050:
051: protected boolean reportResolutionErrors;
052:
053: static {
054: // By default, a generic configuration is set
055: configInfos = new ArrayList(1);
056: configInfos.add(Config.genericConfig());
057: }
058:
059: public static List getConfigInfos() {
060: return configInfos;
061: }
062:
063: /**
064: * Starting point for script generation. See subclass implementations for
065: * individual comments.
066: *
067: * @throws CoreException
068: */
069: public abstract void generate() throws CoreException;
070:
071: protected static void setStaticAntProperties(Properties properties) {
072: if (properties == null)
073: immutableAntProperties = new Properties();
074: else
075: immutableAntProperties = properties;
076: if (getImmutableAntProperty(IBuildPropertiesConstants.PROPERTY_PACKAGER_MODE) == null) {
077: immutableAntProperties.setProperty(
078: IBuildPropertiesConstants.PROPERTY_PACKAGER_MODE,
079: "false"); //$NON-NLS-1$
080: }
081: //When we are generating build scripts, the normalization needs to be set, and when doing packaging the default is to set normalization to true for backward compatibility
082: if (!getPropertyAsBoolean(IBuildPropertiesConstants.PROPERTY_PACKAGER_MODE)
083: || getImmutableAntProperty(IBuildPropertiesConstants.PROPERTY_PACKAGER_AS_NORMALIZER) == null) {
084: immutableAntProperties
085: .setProperty(
086: IBuildPropertiesConstants.PROPERTY_PACKAGER_AS_NORMALIZER,
087: "true"); //$NON-NLS-1$
088: }
089: }
090:
091: public static String getImmutableAntProperty(String key) {
092: return getImmutableAntProperty(key, null);
093: }
094:
095: public static boolean getPropertyAsBoolean(String key) {
096: String booleanValue = getImmutableAntProperty(key, null);
097: if ("true".equalsIgnoreCase(booleanValue))
098: return true;
099: else
100: return false;
101: }
102:
103: public static String getImmutableAntProperty(String key,
104: String defaultValue) {
105: if (immutableAntProperties == null
106: || !immutableAntProperties.containsKey(key))
107: return defaultValue;
108: Object obj = immutableAntProperties.get(key);
109: return (obj instanceof String) ? (String) obj : null;
110: }
111:
112: public static void setConfigInfo(String spec) throws CoreException {
113: configInfos.clear();
114: String[] configs = Utils.getArrayFromStringWithBlank(spec, "&"); //$NON-NLS-1$
115: configInfos = new ArrayList(configs.length);
116: String[] os = new String[configs.length];
117: String[] ws = new String[configs.length];
118: String[] archs = new String[configs.length];
119: for (int i = 0; i < configs.length; i++) {
120: String[] configElements = Utils
121: .getArrayFromStringWithBlank(configs[i], ","); //$NON-NLS-1$
122: if (configElements.length != 3) {
123: IStatus error = new Status(IStatus.ERROR,
124: IPDEBuildConstants.PI_PDEBUILD,
125: IPDEBuildConstants.EXCEPTION_CONFIG_FORMAT, NLS
126: .bind(Messages.error_configWrongFormat,
127: configs[i]), null);
128: throw new CoreException(error);
129: }
130: Config aConfig = new Config(configs[i]);
131: if (aConfig.equals(Config.genericConfig()))
132: configInfos.add(Config.genericConfig());
133: else
134: configInfos.add(aConfig);
135:
136: // create a list of all ws, os and arch to feed the SiteManager
137: os[i] = aConfig.getOs();
138: ws[i] = aConfig.getWs();
139: archs[i] = aConfig.getArch();
140: }
141: SiteManager.setOS(Utils.getStringFromArray(os, ",")); //$NON-NLS-1$
142: SiteManager.setWS(Utils.getStringFromArray(ws, ",")); //$NON-NLS-1$
143: SiteManager.setOSArch(Utils.getStringFromArray(archs, ",")); //$NON-NLS-1$
144: }
145:
146: public void setWorkingDirectory(String location) {
147: workingDirectory = location;
148: }
149:
150: /**
151: * Return the file system location for the given plug-in model object.
152: *
153: * @param model the plug-in
154: * @return String
155: */
156: public String getLocation(BundleDescription model) {
157: return model.getLocation();
158: }
159:
160: static public class MissingProperties extends Properties {
161: private static final long serialVersionUID = 3546924667060303927L;
162: private static MissingProperties singleton;
163:
164: private MissingProperties() {
165: //nothing to do;
166: }
167:
168: public synchronized Object setProperty(String key, String value) {
169: throw new UnsupportedOperationException();
170: }
171:
172: public synchronized Object put(Object key, Object value) {
173: throw new UnsupportedOperationException();
174: }
175:
176: public static MissingProperties getInstance() {
177: if (singleton == null)
178: singleton = new MissingProperties();
179: return singleton;
180: }
181: }
182:
183: public static Properties readProperties(String location,
184: String fileName, int errorLevel) throws CoreException {
185: Properties result = new Properties();
186: File file = new File(location, fileName);
187: try {
188: InputStream input = new BufferedInputStream(
189: new FileInputStream(file));
190: try {
191: result.load(input);
192: } finally {
193: input.close();
194: }
195: } catch (FileNotFoundException e) {
196: if (errorLevel != IStatus.INFO && errorLevel != IStatus.OK) {
197: String message = NLS.bind(
198: Messages.exception_missingFile, file);
199: BundleHelper.getDefault().getLog().log(
200: new Status(errorLevel, PI_PDEBUILD,
201: EXCEPTION_READING_FILE, message, null));
202: }
203: result = MissingProperties.getInstance();
204: } catch (IOException e) {
205: String message = NLS.bind(Messages.exception_readingFile,
206: file);
207: throw new CoreException(new Status(IStatus.ERROR,
208: PI_PDEBUILD, EXCEPTION_READING_FILE, message, e));
209: }
210: return result;
211: }
212:
213: public void openScript(String scriptLocation, String scriptName)
214: throws CoreException {
215: if (script != null)
216: return;
217:
218: try {
219: OutputStream scriptStream = new BufferedOutputStream(
220: new FileOutputStream(scriptLocation + '/'
221: + scriptName));
222: try {
223: script = new AntScript(scriptStream);
224: } catch (IOException e) {
225: try {
226: scriptStream.close();
227: String message = NLS.bind(
228: Messages.exception_writingFile,
229: scriptLocation + '/' + scriptName);
230: throw new CoreException(new Status(IStatus.ERROR,
231: PI_PDEBUILD, EXCEPTION_WRITING_FILE,
232: message, e));
233: } catch (IOException e1) {
234: // Ignored
235: }
236: }
237: } catch (FileNotFoundException e) {
238: String message = NLS.bind(Messages.exception_writingFile,
239: scriptLocation + '/' + scriptName);
240: throw new CoreException(new Status(IStatus.ERROR,
241: PI_PDEBUILD, EXCEPTION_WRITING_FILE, message, e));
242: }
243: }
244:
245: public void closeScript() {
246: script.close();
247: }
248:
249: public void setBuildingOSGi(boolean b) {
250: buildingOSGi = b;
251: }
252:
253: public static boolean isBuildingOSGi() {
254: return buildingOSGi;
255: }
256:
257: public static String getWorkingDirectory() {
258: return workingDirectory;
259: }
260:
261: public static String getDefaultOutputFormat() {
262: return "zip"; //$NON-NLS-1$
263: }
264:
265: public static boolean getDefaultEmbeddedSource() {
266: return false;
267: }
268:
269: public static void setEmbeddedSource(boolean embed) {
270: embeddedSource = embed;
271: }
272:
273: public static boolean getForceUpdateJarFormat() {
274: return false;
275: }
276:
277: public static void setForceUpdateJar(boolean force) {
278: forceUpdateJarFormat = force;
279: }
280:
281: public static String getDefaultConfigInfos() {
282: return "*, *, *"; //$NON-NLS-1$
283: }
284:
285: public static boolean getDefaultBuildingOSGi() {
286: return true;
287: }
288:
289: /**
290: * Return a build time site referencing things to be built.
291: * @param refresh : indicate if a refresh must be performed. Although this flag is set to true, a new site is not rebuild if the urls of the site did not changed
292: * @return BuildTimeSite
293: * @throws CoreException
294: */
295: public BuildTimeSite getSite(boolean refresh) throws CoreException {
296: if (siteFactory != null && refresh == false)
297: return (BuildTimeSite) siteFactory.createSite();
298:
299: if (siteFactory == null || refresh == true) {
300: siteFactory = new BuildTimeSiteFactory();
301: siteFactory.setFilterState(filterState);
302: siteFactory.setFilterRoots(featuresForFilterRoots,
303: pluginsForFilterRoots);
304: siteFactory
305: .setReportResolutionErrors(reportResolutionErrors);
306: }
307:
308: siteFactory.setSitePaths(getPaths());
309: siteFactory.setInitialState(pdeUIState);
310: BuildTimeSite result = (BuildTimeSite) siteFactory.createSite();
311: if (platformProperties != null)
312: result.setPlatformPropeties(platformProperties);
313: return result;
314: }
315:
316: /**
317: * Method getPaths. These are the paths used for the BuildTimeSite
318: * @return URL[]
319: */
320: private String[] getPaths() {
321: if (sitePaths == null) {
322: if (pluginPath != null) {
323: sitePaths = new String[pluginPath.length + 1];
324: System.arraycopy(pluginPath, 0, sitePaths, 0,
325: pluginPath.length);
326: sitePaths[sitePaths.length - 1] = workingDirectory;
327: } else {
328: sitePaths = new String[] { workingDirectory };
329: }
330: }
331:
332: return sitePaths;
333: }
334:
335: public void setBuildSiteFactory(BuildTimeSiteFactory siteFactory) {
336: this .siteFactory = siteFactory;
337: }
338:
339: /**
340: * Return the path of the plugins //TODO Do we need to add support for features, or do we simply consider one list of URL? It is just a matter of style/
341: * @return URL[]
342: */
343: public String[] getPluginPath() {
344: return pluginPath;
345: }
346:
347: /**
348: * Sets the pluginPath.
349: *
350: * @param path
351: */
352: public void setPluginPath(String[] path) {
353: pluginPath = path;
354: }
355:
356: public void setPDEState(State state) {
357: ensurePDEUIStateNotNull();
358: pdeUIState.setState(state);
359: }
360:
361: public void setStateExtraData(HashMap classpath, Map patchData) {
362: ensurePDEUIStateNotNull();
363: pdeUIState.setExtraData(classpath, patchData);
364: }
365:
366: public void setNextId(long nextId) {
367: ensurePDEUIStateNotNull();
368: pdeUIState.setNextId(nextId);
369: }
370:
371: protected void flushState() {
372: pdeUIState = null;
373: }
374:
375: private void ensurePDEUIStateNotNull() {
376: if (pdeUIState == null)
377: pdeUIState = new PDEUIStateWrapper();
378: }
379:
380: protected boolean havePDEUIState() {
381: return pdeUIState != null;
382: }
383:
384: //Find a file in a bundle or a feature.
385: //location is assumed to be structured like : /<featureId | pluginId>/path.to.the.file
386: protected String findFile(String location, boolean makeRelative) {
387: if (location == null || location.length() == 0)
388: return null;
389: PDEState state;
390: try {
391: state = getSite(false).getRegistry();
392: } catch (CoreException e) {
393: return null;
394: }
395: Path path = new Path(location);
396: String id = path.segment(0);
397: BundleDescription[] matches = state.getState().getBundles(id);
398: if (matches != null && matches.length != 0) {
399: BundleDescription bundle = matches[0];
400: if (bundle != null) {
401: String result = checkFile(
402: new Path(bundle.getLocation()), path,
403: makeRelative);
404: if (result != null)
405: return result;
406: }
407: }
408: // Couldn't find the file in any of the plugins, try in a feature.
409: IFeature feature = null;
410: try {
411: feature = getSite(false).findFeature(id, null, false);
412: } catch (CoreException e) {
413: //Ignore
414: }
415: if (feature == null)
416: return null;
417: ISiteFeatureReference ref = feature.getSite()
418: .getFeatureReference(feature);
419: IPath featureBase = new Path(ref.getURL().getFile())
420: .removeLastSegments(1);
421: return checkFile(featureBase, path, makeRelative);
422: }
423:
424: private String checkFile(IPath base, Path target,
425: boolean makeRelative) {
426: IPath path = base.append(target.removeFirstSegments(1));
427: String result = path.toOSString();
428: if (!new File(result).exists())
429: return null;
430: if (makeRelative)
431: return Utils.makeRelative(path, new Path(workingDirectory))
432: .toOSString();
433: return result;
434: }
435:
436: public void setFilterState(boolean filter) {
437: filterState = filter;
438: }
439:
440: /*
441: * If the user has specified a platform properties then load it.
442: */
443: public void setPlatformProperties(String filename) {
444: if (filename == null || filename.trim().length() == 0)
445: return;
446: File file = new File(filename);
447: if (!file.exists())
448: return;
449: platformProperties = new Properties();
450: InputStream input = null;
451: try {
452: input = new BufferedInputStream(new FileInputStream(file));
453: platformProperties.load(input);
454: } catch (IOException e) {
455: platformProperties = null;
456: String message = NLS.bind(
457: Messages.error_loading_platform_properties,
458: filename);
459: IStatus status = new Status(IStatus.WARNING,
460: IPDEBuildConstants.PI_PDEBUILD, message, e);
461: BundleHelper.getDefault().getLog().log(status);
462: } finally {
463: if (input != null)
464: try {
465: input.close();
466: } catch (IOException e) {
467: // ignore
468: }
469: }
470: }
471:
472: }
|