You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2017/05/31 14:41:45 UTC

svn commit: r1797047 - in /sling/whiteboard/cziegeler/feature: ./ src/main/java/org/apache/sling/feature/ src/main/java/org/apache/sling/feature/json/ src/test/java/org/apache/sling/feature/

Author: cziegeler
Date: Wed May 31 14:41:45 2017
New Revision: 1797047

URL: http://svn.apache.org/viewvc?rev=1797047&view=rev
Log:
Remove dependency to org.osgi

Added:
    sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Version.java   (with props)
    sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/VersionRange.java   (with props)
Modified:
    sling/whiteboard/cziegeler/feature/pom.xml
    sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/ArtifactId.java
    sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java
    sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/ArtifactIdTest.java

Modified: sling/whiteboard/cziegeler/feature/pom.xml
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/pom.xml?rev=1797047&r1=1797046&r2=1797047&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/feature/pom.xml (original)
+++ sling/whiteboard/cziegeler/feature/pom.xml Wed May 31 14:41:45 2017
@@ -49,7 +49,6 @@
                 <configuration>
                     <instructions>
                         <Conditional-Package>
-                            org.apache.felix.configurator.impl.conversion,
                             org.apache.felix.configurator.impl.json,
                             org.apache.felix.configurator.impl.model                            
                         </Conditional-Package>
@@ -60,10 +59,6 @@
     </build>
     <dependencies>
         <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>osgi.core</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.apache.geronimo.specs</groupId>
             <artifactId>geronimo-json_1.0_spec</artifactId>
             <version>1.0-alpha-1</version>
@@ -87,6 +82,11 @@
         	<artifactId>junit</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.johnzon</groupId>
             <artifactId>johnzon-core</artifactId>
             <version>1.0.0</version>

Modified: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/ArtifactId.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/ArtifactId.java?rev=1797047&r1=1797046&r2=1797047&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/ArtifactId.java (original)
+++ sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/ArtifactId.java Wed May 31 14:41:45 2017
@@ -16,8 +16,6 @@
  */
 package org.apache.sling.feature;
 
