| /******************************************************************************* |
| * Copyright (c) 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Pascal Rapicault, IBM - Initial implementation |
| * David Williams, IBM, - added |
| * 'conservative' directive |
| * 'workpaceRoot' directive |
| * maintained some other attributes in pre-req'd bundles |
| * made output "ready to paste", if desired. |
| * |
| *******************************************************************************/ |
| package org.eclipse.callisto.tools.versionchecker; |
| |
| import java.io.BufferedReader; |
| import java.io.BufferedWriter; |
| import java.io.FileNotFoundException; |
| import java.io.FileReader; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.io.Reader; |
| import java.io.Writer; |
| import java.util.ArrayList; |
| |
| import org.eclipse.core.runtime.IPlatformRunnable; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.osgi.service.resolver.BundleDescription; |
| import org.eclipse.osgi.service.resolver.BundleSpecification; |
| import org.eclipse.osgi.service.resolver.VersionRange; |
| import org.osgi.framework.Version; |
| |
| /** |
| * A simple, unsupported, little-tested utility to help convert from using |
| * unconstrained pre-req'd bundles, to ones constrained to be within a certain |
| * range. |
| * |
| * For example, if a plugin's manifest.mf file specifies |
| * |
| * <p> |
| * <code>Require-Bundle: org.eclipse.core.runtime</code> |
| * </p> |
| * <p> |
| * this utility will write |
| * </p> |
| * <p> |
| * <code>Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)"</code> |
| * </p> |
| * <p> |
| * or |
| * </p> |
| * <p> |
| * <code>Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,3.3.0)"</code> |
| * </p> |
| * <p> |
| * if <i>-conservative</i> is specified. In all case the lower bound is |
| * determined by the version found as this utility actually runs. |
| * |
| * </pre> |
| * |
| * <p> |
| * Directives: |
| * </p> |
| * <p> |
| * -filter "some regx expression" |
| * </p> |
| * <p> |
| * Will write/check manifest only for those plugins matching regx expression. |
| * </p> |
| * <p> |
| * -conservative |
| * </p> |
| * <p> |
| * Will increment 'minor' code, instead of 'major' code in upper bound of the |
| * range. This is required for those using another plugin's internal (non-API) |
| * methods, and recommended if you do not know for sure you are using |
| * API-only. The default is not-conservative, which increments the major |
| * field. |
| * </p> |
| * <p> |
| * -workspaceRoot "absolute file system path name to workspace" |
| * </p> |
| * <p> |
| * If specified, the manifest.mf files found in the workspace will be |
| * re-written with the results of this tool. Note. The workspace must "match" |
| * the runtime the tool is running in, for this to make any sense. The default |
| * is to simply write the recommended "Require-Bundle:" section the console |
| * log. |
| * </p> |
| * <p> |
| * Note: re-export visibility and optional resolution are maintained "as is" |
| * in output (but other pre-req settings (e.g. vendor?) may be lost. The |
| * intent is to provide "ready for pasting" content, if its happens to work |
| * well for your cases. |
| * </p> |
| * <p> |
| * Example invocation: |
| * </p> |
| * <p> |
| * |
| * <pre> |
| * |
| * java -jar startup.jar -clean -application |
| * org.eclipse.callisto.tools.versionchecker.dependencyChecker |
| * |
| * </pre> |
| * |
| * </p> |
| * |
| * <p> |
| * Example output: |
| * </p> |
| * |
| * <pre> |
| * |
| * bundle org.eclipse.wst.xml.core Require-Bundle: |
| * org.eclipse.core.runtime;bundle-version="[3.2.0,3.3.0)", |
| * org.eclipse.core.resources;bundle-version="[3.2.0,3.3.0)", |
| * org.eclipse.wst.common.uriresolver;bundle-version="[1.1.0,1.2.0)", |
| * org.eclipse.wst.sse.core;bundle-version="[1.1.0,1.2.0)", |
| * org.eclipse.text;bundle-version="[3.2.0,3.3.0)", |
| * org.eclipse.jem.util;resolution:=optional;bundle-version="[1.2.0,1.3.0)", |
| * org.eclipse.wst.validation;bundle-version="[1.1.0,1.2.0)", |
| * org.eclipse.emf.ecore.edit;resolution:=optional;bundle-version="[2.2.0,2.3.0)", |
| * org.eclipse.wst.common.emf;resolution:=optional;bundle-version="[1.1.0,1.2.0)", |
| * org.eclipse.emf.ecore.xmi;resolution:=optional;bundle-version="[2.2.0,2.3.0)", |
| * org.eclipse.wst.common.emfworkbench.integration;resolution:=optional;bundle-version="[1.1.0,1.2.0)", |
| * org.eclipse.wst.common.core;bundle-version="[1.1.0,1.2.0)", |
| * com.ibm.icu;bundle-version="[3.4.4,3.5.0)", |
| * org.apache.xerces;visibility:=reexport;bundle-version="[2.8.0,2.9.0)" |
| * |
| * </pre> |
| */ |
| public class DependencyChecker implements IPlatformRunnable { |
| |
| private static final String CONSERVATIVE_DIRECTIVE = "-conservative"; |
| private static final String FILTER_DIRECTIVE = "-filter"; |
| private static final String WORKSPACEROOT_DIRECTIVE = "-workspaceRoot"; |
| |
| private static final String REQUIRE_BUNDLE = "Require-Bundle:"; |
| private static final String EOL = System.getProperty("line.separator"); |
| private boolean conservative = false; |
| private String workspaceroot; |
| |
| |
| |
| public DependencyChecker() { |
| } |
| |
| public Object run(Object o) throws Exception { |
| String args[] = Platform.getApplicationArgs(); |
| String filter = null; |
| for (int nArgs = 0; nArgs < args.length; nArgs++) { |
| if (args[nArgs].equals(FILTER_DIRECTIVE) && (nArgs + 1 < args.length)) |
| filter = args[nArgs + 1]; |
| else if (args[nArgs].equals(CONSERVATIVE_DIRECTIVE)) { |
| conservative = true; |
| } |
| else if (args[nArgs].equals(WORKSPACEROOT_DIRECTIVE) && (nArgs + 1 < args.length)) |
| workspaceroot = args[nArgs + 1]; |
| |
| } |
| |
| BundleDescription bundles[] = Platform.getPlatformAdmin().getState().getBundles(); |
| for (int i = 0; i < bundles.length; i++) { |
| String bundleName = bundles[i].getSymbolicName(); |
| if ((filter == null) || bundleName.matches(filter)) { |
| BundleSpecification req[] = bundles[i].getRequiredBundles(); |
| ArrayList bundleSpecStrings = new ArrayList(); |
| for (int j = 0; j < req.length; j++) { |
| |
| BundleSpecification currentBundle = req[j]; |
| VersionRange specifiedRange = currentBundle.getVersionRange(); |
| if (specifiedRange == VersionRange.emptyRange) { |
| |
| BundleDescription required = Platform.getPlatformAdmin().getState().getBundle(currentBundle.getName(), null); |
| if (required != null) { |
| Version reqVersion = required.getVersion(); |
| Version minVersion = new Version(reqVersion.getMajor(), reqVersion.getMinor(), reqVersion.getMicro()); |
| Version maxVersion = null; |
| if (conservative) { |
| maxVersion = new Version(minVersion.getMajor(), minVersion.getMinor() + 1, 0); |
| } |
| else { |
| maxVersion = new Version(minVersion.getMajor() + 1, 0, 0); |
| |
| } |
| |
| String name = currentBundle.getName(); |
| |
| String exported = ""; |
| if (currentBundle.isExported()) { |
| exported = ";visibility:=reexport"; |
| } |
| |
| String optional = ""; |
| if (currentBundle.isOptional()) { |
| exported = ";resolution:=optional"; |
| } |
| |
| String requiredRange = ";bundle-version=\"" + new VersionRange(minVersion, true, maxVersion, false) + "\""; |
| |
| String spec = new String(" " + name + exported + optional + requiredRange); |
| |
| bundleSpecStrings.add(spec); |
| } |
| } |
| } |
| |
| // print |
| if (bundleSpecStrings.size() > 0) { |
| // header |
| System.out.println(); |
| System.out.println("bundle " + bundleName); |
| |
| StringBuffer sb = formStringBuffer(bundleSpecStrings); |
| |
| System.out.println(sb); |
| |
| if (workspaceroot != null) { |
| rewriteManifest(bundleName, sb); |
| } |
| |
| } |
| } |
| } |
| |
| return IPlatformRunnable.EXIT_OK; |
| } |
| |
| private void rewriteManifest(String bundleName, StringBuffer sb) throws IOException { |
| |
| try { |
| Reader reader = new FileReader(workspaceroot + bundleName + "/META-INF/MANIFEST.MF"); |
| |
| BufferedReader bufferedReader = new BufferedReader(reader); |
| ArrayList initialLines = new ArrayList(); |
| ArrayList finalLines = new ArrayList(); |
| String inline = null; |
| inline = bufferedReader.readLine(); |
| while ((inline != null) && (!(inline.startsWith(REQUIRE_BUNDLE)))) { |
| initialLines.add(new String(inline)); |
| inline = bufferedReader.readLine(); |
| } |
| |
| if (inline != null) { |
| inline = bufferedReader.readLine(); |
| while (((inline != null) && (inline.startsWith(" ")))) { |
| inline = bufferedReader.readLine(); |
| } |
| } |
| |
| while (inline != null) { |
| finalLines.add(new String(inline)); |
| inline = bufferedReader.readLine(); |
| } |
| bufferedReader.close(); |
| |
| Writer writer = new FileWriter(workspaceroot + bundleName + "/META-INF/MANIFEST.MF"); |
| BufferedWriter bufferedWriter = new BufferedWriter(writer); |
| for (int lines = 0; lines < initialLines.size(); lines++) { |
| bufferedWriter.write(initialLines.get(lines) + EOL); |
| } |
| bufferedWriter.write(sb.toString()); |
| for (int lines = 0; lines < finalLines.size(); lines++) { |
| bufferedWriter.write(finalLines.get(lines) + EOL); |
| } |
| bufferedWriter.close(); |
| } |
| catch (FileNotFoundException e) { |
| // if no manifest file, ignore, there's nothing to re-write |
| } |
| } |
| |
| private StringBuffer formStringBuffer(ArrayList bundleSpecStrings) { |
| StringBuffer sb = new StringBuffer(); |
| |
| // spec section (note, print only, no EOL, no space) |
| sb.append(REQUIRE_BUNDLE); |
| |
| for (int k = 0; k < bundleSpecStrings.size(); k++) { |
| sb.append(bundleSpecStrings.get(k)); |
| String COMMA = ""; |
| if (k < bundleSpecStrings.size() - 1) { |
| COMMA = ","; |
| } |
| sb.append(COMMA + EOL); |
| } |
| |
| return sb; |
| |
| } |
| } |