You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by mc...@apache.org on 2011/10/17 12:31:51 UTC
svn commit: r1185095 [11/15] - in /felix/trunk/bundleplugin: ./
src/main/java/aQute/ src/main/java/aQute/bnd/
src/main/java/aQute/bnd/annotation/
src/main/java/aQute/bnd/annotation/component/
src/main/java/aQute/bnd/annotation/metatype/ src/main/java/a...
Added: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,240 @@
+package aQute.lib.osgi;
+
+import java.nio.charset.*;
+import java.util.regex.*;
+
+public interface Constants {
+ /*
+ * Defined in OSGi
+ */
+ /**
+ * @syntax Bundle-ActivationPolicy ::= policy ( â;â directive )* policy ::=
+ * âlazyâ
+ */
+ String BND_ADDXMLTOTEST = "Bnd-AddXMLToTest";
+ String BUNDLE_ACTIVATIONPOLICY = "Bundle-ActivationPolicy";
+ String BUNDLE_ACTIVATOR = "Bundle-Activator";
+ String BUNDLE_BLUEPRINT = "Bundle-Copyright";
+ String BUNDLE_CATEGORY = "Bundle-Category";
+ String BUNDLE_CLASSPATH = "Bundle-ClassPath";
+ String BUNDLE_CONTACTADDRESS = "Bundle-ContactAddress";
+ String BUNDLE_COPYRIGHT = "Bundle-Copyright";
+ String BUNDLE_DESCRIPTION = "Bundle-Description";
+ String BUNDLE_DOCURL = "Bundle-DocURL";
+ String BUNDLE_ICON = "Bundle-Icon";
+ String BUNDLE_LICENSE = "Bundle-License";
+ String BUNDLE_LOCALIZATION = "Bundle-Localization";
+ String BUNDLE_MANIFESTVERSION = "Bundle-ManifestVersion";
+ String BUNDLE_NAME = "Bundle-Name";
+ String BUNDLE_NATIVECODE = "Bundle-NativeCode";
+ String BUNDLE_REQUIREDEXECUTIONENVIRONMENT = "Bundle-RequiredExecutionEnvironment";
+ String BUNDLE_SYMBOLICNAME = "Bundle-SymbolicName";
+ String BUNDLE_UPDATELOCATION = "Bundle-UpdateLocation";
+ String BUNDLE_VENDOR = "Bundle-Vendor";
+ String BUNDLE_VERSION = "Bundle-Version";
+ String DYNAMICIMPORT_PACKAGE = "DynamicImport-Package";
+ String EXPORT_PACKAGE = "Export-Package";
+ String EXPORT_SERVICE = "Export-Service";
+ String FRAGMENT_HOST = "Fragment-Host";
+ String IMPORT_PACKAGE = "Import-Package";
+ String IMPORT_SERVICE = "Import-Service";
+ String REQUIRE_BUNDLE = "Require-Bundle";
+ String SERVICE_COMPONENT = "Service-Component";
+
+ String PRIVATE_PACKAGE = "Private-Package";
+ String IGNORE_PACKAGE = "Ignore-Package";
+ String INCLUDE_RESOURCE = "Include-Resource";
+ String CONDITIONAL_PACKAGE = "Conditional-Package";
+ String BND_LASTMODIFIED = "Bnd-LastModified";
+ String CREATED_BY = "Created-By";
+ String TOOL = "Tool";
+ String TESTCASES = "Test-Cases";
+ String SIGNATURE_TEST = "-signaturetest";
+
+ String headers[] = { BUNDLE_ACTIVATOR,
+ BUNDLE_CONTACTADDRESS, BUNDLE_COPYRIGHT, BUNDLE_DESCRIPTION, BUNDLE_DOCURL,
+ BUNDLE_LOCALIZATION, BUNDLE_NATIVECODE, BUNDLE_VENDOR, BUNDLE_VERSION, BUNDLE_LICENSE,
+ BUNDLE_CLASSPATH, SERVICE_COMPONENT, EXPORT_PACKAGE, IMPORT_PACKAGE,
+ BUNDLE_LOCALIZATION, BUNDLE_MANIFESTVERSION, BUNDLE_NAME, BUNDLE_NATIVECODE,
+ BUNDLE_REQUIREDEXECUTIONENVIRONMENT, BUNDLE_SYMBOLICNAME, BUNDLE_VERSION,
+ FRAGMENT_HOST, PRIVATE_PACKAGE, IGNORE_PACKAGE, INCLUDE_RESOURCE, REQUIRE_BUNDLE,
+ IMPORT_SERVICE, EXPORT_SERVICE, CONDITIONAL_PACKAGE, BND_LASTMODIFIED, TESTCASES,
+ SIGNATURE_TEST };
+
+ String BUILDPATH = "-buildpath";
+ String BUILDPACKAGES = "-buildpackages";
+ String BUMPPOLICY = "-bumppolicy";
+ String CONDUIT = "-conduit";
+ String COMPILER_SOURCE = "-source";
+ String COMPILER_TARGET = "-target";
+ String DEPENDSON = "-dependson";
+ String DEPLOY = "-deploy";
+ String DEPLOYREPO = "-deployrepo";
+ String DONOTCOPY = "-donotcopy";
+ String DEBUG = "-debug";
+ String EXPORT_CONTENTS = "-exportcontents";
+ String FAIL_OK = "-failok";
+ String INCLUDE = "-include";
+ String INCLUDERESOURCE = "-includeresource";
+ String MAKE = "-make";
+ String METATYPE = "-metatype";
+ String MANIFEST = "-manifest";
+ String SAVEMANIFEST = "-savemanifest";
+ String NODEFAULTVERSION = "-nodefaultversion";
+ String NOEXTRAHEADERS = "-noextraheaders";
+ String NOMANIFEST = "-nomanifest";
+ String NOUSES = "-nouses";
+ @Deprecated String NOPE = "-nope";
+ String NOBUNDLES = "-nobundles";
+ String PEDANTIC = "-pedantic";
+ String PLUGIN = "-plugin";
+ String POM = "-pom";
+ String RELEASEREPO = "-releaserepo";
+ String REMOVEHEADERS = "-removeheaders";
+ String RESOURCEONLY = "-resourceonly";
+ String SOURCES = "-sources";
+ String SOURCEPATH = "-sourcepath";
+ String SUB = "-sub";
+ String RUNPROPERTIES = "-runproperties";
+ String RUNSYSTEMPACKAGES = "-runsystempackages";
+ String RUNBUNDLES = "-runbundles";
+ String RUNPATH = "-runpath";
+ String RUNSTORAGE = "-runstorage";
+ String RUNBUILDS = "-runbuilds";
+ String RUNPATH_MAIN_DIRECTIVE = "main:";
+ String RUNPATH_LAUNCHER_DIRECTIVE = "launcher:";
+ String RUNVM = "-runvm";
+ String RUNTRACE = "-runtrace";
+ String RUNFRAMEWORK = "-runframework";
+ String RUNTIMEOUT = "-runtimeout";
+ String SNAPSHOT = "-snapshot";
+ String RUNFRAMEWORK_SERVICES = "services";
+ String RUNFRAMEWORK_NONE = "none";
+ String REPORTNEWER = "-reportnewer";
+ String SIGN = "-sign";
+ String TESTPACKAGES = "-testpackages";
+ String TESTREPORT = "-testreport";
+ String TESTPATH = "-testpath";
+ String TESTCONTINUOUS = "-testcontinuous";
+ String UNDERTEST = "-undertest";
+ String VERBOSE = "-verbose";
+ @Deprecated String VERSIONPOLICY_IMPL = "-versionpolicy-impl";
+ @Deprecated String VERSIONPOLICY_USES = "-versionpolicy-uses";
+ String PROVIDER_POLICY = "-provider-policy";
+ String CONSUMER_POLICY = "-consumer-policy";
+ @Deprecated String VERSIONPOLICY = "-versionpolicy";
+ String WAB = "-wab";
+ String WABLIB = "-wablib";
+ String REQUIRE_BND = "-require-bnd";
+
+ // Deprecated
+ String CLASSPATH = "-classpath";
+
+ String options[] = { BUILDPATH, BUMPPOLICY,
+ CONDUIT, CLASSPATH, CONSUMER_POLICY, DEPENDSON, DONOTCOPY, EXPORT_CONTENTS, FAIL_OK,
+ INCLUDE, INCLUDERESOURCE, MAKE, MANIFEST, NOEXTRAHEADERS, NOUSES, NOBUNDLES, PEDANTIC,
+ PLUGIN, POM, PROVIDER_POLICY, REMOVEHEADERS, RESOURCEONLY, SOURCES, SOURCEPATH,
+ SOURCES, SOURCEPATH, SUB, RUNBUNDLES, RUNPATH, RUNSYSTEMPACKAGES, RUNPROPERTIES,
+ REPORTNEWER, UNDERTEST, TESTPATH, TESTPACKAGES, TESTREPORT, VERBOSE, NOMANIFEST,
+ DEPLOYREPO, RELEASEREPO, SAVEMANIFEST, RUNVM, WAB, WABLIB, RUNFRAMEWORK, RUNTRACE,
+ TESTCONTINUOUS, SNAPSHOT };
+
+ // Ignore bundle specific headers. These bundles do not make
+ // a lot of sense to inherit
+ String[] BUNDLE_SPECIFIC_HEADERS = new String[] {
+ INCLUDE_RESOURCE, BUNDLE_ACTIVATOR, BUNDLE_CLASSPATH, BUNDLE_NAME, BUNDLE_NATIVECODE,
+ BUNDLE_SYMBOLICNAME, IMPORT_PACKAGE, EXPORT_PACKAGE, DYNAMICIMPORT_PACKAGE,
+ FRAGMENT_HOST, REQUIRE_BUNDLE, PRIVATE_PACKAGE, EXPORT_CONTENTS, TESTCASES, NOMANIFEST,
+ SIGNATURE_TEST, WAB, WABLIB };
+
+ char DUPLICATE_MARKER = '~';
+ String SPECIFICATION_VERSION = "specification-version";
+ String SPLIT_PACKAGE_DIRECTIVE = "-split-package:";
+ String IMPORT_DIRECTIVE = "-import:";
+ String NO_IMPORT_DIRECTIVE = "-noimport:";
+ String REMOVE_ATTRIBUTE_DIRECTIVE = "-remove-attribute:";
+ String LIB_DIRECTIVE = "lib:";
+ String NOANNOTATIONS = "-noannotations";
+ String COMMAND_DIRECTIVE = "command:";
+ String USES_DIRECTIVE = "uses:";
+ String MANDATORY_DIRECTIVE = "mandatory:";
+ String INCLUDE_DIRECTIVE = "include:";
+ String PROVIDE_DIRECTIVE = "provide:";
+ String EXCLUDE_DIRECTIVE = "exclude:";
+ String PRESENCE_DIRECTIVE = "presence:";
+ String PRIVATE_DIRECTIVE = "private:";
+ String SINGLETON_DIRECTIVE = "singleton:";
+ String EXTENSION_DIRECTIVE = "extension:";
+ String VISIBILITY_DIRECTIVE = "visibility:";
+ String FRAGMENT_ATTACHMENT_DIRECTIVE = "fragment-attachment:";
+ String RESOLUTION_DIRECTIVE = "resolution:";
+ String PATH_DIRECTIVE = "path:";
+ String SIZE_ATTRIBUTE = "size";
+ String LINK_ATTRIBUTE = "link";
+ String NAME_ATTRIBUTE = "name";
+ String DESCRIPTION_ATTRIBUTE = "description";
+ String OSNAME_ATTRIBUTE = "osname";
+ String OSVERSION_ATTRIBUTE = "osversion";
+ String PROCESSOR_ATTRIBUTE = "processor";
+ String LANGUAGE_ATTRIBUTE = "language";
+ String SELECTION_FILTER_ATTRIBUTE = "selection-filter";
+ String BLUEPRINT_WAIT_FOR_DEPENDENCIES_ATTRIBUTE = "blueprint.wait-for-dependencies";
+ String BLUEPRINT_TIMEOUT_ATTRIBUTE = "blueprint.timeout";
+ String VERSION_ATTRIBUTE = "version";
+ String BUNDLE_SYMBOLIC_NAME_ATTRIBUTE = "bundle-symbolic-name";
+ String BUNDLE_VERSION_ATTRIBUTE = "bundle-version";
+ String FROM_DIRECTIVE = "from:";
+
+ String KEYSTORE_LOCATION_DIRECTIVE = "keystore:";
+ String KEYSTORE_PROVIDER_DIRECTIVE = "provider:";
+ String KEYSTORE_PASSWORD_DIRECTIVE = "password:";
+ String SIGN_PASSWORD_DIRECTIVE = "sign-password:";
+
+ String NONE = "none";
+
+ String directives[] = {
+ SPLIT_PACKAGE_DIRECTIVE, NO_IMPORT_DIRECTIVE, IMPORT_DIRECTIVE, RESOLUTION_DIRECTIVE,
+ INCLUDE_DIRECTIVE, USES_DIRECTIVE, EXCLUDE_DIRECTIVE, KEYSTORE_LOCATION_DIRECTIVE,
+ KEYSTORE_PROVIDER_DIRECTIVE, KEYSTORE_PASSWORD_DIRECTIVE, SIGN_PASSWORD_DIRECTIVE,
+ COMMAND_DIRECTIVE, NOANNOTATIONS, LIB_DIRECTIVE, RUNPATH_LAUNCHER_DIRECTIVE,
+ FROM_DIRECTIVE, PRIVATE_DIRECTIVE
+
+ // TODO
+ };
+
+ String USES_USES = "<<USES>>";
+ String CURRENT_USES = "@uses";
+ String IMPORT_REFERENCE = "reference";
+ String IMPORT_PRIVATE = "private";
+ String[] importDirectives = { IMPORT_REFERENCE,
+ IMPORT_PRIVATE };
+
+ static final Pattern VALID_PROPERTY_TYPES = Pattern
+ .compile("(String|Long|Double|Float|Integer|Byte|Character|Boolean|Short)");
+
+ String DEFAULT_BND_EXTENSION = ".bnd";
+ String DEFAULT_JAR_EXTENSION = ".jar";
+ String DEFAULT_BAR_EXTENSION = ".bar";
+ String DEFAULT_BNDRUN_EXTENSION = ".bndrun";
+ String[] METAPACKAGES = { "META-INF", "OSGI-INF",
+ "OSGI-OPT" };
+
+ String CURRENT_VERSION = "@";
+ String CURRENT_PACKAGE = "@package";
+
+ String BUILDFILES = "buildfiles";
+
+ String EMPTY_HEADER = "<<EMPTY>>";
+
+ String EMBEDDED_REPO = "/embedded-repo.jar";
+ String LAUNCHER_PLUGIN = "Launcher-Plugin";
+ String TESTER_PLUGIN = "Tester-Plugin";
+
+ String DEFAULT_LAUNCHER_BSN = "biz.aQute.launcher";
+ String DEFAULT_TESTER_BSN = "biz.aQute.junit";
+
+ String DEFAULT_DO_NOT_COPY = "CVS|\\.svn|\\.git|\\.DS_Store";
+
+ Charset DEFAULT_CHARSET = Charset.forName("UTF8");
+ String VERSION_FILTER = "version";
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Constants.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/EmbeddedResource.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/EmbeddedResource.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/EmbeddedResource.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/EmbeddedResource.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,86 @@
+package aQute.lib.osgi;
+
+import java.io.*;
+import java.util.zip.*;
+
+public class EmbeddedResource implements Resource {
+ byte data[];
+ long lastModified;
+ String extra;
+
+ public EmbeddedResource(byte data[], long lastModified) {
+ this.data = data;
+ this.lastModified = lastModified;
+ }
+
+ public InputStream openInputStream() throws FileNotFoundException {
+ return new ByteArrayInputStream(data);
+ }
+
+ public void write(OutputStream out) throws IOException {
+ out.write(data);
+ }
+
+ public String toString() {
+ return ":" + data.length + ":";
+ }
+
+ public static void build(Jar jar, InputStream in, long lastModified) throws IOException {
+ ZipInputStream jin = new ZipInputStream(in);
+ ZipEntry entry = jin.getNextEntry();
+ while (entry != null) {
+ if (!entry.isDirectory()) {
+ byte data[] = collect(jin);
+ jar.putResource(entry.getName(), new EmbeddedResource(data, lastModified), true);
+ }
+ entry = jin.getNextEntry();
+ }
+ jin.close();
+ }
+
+ /**
+ * Convenience method to turn an inputstream into a byte array. The method
+ * uses a recursive algorithm to minimize memory usage.
+ *
+ * @param in stream with data
+ * @param offset where we are in the stream
+ * @returns byte array filled with data
+ */
+ static byte[] collect(InputStream in) throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ copy(in,out);
+ return out.toByteArray();
+ }
+
+ static void copy(InputStream in, OutputStream out) throws IOException {
+ int available = in.available();
+ if ( available <= 10000)
+ available = 64000;
+ byte [] buffer = new byte[available];
+ int size;
+ while ( (size=in.read(buffer))>0)
+ out.write(buffer,0,size);
+ }
+
+ public long lastModified() {
+ return lastModified;
+ }
+
+ public static void build(Jar sub, Resource resource) throws Exception {
+ InputStream in = resource.openInputStream();
+ build(sub,in, resource.lastModified());
+ in.close();
+ }
+
+ public String getExtra() {
+ return extra;
+ }
+
+ public void setExtra(String extra) {
+ this.extra = extra;
+ }
+
+ public long size() {
+ return data.length;
+ }
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/EmbeddedResource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/EmbeddedResource.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/FileResource.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/FileResource.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/FileResource.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/FileResource.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,84 @@
+package aQute.lib.osgi;
+
+import java.io.*;
+import java.util.regex.Pattern;
+
+public class FileResource implements Resource {
+ File file;
+ String extra;
+
+ public FileResource(File file) {
+ this.file = file;
+ }
+
+ public InputStream openInputStream() throws FileNotFoundException {
+ return new FileInputStream(file);
+ }
+
+ public static void build(Jar jar, File directory, Pattern doNotCopy) {
+ traverse(
+ jar,
+ directory.getAbsolutePath().length(),
+ directory,
+ doNotCopy);
+ }
+
+ public String toString() {
+ return ":" + file.getName() + ":";
+ }
+
+ public void write(OutputStream out) throws Exception {
+ copy(this, out);
+ }
+
+ static synchronized void copy(Resource resource, OutputStream out)
+ throws Exception {
+ InputStream in = resource.openInputStream();
+ try {
+ byte buffer[] = new byte[20000];
+ int size = in.read(buffer);
+ while (size > 0) {
+ out.write(buffer, 0, size);
+ size = in.read(buffer);
+ }
+ }
+ finally {
+ in.close();
+ }
+ }
+
+ static void traverse(Jar jar, int rootlength, File directory,
+ Pattern doNotCopy) {
+ if (doNotCopy != null && doNotCopy.matcher(directory.getName()).matches())
+ return;
+
+ File files[] = directory.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].isDirectory())
+ traverse(jar, rootlength, files[i], doNotCopy);
+ else {
+ String path = files[i].getAbsolutePath().substring(
+ rootlength + 1);
+ if (File.separatorChar != '/')
+ path = path.replace(File.separatorChar, '/');
+ jar.putResource(path, new FileResource(files[i]), true);
+ }
+ }
+ }
+
+ public long lastModified() {
+ return file.lastModified();
+ }
+
+ public String getExtra() {
+ return extra;
+ }
+
+ public void setExtra(String extra) {
+ this.extra = extra;
+ }
+
+ public long size() {
+ return (int) file.length();
+ }
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/FileResource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/FileResource.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,130 @@
+package aQute.lib.osgi;
+
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.libg.generics.*;
+
+public class Instruction {
+ Pattern pattern;
+ String instruction;
+ boolean negated;
+ boolean optional;
+
+ public Instruction(String instruction, boolean negated) {
+ this.instruction = instruction;
+ this.negated = negated;
+ }
+
+ public boolean matches(String value) {
+ return getMatcher(value).matches();
+ }
+
+ public boolean isNegated() {
+ return negated;
+ }
+
+ public String getPattern() {
+ return instruction;
+ }
+
+ /**
+ * Convert a string based pattern to a regular expression based pattern.
+ * This is called an instruction, this object makes it easier to handle the
+ * different cases
+ *
+ * @param string
+ * @return
+ */
+ public static Instruction getPattern(String string) {
+ boolean negated = false;
+ if (string.startsWith("!")) {
+ negated = true;
+ string = string.substring(1);
+ }
+ StringBuffer sb = new StringBuffer();
+ for (int c = 0; c < string.length(); c++) {
+ switch (string.charAt(c)) {
+ case '.':
+ sb.append("\\.");
+ break;
+ case '*':
+ sb.append(".*");
+ break;
+ case '?':
+ sb.append(".?");
+ break;
+ default:
+ sb.append(string.charAt(c));
+ break;
+ }
+ }
+ string = sb.toString();
+ if (string.endsWith("\\..*")) {
+ sb.append("|");
+ sb.append(string.substring(0, string.length() - 4));
+ }
+ return new Instruction(sb.toString(), negated);
+ }
+
+ public String toString() {
+ return getPattern();
+ }
+
+ public Matcher getMatcher(String value) {
+ if (pattern == null) {
+ pattern = Pattern.compile(instruction);
+ }
+ return pattern.matcher(value);
+ }
+
+ public int hashCode() {
+ return instruction.hashCode();
+ }
+
+ public boolean equals(Object other) {
+ return other != null && (other instanceof Instruction)
+ && instruction.equals(((Instruction) other).instruction);
+ }
+
+ public void setOptional() {
+ optional = true;
+ }
+
+ public boolean isOptional() {
+ return optional;
+ }
+
+ public static Map<Instruction, Map<String, String>> replaceWithInstruction(
+ Map<String, Map<String, String>> header) {
+ Map<Instruction, Map<String, String>> map = Processor.newMap();
+ for (Iterator<Map.Entry<String, Map<String, String>>> e = header
+ .entrySet().iterator(); e.hasNext();) {
+ Map.Entry<String, Map<String, String>> entry = e.next();
+ String pattern = entry.getKey();
+ Instruction instr = getPattern(pattern);
+ String presence = entry.getValue()
+ .get(Constants.PRESENCE_DIRECTIVE);
+ if ("optional".equals(presence))
+ instr.setOptional();
+ map.put(instr, entry.getValue());
+ }
+ return map;
+ }
+
+ public static <T> Collection<T> select(Collection<Instruction> matchers,
+ Collection<T> targets) {
+ Collection<T> result = Create.list();
+ outer: for (T t : targets) {
+ String s = t.toString();
+ for (Instruction i : matchers) {
+ if (i.matches(s)) {
+ if (!i.isNegated())
+ result.add(t);
+ continue outer;
+ }
+ }
+ }
+ return result;
+ }
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Instruction.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/InstructionFilter.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/InstructionFilter.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/InstructionFilter.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/InstructionFilter.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,37 @@
+package aQute.lib.osgi;
+
+import java.io.*;
+import java.util.regex.*;
+
+public class InstructionFilter implements FileFilter {
+
+ private Instruction instruction;
+ private boolean recursive;
+ private Pattern doNotCopy;
+
+ public InstructionFilter (Instruction instruction, boolean recursive, Pattern doNotCopy) {
+ this.instruction = instruction;
+ this.recursive = recursive;
+ this.doNotCopy = doNotCopy;
+ }
+ public InstructionFilter (Instruction instruction, boolean recursive) {
+ this(instruction, recursive, Pattern.compile(Constants.DEFAULT_DO_NOT_COPY));
+ }
+ public boolean isRecursive() {
+ return recursive;
+ }
+ public boolean accept(File pathname) {
+ if (doNotCopy != null && doNotCopy.matcher(pathname.getName()).matches()) {
+ return false;
+ }
+
+ if (pathname.isDirectory() && isRecursive()) {
+ return true;
+ }
+
+ if (instruction == null) {
+ return true;
+ }
+ return !instruction.isNegated() == instruction.matches(pathname.getName());
+ }
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/InstructionFilter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/InstructionFilter.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,690 @@
+package aQute.lib.osgi;
+
+import static aQute.lib.io.IO.*;
+
+import java.io.*;
+import java.security.*;
+import java.util.*;
+import java.util.jar.*;
+import java.util.regex.*;
+import java.util.zip.*;
+
+import aQute.lib.base64.*;
+import aQute.libg.reporter.*;
+
+public class Jar implements Closeable {
+ public static final Object[] EMPTY_ARRAY = new Jar[0];
+ Map<String, Resource> resources = new TreeMap<String, Resource>();
+ Map<String, Map<String, Resource>> directories = new TreeMap<String, Map<String, Resource>>();
+ Manifest manifest;
+ boolean manifestFirst;
+ String name;
+ File source;
+ ZipFile zipFile;
+ long lastModified;
+ String lastModifiedReason;
+ Reporter reporter;
+ boolean doNotTouchManifest;
+ boolean nomanifest;
+
+ public Jar(String name) {
+ this.name = name;
+ }
+
+ public Jar(String name, File dirOrFile, Pattern doNotCopy) throws ZipException, IOException {
+ this(name);
+ source = dirOrFile;
+ if (dirOrFile.isDirectory())
+ FileResource.build(this, dirOrFile, doNotCopy);
+ else if (dirOrFile.isFile()) {
+ zipFile = ZipResource.build(this, dirOrFile);
+ } else {
+ throw new IllegalArgumentException("A Jar can only accept a valid file or directory: "
+ + dirOrFile);
+ }
+ }
+
+ public Jar(String name, InputStream in, long lastModified) throws IOException {
+ this(name);
+ EmbeddedResource.build(this, in, lastModified);
+ }
+
+ public Jar(String name, String path) throws IOException {
+ this(name);
+ File f = new File(path);
+ InputStream in = new FileInputStream(f);
+ EmbeddedResource.build(this, in, f.lastModified());
+ in.close();
+ }
+
+ public Jar(File f) throws IOException {
+ this(getName(f), f, null);
+ }
+
+ /**
+ * Make the JAR file name the project name if we get a src or bin directory.
+ *
+ * @param f
+ * @return
+ */
+ private static String getName(File f) {
+ f = f.getAbsoluteFile();
+ String name = f.getName();
+ if (name.equals("bin") || name.equals("src"))
+ return f.getParentFile().getName();
+ else {
+ if (name.endsWith(".jar"))
+ name = name.substring(0, name.length() - 4);
+ return name;
+ }
+ }
+
+ public Jar(String string, InputStream resourceAsStream) throws IOException {
+ this(string, resourceAsStream, 0);
+ }
+
+ public Jar(String string, File file) throws ZipException, IOException {
+ this(string, file, Pattern.compile(Constants.DEFAULT_DO_NOT_COPY));
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ return "Jar:" + name;
+ }
+
+ public boolean putResource(String path, Resource resource) {
+ return putResource(path, resource, true);
+ }
+
+ public boolean putResource(String path, Resource resource, boolean overwrite) {
+ updateModified(resource.lastModified(), path);
+ while (path.startsWith("/"))
+ path = path.substring(1);
+
+ if (path.equals("META-INF/MANIFEST.MF")) {
+ manifest = null;
+ if (resources.isEmpty())
+ manifestFirst = true;
+ }
+ String dir = getDirectory(path);
+ Map<String, Resource> s = directories.get(dir);
+ if (s == null) {
+ s = new TreeMap<String, Resource>();
+ directories.put(dir, s);
+ int n = dir.lastIndexOf('/');
+ while (n > 0) {
+ String dd = dir.substring(0, n);
+ if (directories.containsKey(dd))
+ break;
+ directories.put(dd, null);
+ n = dd.lastIndexOf('/');
+ }
+ }
+ boolean duplicate = s.containsKey(path);
+ if (!duplicate || overwrite) {
+ resources.put(path, resource);
+ s.put(path, resource);
+ }
+ return duplicate;
+ }
+
+ public Resource getResource(String path) {
+ return resources.get(path);
+ }
+
+ private String getDirectory(String path) {
+ int n = path.lastIndexOf('/');
+ if (n < 0)
+ return "";
+
+ return path.substring(0, n);
+ }
+
+ public Map<String, Map<String, Resource>> getDirectories() {
+ return directories;
+ }
+
+ public Map<String, Resource> getResources() {
+ return resources;
+ }
+
+ public boolean addDirectory(Map<String, Resource> directory, boolean overwrite) {
+ boolean duplicates = false;
+ if (directory == null)
+ return false;
+
+ for (Map.Entry<String, Resource> entry : directory.entrySet()) {
+ String key = entry.getKey();
+ if (!key.endsWith(".java")) {
+ duplicates |= putResource(key, (Resource) entry.getValue(), overwrite);
+ }
+ }
+ return duplicates;
+ }
+
+ public Manifest getManifest() throws Exception {
+ if (manifest == null) {
+ Resource manifestResource = getResource("META-INF/MANIFEST.MF");
+ if (manifestResource != null) {
+ InputStream in = manifestResource.openInputStream();
+ manifest = new Manifest(in);
+ in.close();
+ }
+ }
+ return manifest;
+ }
+
+ public boolean exists(String path) {
+ return resources.containsKey(path);
+ }
+
+ public void setManifest(Manifest manifest) {
+ manifestFirst = true;
+ this.manifest = manifest;
+ }
+
+ public void write(File file) throws Exception {
+ try {
+ OutputStream out = new FileOutputStream(file);
+ write(out);
+ out.close();
+ return;
+
+ } catch (Exception t) {
+ file.delete();
+ throw t;
+ }
+ }
+
+ public void write(String file) throws Exception {
+ write(new File(file));
+ }
+
+ public void write(OutputStream out) throws Exception {
+ ZipOutputStream jout = nomanifest || doNotTouchManifest ? new ZipOutputStream(out)
+ : new JarOutputStream(out);
+ Set<String> done = new HashSet<String>();
+
+ Set<String> directories = new HashSet<String>();
+ if (doNotTouchManifest) {
+ Resource r = getResource("META-INF/MANIFEST.MF");
+ if (r != null) {
+ writeResource(jout, directories, "META-INF/MANIFEST.MF", r);
+ done.add("META-INF/MANIFEST.MF");
+ }
+ } else
+ doManifest(done, jout);
+
+ for (Map.Entry<String, Resource> entry : getResources().entrySet()) {
+ // Skip metainf contents
+ if (!done.contains(entry.getKey()))
+ writeResource(jout, directories, (String) entry.getKey(),
+ (Resource) entry.getValue());
+ }
+ jout.finish();
+ }
+
+ private void doManifest(Set<String> done, ZipOutputStream jout) throws Exception {
+ if (nomanifest)
+ return;
+
+ JarEntry ze = new JarEntry("META-INF/MANIFEST.MF");
+ jout.putNextEntry(ze);
+ writeManifest(jout);
+ jout.closeEntry();
+ done.add(ze.getName());
+ }
+
+ /**
+ * Cleanup the manifest for writing. Cleaning up consists of adding a space
+ * after any \n to prevent the manifest to see this newline as a delimiter.
+ *
+ * @param out
+ * Output
+ * @throws IOException
+ */
+
+ public void writeManifest(OutputStream out) throws Exception {
+ writeManifest(getManifest(), out);
+ }
+
+ public static void writeManifest(Manifest manifest, OutputStream out) throws IOException {
+ if (manifest == null)
+ return;
+
+ manifest = clean(manifest);
+ outputManifest(manifest, out);
+ }
+
+ /**
+ * Unfortunately we have to write our own manifest :-( because of a stupid
+ * bug in the manifest code. It tries to handle UTF-8 but the way it does it
+ * it makes the bytes platform dependent.
+ *
+ * So the following code outputs the manifest.
+ *
+ * A Manifest consists of
+ *
+ * <pre>
+ * 'Manifest-Version: 1.0\r\n'
+ * main-attributes *
+ * \r\n
+ * name-section
+ *
+ * main-attributes ::= attributes
+ * attributes ::= key ': ' value '\r\n'
+ * name-section ::= 'Name: ' name '\r\n' attributes
+ * </pre>
+ *
+ * Lines in the manifest should not exceed 72 bytes (! this is where the
+ * manifest screwed up as well when 16 bit unicodes were used).
+ *
+ * <p>
+ * As a bonus, we can now sort the manifest!
+ */
+ static byte[] CONTINUE = new byte[] {'\r','\n', ' '};
+
+ /**
+ * Main function to output a manifest properly in UTF-8.
+ *
+ * @param manifest
+ * The manifest to output
+ * @param out
+ * The output stream
+ * @throws IOException
+ * when something fails
+ */
+ public static void outputManifest(Manifest manifest, OutputStream out) throws IOException {
+ writeEntry(out, "Manifest-Version", "1.0");
+ attributes(manifest.getMainAttributes(), out);
+
+ TreeSet<String> keys = new TreeSet<String>();
+ for (Object o : manifest.getEntries().keySet())
+ keys.add(o.toString());
+
+ for (String key : keys) {
+ write(out, 0, "\r\n");
+ writeEntry(out, "Name", key);
+ attributes(manifest.getAttributes(key), out);
+ }
+ }
+
+ /**
+ * Write out an entry, handling proper unicode and line length constraints
+ *
+ */
+ private static void writeEntry(OutputStream out, String name, String value) throws IOException {
+ int n = write(out, 0, name + ": ");
+ n = write(out, n, value);
+ write(out, 0, "\r\n");
+ }
+
+ /**
+ * Convert a string to bytes with UTF8 and then output in max 72 bytes
+ *
+ * @param out
+ * the output string
+ * @param i
+ * the current width
+ * @param s
+ * the string to output
+ * @return the new width
+ * @throws IOException
+ * when something fails
+ */
+ private static int write(OutputStream out, int i, String s) throws IOException {
+ byte[] bytes = s.getBytes("UTF8");
+ return write(out, i, bytes);
+ }
+
+ /**
+ * Write the bytes but ensure that the line length does not exceed 72
+ * characters. If it is more than 70 characters, we just put a cr/lf +
+ * space.
+ *
+ * @param out
+ * The output stream
+ * @param width
+ * The nr of characters output in a line before this method
+ * started
+ * @param bytes
+ * the bytes to output
+ * @return the nr of characters in the last line
+ * @throws IOException
+ * if something fails
+ */
+ private static int write(OutputStream out, int width, byte[] bytes) throws IOException {
+ for (int i = 0; i < bytes.length; i++) {
+ if (width >= 72) { // we need to add the \n\r!
+ out.write(CONTINUE);
+ width = 1;
+ }
+ out.write(bytes[i]);
+ width++;
+ }
+ return width;
+ }
+
+ /**
+ * Output an Attributes map. We will sort this map before outputing.
+ *
+ * @param value
+ * the attrbutes
+ * @param out
+ * the output stream
+ * @throws IOException
+ * when something fails
+ */
+ private static void attributes(Attributes value, OutputStream out) throws IOException {
+ TreeMap<String, String> map = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
+ for (Map.Entry<Object, Object> entry : value.entrySet()) {
+ map.put(entry.getKey().toString(), entry.getValue().toString());
+ }
+
+ map.remove("Manifest-Version"); // get rid of
+ // manifest
+ // version
+ for (Map.Entry<String, String> entry : map.entrySet()) {
+ writeEntry(out, entry.getKey(), entry.getValue());
+ }
+ }
+
+ private static Manifest clean(Manifest org) {
+
+ Manifest result = new Manifest();
+ for (Map.Entry<?, ?> entry : org.getMainAttributes().entrySet()) {
+ String nice = clean((String) entry.getValue());
+ result.getMainAttributes().put(entry.getKey(), nice);
+ }
+ for (String name : org.getEntries().keySet()) {
+ Attributes attrs = result.getAttributes(name);
+ if (attrs == null) {
+ attrs = new Attributes();
+ result.getEntries().put(name, attrs);
+ }
+
+ for (Map.Entry<?, ?> entry : org.getAttributes(name).entrySet()) {
+ String nice = clean((String) entry.getValue());
+ attrs.put((Attributes.Name) entry.getKey(), nice);
+ }
+ }
+ return result;
+ }
+
+ private static String clean(String s) {
+ if (s.indexOf('\n') < 0)
+ return s;
+
+ StringBuffer sb = new StringBuffer(s);
+ for (int i = 0; i < sb.length(); i++) {
+ if (sb.charAt(i) == '\n')
+ sb.insert(++i, ' ');
+ }
+ return sb.toString();
+ }
+
+ private void writeResource(ZipOutputStream jout, Set<String> directories, String path,
+ Resource resource) throws Exception {
+ if (resource == null)
+ return;
+
+ createDirectories(directories, jout, path);
+ ZipEntry ze = new ZipEntry(path);
+ ze.setMethod(ZipEntry.DEFLATED);
+ long lastModified = resource.lastModified();
+ if (lastModified == 0L) {
+ lastModified = System.currentTimeMillis();
+ }
+ ze.setTime(lastModified);
+ if (resource.getExtra() != null)
+ ze.setExtra(resource.getExtra().getBytes());
+ jout.putNextEntry(ze);
+ resource.write(jout);
+ jout.closeEntry();
+ }
+
+ void createDirectories(Set<String> directories, ZipOutputStream zip, String name)
+ throws IOException {
+ int index = name.lastIndexOf('/');
+ if (index > 0) {
+ String path = name.substring(0, index);
+ if (directories.contains(path))
+ return;
+ createDirectories(directories, zip, path);
+ ZipEntry ze = new ZipEntry(path + '/');
+ zip.putNextEntry(ze);
+ zip.closeEntry();
+ directories.add(path);
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Add all the resources in the given jar that match the given filter.
+ *
+ * @param sub
+ * the jar
+ * @param filter
+ * a pattern that should match the resoures in sub to be added
+ */
+ public boolean addAll(Jar sub, Instruction filter) {
+ return addAll(sub, filter, "");
+ }
+
+ /**
+ * Add all the resources in the given jar that match the given filter.
+ *
+ * @param sub
+ * the jar
+ * @param filter
+ * a pattern that should match the resoures in sub to be added
+ */
+ public boolean addAll(Jar sub, Instruction filter, String destination) {
+ boolean dupl = false;
+ for (String name : sub.getResources().keySet()) {
+ if ("META-INF/MANIFEST.MF".equals(name))
+ continue;
+
+ if (filter == null || filter.matches(name) != filter.isNegated())
+ dupl |= putResource(Processor.appendPath(destination, name), sub.getResource(name),
+ true);
+ }
+ return dupl;
+ }
+
+ public void close() {
+ if (zipFile != null)
+ try {
+ zipFile.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ resources = null;
+ directories = null;
+ manifest = null;
+ source = null;
+ }
+
+ public long lastModified() {
+ return lastModified;
+ }
+
+ public void updateModified(long time, String reason) {
+ if (time > lastModified) {
+ lastModified = time;
+ lastModifiedReason = reason;
+ }
+ }
+
+ public void setReporter(Reporter reporter) {
+ this.reporter = reporter;
+ }
+
+ public boolean hasDirectory(String path) {
+ return directories.get(path) != null;
+ }
+
+ public List<String> getPackages() {
+ List<String> list = new ArrayList<String>(directories.size());
+
+ for (Map.Entry<String, Map<String, Resource>> i : directories.entrySet()) {
+ if (i.getValue() != null) {
+ String path = i.getKey();
+ String pack = path.replace('/', '.');
+ list.add(pack);
+ }
+ }
+ return list;
+ }
+
+ public File getSource() {
+ return source;
+ }
+
+ public boolean addAll(Jar src) {
+ return addAll(src, null);
+ }
+
+ public boolean rename(String oldPath, String newPath) {
+ Resource resource = remove(oldPath);
+ if (resource == null)
+ return false;
+
+ return putResource(newPath, resource);
+ }
+
+ public Resource remove(String path) {
+ Resource resource = resources.remove(path);
+ String dir = getDirectory(path);
+ Map<String, Resource> mdir = directories.get(dir);
+ // must be != null
+ mdir.remove(path);
+ return resource;
+ }
+
+ /**
+ * Make sure nobody touches the manifest! If the bundle is signed, we do not
+ * want anybody to touch the manifest after the digests have been
+ * calculated.
+ */
+ public void setDoNotTouchManifest() {
+ doNotTouchManifest = true;
+ }
+
+ /**
+ * Calculate the checksums and set them in the manifest.
+ */
+
+ public void calcChecksums(String algorithms[]) throws Exception {
+ if (algorithms == null)
+ algorithms = new String[] { "SHA", "MD5" };
+
+ Manifest m = getManifest();
+ if ( m == null) {
+ m= new Manifest();
+ setManifest(m);
+ }
+
+ MessageDigest digests[] = new MessageDigest[algorithms.length];
+ int n = 0;
+ for (String algorithm : algorithms)
+ digests[n++] = MessageDigest.getInstance(algorithm);
+
+ byte buffer[] = new byte[30000];
+
+ for (Map.Entry<String, Resource> entry : resources.entrySet()) {
+
+ // Skip the manifest
+ if (entry.getKey().equals("META-INF/MANIFEST.MF"))
+ continue;
+
+ Resource r = entry.getValue();
+ Attributes attributes = m.getAttributes(entry.getKey());
+ if (attributes == null) {
+ attributes = new Attributes();
+ getManifest().getEntries().put(entry.getKey(), attributes);
+ }
+ InputStream in = r.openInputStream();
+ try {
+ for (MessageDigest d : digests)
+ d.reset();
+ int size = in.read(buffer);
+ while (size > 0) {
+ for (MessageDigest d : digests)
+ d.update(buffer, 0, size);
+ size = in.read(buffer);
+ }
+ } finally {
+ in.close();
+ }
+ for (MessageDigest d : digests)
+ attributes.putValue(d.getAlgorithm() + "-Digest", Base64.encodeBase64(d.digest()));
+ }
+ }
+
+ Pattern BSN = Pattern.compile("\\s*([-\\w\\d\\._]+)\\s*;?.*");
+
+ public String getBsn() throws Exception {
+ Manifest m = getManifest();
+ if (m == null)
+ return null;
+
+ String s = m.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
+ Matcher matcher = BSN.matcher(s);
+ if (matcher.matches()) {
+ return matcher.group(1);
+ }
+ return null;
+ }
+
+ public String getVersion() throws Exception {
+ Manifest m = getManifest();
+ if (m == null)
+ return null;
+
+ String s = m.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
+ if (s == null)
+ return null;
+
+ return s.trim();
+ }
+
+ /**
+ * Expand the JAR file to a directory.
+ *
+ * @param dir
+ * the dst directory, is not required to exist
+ * @throws Exception
+ * if anything does not work as expected.
+ */
+ public void expand(File dir) throws Exception {
+ dir = dir.getAbsoluteFile();
+ dir.mkdirs();
+ if (!dir.isDirectory()) {
+ throw new IllegalArgumentException("Not a dir: " + dir.getAbsolutePath());
+ }
+
+ for (Map.Entry<String, Resource> entry : getResources().entrySet()) {
+ File f = getFile(dir, entry.getKey());
+ f.getParentFile().mkdirs();
+ copy(entry.getValue().openInputStream(), f);
+ }
+ }
+
+ /**
+ * Make sure we have a manifest
+ * @throws Exception
+ */
+ public void ensureManifest() throws Exception {
+ if ( getManifest() != null)
+ return;
+ manifest = new Manifest();
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Jar.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/JarResource.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/JarResource.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/JarResource.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/JarResource.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,46 @@
+package aQute.lib.osgi;
+
+import java.io.*;
+
+public class JarResource implements Resource {
+ Jar jar;
+ String extra;
+
+ public JarResource(Jar jar ) {
+ this.jar = jar;
+ }
+
+ public String getExtra() {
+ return extra;
+ }
+
+ public long lastModified() {
+ return jar.lastModified();
+ }
+
+
+ public void write(OutputStream out) throws Exception {
+ jar.write(out);
+ }
+
+ public InputStream openInputStream() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ write(out);
+ out.close();
+ ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+ return in;
+ }
+
+ public void setExtra(String extra) {
+ this.extra = extra;
+ }
+
+ public Jar getJar() {
+ return jar;
+ }
+
+ public String toString() {
+ return ":" + jar.getName() + ":";
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/JarResource.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/JarResource.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Added: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java
URL: http://svn.apache.org/viewvc/felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java?rev=1185095&view=auto
==============================================================================
--- felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java (added)
+++ felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java Mon Oct 17 10:31:43 2011
@@ -0,0 +1,952 @@
+package aQute.lib.osgi;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.text.*;
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.lib.io.*;
+import aQute.libg.sed.*;
+import aQute.libg.version.*;
+
+/**
+ * Provide a macro processor. This processor can replace variables in strings
+ * based on a properties and a domain. The domain can implement functions that
+ * start with a "_" and take args[], the names of these functions are available
+ * as functions in the macro processor (without the _). Macros can nest to any
+ * depth but may not contain loops.
+ *
+ * Add POSIX macros:
+ * ${#parameter}
+ String length.
+
+${parameter%word}
+ Remove smallest suffix pattern.
+
+${parameter%%word}
+ Remove largest suffix pattern.
+
+${parameter#word}
+ Remove smallest prefix pattern.
+
+${parameter##word}
+ Remove largest prefix pattern.
+ */
+public class Macro implements Replacer {
+ Processor domain;
+ Object targets[];
+ boolean flattening;
+
+ public Macro(Processor domain, Object... targets) {
+ this.domain = domain;
+ this.targets = targets;
+ if (targets != null) {
+ for (Object o : targets) {
+ assert o != null;
+ }
+ }
+ }
+
+ public String process(String line, Processor source) {
+ return process(line, new Link(source,null,line));
+ }
+
+ String process(String line, Link link) {
+ StringBuffer sb = new StringBuffer();
+ process(line, 0, '\u0000', '\u0000', sb, link);
+ return sb.toString();
+ }
+
+ int process(CharSequence org, int index, char begin, char end, StringBuffer result, Link link) {
+ StringBuilder line = new StringBuilder(org);
+ int nesting = 1;
+
+ StringBuffer variable = new StringBuffer();
+ outer: while (index < line.length()) {
+ char c1 = line.charAt(index++);
+ if (c1 == end) {
+ if (--nesting == 0) {
+ result.append(replace(variable.toString(), link));
+ return index;
+ }
+ } else if (c1 == begin)
+ nesting++;
+ else if (c1 == '\\' && index < line.length() - 1 && line.charAt(index) == '$') {
+ // remove the escape backslash and interpret the dollar as a
+ // literal
+ index++;
+ variable.append('$');
+ continue outer;
+ } else if (c1 == '$' && index < line.length() - 2) {
+ char c2 = line.charAt(index);
+ char terminator = getTerminator(c2);
+ if (terminator != 0) {
+ index = process(line, index + 1, c2, terminator, variable, link);
+ continue outer;
+ }
+ }
+ variable.append(c1);
+ }
+ result.append(variable);
+ return index;
+ }
+
+ public static char getTerminator(char c) {
+ switch (c) {
+ case '(':
+ return ')';
+ case '[':
+ return ']';
+ case '{':
+ return '}';
+ case '<':
+ return '>';
+ case '\u00ab': // Guillemet double << >>
+ return '\u00bb';
+ case '\u2039': // Guillemet single
+ return '\u203a';
+ }
+ return 0;
+ }
+
+ protected String replace(String key, Link link) {
+ if (link != null && link.contains(key))
+ return "${infinite:" + link.toString() + "}";
+
+ if (key != null) {
+ key = key.trim();
+ if (key.length() > 0) {
+ Processor source = domain;
+ String value = null;
+ while( source != null) {
+ value = source.getProperties().getProperty(key);
+ if ( value != null )
+ break;
+
+ source = source.getParent();
+ }
+
+ if (value != null)
+ return process(value, new Link(source,link, key));
+
+ value = doCommands(key, link);
+ if (value != null)
+ return process(value, new Link(source, link, key));
+
+ if (key != null && key.trim().length() > 0) {
+ value = System.getProperty(key);
+ if (value != null)
+ return value;
+ }
+ if (!flattening)
+ domain.warning("No translation found for macro: " + key);
+ } else {
+ domain.warning("Found empty macro key");
+ }
+ } else {
+ domain.warning("Found null macro key");
+ }
+ return "${" + key + "}";
+ }
+
+ /**
+ * Parse the key as a command. A command consist of parameters separated by
+ * ':'.
+ *
+ * @param key
+ * @return
+ */
+ static Pattern commands = Pattern.compile("(?<!\\\\);");
+
+ private String doCommands(String key, Link source) {
+ String[] args = commands.split(key);
+ if (args == null || args.length == 0)
+ return null;
+
+ for (int i = 0; i < args.length; i++)
+ if (args[i].indexOf('\\') >= 0)
+ args[i] = args[i].replaceAll("\\\\;", ";");
+
+
+ if ( args[0].startsWith("^")) {
+ String varname = args[0].substring(1).trim();
+
+ Processor parent = source.start.getParent();
+ if ( parent != null)
+ return parent.getProperty(varname);
+ else
+ return null;
+ }
+
+
+ Processor rover = domain;
+ while (rover != null) {
+ String result = doCommand(rover, args[0], args);
+ if (result != null)
+ return result;
+
+ rover = rover.getParent();
+ }
+
+ for (int i = 0; targets != null && i < targets.length; i++) {
+ String result = doCommand(targets[i], args[0], args);
+ if (result != null)
+ return result;
+ }
+
+ return doCommand(this, args[0], args);
+ }
+
+ private String doCommand(Object target, String method, String[] args) {
+ if (target == null)
+ ; // System.out.println("Huh? Target should never be null " +
+ // domain);
+ else {
+ String cname = "_" + method.replaceAll("-", "_");
+ try {
+ Method m = target.getClass().getMethod(cname, new Class[] { String[].class });
+ return (String) m.invoke(target, new Object[] { args });
+ } catch (NoSuchMethodException e) {
+ // Ignore
+ } catch (InvocationTargetException e) {
+ if ( e.getCause() instanceof IllegalArgumentException ) {
+ domain.error("%s, for cmd: %s, arguments; %s", e.getMessage(), method, Arrays.toString(args));
+ } else {
+ domain.warning("Exception in replace: " + e.getCause());
+ e.getCause().printStackTrace();
+ }
+ } catch (Exception e) {
+ domain.warning("Exception in replace: " + e + " method=" + method);
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return a unique list where the duplicates are removed.
+ *
+ * @param args
+ * @return
+ */
+ static String _uniqHelp = "${uniq;<list> ...}";
+
+ public String _uniq(String args[]) {
+ verifyCommand(args, _uniqHelp, null, 1, Integer.MAX_VALUE);
+ Set<String> set = new LinkedHashSet<String>();
+ for (int i = 1; i < args.length; i++) {
+ Processor.split(args[i], set);
+ }
+ return Processor.join(set, ",");
+ }
+
+ public String _pathseparator(String args[]) {
+ return File.pathSeparator;
+ }
+
+ public String _separator(String args[]) {
+ return File.separator;
+ }
+
+ public String _filter(String args[]) {
+ return filter(args, false);
+ }
+
+ public String _filterout(String args[]) {
+ return filter(args, true);
+
+ }
+
+ static String _filterHelp = "${%s;<list>;<regex>}";
+
+ String filter(String[] args, boolean include) {
+ verifyCommand(args, String.format(_filterHelp, args[0]), null, 3, 3);
+
+ Collection<String> list = new ArrayList<String>(Processor.split(args[1]));
+ Pattern pattern = Pattern.compile(args[2]);
+
+ for (Iterator<String> i = list.iterator(); i.hasNext();) {
+ if (pattern.matcher(i.next()).matches() == include)
+ i.remove();
+ }
+ return Processor.join(list);
+ }
+
+ static String _sortHelp = "${sort;<list>...}";
+
+ public String _sort(String args[]) {
+ verifyCommand(args, _sortHelp, null, 2, Integer.MAX_VALUE);
+
+ List<String> result = new ArrayList<String>();
+ for (int i = 1; i < args.length; i++) {
+ Processor.split(args[i], result);
+ }
+ Collections.sort(result);
+ return Processor.join(result);
+ }
+
+ static String _joinHelp = "${join;<list>...}";
+
+ public String _join(String args[]) {
+
+ verifyCommand(args, _joinHelp, null, 1, Integer.MAX_VALUE);
+
+ List<String> result = new ArrayList<String>();
+ for (int i = 1; i < args.length; i++) {
+ Processor.split(args[i], result);
+ }
+ return Processor.join(result);
+ }
+
+ static String _ifHelp = "${if;<condition>;<iftrue> [;<iffalse>] }";
+
+ public String _if(String args[]) {
+ verifyCommand(args, _ifHelp, null, 3, 4);
+ String condition = args[1].trim();
+ if (condition.length() != 0)
+ return args[2];
+ if (args.length > 3)
+ return args[3];
+ else
+ return "";
+ }
+
+ public String _now(String args[]) {
+ return new Date().toString();
+ }
+
+ public static String _fmodifiedHelp = "${fmodified;<list of filenames>...}, return latest modification date";
+
+ public String _fmodified(String args[]) throws Exception {
+ verifyCommand(args, _fmodifiedHelp, null, 2, Integer.MAX_VALUE);
+
+ long time = 0;
+ Collection<String> names = new ArrayList<String>();
+ for (int i = 1; i < args.length; i++) {
+ Processor.split(args[i], names);
+ }
+ for (String name : names) {
+ File f = new File(name);
+ if (f.exists() && f.lastModified() > time)
+ time = f.lastModified();
+ }
+ return "" + time;
+ }
+
+ public String _long2date(String args[]) {
+ try {
+ return new Date(Long.parseLong(args[1])).toString();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return "not a valid long";
+ }
+
+ public String _literal(String args[]) {
+ if (args.length != 2)
+ throw new RuntimeException("Need a value for the ${literal;<value>} macro");
+ return "${" + args[1] + "}";
+ }
+
+ public String _def(String args[]) {
+ if (args.length != 2)
+ throw new RuntimeException("Need a value for the ${def;<value>} macro");
+
+ return domain.getProperty(args[1], "");
+ }
+
+ /**
+ *
+ * replace ; <list> ; regex ; replace
+ *
+ * @param args
+ * @return
+ */
+ public String _replace(String args[]) {
+ if (args.length != 4) {
+ domain.warning("Invalid nr of arguments to replace " + Arrays.asList(args));
+ return null;
+ }
+
+ String list[] = args[1].split("\\s*,\\s*");
+ StringBuffer sb = new StringBuffer();
+ String del = "";
+ for (int i = 0; i < list.length; i++) {
+ String element = list[i].trim();
+ if (!element.equals("")) {
+ sb.append(del);
+ sb.append(element.replaceAll(args[2], args[3]));
+ del = ", ";
+ }
+ }
+
+ return sb.toString();
+ }
+
+ public String _warning(String args[]) {
+ for (int i = 1; i < args.length; i++) {
+ domain.warning(process(args[i]));
+ }
+ return "";
+ }
+
+ public String _error(String args[]) {
+ for (int i = 1; i < args.length; i++) {
+ domain.error(process(args[i]));
+ }
+ return "";
+ }
+
+ /**
+ * toclassname ; <path>.class ( , <path>.class ) *
+ *
+ * @param args
+ * @return
+ */
+ static String _toclassnameHelp = "${classname;<list of class names>}, convert class paths to FQN class names ";
+
+ public String _toclassname(String args[]) {
+ verifyCommand(args, _toclassnameHelp, null, 2, 2);
+ Collection<String> paths = Processor.split(args[1]);
+
+ List<String> names = new ArrayList<String>(paths.size());
+ for (String path : paths) {
+ if (path.endsWith(".class")) {
+ String name = path.substring(0, path.length() - 6).replace('/', '.');
+ names.add(name);
+ } else if (path.endsWith(".java")) {
+ String name = path.substring(0, path.length() - 5).replace('/', '.');
+ names.add(name);
+ } else {
+ domain.warning("in toclassname, " + args[1]
+ + " is not a class path because it does not end in .class");
+ }
+ }
+ return Processor.join(names, ",");
+ }
+
+ /**
+ * toclassname ; <path>.class ( , <path>.class ) *
+ *
+ * @param args
+ * @return
+ */
+
+ static String _toclasspathHelp = "${toclasspath;<list>[;boolean]}, convert a list of class names to paths";
+
+ public String _toclasspath(String args[]) {
+ verifyCommand(args, _toclasspathHelp, null, 2, 3);
+ boolean cl = true;
+ if (args.length > 2)
+ cl = new Boolean(args[2]);
+
+ Collection<String> names = Processor.split(args[1]);
+ Collection<String> paths = new ArrayList<String>(names.size());
+ for (String name : names) {
+ String path = name.replace('.', '/') + (cl ? ".class" : "");
+ paths.add(path);
+ }
+ return Processor.join(paths, ",");
+ }
+
+ public String _dir(String args[]) {
+ if (args.length < 2) {
+ domain.warning("Need at least one file name for ${dir;...}");
+ return null;
+ } else {
+ String del = "";
+ StringBuffer sb = new StringBuffer();
+ for (int i = 1; i < args.length; i++) {
+ File f = domain.getFile(args[i]);
+ if (f.exists() && f.getParentFile().exists()) {
+ sb.append(del);
+ sb.append(f.getParentFile().getAbsolutePath());
+ del = ",";
+ }
+ }
+ return sb.toString();
+ }
+
+ }
+
+ public String _basename(String args[]) {
+ if (args.length < 2) {
+ domain.warning("Need at least one file name for ${basename;...}");
+ return null;
+ } else {
+ String del = "";
+ StringBuffer sb = new StringBuffer();
+ for (int i = 1; i < args.length; i++) {
+ File f = domain.getFile(args[i]);
+ if (f.exists() && f.getParentFile().exists()) {
+ sb.append(del);
+ sb.append(f.getName());
+ del = ",";
+ }
+ }
+ return sb.toString();
+ }
+
+ }
+
+ public String _isfile(String args[]) {
+ if (args.length < 2) {
+ domain.warning("Need at least one file name for ${isfile;...}");
+ return null;
+ } else {
+ boolean isfile = true;
+ for (int i = 1; i < args.length; i++) {
+ File f = new File(args[i]).getAbsoluteFile();
+ isfile &= f.isFile();
+ }
+ return isfile ? "true" : "false";
+ }
+
+ }
+
+ public String _isdir(String args[]) {
+ if (args.length < 2) {
+ domain.warning("Need at least one file name for ${isdir;...}");
+ return null;
+ } else {
+ boolean isdir = true;
+ for (int i = 1; i < args.length; i++) {
+ File f = new File(args[i]).getAbsoluteFile();
+ isdir &= f.isDirectory();
+ }
+ return isdir ? "true" : "false";
+ }
+
+ }
+
+ public String _tstamp(String args[]) {
+ String format = "yyyyMMddHHmm";
+ long now = System.currentTimeMillis();
+
+ if (args.length > 1) {
+ format = args[1];
+ if (args.length > 2) {
+ now = Long.parseLong(args[2]);
+ if (args.length > 3) {
+ domain.warning("Too many arguments for tstamp: " + Arrays.toString(args));
+ }
+ }
+ }
+ SimpleDateFormat sdf = new SimpleDateFormat(format);
+ return sdf.format(new Date(now));
+ }
+
+ /**
+ * Wildcard a directory. The lists can contain Instruction that are matched
+ * against the given directory
+ *
+ * ${lsr;<dir>;<list>(;<list>)*} ${lsa;<dir>;<list>(;<list>)*}
+ *
+ * @author aqute
+ *
+ */
+
+ public String _lsr(String args[]) {
+ return ls(args, true);
+ }
+
+ public String _lsa(String args[]) {
+ return ls(args, false);
+ }
+
+ String ls(String args[], boolean relative) {
+ if (args.length < 2)
+ throw new IllegalArgumentException(
+ "the ${ls} macro must at least have a directory as parameter");
+
+ File dir = domain.getFile(args[1]);
+ if (!dir.isAbsolute())
+ throw new IllegalArgumentException(
+ "the ${ls} macro directory parameter is not absolute: " + dir);
+
+ if (!dir.exists())
+ throw new IllegalArgumentException(
+ "the ${ls} macro directory parameter does not exist: " + dir);
+
+ if (!dir.isDirectory())
+ throw new IllegalArgumentException(
+ "the ${ls} macro directory parameter points to a file instead of a directory: "
+ + dir);
+
+ String[] files = dir.list();
+ List<String> result;
+
+ if (args.length < 3) {
+ result = Arrays.asList(files);
+ } else
+ result = new ArrayList<String>();
+
+ for (int i = 2; i < args.length; i++) {
+ String parts[] = args[i].split("\\s*,\\s*");
+ for (String pattern : parts) {
+ // So make it in to an instruction
+ Instruction instr = Instruction.getPattern(pattern);
+
+ // For each project, match it against the instruction
+ for (int f = 0; f < files.length; f++) {
+ if (files[f] != null) {
+ if (instr.matches(files[f])) {
+ if (!instr.isNegated()) {
+ if (relative)
+ result.add(files[f]);
+ else
+ result.add(new File(dir, files[f]).getAbsolutePath());
+ }
+ files[f] = null;
+ }
+ }
+ }
+ }
+ }
+ return Processor.join(result, ",");
+ }
+
+ public String _currenttime(String args[]) {
+ return Long.toString(System.currentTimeMillis());
+ }
+
+ /**
+ * Modify a version to set a version policy. Thed policy is a mask that is
+ * mapped to a version.
+ *
+ * <pre>
+ * + increment
+ * - decrement
+ * = maintain
+ * ˜ discard
+ *
+ * ==+ = maintain major, minor, increment micro, discard qualifier
+ * ˜˜˜= = just get the qualifier
+ * version="[${version;==;${@}},${version;=+;${@}})"
+ * </pre>
+ *
+ *
+ *
+ *
+ * @param args
+ * @return
+ */
+ final static String MASK_STRING = "[\\-+=~0123456789]{0,3}[=~]?";
+ final static Pattern MASK = Pattern.compile(MASK_STRING);
+ final static String _versionHelp = "${version;<mask>;<version>}, modify a version\n"
+ + "<mask> ::= [ M [ M [ M [ MQ ]]]\n"
+ + "M ::= '+' | '-' | MQ\n"
+ + "MQ ::= '~' | '='";
+ final static Pattern _versionPattern[] = new Pattern[] { null, null, MASK,
+ Verifier.VERSION };
+
+ public String _version(String args[]) {
+ verifyCommand(args, _versionHelp, null, 2, 3);
+
+ String mask = args[1];
+
+ Version version = null;
+ if (args.length >= 3)
+ version = new Version(args[2]);
+
+ return version(version, mask);
+ }
+
+ String version(Version version, String mask) {
+ if (version == null) {
+ String v = domain.getProperty("@");
+ if (v == null) {
+ domain
+ .error(
+ "No version specified for ${version} or ${range} and no implicit version ${@} either, mask=%s",
+ mask);
+ v = "0";
+ }
+ version = new Version(v);
+ }
+
+ StringBuilder sb = new StringBuilder();
+ String del = "";
+
+ for (int i = 0; i < mask.length(); i++) {
+ char c = mask.charAt(i);
+ String result = null;
+ if (c != '~') {
+ if (i == 3) {
+ result = version.getQualifier();
+ } else if (Character.isDigit(c)) {
+ // Handle masks like +00, =+0
+ result = String.valueOf(c);
+ } else {
+ int x = version.get(i);
+ switch (c) {
+ case '+':
+ x++;
+ break;
+ case '-':
+ x--;
+ break;
+ case '=':
+ break;
+ }
+ result = Integer.toString(x);
+ }
+ if (result != null) {
+ sb.append(del);
+ del = ".";
+ sb.append(result);
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Schortcut for version policy
+ *
+ * <pre>
+ * -provide-policy : ${policy;[==,=+)}
+ * -consume-policy : ${policy;[==,+)}
+ * </pre>
+ *
+ * @param args
+ * @return
+ */
+
+ static Pattern RANGE_MASK = Pattern.compile("(\\[|\\()(" + MASK_STRING + "),(" + MASK_STRING +")(\\]|\\))");
+ static String _rangeHelp = "${range;<mask>[;<version>]}, range for version, if version not specified lookyp ${@}\n"
+ + "<mask> ::= [ M [ M [ M [ MQ ]]]\n"
+ + "M ::= '+' | '-' | MQ\n" + "MQ ::= '~' | '='";
+ static Pattern _rangePattern[] = new Pattern[] { null, RANGE_MASK };
+
+ public String _range(String args[]) {
+ verifyCommand(args, _rangeHelp, _rangePattern, 2, 3);
+ Version version = null;
+ if (args.length >= 3)
+ version = new Version(args[2]);
+
+ String spec = args[1];
+
+ Matcher m = RANGE_MASK.matcher(spec);
+ m.matches();
+ String floor = m.group(1);
+ String floorMask = m.group(2);
+ String ceilingMask = m.group(3);
+ String ceiling = m.group(4);
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(floor);
+ sb.append(version(version, floorMask));
+ sb.append(",");
+ sb.append(version(version, ceilingMask));
+ sb.append(ceiling);
+
+ String s = sb.toString();
+ VersionRange vr = new VersionRange(s);
+ if (!(vr.includes(vr.getHigh()) || vr.includes(vr.getLow()))) {
+ domain.error("${range} macro created an invalid range %s from %s and mask %s", s,
+ version, spec);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * System command. Execute a command and insert the result.
+ *
+ * @param args
+ * @param help
+ * @param patterns
+ * @param low
+ * @param high
+ */
+ public String _system(String args[]) throws Exception {
+ verifyCommand(args, "${system;<command>[;<in>]}, execute a system command", null, 2, 3);
+ String command = args[1];
+ String input = null;
+
+ if (args.length > 2) {
+ input = args[2];
+ }
+
+ Process process = Runtime.getRuntime().exec(command, null, domain.getBase());
+ if (input != null) {
+ process.getOutputStream().write(input.getBytes("UTF-8"));
+ }
+ process.getOutputStream().close();
+
+ String s = IO.collect(process.getInputStream(), "UTF-8");
+ int exitValue = process.waitFor();
+ if (exitValue != 0) {
+ domain.error("System command " + command + " failed with " + exitValue);
+ }
+ return s.trim();
+ }
+
+ public String _env(String args[]) {
+ verifyCommand(args, "${env;<name>}, get the environmet variable", null, 2, 2);
+
+ try {
+ return System.getenv(args[1]);
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+
+ /**
+ * Get the contents of a file.
+ *
+ * @param in
+ * @return
+ * @throws IOException
+ */
+
+ public String _cat(String args[]) throws IOException {
+ verifyCommand(args, "${cat;<in>}, get the content of a file", null, 2, 2);
+ File f = domain.getFile(args[1]);
+ if (f.isFile()) {
+ return IO.collect(f);
+ } else if (f.isDirectory()) {
+ return Arrays.toString(f.list());
+ } else {
+ try {
+ URL url = new URL(args[1]);
+ return IO.collect(url, "UTF-8");
+ } catch (MalformedURLException mfue) {
+ // Ignore here
+ }
+ return null;
+ }
+ }
+
+ public static void verifyCommand(String args[], String help, Pattern[] patterns, int low,
+ int high) {
+ String message = "";
+ if (args.length > high) {
+ message = "too many arguments";
+ } else if (args.length < low) {
+ message = "too few arguments";
+ } else {
+ for (int i = 0; patterns != null && i < patterns.length && i < args.length; i++) {
+ if (patterns[i] != null) {
+ Matcher m = patterns[i].matcher(args[i]);
+ if (!m.matches())
+ message += String.format("Argument %s (%s) does not match %s\n", i,
+ args[i], patterns[i].pattern());
+ }
+ }
+ }
+ if (message.length() != 0) {
+ StringBuilder sb = new StringBuilder();
+ String del = "${";
+ for (String arg : args) {
+ sb.append(del);
+ sb.append(arg);
+ del = ";";
+ }
+ sb.append("}, is not understood. ");
+ sb.append(message);
+ throw new IllegalArgumentException(sb.toString());
+ }
+ }
+
+ // Helper class to track expansion of variables
+ // on the stack.
+ static class Link {
+ Link previous;
+ String key;
+ Processor start;
+
+ public Link(Processor start, Link previous, String key) {
+ this.previous = previous;
+ this.key = key;
+ this.start = start;
+ }
+
+ public boolean contains(String key) {
+ if (this.key.equals(key))
+ return true;
+
+ if (previous == null)
+ return false;
+
+ return previous.contains(key);
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ String del = "[";
+ for (Link r = this; r != null; r = r.previous) {
+ sb.append(del);
+ sb.append(r.key);
+ del = ",";
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+ }
+
+ /**
+ * Take all the properties and translate them to actual values. This method
+ * takes the set properties and traverse them over all entries, including
+ * the default properties for that properties. The values no longer contain
+ * macros.
+ *
+ * @return A new Properties with the flattened values
+ */
+ public Properties getFlattenedProperties() {
+ // Some macros only work in a lower processor, so we
+ // do not report unknown macros while flattening
+ flattening = true;
+ try {
+ Properties flattened = new Properties();
+ Properties source = domain.getProperties();
+ for (Enumeration<?> e = source.propertyNames(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ if (!key.startsWith("_"))
+ if (key.startsWith("-"))
+ flattened.put(key, source.getProperty(key));
+ else
+ flattened.put(key, process(source.getProperty(key)));
+ }
+ return flattened;
+ } finally {
+ flattening = false;
+ }
+ };
+
+ public static String _fileHelp = "${file;<base>;<paths>...}, create correct OS dependent path";
+
+ public String _osfile(String args[]) {
+ verifyCommand(args, _fileHelp, null, 3, 3);
+ File base = new File(args[1]);
+ File f = Processor.getFile(base, args[2]);
+ return f.getAbsolutePath();
+ }
+
+ public String _path(String args[]) {
+ List<String> list = new ArrayList<String>();
+ for (int i = 1; i < args.length; i++) {
+ list.addAll(Processor.split(args[i]));
+ }
+ return Processor.join(list, File.pathSeparator);
+ }
+
+ public static Properties getParent(Properties p) {
+ try {
+ Field f = Properties.class.getDeclaredField("defaults");
+ f.setAccessible(true);
+ return (Properties) f.get(p);
+ } catch (Exception e) {
+ Field[] fields = Properties.class.getFields();
+ System.out.println(Arrays.toString(fields));
+ return null;
+ }
+ }
+
+ public String process(String line) {
+ return process(line,domain);
+ }
+
+}
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: felix/trunk/bundleplugin/src/main/java/aQute/lib/osgi/Macro.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision