Sync bndlib code

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1399825 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/WorkspaceRepository.java b/bundleplugin/src/main/java/aQute/bnd/build/WorkspaceRepository.java
index ce5cb66..9e06e7e 100644
--- a/bundleplugin/src/main/java/aQute/bnd/build/WorkspaceRepository.java
+++ b/bundleplugin/src/main/java/aQute/bnd/build/WorkspaceRepository.java
@@ -21,19 +21,24 @@
 		Collection<Project> projects = workspace.getAllProjects();
 		SortedMap<Version,File> foundVersion = new TreeMap<Version,File>();
 		for (Project project : projects) {
-			File[] build = project.build(false);
-			if (build != null) {
-				for (File file : build) {
-					Jar jar = new Jar(file);
-					if (bsn.equals(jar.getBsn())) {
-						Version version = new Version(jar.getVersion());
-						boolean exact = range.matches("[0-9]+\\.[0-9]+\\.[0-9]+\\..*");
-						if ("latest".equals(range) || matchVersion(range, version, exact)) {
-							foundVersion.put(version, file);
+			for (Builder builder : project.getSubBuilders()) {	
+				if (!bsn.equals(builder.getBsn())) {
+					continue;
+				}
+				Version version = new Version(builder.getVersion());
+				boolean exact = range.matches("[0-9]+\\.[0-9]+\\.[0-9]+\\..*");
+				if ("latest".equals(range) || matchVersion(range, version, exact)) {
+					File file = project.getOutputFile(bsn);
+					if (!file.exists()) {
+						Jar jar = builder.build();
+						if (jar == null) {
+							project.getInfo(builder);
+							continue;
 						}
+						file = project.saveBuild(jar);
+						jar.close();
 					}
-					
-					jar.close();
+					foundVersion.put(version, file);
 				}
 			}
 		}
@@ -98,26 +103,20 @@
 		List<String> names = new ArrayList<String>();
 		Collection<Project> projects = workspace.getAllProjects();
 		for (Project project : projects) {
-			File[] build = project.build(false);
-			if (build != null) {
-				for (File file : build) {
-					Jar jar = new Jar(file);
-					String bsn = jar.getBsn();
-					if (pattern != null) {
-						Glob glob = new Glob(pattern);
-						Matcher matcher = glob.matcher(bsn);
-						if (matcher.matches()) {
-							if (!names.contains(bsn)) {
-								names.add(bsn);
-							}
-						}
-					} else {
+			for (Builder builder : project.getSubBuilders()) {	
+				String bsn = builder.getBsn();
+				if (pattern != null) {
+					Glob glob = new Glob(pattern);
+					Matcher matcher = glob.matcher(bsn);
+					if (matcher.matches()) {
 						if (!names.contains(bsn)) {
 							names.add(bsn);
 						}
 					}
-					
-					jar.close();
+				} else {
+					if (!names.contains(bsn)) {
+						names.add(bsn);
+					}
 				}
 			}
 		}
diff --git a/bundleplugin/src/main/java/aQute/bnd/build/model/BndEditModel.java b/bundleplugin/src/main/java/aQute/bnd/build/model/BndEditModel.java
index 5a6ca78..41b9ac9 100644
--- a/bundleplugin/src/main/java/aQute/bnd/build/model/BndEditModel.java
+++ b/bundleplugin/src/main/java/aQute/bnd/build/model/BndEditModel.java
@@ -7,6 +7,7 @@
 
 import org.osgi.resource.*;
 
+import aQute.bnd.build.*;
 import aQute.bnd.build.model.clauses.*;
 import aQute.bnd.build.model.conversions.*;
 import aQute.bnd.header.*;
@@ -59,7 +60,7 @@
 	private final Properties										properties					= new Properties();
 
 	private File													bndResource;
-	private boolean													projectFile;
+	private String													bndResourceName;
 	private final Map<String,Object>								objectProperties			= new HashMap<String,Object>();
 	private final Map<String,String>								changesToSave				= new HashMap<String,String>();
 
@@ -764,12 +765,12 @@
 		propChangeSupport.firePropertyChange(name, oldValue, newValue);
 	}
 
-	public void setProjectFile(boolean projectFile) {
-		this.projectFile = projectFile;
+	public boolean isProjectFile() {
+		return Project.BNDFILE.equals(getBndResourceName());
 	}
 
-	public boolean isProjectFile() {
-		return this.projectFile;
+	public boolean isBndrun() {
+		return getBndResourceName().endsWith(Constants.DEFAULT_BNDRUN_EXTENSION);
 	}
 
 	public void addPropertyChangeListener(PropertyChangeListener listener) {
@@ -795,4 +796,14 @@
 	public File getBndResource() {
 		return bndResource;
 	}
+
+	public String getBndResourceName() {
+		if (bndResourceName == null)
+			return "";
+		return bndResourceName;
+	}
+
+	public void setBndResourceName(String bndResourceName) {
+		this.bndResourceName = bndResourceName;
+	}
 }
diff --git a/bundleplugin/src/main/java/aQute/bnd/differ/Baseline.java b/bundleplugin/src/main/java/aQute/bnd/differ/Baseline.java
index fe79c7d..cd2d9b6 100644
--- a/bundleplugin/src/main/java/aQute/bnd/differ/Baseline.java
+++ b/bundleplugin/src/main/java/aQute/bnd/differ/Baseline.java
@@ -78,7 +78,14 @@
 
 		newerVersion = getVersion(n);
 		olderVersion = getVersion(o);
-		
+
+		boolean firstRelease = false;
+		if (o.get("<manifest>") == null) {
+			firstRelease = true;
+			if (newerVersion.equals(Version.emptyVersion)) {
+				newerVersion = Version.ONE;
+			}
+		}
 		Delta highestDelta = Delta.MICRO;
 		for (Diff pdiff : apiDiff.getChildren()) {
 			if (pdiff.getType() != Type.PACKAGE) // Just packages
@@ -108,7 +115,14 @@
 			} else if (pdiff.getDelta() == Delta.REMOVED) {
 				info.suggestedVersion = null;
 			} else if (pdiff.getDelta() == Delta.ADDED) {
-				info.suggestedVersion = Version.ONE;
+				if (firstRelease) {
+					info.suggestedVersion = info.newerVersion;
+					if (info.suggestedVersion.equals(Version.emptyVersion)) {
+						info.suggestedVersion = newerVersion.getWithoutQualifier();
+					}
+				} else {
+					info.suggestedVersion = Version.ONE;
+				}
 			} else {
 				// We have an API change
 				info.suggestedVersion = bump(pdiff.getDelta(), info.olderVersion, 1, 0);
@@ -151,9 +165,10 @@
 				highestDelta = pdiff.getDelta();
 			}
 		}
-		suggestedVersion = bumpBundle(highestDelta, olderVersion, 1, 0);
-		if (suggestedVersion.getMajor() == 0) {
-			suggestedVersion = Version.ONE;
+		if (firstRelease) {
+			suggestedVersion = newerVersion;
+		} else {
+			suggestedVersion = bumpBundle(highestDelta, olderVersion, 1, 0);
 		}
 		return infos;
 	}
diff --git a/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java b/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java
index 38de872..c1d28a4 100644
--- a/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java
+++ b/bundleplugin/src/main/java/aQute/bnd/differ/DiffPluginImpl.java
@@ -33,6 +33,11 @@
 	 */
 	final static Set<String>	IGNORE_HEADERS	= new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
 
+	/**
+	 * Headers that have values that should be sorted
+	 */
+	final static Set<String>	ORDERED_HEADERS	= new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
+
 	static {
 		MAJOR_HEADERS.add(Constants.EXPORT_PACKAGE);
 		MAJOR_HEADERS.add(Constants.IMPORT_PACKAGE);
@@ -47,6 +52,8 @@
 		IGNORE_HEADERS.add(Constants.TOOL);
 		IGNORE_HEADERS.add(Constants.BND_LASTMODIFIED);
 		IGNORE_HEADERS.add(Constants.CREATED_BY);
+
+		ORDERED_HEADERS.add(Constants.SERVICE_COMPONENT);
 	}
 
 	/**
@@ -166,6 +173,10 @@
 					clausesDef.add(new Element(Type.CLAUSE, clause.getKey(), parameterDef, CHANGED, CHANGED, null));
 				}
 				result.add(new Element(Type.HEADER, header, clausesDef, CHANGED, CHANGED, null));
+			} else if (ORDERED_HEADERS.contains(header)) {
+				ExtList<String> values = ExtList.from(value);
+				Collections.sort(values);
+				result.add(new Element(Type.HEADER, header + ":" + values.join(), null, CHANGED, CHANGED, null));
 			} else {
 				result.add(new Element(Type.HEADER, header + ":" + value, null, CHANGED, CHANGED, null));
 			}
diff --git a/bundleplugin/src/main/java/aQute/bnd/osgi/Analyzer.java b/bundleplugin/src/main/java/aQute/bnd/osgi/Analyzer.java
index d6be831..fbbf4fa 100755
--- a/bundleplugin/src/main/java/aQute/bnd/osgi/Analyzer.java
+++ b/bundleplugin/src/main/java/aQute/bnd/osgi/Analyzer.java
@@ -23,6 +23,7 @@
 
 import java.io.*;
 import java.net.*;
+import java.text.*;
 import java.util.*;
 import java.util.Map.Entry;
 import java.util.jar.*;
@@ -712,12 +713,17 @@
 		return getBndInfo("version", "<unknown>");
 	}
 
+	static SimpleDateFormat df = new SimpleDateFormat("EEE MMM dd hh:mm:ss z yyyy");
 	public long getBndLastModified() {
 		String time = getBndInfo("lastmodified", "0");
-		try {
+		if ( time.matches("\\d+"))
 			return Long.parseLong(time);
-		}
-		catch (Exception e) {
+		
+		try {
+			Date parse = df.parse(time);
+			if ( parse != null)
+				return parse.getTime();
+		} catch( ParseException e) {
 			// Ignore
 		}
 		return 0;
diff --git a/bundleplugin/src/main/java/aQute/bnd/osgi/Builder.java b/bundleplugin/src/main/java/aQute/bnd/osgi/Builder.java
index b5ed9be..0970bd3 100755
--- a/bundleplugin/src/main/java/aQute/bnd/osgi/Builder.java
+++ b/bundleplugin/src/main/java/aQute/bnd/osgi/Builder.java
@@ -260,7 +260,7 @@
 	 */
 
 	void sign(@SuppressWarnings("unused") Jar jar) throws Exception {
-		String signing = getProperty("-sign");
+		String signing = getProperty(SIGN);
 		if (signing == null)
 			return;
 
diff --git a/bundleplugin/src/main/java/aQute/bnd/osgi/Macro.java b/bundleplugin/src/main/java/aQute/bnd/osgi/Macro.java
index bfd0621..be1a4c8 100755
--- a/bundleplugin/src/main/java/aQute/bnd/osgi/Macro.java
+++ b/bundleplugin/src/main/java/aQute/bnd/osgi/Macro.java
@@ -229,7 +229,8 @@
 			}
 			catch (InvocationTargetException e) {
 				if (e.getCause() instanceof IllegalArgumentException) {
-					domain.error("%s, for cmd: %s, arguments; %s", e.getCause().getMessage(), method, Arrays.toString(args));
+					domain.error("%s, for cmd: %s, arguments; %s", e.getCause().getMessage(), method,
+							Arrays.toString(args));
 				} else {
 					domain.warning("Exception in replace: %s", e.getCause());
 					e.getCause().printStackTrace();
@@ -260,11 +261,11 @@
 		return Processor.join(set, ",");
 	}
 
-	public String _pathseparator(@SuppressWarnings("unused") String args[]) {
+	public String _pathseparator(String args[]) {
 		return File.pathSeparator;
 	}
 
-	public String _separator(@SuppressWarnings("unused") String args[]) {
+	public String _separator(String args[]) {
 		return File.separator;
 	}
 
@@ -332,8 +333,20 @@
 		return "";
 	}
 
-	public String _now(@SuppressWarnings("unused") String args[]) {
-		return new Date().toString();
+	public final static String	_nowHelp	= "${now;pattern|'long'}, returns current time";
+
+	public Object _now(String args[]) {
+		verifyCommand(args, _nowHelp, null, 1, 2);
+		Date now = new Date();
+
+		if (args.length == 2) {
+			if ("long".equals(args[1]))
+				return now.getTime();
+
+			DateFormat df = new SimpleDateFormat(args[1]);
+			return df.format(now);
+		}
+		return new Date();
 	}
 
 	public final static String	_fmodifiedHelp	= "${fmodified;<list of filenames>...}, return latest modification date";
@@ -604,7 +617,7 @@
 		return Processor.join(result, ",");
 	}
 
-	public String _currenttime(@SuppressWarnings("unused") String args[]) {
+	public String _currenttime(String args[]) {
 		return Long.toString(System.currentTimeMillis());
 	}
 
@@ -842,7 +855,7 @@
 		}
 	}
 
-	public static void verifyCommand(String args[], @SuppressWarnings("unused") String help, Pattern[] patterns, int low, int high) {
+	public static void verifyCommand(String args[], String help, Pattern[] patterns, int low, int high) {
 		String message = "";
 		if (args.length > high) {
 			message = "too many arguments";
diff --git a/bundleplugin/src/main/java/aQute/bnd/service/RepositoryPlugin.java b/bundleplugin/src/main/java/aQute/bnd/service/RepositoryPlugin.java
index f3ee1f0..f213238 100644
--- a/bundleplugin/src/main/java/aQute/bnd/service/RepositoryPlugin.java
+++ b/bundleplugin/src/main/java/aQute/bnd/service/RepositoryPlugin.java
@@ -17,8 +17,8 @@
 	 * Options used to steer the put operation
 	 */
 	class PutOptions {
-		public String	BUNDLE	= "application/vnd.osgi.bundle";
-		public String	LIB		= "application/vnd.aQute.lib";
+		public static final String	BUNDLE	= "application/vnd.osgi.bundle";
+		public static final String	LIB		= "application/vnd.aQute.lib";
 
 		/**
 		 * The <b>SHA1</b> digest of the artifact to put into the repository.
diff --git a/bundleplugin/src/main/java/aQute/lib/converter/Converter.java b/bundleplugin/src/main/java/aQute/lib/converter/Converter.java
index 72b380c..9eae98a 100644
--- a/bundleplugin/src/main/java/aQute/lib/converter/Converter.java
+++ b/bundleplugin/src/main/java/aQute/lib/converter/Converter.java
@@ -192,7 +192,12 @@
 				return Base64.decodeBase64(input);
 
 			if (Enum.class.isAssignableFrom(resultType)) {
-				return Enum.valueOf((Class<Enum>) resultType, input);
+				try {
+					return Enum.valueOf((Class<Enum>) resultType, input);
+				} catch( Exception e) {
+					input = input.toUpperCase();
+					return Enum.valueOf((Class<Enum>) resultType, input);
+				}
 			}
 			if (resultType == Pattern.class) {
 				return Pattern.compile(input);
diff --git a/bundleplugin/src/main/resources/aQute/lib/spring/extract.xsl b/bundleplugin/src/main/resources/aQute/lib/spring/extract.xsl
index efad6cd..14bd8f4 100644
--- a/bundleplugin/src/main/resources/aQute/lib/spring/extract.xsl
+++ b/bundleplugin/src/main/resources/aQute/lib/spring/extract.xsl
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:jms="http://www.springframework.org/schema/jms" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:osgi-compendium="http://www.springframework.org/schema/osgi-compendium" xmlns:osgi="http://www.springframework.org/schema/osgi" xmlns:tool="http://www.springframework.org/schema/tool" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:webflow-config="http://www.springframework.org/schema/webflow-config">
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:jms="http://www.springframework.org/schema/jms" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:osgi-compendium="http://www.springframework.org/schema/osgi-compendium" xmlns:osgi="http://www.springframework.org/schema/osgi" xmlns:tool="http://www.springframework.org/schema/tool" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:webflow-config="http://www.springframework.org/schema/webflow-config" xmlns:blueprint="http://www.eclipse.org/gemini/blueprint/schema/blueprint">
 	<xsl:output method="text" />
 
 	<xsl:template match="/">
@@ -20,6 +20,7 @@
 			|	//jee:*/@business-interface
 			|	//lang:*/@script-interfaces
 			|	//osgi:*/@interface
+			|	//blueprint:*/@interface
 			|	//util:list/@list-class
 			|	//util:set/@set-class
 			|	//util:map/@map-class