-import org.osgi.framework.Version;
-
 /**
  * An artifact identifier.
  *

Added: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Version.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Version.java?rev=1797047&view=auto
==============================================================================
--- sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Version.java (added)
+++ sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Version.java Wed May 31 14:41:45 2017
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2014). 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 org.apache.sling.feature;
+
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+/**
+ * This is a copy of org.osgi.framework.Version in order to avoid a dependency
+ * on the framework.
+ * Version identifier for capabilities such as bundles and packages.
+ *
+ * <p>
+ * Version identifiers have four components.
+ * <ol>
+ * <li>Major version. A non-negative integer.</li>
+ * <li>Minor version. A non-negative integer.</li>
+ * <li>Micro version. A non-negative integer.</li>
+ * <li>Qualifier. A text string. See {@code Version(String)} for the format of
+ * the qualifier string.</li>
+ * </ol>
+ *
+ * <p>
+ * {@code Version} objects are immutable.
+ *
+ */
+public class Version implements Comparable<Version> {
+	private final int			major;
+	private final int			minor;
+	private final int			micro;
+	private final String		qualifier;
+	private static final String	SEPARATOR		= ".";
+	private transient String	versionString /* default to null */;
+	private transient int		hash /* default to 0 */;
+
+	/**
+	 * The empty version "0.0.0".
+	 */
+	public static final Version	emptyVersion	= new Version(0, 0, 0);
+
+	/**
+	 * Creates a version identifier from the specified numerical components.
+	 *
+	 * <p>
+	 * The qualifier is set to the empty string.
+	 *
+	 * @param major Major component of the version identifier.
+	 * @param minor Minor component of the version identifier.
+	 * @param micro Micro component of the version identifier.
+	 * @throws IllegalArgumentException If the numerical components are
+	 *         negative.
+	 */
+	public Version(int major, int minor, int micro) {
+		this(major, minor, micro, null);
+	}
+
+	/**
+	 * Creates a version identifier from the specified components.
+	 *
+	 * @param major Major component of the version identifier.
+	 * @param minor Minor component of the version identifier.
+	 * @param micro Micro component of the version identifier.
+	 * @param qualifier Qualifier component of the version identifier. If
+	 *        {@code null} is specified, then the qualifier will be set to the
+	 *        empty string.
+	 * @throws IllegalArgumentException If the numerical components are negative
+	 *         or the qualifier string is invalid.
+	 */
+	public Version(int major, int minor, int micro, String qualifier) {
+		if (qualifier == null) {
+			qualifier = "";
+		}
+
+		this.major = major;
+		this.minor = minor;
+		this.micro = micro;
+		this.qualifier = qualifier;
+		validate();
+	}
+
+	/**
+	 * Creates a version identifier from the specified string.
+	 *
+	 * <p>
+	 * Version string grammar:
+	 *
+	 * <pre>
+	 * version ::= major('.'minor('.'micro('.'qualifier)?)?)?
+	 * major ::= digit+
+	 * minor ::= digit+
+	 * micro ::= digit+
+	 * qualifier ::= (alpha|digit|'_'|'-')+
+	 * digit ::= [0..9]
+	 * alpha ::= [a..zA..Z]
+	 * </pre>
+	 *
+	 * @param version String representation of the version identifier. There
+	 *        must be no whitespace in the argument.
+	 * @throws IllegalArgumentException If {@code version} is improperly
+	 *         formatted.
+	 */
+	public Version(String version) {
+		int maj = 0;
+		int min = 0;
+		int mic = 0;
+		String qual = "";
+
+		try {
+			StringTokenizer st = new StringTokenizer(version, SEPARATOR, true);
+			maj = parseInt(st.nextToken(), version);
+
+			if (st.hasMoreTokens()) { // minor
+				st.nextToken(); // consume delimiter
+				min = parseInt(st.nextToken(), version);
+
+				if (st.hasMoreTokens()) { // micro
+					st.nextToken(); // consume delimiter
+					mic = parseInt(st.nextToken(), version);
+
+					if (st.hasMoreTokens()) { // qualifier separator
+						st.nextToken(); // consume delimiter
+						qual = st.nextToken(""); // remaining string
+
+						if (st.hasMoreTokens()) { // fail safe
+							throw new IllegalArgumentException("invalid version \"" + version + "\": invalid format");
+						}
+					}
+				}
+			}
+		} catch (NoSuchElementException e) {
+			IllegalArgumentException iae = new IllegalArgumentException("invalid version \"" + version + "\": invalid format");
+			iae.initCause(e);
+			throw iae;
+		}
+
+		major = maj;
+		minor = min;
+		micro = mic;
+		qualifier = qual;
+		validate();
+	}
+
+	/**
+	 * Parse numeric component into an int.
+	 *
+	 * @param value Numeric component
+	 * @param version Complete version string for exception message, if any
+	 * @return int value of numeric component
+	 */
+	private static int parseInt(String value, String version) {
+		try {
+			return Integer.parseInt(value);
+		} catch (NumberFormatException e) {
+			IllegalArgumentException iae = new IllegalArgumentException("invalid version \"" + version + "\": non-numeric \"" + value + "\"");
+			iae.initCause(e);
+			throw iae;
+		}
+	}
+
+	/**
+	 * Called by the Version constructors to validate the version components.
+	 *
+	 * @throws IllegalArgumentException If the numerical components are negative
+	 *         or the qualifier string is invalid.
+	 */
+	private void validate() {
+		if (major < 0) {
+			throw new IllegalArgumentException("invalid version \"" + toString0() + "\": negative number \"" + major + "\"");
+		}
+		if (minor < 0) {
+			throw new IllegalArgumentException("invalid version \"" + toString0() + "\": negative number \"" + minor + "\"");
+		}
+		if (micro < 0) {
+			throw new IllegalArgumentException("invalid version \"" + toString0() + "\": negative number \"" + micro + "\"");
+		}
+		for (char ch : qualifier.toCharArray()) {
+			if (('A' <= ch) && (ch <= 'Z')) {
+				continue;
+			}
+			if (('a' <= ch) && (ch <= 'z')) {
+				continue;
+			}
+			if (('0' <= ch) && (ch <= '9')) {
+				continue;
+			}
+			if ((ch == '_') || (ch == '-')) {
+				continue;
+			}
+			throw new IllegalArgumentException("invalid version \"" + toString0() + "\": invalid qualifier \"" + qualifier + "\"");
+		}
+	}
+
+	/**
+	 * Parses a version identifier from the specified string.
+	 *
+	 * <p>
+	 * See {@link #Version(String)} for the format of the version string.
+	 *
+	 * @param version String representation of the version identifier. Leading
+	 *        and trailing whitespace will be ignored.
+	 * @return A {@code Version} object representing the version identifier. If
+	 *         {@code version} is {@code null} or the empty string then
+	 *         {@link #emptyVersion} will be returned.
+	 * @throws IllegalArgumentException If {@code version} is improperly
+	 *         formatted.
+	 */
+	public static Version parseVersion(String version) {
+		if (version == null) {
+			return emptyVersion;
+		}
+
+		return valueOf(version);
+	}
+
+	/**
+	 * Returns a {@code Version} object holding the version identifier in the
+	 * specified {@code String}.
+	 *
+	 * <p>
+	 * See {@link #Version(String)} for the format of the version string.
+	 *
+	 * <p>
+	 * This method performs a similar function as {@link #parseVersion(String)}
+	 * but has the static factory {@code valueOf(String)} method signature.
+	 *
+	 * @param version String representation of the version identifier. Leading
+	 *        and trailing whitespace will be ignored. Must not be {@code null}.
+	 * @return A {@code Version} object representing the version identifier. If
+	 *         {@code version} is the empty string then {@link #emptyVersion}
+	 *         will be returned.
+	 * @throws IllegalArgumentException If {@code version} is improperly
+	 *         formatted.
+	 * @since 1.8
+	 */
+	public static Version valueOf(String version) {
+		version = version.trim();
+		if (version.length() == 0) {
+			return emptyVersion;
+		}
+
+		return new Version(version);
+	}
+
+	/**
+	 * Returns the major component of this version identifier.
+	 *
+	 * @return The major component.
+	 */
+	public int getMajor() {
+		return major;
+	}
+
+	/**
+	 * Returns the minor component of this version identifier.
+	 *
+	 * @return The minor component.
+	 */
+	public int getMinor() {
+		return minor;
+	}
+
+	/**
+	 * Returns the micro component of this version identifier.
+	 *
+	 * @return The micro component.
+	 */
+	public int getMicro() {
+		return micro;
+	}
+
+	/**
+	 * Returns the qualifier component of this version identifier.
+	 *
+	 * @return The qualifier component.
+	 */
+	public String getQualifier() {
+		return qualifier;
+	}
+
+	/**
+	 * Returns the string representation of this version identifier.
+	 *
+	 * <p>
+	 * The format of the version string will be {@code major.minor.micro} if
+	 * qualifier is the empty string or {@code major.minor.micro.qualifier}
+	 * otherwise.
+	 *
+	 * @return The string representation of this version identifier.
+	 */
+	@Override
+	public String toString() {
+		return toString0();
+	}
+
+	/**
+	 * Internal toString behavior
+	 *
+	 * @return The string representation of this version identifier.
+	 */
+	String toString0() {
+		String s = versionString;
+		if (s != null) {
+			return s;
+		}
+		int q = qualifier.length();
+		StringBuffer result = new StringBuffer(20 + q);
+		result.append(major);
+		result.append(SEPARATOR);
+		result.append(minor);
+		result.append(SEPARATOR);
+		result.append(micro);
+		if (q > 0) {
+			result.append(SEPARATOR);
+			result.append(qualifier);
+		}
+		return versionString = result.toString();
+	}
+
+	/**
+	 * Returns a hash code value for the object.
+	 *
+	 * @return An integer which is a hash code value for this object.
+	 */
+	@Override
+	public int hashCode() {
+		int h = hash;
+		if (h != 0) {
+			return h;
+		}
+		h = 31 * 17;
+		h = 31 * h + major;
+		h = 31 * h + minor;
+		h = 31 * h + micro;
+		h = 31 * h + qualifier.hashCode();
+		return hash = h;
+	}
+
+	/**
+	 * Compares this {@code Version} object to another object.
+	 *
+	 * <p>
+	 * A version is considered to be <b>equal to </b> another version if the
+	 * major, minor and micro components are equal and the qualifier component
+	 * is equal (using {@code String.equals}).
+	 *
+	 * @param object The {@code Version} object to be compared.
+	 * @return {@code true} if {@code object} is a {@code Version} and is equal
+	 *         to this object; {@code false} otherwise.
+	 */
+	@Override
+	public boolean equals(Object object) {
+		if (object == this) { // quicktest
+			return true;
+		}
+
+		if (!(object instanceof Version)) {
+			return false;
+		}
+
+		Version other = (Version) object;
+		return (major == other.major) && (minor == other.minor) && (micro == other.micro) && qualifier.equals(other.qualifier);
+	}
+
+	/**
+	 * Compares this {@code Version} object to another {@code Version}.
+	 *
+	 * <p>
+	 * A version is considered to be <b>less than</b> another version if its
+	 * major component is less than the other version's major component, or the
+	 * major components are equal and its minor component is less than the other
+	 * version's minor component, or the major and minor components are equal
+	 * and its micro component is less than the other version's micro component,
+	 * or the major, minor and micro components are equal and it's qualifier
+	 * component is less than the other version's qualifier component (using
+	 * {@code String.compareTo}).
+	 *
+	 * <p>
+	 * A version is considered to be <b>equal to</b> another version if the
+	 * major, minor and micro components are equal and the qualifier component
+	 * is equal (using {@code String.compareTo}).
+	 *
+	 * @param other The {@code Version} object to be compared.
+	 * @return A negative integer, zero, or a positive integer if this version
+	 *         is less than, equal to, or greater than the specified
+	 *         {@code Version} object.
+	 * @throws ClassCastException If the specified object is not a
+	 *         {@code Version} object.
+	 */
+	@Override
+    public int compareTo(Version other) {
+		if (other == this) { // quicktest
+			return 0;
+		}
+
+		int result = major - other.major;
+		if (result != 0) {
+			return result;
+		}
+
+		result = minor - other.minor;
+		if (result != 0) {
+			return result;
+		}
+
+		result = micro - other.micro;
+		if (result != 0) {
+			return result;
+		}
+
+		return qualifier.compareTo(other.qualifier);
+	}
+}

