Latest bnd code
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1355520 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/libg/classdump/ClassDumper.java b/bundleplugin/src/main/java/aQute/libg/classdump/ClassDumper.java
index adf9824..1f29467 100755
--- a/bundleplugin/src/main/java/aQute/libg/classdump/ClassDumper.java
+++ b/bundleplugin/src/main/java/aQute/libg/classdump/ClassDumper.java
@@ -1,5 +1,3 @@
-/* Copyright 2006 aQute SARL
- * Licensed under the Apache License, Version 2.0, see http://www.apache.org/licenses/LICENSE-2.0 */
package aQute.libg.classdump;
import java.io.*;
diff --git a/bundleplugin/src/main/java/aQute/libg/clauses/Selector.java b/bundleplugin/src/main/java/aQute/libg/clauses/Selector.java
index a2a9699..8bd998d 100755
--- a/bundleplugin/src/main/java/aQute/libg/clauses/Selector.java
+++ b/bundleplugin/src/main/java/aQute/libg/clauses/Selector.java
@@ -1,21 +1,3 @@
-/*
- * $Header: /cvsroot/bnd/aQute.libg/src/aQute/libg/clauses/Selector.java,v 1.1 2009/01/19 14:17:42 pkriens Exp $
- *
- * Copyright (c) OSGi Alliance (2006). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
package aQute.libg.clauses;
import java.util.*;
diff --git a/bundleplugin/src/main/java/aQute/libg/command/Command.java b/bundleplugin/src/main/java/aQute/libg/command/Command.java
index 6bb24c3..deb06c5 100644
--- a/bundleplugin/src/main/java/aQute/libg/command/Command.java
+++ b/bundleplugin/src/main/java/aQute/libg/command/Command.java
@@ -7,7 +7,7 @@
import java.util.concurrent.atomic.*;
import aQute.lib.io.*;
-import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
public class Command {
diff --git a/bundleplugin/src/main/java/aQute/libg/glob/Glob.java b/bundleplugin/src/main/java/aQute/libg/glob/Glob.java
index b48c147..6202524 100644
--- a/bundleplugin/src/main/java/aQute/libg/glob/Glob.java
+++ b/bundleplugin/src/main/java/aQute/libg/glob/Glob.java
@@ -1,5 +1,6 @@
package aQute.libg.glob;
+import java.util.*;
import java.util.regex.*;
public class Glob {
@@ -25,15 +26,6 @@
line = line.trim();
int strLen = line.length();
StringBuilder sb = new StringBuilder(strLen);
- // Remove beginning and ending * globs because they're useless
- if (line.startsWith("*")) {
- line = line.substring(1);
- strLen--;
- }
- if (line.endsWith("*")) {
- line = line.substring(0, strLen - 1);
- strLen--;
- }
boolean escaping = false;
int inCurlies = 0;
for (char currentChar : line.toCharArray()) {
@@ -106,4 +98,21 @@
}
return sb.toString();
}
+
+ public void select(List<?> objects) {
+ for ( Iterator<?> i =objects.iterator(); i.hasNext(); ) {
+ String s = i.next().toString();
+ if ( !matcher(s).matches())
+ i.remove();
+ }
+ }
+
+ public static Pattern toPattern(String s) {
+ try {
+ return Pattern.compile( convertGlobToRegEx(s));
+ } catch( Exception e) {
+ // ignore
+ }
+ return null;
+ }
}
diff --git a/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java b/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java
index 6be995a..a372527 100755
--- a/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java
+++ b/bundleplugin/src/main/java/aQute/libg/header/OSGiHeader.java
@@ -4,7 +4,7 @@
import aQute.libg.generics.*;
import aQute.libg.qtokens.*;
-import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
public class OSGiHeader {
diff --git a/bundleplugin/src/main/java/aQute/libg/header/Parameters.java b/bundleplugin/src/main/java/aQute/libg/header/Parameters.java
index f2354c4..02e3463 100644
--- a/bundleplugin/src/main/java/aQute/libg/header/Parameters.java
+++ b/bundleplugin/src/main/java/aQute/libg/header/Parameters.java
@@ -3,7 +3,7 @@
import java.util.*;
import aQute.lib.collections.*;
-import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
public class Parameters implements Map<String,Attrs> {
private LinkedHashMap<String,Attrs> map;
diff --git a/bundleplugin/src/main/java/aQute/libg/reporter/Message.java b/bundleplugin/src/main/java/aQute/libg/reporter/Message.java
index 28386c0..afaad88 100644
--- a/bundleplugin/src/main/java/aQute/libg/reporter/Message.java
+++ b/bundleplugin/src/main/java/aQute/libg/reporter/Message.java
@@ -1,19 +1,3 @@
-/*
- * Copyright (c) OSGi Alliance (2012). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
package aQute.libg.reporter;
public @interface Message {
diff --git a/bundleplugin/src/main/java/aQute/libg/reporter/Messages.java b/bundleplugin/src/main/java/aQute/libg/reporter/Messages.java
index 033df00..c61cfb5 100644
--- a/bundleplugin/src/main/java/aQute/libg/reporter/Messages.java
+++ b/bundleplugin/src/main/java/aQute/libg/reporter/Messages.java
@@ -1,26 +1,12 @@
-/*
- * Copyright (c) OSGi Alliance (2012). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
package aQute.libg.reporter;
+import aQute.service.reporter.*;
+
public interface Messages {
- static public class ERROR {}
+ static public interface ERROR extends Reporter.SetLocation {}
- static public class WARNING {}
+ static public interface WARNING extends Reporter.SetLocation {}
ERROR NoSuchFile_(Object r);
diff --git a/bundleplugin/src/main/java/aQute/libg/reporter/Reporter.java b/bundleplugin/src/main/java/aQute/libg/reporter/Reporter.java
deleted file mode 100755
index 1ad0c31..0000000
--- a/bundleplugin/src/main/java/aQute/libg/reporter/Reporter.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package aQute.libg.reporter;
-
-import java.util.*;
-
-public interface Reporter {
- void error(String s, Object... args);
-
- void warning(String s, Object... args);
-
- void progress(String s, Object... args);
-
- void trace(String s, Object... args);
-
- List<String> getWarnings();
-
- List<String> getErrors();
-
- boolean isPedantic();
-
- boolean isExceptions();
-}
diff --git a/bundleplugin/src/main/java/aQute/libg/reporter/ReporterAdapter.java b/bundleplugin/src/main/java/aQute/libg/reporter/ReporterAdapter.java
index 676fb1b..dfb2c9e 100644
--- a/bundleplugin/src/main/java/aQute/libg/reporter/ReporterAdapter.java
+++ b/bundleplugin/src/main/java/aQute/libg/reporter/ReporterAdapter.java
@@ -5,18 +5,61 @@
import java.util.regex.*;
import aQute.libg.generics.*;
+import aQute.service.reporter.*;
/**
* Mainly used for testing where reporters are needed.
*/
-public class ReporterAdapter implements Reporter {
+public class ReporterAdapter implements Reporter, Report {
final List<String> errors = new ArrayList<String>();
final List<String> warnings = new ArrayList<String>();
+ final List<LocationImpl> locations = new ArrayList<LocationImpl>();
+
+ static class LocationImpl extends Location implements SetLocation {
+
+
+
+ public LocationImpl(String e) {
+ // TODO Auto-generated constructor stub
+ }
+
+ public SetLocation file(String file) {
+ this.file = file;
+ return this;
+ }
+
+ public SetLocation header(String header) {
+ this.header = header;
+ return this;
+ }
+
+ public SetLocation context(String context) {
+ this.context = context;
+ return this;
+ }
+
+ public SetLocation method(String methodName) {
+ this.methodName = methodName;
+ return this;
+ }
+
+ public SetLocation line(int line) {
+ this.line = line;
+ return this;
+ }
+
+ public SetLocation reference(String reference) {
+ this.reference = reference;
+ return this;
+ }
+
+ }
+
final Formatter out;
boolean trace;
boolean pedantic;
boolean exceptions;
-
+
/**
* @return the exceptions
*/
@@ -62,13 +105,14 @@
out = new Formatter(app);
}
- public void error(String s, Object... args) {
+ public SetLocation error(String s, Object... args) {
String e = String.format(s, args);
errors.add(e);
trace("ERROR: %s", e);
+ return location(e);
}
- public void exception(Throwable t, String s, Object... args) {
+ public SetLocation exception(Throwable t, String s, Object... args) {
String e = String.format(s, args);
errors.add(e);
trace("ERROR: %s", e);
@@ -77,15 +121,23 @@
t.getCause().printStackTrace(System.err);
else
t.printStackTrace(System.err);
+ return location(e);
}
- public void warning(String s, Object... args) {
+ public SetLocation warning(String s, Object... args) {
String e = String.format(s, args);
warnings.add(e);
trace("warning: %s", e);
+ return location(e);
}
- public void progress(String s, Object... args) {
+ private SetLocation location(String e) {
+ LocationImpl loc = new LocationImpl(e);
+ locations.add( loc );
+ return loc;
+ }
+
+ public void progress(float progress, String s, Object... args) {
if (out != null) {
out.format(s, args);
if (!s.endsWith("\n"))
@@ -178,4 +230,32 @@
}
}
+ public boolean getInfo(Report other) {
+ return getInfo(other,null);
+ }
+ public boolean getInfo(Report other, String prefix) {
+ boolean ok = true;
+ if ( prefix == null)
+ prefix = "";
+ else
+ prefix = prefix + ": ";
+ for ( String error : other.getErrors()) {
+ errors.add( prefix + error);
+ ok = false;
+ }
+
+ for ( String warning : other.getWarnings()) {
+ warnings.add( prefix + warning);
+ }
+ return ok;
+ }
+
+ public Location getLocation(String msg) {
+ for ( LocationImpl loc : locations ) {
+ if ((loc.message != null) && loc.message.equals(msg))
+ return loc;
+ }
+ return null;
+ }
+
}
diff --git a/bundleplugin/src/main/java/aQute/libg/reporter/ReporterMessages.java b/bundleplugin/src/main/java/aQute/libg/reporter/ReporterMessages.java
index eaf363c..375dbc6 100644
--- a/bundleplugin/src/main/java/aQute/libg/reporter/ReporterMessages.java
+++ b/bundleplugin/src/main/java/aQute/libg/reporter/ReporterMessages.java
@@ -1,19 +1,3 @@
-/*
- * Copyright (c) OSGi Alliance (2012). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
package aQute.libg.reporter;
import java.lang.reflect.*;
@@ -21,21 +5,55 @@
import aQute.libg.reporter.Messages.ERROR;
import aQute.libg.reporter.Messages.WARNING;
+import aQute.service.reporter.*;
+import aQute.service.reporter.Reporter.SetLocation;
public class ReporterMessages {
+ static class WARNINGImpl implements ERROR {
+ Reporter.SetLocation loc;
+
+ public SetLocation file(String file) {
+ return loc.file(file);
+ }
+
+ public SetLocation header(String header) {
+ return loc.header(header);
+ }
+
+ public SetLocation context(String context) {
+ return loc.context(context);
+ }
+
+ public SetLocation method(String methodName) {
+ return loc.method(methodName);
+ }
+
+ public SetLocation line(int n) {
+ return loc.line(n);
+ }
+
+ public SetLocation reference(String reference) {
+ return loc.reference(reference);
+ }
+
+ public WARNINGImpl(Reporter.SetLocation loc) {
+ this.loc = loc;
+ }
+ }
+
+ static class ERRORImpl extends WARNINGImpl implements WARNING {
+ public ERRORImpl(SetLocation e) {
+ super(e);
+ }
+ }
+
public static <T> T base(final Reporter reporter, Class<T> messages) {
return (T) Proxy.newProxyInstance(messages.getClassLoader(), new Class[] {
messages
}, new InvocationHandler() {
public Object invoke(Object target, Method method, Object[] args) throws Throwable {
- if (reporter.isExceptions() && args!=null) {
- for (Object o : args) {
- if (o instanceof Throwable)
- ((Throwable) o).printStackTrace();
- }
- }
String format;
Message d = method.getAnnotation(Message.class);
if (d == null) {
@@ -63,9 +81,10 @@
try {
if (method.getReturnType() == ERROR.class) {
- reporter.error(format, args);
+ return new ERRORImpl(reporter.error(format, args));
+
} else if (method.getReturnType() == WARNING.class) {
- reporter.warning(format, args);
+ return new WARNINGImpl(reporter.warning(format, args));
} else
reporter.trace(format, args);
}
diff --git a/bundleplugin/src/main/java/aQute/libg/sed/Domain.java b/bundleplugin/src/main/java/aQute/libg/sed/Domain.java
new file mode 100644
index 0000000..c030c83
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/sed/Domain.java
@@ -0,0 +1,9 @@
+package aQute.libg.sed;
+
+import java.util.*;
+
+public interface Domain {
+ Map<String,String> getMap();
+
+ Domain getParent();
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/sed/ReplacerAdapter.java b/bundleplugin/src/main/java/aQute/libg/sed/ReplacerAdapter.java
new file mode 100644
index 0000000..d62a014
--- /dev/null
+++ b/bundleplugin/src/main/java/aQute/libg/sed/ReplacerAdapter.java
@@ -0,0 +1,940 @@
+package aQute.libg.sed;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.text.*;
+import java.util.*;
+import java.util.regex.*;
+
+import aQute.lib.collections.*;
+import aQute.lib.io.*;
+import aQute.libg.glob.*;
+import aQute.libg.reporter.*;
+import aQute.service.reporter.*;
+
+/**
+ * Provide a macro Domain. This Domain 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 Domain (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 ReplacerAdapter extends ReporterAdapter implements Replacer {
+ static final Random random = new Random();
+ static Pattern WILDCARD = Pattern.compile("[*?|[\\\\]\\(\\)]");
+ Domain domain;
+ List<Object> targets = new ArrayList<Object>();
+ boolean flattening;
+ File base = new File(System.getProperty("user.dir"));
+ Reporter reporter = this;
+
+ public ReplacerAdapter(Domain domain) {
+ this.domain = domain;
+ }
+
+ public ReplacerAdapter(final Map<String,String> domain) {
+ this(new Domain() {
+
+ public Map<String,String> getMap() {
+ return domain;
+ }
+
+ public Domain getParent() {
+ return null;
+ }
+
+ });
+ }
+
+ public ReplacerAdapter target(Object target) {
+ assert target != null;
+ targets.add(target);
+ return this;
+ }
+
+ public ReplacerAdapter target(File base) {
+ this.base = base;
+ return this;
+ }
+
+ public String process(String line, Domain source) {
+ return process(line, new Link(source, null, line));
+ }
+
+ String process(String line, Link link) {
+ StringBuilder sb = new StringBuilder();
+ process(line, 0, '\u0000', '\u0000', sb, link);
+ return sb.toString();
+ }
+
+ int process(CharSequence org, int index, char begin, char end, StringBuilder result, Link link) {
+ StringBuilder line = new StringBuilder(org);
+ int nesting = 1;
+
+ StringBuilder variable = new StringBuilder();
+ 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;
+ }
+ } else if (c1 == '.' && index < line.length() && line.charAt(index) == '/') {
+ // Found the sequence ./
+ if (index == 1 || Character.isWhitespace(line.charAt(index - 2))) {
+ // make sure it is preceded by whitespace or starts at begin
+ index++;
+ variable.append(base.getAbsolutePath());
+ variable.append('/');
+ 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;
+ }
+
+ public String getProcessed(String key) {
+ return replace(key, null);
+ }
+
+ 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) {
+ Domain source = domain;
+ String value = null;
+ if (key.indexOf(';') < 0) {
+ if (WILDCARD.matcher(key).find()) {
+ Glob ins = new Glob(key);
+ StringBuilder sb = new StringBuilder();
+ String del = "";
+ for (String k : getAllKeys()) {
+ if (ins.matcher(k).find()) {
+ String v = replace(k, new Link(source, link, key));
+ if (v != null) {
+ sb.append(del);
+ del = ",";
+ sb.append(v);
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ while (value == null && source != null) {
+ value = source.getMap().get(key);
+ if (value != null)
+ return process(value, new Link(source, link, key));
+
+ source = source.getParent();
+ }
+ }
+ 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 && !key.equals("@"))
+ reporter.warning("No translation found for macro: " + key);
+ } else {
+ reporter.warning("Found empty macro key");
+ }
+ } else {
+ reporter.warning("Found null macro key");
+ }
+ return "${" + key + "}";
+ }
+
+ private List<String> getAllKeys() {
+ List<String> l = new ArrayList<String>();
+ Domain source = domain;
+ do {
+ l.addAll(source.getMap().keySet());
+ source = source.getParent();
+ } while (source != null);
+
+ Collections.sort(l);
+ return l;
+ }
+
+ /**
+ * 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();
+
+ Domain parent = source.start.getParent();
+ if (parent != null)
+ return parent.getMap().get(varname);
+ else
+ return null;
+ }
+
+ Domain rover = domain;
+ while (rover != null) {
+ String result = doCommand(rover, args[0], args);
+ if (result != null)
+ return result;
+
+ rover = rover.getParent();
+ }
+
+ for (Object target : targets) {
+ String result = doCommand(target, 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.err.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) {
+ reporter.error("%s, for cmd: %s, arguments; %s", e.getMessage(), method, Arrays.toString(args));
+ } else {
+ reporter.warning("Exception in replace: " + e.getCause());
+ e.getCause().printStackTrace();
+ }
+ }
+ catch (Exception e) {
+ reporter.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++) {
+ set.addAll(ExtList.from(args[i].trim()));
+ }
+ ExtList<String> rsult = new ExtList<String>();
+ rsult.addAll(set);
+ return rsult.join(",");
+ }
+
+ 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);
+
+ ExtList<String> list = ExtList.from(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 list.join();
+ }
+
+ static String _sortHelp = "${sort;<list>...}";
+
+ public String _sort(String args[]) {
+ verifyCommand(args, _sortHelp, null, 2, Integer.MAX_VALUE);
+
+ ExtList<String> result = new ExtList<String>();
+ for (int i = 1; i < args.length; i++) {
+ result.addAll(ExtList.from(args[i]));
+ }
+ Collections.sort(result);
+ return result.join();
+ }
+
+ static String _joinHelp = "${join;<list>...}";
+
+ public String _join(String args[]) {
+
+ verifyCommand(args, _joinHelp, null, 1, Integer.MAX_VALUE);
+
+ ExtList<String> result = new ExtList<String>();
+ for (int i = 1; i < args.length; i++) {
+ result.addAll(ExtList.from(args[i]));
+ }
+ return result.join();
+ }
+
+ 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.equalsIgnoreCase("false"))
+ 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 final 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 ExtList<String>();
+ for (int i = 1; i < args.length; i++) {
+ names.addAll(ExtList.from(args[i]));
+ }
+ 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");
+
+ String value = domain.getMap().get(args[1]);
+ if (value == null)
+ return "";
+
+ return value;
+ }
+
+ /**
+ * replace ; <list> ; regex ; replace
+ *
+ * @param args
+ * @return
+ */
+ public String _replace(String args[]) {
+ if (args.length != 4) {
+ reporter.warning("Invalid nr of arguments to replace " + Arrays.asList(args));
+ return null;
+ }
+
+ String list[] = args[1].split("\\s*,\\s*");
+ StringBuilder sb = new StringBuilder();
+ 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++) {
+ reporter.warning(process(args[i]));
+ }
+ return "";
+ }
+
+ public String _error(String args[]) {
+ for (int i = 1; i < args.length; i++) {
+ reporter.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 = ExtList.from(args[1]);
+
+ ExtList<String> names = new ExtList<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 {
+ reporter.warning("in toclassname, %s, is not a class path because it does not end in .class", args[1]);
+ }
+ }
+ return names.join(",");
+ }
+
+ /**
+ * 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 = Boolean.valueOf(args[2]);
+
+ ExtList<String> names = ExtList.from(args[1]);
+ ExtList<String> paths = new ExtList<String>(names.size());
+ for (String name : names) {
+ String path = name.replace('.', '/') + (cl ? ".class" : "");
+ paths.add(path);
+ }
+ return paths.join(",");
+ }
+
+ public String _dir(String args[]) {
+ if (args.length < 2) {
+ reporter.warning("Need at least one file name for ${dir;...}");
+ return null;
+ } else {
+ String del = "";
+ StringBuilder sb = new StringBuilder();
+ for (int i = 1; i < args.length; i++) {
+ File f = IO.getFile(base, 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) {
+ reporter.warning("Need at least one file name for ${basename;...}");
+ return null;
+ } else {
+ String del = "";
+ StringBuilder sb = new StringBuilder();
+ for (int i = 1; i < args.length; i++) {
+ File f = IO.getFile(base, 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) {
+ reporter.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) {
+ reporter.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();
+ TimeZone tz = TimeZone.getTimeZone("UTC");
+
+ if (args.length > 1) {
+ format = args[1];
+ }
+ if (args.length > 2) {
+ tz = TimeZone.getTimeZone(args[2]);
+ }
+ if (args.length > 3) {
+ now = Long.parseLong(args[3]);
+ }
+ if (args.length > 4) {
+ reporter.warning("Too many arguments for tstamp: " + Arrays.toString(args));
+ }
+
+ SimpleDateFormat sdf = new SimpleDateFormat(format);
+ sdf.setTimeZone(tz);
+
+ 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 = IO.getFile(base, 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);
+
+ List<File> files = new ArrayList<File>(new SortedList<File>(dir.listFiles()));
+
+ for (int i = 2; i < args.length; i++) {
+ Glob filters = new Glob(args[i]);
+ filters.select(files);
+ }
+
+ ExtList<String> result = new ExtList<String>();
+ for (File file : files)
+ result.add(relative ? file.getName() : file.getAbsolutePath());
+
+ return result.join(",");
+ }
+
+ public String _currenttime(String args[]) {
+ return Long.toString(System.currentTimeMillis());
+ }
+
+ /**
+ * System command. Execute a command and insert the result.
+ *
+ * @param args
+ * @param help
+ * @param patterns
+ * @param low
+ * @param high
+ */
+ public String system_internal(boolean allowFail, String args[]) throws Exception {
+ verifyCommand(args, "${" + (allowFail ? "system-allow-fail" : "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, base);
+ 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)
+ return exitValue + "";
+
+ if (!allowFail && (exitValue != 0)) {
+ reporter.error("System command " + command + " failed with " + exitValue);
+ }
+ return s.trim();
+ }
+
+ public String _system(String args[]) throws Exception {
+ return system_internal(false, args);
+ }
+
+ public String _system_allow_fail(String args[]) throws Exception {
+ String result = "";
+ try {
+ result = system_internal(true, args);
+ }
+ catch (Throwable t) {
+ /* ignore */
+ }
+ return result;
+ }
+
+ 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 = IO.getFile(base, 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;
+ Domain start;
+
+ public Link(Domain 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() {
+ StringBuilder sb = new StringBuilder("[");
+ append(sb);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ private void append(StringBuilder sb) {
+ if (previous != null) {
+ previous.append(sb);
+ sb.append(",");
+ }
+ sb.append(key);
+ }
+ }
+
+ /**
+ * 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 Map<String,String> getFlattenedProperties() {
+ // Some macros only work in a lower Domain, so we
+ // do not report unknown macros while flattening
+ flattening = true;
+ try {
+ Map<String,String> flattened = new HashMap<String,String>();
+ Map<String,String> source = domain.getMap();
+ for (String key : source.keySet()) {
+ if (!key.startsWith("_"))
+ if (key.startsWith("-"))
+ flattened.put(key, source.get(key));
+ else
+ flattened.put(key, process(source.get(key)));
+ }
+ return flattened;
+ }
+ finally {
+ flattening = false;
+ }
+ }
+
+ public final 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 = IO.getFile(base, args[2]);
+ return f.getAbsolutePath();
+ }
+
+ public String _path(String args[]) {
+ ExtList<String> list = new ExtList<String>();
+ for (int i = 1; i < args.length; i++) {
+ list.addAll(ExtList.from(args[i]));
+ }
+ return list.join(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.err.println(Arrays.toString(fields));
+ return null;
+ }
+ }
+
+ public String process(String line) {
+ return process(line, domain);
+ }
+
+ /**
+ * Generate a random string, which is guaranteed to be a valid Java
+ * identifier (first character is an ASCII letter, subsequent characters are
+ * ASCII letters or numbers). Takes an optional parameter for the length of
+ * string to generate; default is 8 characters.
+ */
+ public String _random(String[] args) {
+ int numchars = 8;
+ if (args.length > 1) {
+ try {
+ numchars = Integer.parseInt(args[1]);
+ }
+ catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid character count parameter in ${random} macro.");
+ }
+ }
+
+ char[] letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
+ char[] alphanums = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
+
+ char[] array = new char[numchars];
+ for (int i = 0; i < numchars; i++) {
+ char c;
+ if (i == 0)
+ c = letters[random.nextInt(letters.length)];
+ else
+ c = alphanums[random.nextInt(alphanums.length)];
+ array[i] = c;
+ }
+
+ return new String(array);
+ }
+
+ public void setReporter(Reporter reporter) {
+ this.reporter = reporter;
+ }
+
+
+ public int _processors(String args[]) {
+ float multiplier = 1F;
+ if ( args.length > 1 )
+ multiplier = Float.parseFloat(args[1]);
+
+ return (int) (Runtime.getRuntime().availableProcessors() * multiplier);
+ }
+
+ public long _maxMemory(String args[]) {
+ return Runtime.getRuntime().maxMemory();
+ }
+ public long _freeMemory(String args[]) {
+ return Runtime.getRuntime().freeMemory();
+ }
+
+ public long _nanoTime(String args[]) {
+ return System.nanoTime();
+ }
+
+}
diff --git a/bundleplugin/src/main/java/aQute/libg/sed/Sed.java b/bundleplugin/src/main/java/aQute/libg/sed/Sed.java
index 4642c92..0542f65 100644
--- a/bundleplugin/src/main/java/aQute/libg/sed/Sed.java
+++ b/bundleplugin/src/main/java/aQute/libg/sed/Sed.java
@@ -4,7 +4,7 @@
import java.util.*;
import java.util.regex.*;
-import aQute.lib.io.IO;
+import aQute.lib.io.*;
public class Sed {
final File file;