Propchange: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Version.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/Version.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/VersionRange.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/VersionRange.java?rev=1797047&view=auto
==============================================================================
--- sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/VersionRange.java (added)
+++ sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/VersionRange.java Wed May 31 14:41:45 2017
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2013). 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 org.apache.sling.feature;
+
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+/**
+ * This is a copy of org.osgi.framework.VersionRange in order to avoid a dependency
+ * on the framework.
+ * Version range. A version range is an interval describing a set of
+ * {@link Version versions}.
+ *
+ * <p>
+ * A range has a left (lower) endpoint and a right (upper) endpoint. Each
+ * endpoint can be open (excluded from the set) or closed (included in the set).
+ *
+ * <p>
+ * {@code VersionRange} objects are immutable.
+ *
+ */
+
+public class VersionRange {
+	/**
+	 * The left endpoint is open and is excluded from the range.
+	 * <p>
+	 * The value of {@code LEFT_OPEN} is {@code '('}.
+	 */
+	public static final char	LEFT_OPEN				= '(';
+	/**
+	 * The left endpoint is closed and is included in the range.
+	 * <p>
+	 * The value of {@code LEFT_CLOSED} is {@code '['}.
+	 */
+	public static final char	LEFT_CLOSED				= '[';
+	/**
+	 * The right endpoint is open and is excluded from the range.
+	 * <p>
+	 * The value of {@code RIGHT_OPEN} is {@code ')'}.
+	 */
+	public static final char	RIGHT_OPEN				= ')';
+	/**
+	 * The right endpoint is closed and is included in the range.
+	 * <p>
+	 * The value of {@code RIGHT_CLOSED} is {@code ']'}.
+	 */
+	public static final char	RIGHT_CLOSED			= ']';
+
+	private final boolean		leftClosed;
+	private final Version		left;
+	private final Version		right;
+	private final boolean		rightClosed;
+	private final boolean		empty;
+
+	private transient String	versionRangeString /* default to null */;
+	private transient int		hash /* default to 0 */;
+
+	private static final String	LEFT_OPEN_DELIMITER		= "(";
+	private static final String	LEFT_CLOSED_DELIMITER	= "[";
+	private static final String	LEFT_DELIMITERS			= LEFT_CLOSED_DELIMITER + LEFT_OPEN_DELIMITER;
+	private static final String	RIGHT_OPEN_DELIMITER	= ")";
+	private static final String	RIGHT_CLOSED_DELIMITER	= "]";
+	private static final String	RIGHT_DELIMITERS		= RIGHT_OPEN_DELIMITER + RIGHT_CLOSED_DELIMITER;
+	private static final String	ENDPOINT_DELIMITER		= ",";
+
+	/**
+	 * Creates a version range from the specified versions.
+	 *
+	 * @param leftType Must be either {@link #LEFT_CLOSED} or {@link #LEFT_OPEN}
+	 *        .
+	 * @param leftEndpoint Left endpoint of range. Must not be {@code null}.
+	 * @param rightEndpoint Right endpoint of range. May be {@code null} to
+	 *        indicate the right endpoint is <i>Infinity</i>.
+	 * @param rightType Must be either {@link #RIGHT_CLOSED} or
+	 *        {@link #RIGHT_OPEN}.
+	 * @throws IllegalArgumentException If the arguments are invalid.
+	 */
+	public VersionRange(char leftType, Version leftEndpoint, Version rightEndpoint, char rightType) {
+		if ((leftType != LEFT_CLOSED) && (leftType != LEFT_OPEN)) {
+			throw new IllegalArgumentException("invalid leftType \"" + leftType + "\"");
+		}
+		if ((rightType != RIGHT_OPEN) && (rightType != RIGHT_CLOSED)) {
+			throw new IllegalArgumentException("invalid rightType \"" + rightType + "\"");
+		}
+		if (leftEndpoint == null) {
+			throw new IllegalArgumentException("null leftEndpoint argument");
+		}
+		leftClosed = leftType == LEFT_CLOSED;
+		rightClosed = rightType == RIGHT_CLOSED;
+		left = leftEndpoint;
+		right = rightEndpoint;
+		empty = isEmpty0();
+	}
+
+	/**
+	 * Creates a version range from the specified string.
+	 *
+	 * <p>
+	 * Version range string grammar:
+	 *
+	 * <pre>
+	 * range ::= interval | atleast
+	 * interval ::= ( '[' | '(' ) left ',' right ( ']' | ')' )
+	 * left ::= version
+	 * right ::= version
+	 * atleast ::= version
+	 * </pre>
+	 *
+	 * @param range String representation of the version range. The versions in
+	 *        the range must contain no whitespace. Other whitespace in the
+	 *        range string is ignored. Must not be {@code null}.
+	 * @throws IllegalArgumentException If {@code range} is improperly
+	 *         formatted.
+	 */
+	public VersionRange(String range) {
+		boolean closedLeft;
+		boolean closedRight;
+		Version endpointLeft;
+		Version endpointRight;
+
+		try {
+			StringTokenizer st = new StringTokenizer(range, LEFT_DELIMITERS, true);
+			String token = st.nextToken().trim(); // whitespace or left delim
+			if (token.length() == 0) { // leading whitespace
+				token = st.nextToken(); // left delim
+			}
+			closedLeft = LEFT_CLOSED_DELIMITER.equals(token);
+			if (!closedLeft && !LEFT_OPEN_DELIMITER.equals(token)) {
+				// first token is not a delimiter, so it must be "atleast"
+				if (st.hasMoreTokens()) { // there must be no more tokens
+					throw new IllegalArgumentException("invalid range \"" + range + "\": invalid format");
+				}
+				leftClosed = true;
+				rightClosed = false;
+				left = parseVersion(token, range);
+				right = null;
+				empty = false;
+				return;
+			}
+			String version = st.nextToken(ENDPOINT_DELIMITER);
+			endpointLeft = parseVersion(version, range);
+			token = st.nextToken(); // consume comma
+			version = st.nextToken(RIGHT_DELIMITERS);
+			token = st.nextToken(); // right delim
+			closedRight = RIGHT_CLOSED_DELIMITER.equals(token);
+			if (!closedRight && !RIGHT_OPEN_DELIMITER.equals(token)) {
+				throw new IllegalArgumentException("invalid range \"" + range + "\": invalid format");
+			}
+			endpointRight = parseVersion(version, range);
+
+			if (st.hasMoreTokens()) { // any more tokens have to be whitespace
+				token = st.nextToken("").trim();
+				if (token.length() != 0) { // trailing whitespace
+					throw new IllegalArgumentException("invalid range \"" + range + "\": invalid format");
+				}
+			}
+		} catch (NoSuchElementException e) {
+			IllegalArgumentException iae = new IllegalArgumentException("invalid range \"" + range + "\": invalid format");
+			iae.initCause(e);
+			throw iae;
+		}
+
+		leftClosed = closedLeft;
+		rightClosed = closedRight;
+		left = endpointLeft;
+		right = endpointRight;
+		empty = isEmpty0();
+	}
+
+	/**
+	 * Parse version component into a Version.
+	 *
+	 * @param version version component string
+	 * @param range Complete range string for exception message, if any
+	 * @return Version
+	 */
+	private static Version parseVersion(String version, String range) {
+		try {
+			return Version.valueOf(version);
+		} catch (IllegalArgumentException e) {
+			IllegalArgumentException iae = new IllegalArgumentException("invalid range \"" + range + "\": " + e.getMessage());
+			iae.initCause(e);
+			throw iae;
+		}
+	}
+
+	/**
+	 * Returns the left endpoint of this version range.
+	 *
+	 * @return The left endpoint.
+	 */
+	public Version getLeft() {
+		return left;
+	}
+
+	/**
+	 * Returns the right endpoint of this version range.
+	 *
+	 * @return The right endpoint. May be {@code null} which indicates the right
+	 *         endpoint is <i>Infinity</i>.
+	 */
+	public Version getRight() {
+		return right;
+	}
+
+	/**
+	 * Returns the type of the left endpoint of this version range.
+	 *
+	 * @return {@link #LEFT_CLOSED} if the left endpoint is closed or
+	 *         {@link #LEFT_OPEN} if the left endpoint is open.
+	 */
+	public char getLeftType() {
+		return leftClosed ? LEFT_CLOSED : LEFT_OPEN;
+	}
+
+	/**
+	 * Returns the type of the right endpoint of this version range.
+	 *
+	 * @return {@link #RIGHT_CLOSED} if the right endpoint is closed or
+	 *         {@link #RIGHT_OPEN} if the right endpoint is open.
+	 */
+	public char getRightType() {
+		return rightClosed ? RIGHT_CLOSED : RIGHT_OPEN;
+	}
+
+	/**
+	 * Returns whether this version range includes the specified version.
+	 *
+	 * @param version The version to test for inclusion in this version range.
+	 * @return {@code true} if the specified version is included in this version
+	 *         range; {@code false} otherwise.
+	 */
+	public boolean includes(Version version) {
+		if (empty) {
+			return false;
+		}
+		if (left.compareTo(version) >= (leftClosed ? 1 : 0)) {
+			return false;
+		}
+		if (right == null) {
+			return true;
+		}
+		return right.compareTo(version) >= (rightClosed ? 0 : 1);
+	}
+
+	/**
+	 * Returns the intersection of this version range with the specified version
+	 * ranges.
+	 *
+	 * @param ranges The version ranges to intersect with this version range.
+	 * @return A version range representing the intersection of this version
+	 *         range and the specified version ranges. If no version ranges are
+	 *         specified, then this version range is returned.
+	 */
+	public VersionRange intersection(VersionRange... ranges) {
+		if ((ranges == null) || (ranges.length == 0)) {
+			return this;
+		}
+		// prime with data from this version range
+		boolean closedLeft = leftClosed;
+		boolean closedRight = rightClosed;
+		Version endpointLeft = left;
+		Version endpointRight = right;
+
+		for (VersionRange range : ranges) {
+			int comparison = endpointLeft.compareTo(range.left);
+			if (comparison == 0) {
+				closedLeft = closedLeft && range.leftClosed;
+			} else {
+				if (comparison < 0) { // move endpointLeft to the right
+					endpointLeft = range.left;
+					closedLeft = range.leftClosed;
+				}
+			}
+			if (range.right != null) {
+				if (endpointRight == null) {
+					endpointRight = range.right;
+					closedRight = range.rightClosed;
+				} else {
+					comparison = endpointRight.compareTo(range.right);
+					if (comparison == 0) {
+						closedRight = closedRight && range.rightClosed;
+					} else {
+						if (comparison > 0) { // move endpointRight to the left
+							endpointRight = range.right;
+							closedRight = range.rightClosed;
+						}
+					}
+				}
+			}
+		}
+
+		return new VersionRange(closedLeft ? LEFT_CLOSED : LEFT_OPEN, endpointLeft, endpointRight, closedRight ? RIGHT_CLOSED : RIGHT_OPEN);
+	}
+
+	/**
+	 * Returns whether this version range is empty. A version range is empty if
+	 * the set of versions defined by the interval is empty.
+	 *
+	 * @return {@code true} if this version range is empty; {@code false}
+	 *         otherwise.
+	 */
+	public boolean isEmpty() {
+		return empty;
+	}
+
+	/**
+	 * Internal isEmpty behavior.
+	 *
+	 * @return {@code true} if this version range is empty; {@code false}
+	 *         otherwise.
+	 */
+	private boolean isEmpty0() {
+		if (right == null) { // infinity
+			return false;
+		}
+		int comparison = left.compareTo(right);
+		if (comparison == 0) { // endpoints equal
+			return !leftClosed || !rightClosed;
+		}
+		return comparison > 0; // true if left > right
+	}
+
+	/**
+	 * Returns whether this version range contains only a single version.
+	 *
+	 * @return {@code true} if this version range contains only a single
+	 *         version; {@code false} otherwise.
+	 */
+	public boolean isExact() {
+		if (empty || (right == null)) {
+			return false;
+		}
+		if (leftClosed) {
+			if (rightClosed) {
+				// [l,r]: exact if l == r
+				return left.equals(right);
+			} else {
+				// [l,r): exact if l++ >= r
+				Version adjacent1 = new Version(left.getMajor(), left.getMinor(), left.getMicro(), left.getQualifier() + "-");
+				return adjacent1.compareTo(right) >= 0;
+			}
+		} else {
+			if (rightClosed) {
+				// (l,r] is equivalent to [l++,r]: exact if l++ == r
+				Version adjacent1 = new Version(left.getMajor(), left.getMinor(), left.getMicro(), left.getQualifier() + "-");
+				return adjacent1.equals(right);
+			} else {
+				// (l,r) is equivalent to [l++,r): exact if (l++)++ >=r
+				Version adjacent2 = new Version(left.getMajor(), left.getMinor(), left.getMicro(), left.getQualifier() + "--");
+				return adjacent2.compareTo(right) >= 0;
+			}
+		}
+	}
+
+	/**
+	 * Returns the string representation of this version range.
+	 *
+	 * <p>
+	 * The format of the version range string will be a version string if the
+	 * right end point is <i>Infinity</i> ({@code null}) or an interval string.
+	 *
+	 * @return The string representation of this version range.
+	 */
+	@Override
+	public String toString() {
+		String s = versionRangeString;
+		if (s != null) {
+			return s;
+		}
+		String leftVersion = left.toString();
+		if (right == null) {
+			StringBuffer result = new StringBuffer(leftVersion.length() + 1);
+			result.append(left.toString0());
+			return versionRangeString = result.toString();
+		}
+		String rightVerion = right.toString();
+		StringBuffer result = new StringBuffer(leftVersion.length() + rightVerion.length() + 5);
+		result.append(leftClosed ? LEFT_CLOSED : LEFT_OPEN);
+		result.append(left.toString0());
+		result.append(ENDPOINT_DELIMITER);
+		result.append(right.toString0());
+		result.append(rightClosed ? RIGHT_CLOSED : RIGHT_OPEN);
+		return versionRangeString = result.toString();
+	}
+
+	/**
+	 * Returns a hash code value for the object.
+	 *
+	 * @return An integer which is a hash code value for this object.
+	 */
+	@Override
+	public int hashCode() {
+		int h = hash;
+		if (h != 0) {
+			return h;
+		}
+		if (empty) {
+			return hash = 31;
+		}
+		h = 31 + (leftClosed ? 7 : 5);
+		h = 31 * h + left.hashCode();
+		if (right != null) {
+			h = 31 * h + right.hashCode();
+			h = 31 * h + (rightClosed ? 7 : 5);
+		}
+		return hash = h;
+	}
+
+	/**
+	 * Compares this {@code VersionRange} object to another object.
+	 *
+	 * <p>
+	 * A version range is considered to be <b>equal to </b> another version
+	 * range if both the endpoints and their types are equal or if both version
+	 * ranges are {@link #isEmpty() empty}.
+	 *
+	 * @param object The {@code VersionRange} object to be compared.
+	 * @return {@code true} if {@code object} is a {@code VersionRange} and is
+	 *         equal to this object; {@code false} otherwise.
+	 */
+	@Override
+	public boolean equals(Object object) {
+		if (object == this) { // quicktest
+			return true;
+		}
+		if (!(object instanceof VersionRange)) {
+			return false;
+		}
+		VersionRange other = (VersionRange) object;
+		if (empty && other.empty) {
+			return true;
+		}
+		if (right == null) {
+			return (leftClosed == other.leftClosed) && (other.right == null) && left.equals(other.left);
+		}
+		return (leftClosed == other.leftClosed) && (rightClosed == other.rightClosed) && left.equals(other.left) && right.equals(other.right);
+	}
+
+	/**
+	 * Returns the filter string for this version range using the specified
+	 * attribute name.
+	 *
+	 * @param attributeName The attribute name to use in the returned filter
+	 *        string.
+	 * @return A filter string for this version range using the specified
+	 *         attribute name.
+	 * @throws IllegalArgumentException If the specified attribute name is not a
+	 *         valid attribute name.
+	 *
+	 * @see "Core Specification, Filters, for a description of the filter string syntax."
+	 */
+	public String toFilterString(String attributeName) {
+		if (attributeName.length() == 0) {
+			throw new IllegalArgumentException("invalid attributeName \"" + attributeName + "\"");
+		}
+		for (char ch : attributeName.toCharArray()) {
+			if ((ch == '=') || (ch == '>') || (ch == '<') || (ch == '~') || (ch == '(') || (ch == ')')) {
+				throw new IllegalArgumentException("invalid attributeName \"" + attributeName + "\"");
+			}
+		}
+
+		StringBuffer result = new StringBuffer(128);
+		final boolean needPresence = !leftClosed && ((right == null) || !rightClosed);
+		final boolean multipleTerms = needPresence || (right != null);
+		if (multipleTerms) {
+			result.append("(&");
+		}
+		if (needPresence) {
+			result.append('(');
+			result.append(attributeName);
+			result.append("=*)");
+		}
+		if (leftClosed) {
+			result.append('(');
+			result.append(attributeName);
+			result.append(">=");
+			result.append(left.toString0());
+			result.append(')');
+		} else {
+			result.append("(!(");
+			result.append(attributeName);
+			result.append("<=");
+			result.append(left.toString0());
+			result.append("))");
+		}
+		if (right != null) {
+			if (rightClosed) {
+				result.append('(');
+				result.append(attributeName);
+				result.append("<=");
+				result.append(right.toString0());
+				result.append(')');
+			} else {
+				result.append("(!(");
+				result.append(attributeName);
+				result.append(">=");
+				result.append(right.toString0());
+				result.append("))");
+			}
+		}
+		if (multipleTerms) {
+			result.append(')');
+		}
+
+		return result.toString();
+	}
+
+	/**
+	 * Returns a {@code VersionRange} object holding the version range in the
+	 * specified {@code String}.
+	 *
+	 * <p>
+	 * See {@link #VersionRange(String)} for the format of the version range
+	 * string.
+	 *
+	 * @param range String representation of the version range. The versions in
+	 *        the range must contain no whitespace. Other whitespace in the
+	 *        range string is ignored. Must not be {@code null}.
+	 * @return A {@code VersionRange} object representing the version range.
+	 * @throws IllegalArgumentException If {@code range} is improperly
+	 *         formatted.
+	 * @since 1.8
+	 */
+	public static VersionRange valueOf(String range) {
+		return new VersionRange(range);
+	}
+}

Propchange: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/VersionRange.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/VersionRange.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Modified: sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java?rev=1797047&r1=1797046&r2=1797047&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java (original)
+++ sling/whiteboard/cziegeler/feature/src/main/java/org/apache/sling/feature/json/FeatureJSONReader.java Wed May 31 14:41:45 2017
@@ -36,9 +36,9 @@ import javax.json.JsonObjectBuilder;
 import javax.json.JsonStructure;
 import javax.json.JsonWriter;
 
-import org.apache.felix.configurator.impl.conversion.TypeConverter;
 import org.apache.felix.configurator.impl.json.JSMin;
 import org.apache.felix.configurator.impl.json.JSONUtil;
+import org.apache.felix.configurator.impl.json.TypeConverter;
 import org.apache.felix.configurator.impl.model.Config;
 import org.apache.sling.feature.Artifact;
 import org.apache.sling.feature.ArtifactId;

Modified: sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/ArtifactIdTest.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/ArtifactIdTest.java?rev=1797047&r1=1797046&r2=1797047&view=diff
==============================================================================
--- sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/ArtifactIdTest.java (original)
+++ sling/whiteboard/cziegeler/feature/src/test/java/org/apache/sling/feature/ArtifactIdTest.java Wed May 31 14:41:45 2017
@@ -20,7 +20,6 @@ import static org.junit.Assert.assertEqu
 import static org.junit.Assert.assertTrue;
 
 import org.junit.Test;
-import org.osgi.framework.Version;
 
 public class ArtifactIdTest {