Merged latest changes from trunk.

git-svn-id: https://svn.apache.org/repos/asf/ant/ivy/core/branches/2.3.x@1326424 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Maarten Coene 2012-04-15 21:01:43 +00:00
parent 914876337f
commit 0407058fca
39 changed files with 503 additions and 687 deletions

View File

@ -131,6 +131,7 @@ for detailed view of each issue, please consult http://issues.apache.org/jira/br
- DOCUMENTATION: wrong default resolver documented on the 'How does it work' page (IVY-1265)
- DOCUMENTATION: Correct outdated links to configuration pages (IVY-1266)
- NEW: [orgPath] can now be used as token in ivy/artifact patterns
- NEW: New Ant datatype ivy:resources, an Ant resource collection like ivy:cachepath or ivy:cachefileset (IVY-334)
- NEW: ivy:resolve and post resole task can now have inlined dependencies declaration.
- NEW: Import Bushel into Ivy core (IVY-1241)
@ -144,7 +145,6 @@ for detailed view of each issue, please consult http://issues.apache.org/jira/br
- IMPROVEMENT: ivy:makepom child element dependency should support the type and classifier attributes (IVY-1262)
- IMPROVEMENT: ivy:retrieve can now create a path or fileset containing the retrieved artifacts (IVY-1235)
- IMPROVEMENT: Improve diagnostics in ssh resolver (IVY-1267) (thanks to Stepan Koltsov)
- IMPROVEMENT: ivy:retrieve can now convert 'dotted'-organisation names into a directory tree.
- IMPROVEMENT: ivy:retrieve now accepts a nested mapper type.
- FIX: Exclude doesn't work when there is some circular dependencies (IVY-1309)

View File

@ -94,6 +94,7 @@ The tokens available depends on where the pattern is used (will it be evaluated
But here are all the tokens currently available:
<ul>
<li>[organisation]</li> the organisation name
<li>[orgPath] <span class="since">(since 2.3)</span></li> the organisation name where '.' has been replaced by '/'. This can be used to configure maven2-like repositories.
<li>[module]</li> the module name
<li>[branch]</li> the branch name
<li>[revision]</li> the revision name

BIN
doc/images/warning.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

View File

@ -28,9 +28,14 @@
Since Apache Ivy&#153; 2.3, some support for OSGi&#153; dependency management has been introduced.
<div class="notice">
<table class="notice">
<tr>
<td style="vertical-align: top"><img src="images/warning.png" style="float:left;" /></td>
<td>
Note that this feature is considered as <b>experimental</b>. It should work with simple configuration but may not in complex ones. If you have any issue with that feature, you are welcomed to come discussed your use case on the <a href="http://ant.apache.org/ivy/mailing-lists.html">ivy-user</a> mailing list, or discuss about implementation issues or improvement you may have found on <a href="http://ant.apache.org/ivy/mailing-lists.html">ant-dev</a>.
</div>
</td>
</tr>
</table>
So with a standard ivy.xml, you can express some dependency on some OSGi bundle and every of their trasitive dependencies will be resolved. You can also declare in your ivy.xml some OSGi dependency, like a <tt>Require-Bundle</tt>, an <tt>Import-Package</tt> or an <tt>Import-Service</tt>, miming an OSGi MANIFEST.MF.

View File

@ -26,9 +26,14 @@
<body>
<textarea id="xooki-source">
<div class="notice">
This documentation is describing the <b>experimental</b> OSGi capability of Ivy. It should work with simple configuration but may not in complex ones. If you have any issue with that feature, you are welcomed to come discussed your use case on the <a href="http://ant.apache.org/ivy/mailing-lists.html">ivy-user</a> mailing list, or discuss about implementation issues or improvement you may have found on <a href="http://ant.apache.org/ivy/mailing-lists.html">ant-dev</a>.
</div>
<table class="notice">
<tr>
<td style="vertical-align: top"><img src="../images/warning.png" style="float:left;" /></td>
<td>
Note that this feature is considered as <b>experimental</b>. It should work with simple configuration but may not in complex ones. If you have any issue with that feature, you are welcomed to come discussed your use case on the <a href="http://ant.apache.org/ivy/mailing-lists.html">ivy-user</a> mailing list, or discuss about implementation issues or improvement you may have found on <a href="http://ant.apache.org/ivy/mailing-lists.html">ant-dev</a>.
</td>
</tr>
</table>
This page describes how to build an Eclipse&#153; plugin with Apache Ivy&#153; and its OSGi&#153; capabilities.
@ -39,6 +44,7 @@ In few steps, we will setup a build to compile and package an Eclipse plugin.
<ol>
<li>download this <a href="../samples/eclipse-plugin/ivy.xml">ivy.xml<a>, this <a href="../samples/eclipse-plugin/ivysettings.xml">ivysettings.xml</a>, this <a href="../samples/eclipse-plugin/ivysettings.properties">ivysettings.properties</a>, this <a href="../samples/eclipse-plugin/build.xml">build.xml</a>, and put them into your plugin folder;</li>
<li>in the ivysettings.properties, specify the location of the plugins folder of your Eclipse target;</li>
<li>in the ivy.xml, change the symbolic name declared in the extends element;</li>
<li><i>(optional)</i> by default the build.xml is expecting the sources to be in the <tt>src</tt> folder. You may want to edit it if it is not the case</li>
<li><i>(optional)</i> if Ivy is not in Ant's classpath, get the jar of <a href="../download.html">Apache Ivy</a> and edit the build.xml accordingly (see the comments at the begining of the file)</li>
</ol>

View File

@ -36,9 +36,8 @@ In OSGi a bundle is identified by its symbolic name. In Ivy there is a notion of
The choosen mapping is:
<ul>
<li>No organisation : org=""</li>
<li>The organisation is "bundle" (transitive dependencies like pakages or services have their own organisations, "package" and "service")</li>
<li>The module name is the symbolic name</li>
<li>an extra attribute is defining it as an OSGi bundle</li>
</ul>
<table border="1" cellspacing="1" cellpadding="4">
@ -50,7 +49,7 @@ The choosen mapping is:
<td> <tt>Bundle-SymbolicName: com.acme.product.plugin</tt> </td>
<td>
<code type="xml">
<info organisation="" module="com.acme.product.plugin" osgi="bundle" />
<info organisation="bundle" module="com.acme.product.plugin" />
</code>
</td>
</tr>
@ -75,7 +74,7 @@ Then about version range, Ivy will understand correctly fully defined range as <
<td><tt>Require-Bundle: com.acme.product.plugin;bundle-version="3.2.1"</tt> </td>
<td>
<code type="xml">
<dependency osgi="bundle" org="" name="com.acme.product.plugin" rev="[3.2.1,)" />
<dependency org="bundle" name="com.acme.product.plugin" rev="[3.2.1,)" />
</code>
</td>
</tr>
@ -159,7 +158,7 @@ If there is the OSGi <tt>resolution</tt> parameter specified to <tt>optional</tt
<td> <tt>Require-Bundle: com.acme.product.plugin;bundle-version="3.2.1";resolution:="optional"</tt> </td>
<td>
<code type="xml">
<dependency osgi="bundle" org="" name="com.acme.product.plugin" rev="[3.2.1,)" conf="optional->default;transitive-optional->transitive-optional" />
<dependency org="bundle" name="com.acme.product.plugin" rev="[3.2.1,)" conf="optional->default;transitive-optional->transitive-optional" />
</code>
</td>
</tr>
@ -183,7 +182,7 @@ As it is an import package the configuration of the dependency will be the <tt>u
</td>
<td>
<code type="xml">
<dependency osgi="pkg" org="" name="com.acme.product.plugin.utils" rev="[3.2.1,)" conf="default->default;use_com.acme.product.plugin.utils->use_com.acme.product.plugin.utils" />
<dependency org="package" name="com.acme.product.plugin.utils" rev="[3.2.1,)" conf="default->default;use_com.acme.product.plugin.utils->use_com.acme.product.plugin.utils" />
</code>
</td>
</tr>
@ -191,7 +190,7 @@ As it is an import package the configuration of the dependency will be the <tt>u
<td> <tt>Import-Package: com.acme.product.plugin.utils;version="3.2.1";resolution:="optional"</tt> </td>
<td>
<code type="xml">
<dependency osgi="pkg" org="" name="com.acme.product.plugin.utils" rev="[3.2.1,)" conf="optional->default;transitive-optional->transitive-optional;use_com.acme.product.plugin.utils->use_com.acme.product.plugin.utils" />
<dependency org="package" name="com.acme.product.plugin.utils" rev="[3.2.1,)" conf="optional->default;transitive-optional->transitive-optional;use_com.acme.product.plugin.utils->use_com.acme.product.plugin.utils" />
</code>
</td>
</tr>
@ -211,9 +210,9 @@ The OSGi <tt>Bundle-RequiredExecutionEnvironment</tt> manifest attribute is spec
<td>
<code type="xml">
<dependencies>
<exclude org="" module="javax.accessibility" osgi="pkg" />
<exclude org="" module="javax.activation" osgi="pkg" />
<exclude org="" module="javax.activity" osgi="pkg" />
<exclude org="package" module="javax.accessibility" />
<exclude org="package" module="javax.activation" />
<exclude org="package" module="javax.activity" />
...
</dependencies>
</code>

View File

@ -26,9 +26,18 @@
<body>
<textarea id="xooki-source">
<div class="notice">
This documentation is describing the <b>experimental</b> OSGi capability of Ivy. It should work with simple configuration but may not in complex ones. If you have any issue with that feature, you are welcomed to come discussed your use case on the <a href="http://ant.apache.org/ivy/mailing-lists.html">ivy-user</a> mailing list, or discuss about implementation issues or improvement you may have found on <a href="http://ant.apache.org/ivy/mailing-lists.html">ant-dev</a>.
</div>
<table class="notice">
<tr>
<td style="vertical-align: top"><img src="../images/warning.png" style="float:left;" /></td>
<td>
Note that this feature is considered as <b>experimental</b>. It should work with simple configuration but may not in complex ones. If you have any issue with that feature, you are welcomed to come discussed your use case on the <a href="http://ant.apache.org/ivy/mailing-lists.html">ivy-user</a> mailing list, or discuss about implementation issues or improvement you may have found on <a href="http://ant.apache.org/ivy/mailing-lists.html">ant-dev</a>.
</td>
</tr>
</table>
<hr />
<center><b>TODO - WORK IN PROGRESS</b></center>
<hr />
This page describes how to build an OSGi&#153; bundle with Apache Ivy&#153;. In this use case, we just basically want to compute a classpath to compile, optionaly one for testing too, and then publish our bundle in a OSGi aware repository.
@ -46,7 +55,6 @@ In few steps, we will setup a build to compile and publish an OSGi bundle.
<li><i>(optional)</i> if Ivy is not in Ant's classpath, get the jar of <a href="../download.html">Apache Ivy</a> and edit the build.xml accordingly (see the comments at the begining of the file)</li>
</ol>
</textarea>
<script type="text/javascript">xooki.postProcess();</script>
</body>

View File

@ -26,13 +26,26 @@
<body>
<textarea id="xooki-source">
<div class="notice">
This documentation is describing the <b>experimental</b> OSGi capability of Ivy. It should work with simple configuration but may not in complex ones. If you have any issue with that feature, you are welcomed to come discussed your use case on the <a href="http://ant.apache.org/ivy/mailing-lists.html">ivy-user</a> mailing list, or discuss about implementation issues or improvement you may have found on <a href="http://ant.apache.org/ivy/mailing-lists.html">ant-dev</a>.
</div>
<table class="notice">
<tr>
<td style="vertical-align: top"><img src="../images/warning.png" style="float:left;" /></td>
<td>
Note that this feature is considered as <b>experimental</b>. It should work with simple configuration but may not in complex ones. If you have any issue with that feature, you are welcomed to come discussed your use case on the <a href="http://ant.apache.org/ivy/mailing-lists.html">ivy-user</a> mailing list, or discuss about implementation issues or improvement you may have found on <a href="http://ant.apache.org/ivy/mailing-lists.html">ant-dev</a>.
</td>
</tr>
</table>
Building an OSGi&#153; bundle with standard tools like <tt>javac</tt> and a classpath computed by Apache Ivy&#153; can be erroneous as these tools doesn't take into account the package visibility enforced by the OSGi metadata. Then switching to OSGi dedicated tools like the Eclipse&#153; JTD can be prefered. This kind of tools still need a "target platform", a set of jars against to compile and then later run. A target platform can be easily managed with Ivy and its OSGi capabilities.
<hr />
<center><b>TODO - WORK IN PROGRESS</b></center>
<hr />
TODO
Building an OSGi&#153; bundle with standard tools like <tt>javac</tt> and a classpath computed by Apache Ivy&#153; can be erroneous as these tools doesn't take into account the package visibility enforced by the OSGi metadata. Then switching to OSGi dedicated tools like the Eclipse&#153; JDT can be prefered. This kind of tools still need a "target platform", a set of jars against to compile and then later run. A target platform can be easily managed with Ivy and its OSGi capabilities.
<ul>Some links of interest:
<li><a href="../resolver/obr.html">OSGi Bundle Repository Resolver</a></li>
<li><a href="../resolver/updatesite.html">Eclipse updatesite Resolver</a></li>
<li><a href="../use/retrieve.html">Ant ivy:retrieve task</a></li>
</ul>
</textarea>
<script type="text/javascript">xooki.postProcess();</script>

View File

@ -18,8 +18,8 @@
under the License.
-->
<ivy-module version="2.2" xmlns:o="http://ant.apache.org/ivy/osgi">
<info organisation="" module="myplugin">
<extends organisation="" module="myplugin" revision="1.0.0.qualifier" location="META-INF/MANIFEST.MF" />
<info organisation="bundle" module="myplugin">
<extends organisation="bundle" module="com.acme.myplugin" revision="1.0.0.qualifier" location="META-INF/MANIFEST.MF" />
</info>
<configurations>
<conf name="compile" extends="default,embedded" description="Dependencies for the compilation" />
@ -32,8 +32,8 @@
<!-- example of a dependency that we can't declare in the MANIFEST.MF because we want it to be embedded -->
<!--dependency osgi="bundle" org="" module="org.apache.commons.httpcore" rev="4.1.0" conf="embedded->default" /-->
<!-- Ivy-Osgi doesn't understand bundle fragment -->
<dependency o:type="bundle" org="" name="org.eclipse.swt.win32.win32.x86" rev="3.+" conf="win32->default" />
<dependency o:type="bundle" org="" name="org.eclipse.swt.cocoa.macosx.x86_64" rev="3.+" conf="macos->default" />
<dependency o:type="bundle" org="" name="org.eclipse.swt.gtk.linux.x86" rev="3.+" conf="linux->default" />
<dependency org="bundle" name="org.eclipse.swt.win32.win32.x86" rev="3.+" conf="win32->default" />
<dependency org="bundle" name="org.eclipse.swt.cocoa.macosx.x86_64" rev="3.+" conf="macos->default" />
<dependency org="bundle" name="org.eclipse.swt.gtk.linux.x86" rev="3.+" conf="linux->default" />
</dependencies>
</ivy-module>

View File

@ -62,11 +62,6 @@ Possible values are:
<li><b>always</b></li> always overwrite the destination file
<li><b>never</b></li> never overwrite the destination file
</ul></td><td>No. Defaults to 'newer'.</td></tr>
<tr><td>dirMode</td><td>option to configure how the [organisation] token in the patterns will be replaced <span class="since">(since 2.3)</span>.
Possible values are:
<ul><li><b>flat</b> (default)</li> don't convert the organisation name, the token will get exactly the same value as the organisation
<li><b>tree</b></li> replace the '.' within the organisation name with '/'
</ul>See the examples below.</td><td>No. Defaults to 'flat'.</td></tr>
<tr><td>symlink</td><td>true to create symbolic links, false to copy the artifacts. The destination of the symbolic links depends on the value of the useOrigin attribute <span class="since">(since 2.0)</span></td><td>No. Defaults to false</td></tr>
<tr><td>settingsRef</td><td>A reference to the ivy settings that must be used by this task <span class="since">(since 2.0)</span></td><td>No, 'ivy.instance' is taken by default.</td></tr></tbody>
<tr><td>log</td><td>the log setting to use during the resolve and retrieve process. <span class="since">(since 2.0)</span><br/>
@ -142,7 +137,7 @@ lib
<hr/>
<code type="xml">
<ivy:retrieve pattern="${lib.dir}/[organisation]/[artifact]-[revision].[ext]" dirMode="flat"/>
<ivy:retrieve pattern="${lib.dir}/[organisation]/[artifact]-[revision].[ext]" />
</code>
Retrieves all dependencies of the last resolve call to a lib directory. The [organisation] token will get the unmodified organisation value. The resulting lib dir could look like this:
<code>
@ -155,9 +150,9 @@ lib
</code>
<code type="xml">
<ivy:retrieve pattern="${lib.dir}/[organisation]/[artifact]-[revision].[ext]" dirMode="tree"/>
<ivy:retrieve pattern="${lib.dir}/[orgPath]/[artifact]-[revision].[ext]" />
</code>
Retrieves all dependencies of the last resolve call to a lib directory. The [organisation] token will get a tree structure. The resulting lib dir could look like this:
Retrieves all dependencies of the last resolve call to a lib directory. The [orgPath] token will get a tree structure. The resulting lib dir could look like this:
<code>
lib
org

View File

@ -30,6 +30,7 @@ import org.apache.ivy.osgi.core.BundleInfo;
import org.apache.ivy.osgi.core.BundleInfoAdapter;
import org.apache.ivy.osgi.core.ExecutionEnvironmentProfileProvider;
import org.apache.ivy.osgi.core.ManifestParser;
import org.apache.ivy.osgi.core.OSGiManifestParser;
import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorWriter;
import org.apache.tools.ant.BuildException;
@ -83,7 +84,8 @@ public class ConvertManifestTask extends IvyTask {
} catch (ParseException e) {
throw new BuildException("Incorrect manifest file '" + manifest + "'", e);
}
ModuleDescriptor md = BundleInfoAdapter.toModuleDescriptor(null, bundleInfo, profileProvider);
ModuleDescriptor md = BundleInfoAdapter.toModuleDescriptor(
OSGiManifestParser.getInstance(), null, bundleInfo, profileProvider);
try {
XmlModuleDescriptorWriter.write(md, ivyFile);

View File

@ -43,10 +43,6 @@ public class IvyRetrieve extends IvyPostResolveTask {
RetrieveOptions.OVERWRITEMODE_NEWER, RetrieveOptions.OVERWRITEMODE_DIFFERENT
});
private static final Collection DIRMODE_VALUES = Arrays.asList(new String[] {
RetrieveOptions.DIRMODE_FLAT, RetrieveOptions.DIRMODE_TREE
});
private String pattern;
private String ivypattern = null;
@ -57,8 +53,6 @@ public class IvyRetrieve extends IvyPostResolveTask {
private String overwriteMode = RetrieveOptions.OVERWRITEMODE_NEWER;
private String dirMode = RetrieveOptions.DIRMODE_FLAT;
private String pathId = null;
private String setId = null;
@ -110,7 +104,6 @@ public class IvyRetrieve extends IvyPostResolveTask {
.setArtifactFilter(artifactFilter)
.setSync(sync)
.setOverwriteMode(getOverwriteMode())
.setDirMode(getDirMode())
.setUseOrigin(isUseOrigin())
.setMakeSymlinks(symlink)
.setResolveId(getResolveId())
@ -187,18 +180,6 @@ public class IvyRetrieve extends IvyPostResolveTask {
return overwriteMode;
}
public void setDirMode(String dirMode) {
if (!DIRMODE_VALUES.contains(dirMode)) {
throw new IllegalArgumentException("invalid dirMode value '" + dirMode + "'. "
+ "Valid values are " + DIRMODE_VALUES);
}
this.dirMode = dirMode;
}
public String getDirMode() {
return dirMode;
}
/**
* Add a mapper to convert the file names.
*

View File

@ -61,6 +61,8 @@ public final class IvyPatternHelper {
public static final String ORGANISATION_KEY2 = "organization";
public static final String ORGANISATION_PATH_KEY = "orgPath";
public static final String ORIGINAL_ARTIFACTNAME_KEY = "originalname";
private static final Pattern PARAM_PATTERN = Pattern.compile("\\@\\{(.*?)\\}");
@ -148,6 +150,7 @@ public final class IvyPatternHelper {
}
tokens.put(ORGANISATION_KEY, org == null ? "" : org);
tokens.put(ORGANISATION_KEY2, org == null ? "" : org);
tokens.put(ORGANISATION_PATH_KEY, org == null ? "" : org.replace('.', '/'));
tokens.put(MODULE_KEY, module == null ? "" : module);
tokens.put(BRANCH_KEY, branch == null ? "" : branch);
tokens.put(REVISION_KEY, revision == null ? "" : revision);
@ -222,6 +225,10 @@ public final class IvyPatternHelper {
if (tokensCopy.containsKey(ORGANISATION_KEY) && !tokensCopy.containsKey(ORGANISATION_KEY2)) {
tokensCopy.put(ORGANISATION_KEY2, tokensCopy.get(ORGANISATION_KEY));
}
if (tokensCopy.containsKey(ORGANISATION_KEY) && !tokensCopy.containsKey(ORGANISATION_PATH_KEY)) {
String org = (String) tokensCopy.get(ORGANISATION_KEY);
tokensCopy.put(ORGANISATION_PATH_KEY, org == null ? "" : org.replace('.', '/'));
}
StringBuffer buffer = new StringBuffer();

View File

@ -313,21 +313,9 @@ public class RetrieveEngine {
continue; // skip this artifact, the filter didn't accept it!
}
String destFileName;
if (RetrieveOptions.DIRMODE_FLAT.equals(options.getDirMode())) {
destFileName = IvyPatternHelper.substitute(destPattern,
String destFileName = IvyPatternHelper.substitute(destPattern,
artifact.getArtifact().getModuleRevisionId(), artifact.getArtifact(),
conf, artifact.getArtifactOrigin());
} else if (RetrieveOptions.DIRMODE_TREE.equals(options.getDirMode())) {
ModuleRevisionId mRevId = artifact.getArtifact().getModuleRevisionId();
String org = mRevId.getOrganisation() == null ? null : mRevId.getOrganisation().replace('.', '/');
destFileName = IvyPatternHelper.substitute(destPattern, org, mRevId.getName(), mRevId.getBranch(),
mRevId.getRevision(), artifact.getName(), artifact.getType(), artifact.getExt(), conf,
artifact.getArtifactOrigin(), mrid.getQualifiedExtraAttributes(), artifact.getArtifact().getQualifiedExtraAttributes());
} else {
throw new IllegalArgumentException("Unsupported dirMode: " + options.getDirMode());
}
Set dest = (Set) artifactsToCopy.get(artifact);
if (dest == null) {
dest = new HashSet();

View File

@ -32,9 +32,6 @@ public class RetrieveOptions extends LogOptions {
public static final String OVERWRITEMODE_NEWER = "newer";
public static final String OVERWRITEMODE_DIFFERENT = "different";
public static final String DIRMODE_FLAT = "flat";
public static final String DIRMODE_TREE = "tree";
/**
* The names of configurations to retrieve. If the array consists only of '*', then all
* configurations of the module will be retrieved.
@ -77,8 +74,6 @@ public class RetrieveOptions extends LogOptions {
*/
private boolean makeSymlinks = false;
private String dirMode = DIRMODE_FLAT;
/**
* The id used to store the resolve information.
*/
@ -99,7 +94,6 @@ public class RetrieveOptions extends LogOptions {
this.overwriteMode = options.overwriteMode;
this.useOrigin = options.useOrigin;
this.makeSymlinks = options.makeSymlinks;
this.dirMode = options.dirMode;
this.resolveId = options.resolveId;
this.mapper = options.mapper;
}
@ -113,15 +107,6 @@ public class RetrieveOptions extends LogOptions {
return this;
}
public String getDirMode() {
return dirMode == null ? DIRMODE_FLAT : dirMode;
}
public RetrieveOptions setDirMode(String dirMode) {
this.dirMode = dirMode;
return this;
}
public Filter getArtifactFilter() {
return artifactFilter;
}

View File

@ -59,7 +59,7 @@ import org.apache.ivy.core.resolve.ResolveEngineSettings;
import org.apache.ivy.core.resolve.ResolveOptions;
import org.apache.ivy.core.retrieve.RetrieveEngineSettings;
import org.apache.ivy.core.sort.SortEngineSettings;
import org.apache.ivy.osgi.core.OsgiRevisionStrategy;
import org.apache.ivy.osgi.core.OsgiLatestStrategy;
import org.apache.ivy.plugins.IvySettingsAware;
import org.apache.ivy.plugins.circular.CircularDependencyStrategy;
import org.apache.ivy.plugins.circular.ErrorCircularDependencyStrategy;
@ -248,12 +248,12 @@ public class IvySettings implements SortEngineSettings, PublishEngineSettings, P
LatestLexicographicStrategy latestLexicographicStrategy = new LatestLexicographicStrategy();
LatestRevisionStrategy latestRevisionStrategy = new LatestRevisionStrategy();
LatestTimeStrategy latestTimeStrategy = new LatestTimeStrategy();
OsgiRevisionStrategy osgiRevisionStrategy = new OsgiRevisionStrategy();
OsgiLatestStrategy osgiLatestStrategy = new OsgiLatestStrategy();
addLatestStrategy("latest-revision", latestRevisionStrategy);
addLatestStrategy("latest-lexico", latestLexicographicStrategy);
addLatestStrategy("latest-time", latestTimeStrategy);
addLatestStrategy("latest-osgi", osgiRevisionStrategy);
addLatestStrategy("latest-osgi", osgiLatestStrategy);
addLockStrategy("no-lock", new NoLockStrategy());
addLockStrategy("artifact-lock", new ArtifactLockStrategy(debugLocking()));

View File

@ -22,12 +22,10 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.ivy.Ivy;
@ -45,6 +43,7 @@ import org.apache.ivy.osgi.util.Version;
import org.apache.ivy.osgi.util.VersionRange;
import org.apache.ivy.plugins.matcher.ExactOrRegexpPatternMatcher;
import org.apache.ivy.plugins.matcher.PatternMatcher;
import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
public class BundleInfoAdapter {
@ -66,16 +65,7 @@ public class BundleInfoAdapter {
public static final String CONF_USE_PREFIX = "use_";
public static final String EXTRA_ATTRIBUTE_NAME = "o:type";
public static final Map/* <String, String> */OSGI_BUNDLE = Collections.singletonMap(
EXTRA_ATTRIBUTE_NAME, BundleInfo.BUNDLE_TYPE);
public static final Map/* <String, String> */OSGI_PACKAGE = Collections.singletonMap(
EXTRA_ATTRIBUTE_NAME, BundleInfo.PACKAGE_TYPE);
public static final Map/* <String, String> */OSGI_SERVICE = Collections.singletonMap(
EXTRA_ATTRIBUTE_NAME, BundleInfo.SERVICE_TYPE);
public static final String EXTRA_INFO_EXPORT_PREFIX = "_osgi_export_";
/**
*
@ -83,14 +73,15 @@ public class BundleInfoAdapter {
* uri to help build the absolute url if the bundle info has a relative uri.
* @param bundle
* @param profileProvider
* @param parser
* @return
* @throws ProfileNotFoundException
*/
public static DefaultModuleDescriptor toModuleDescriptor(URI baseUri, BundleInfo bundle,
public static DefaultModuleDescriptor toModuleDescriptor(ModuleDescriptorParser parser, URI baseUri, BundleInfo bundle,
ExecutionEnvironmentProfileProvider profileProvider) throws ProfileNotFoundException {
DefaultModuleDescriptor md = new DefaultModuleDescriptor(null, null);
DefaultModuleDescriptor md = new DefaultModuleDescriptor(parser, null);
md.addExtraAttributeNamespace("o", Ivy.getIvyHomeURL() + "osgi");
ModuleRevisionId mrid = asMrid(bundle.getSymbolicName(), bundle.getVersion(), OSGI_BUNDLE);
ModuleRevisionId mrid = asMrid(BundleInfo.BUNDLE_TYPE, bundle.getSymbolicName(), bundle.getVersion());
md.setResolvedPublicationDate(new Date());
md.setModuleRevisionId(mrid);
@ -102,6 +93,8 @@ public class BundleInfoAdapter {
Iterator itExport = bundle.getExports().iterator();
while (itExport.hasNext()) {
ExportPackage exportPackage = (ExportPackage) itExport.next();
md.getExtraInfo().put(EXTRA_INFO_EXPORT_PREFIX + exportPackage.getName(),
exportPackage.getVersion().toString());
exportedPkgNames.add(exportPackage.getName());
String[] confDependencies = new String[exportPackage.getUses().size() + 1];
int i = 0;
@ -151,11 +144,11 @@ public class BundleInfoAdapter {
Iterator itPkg = profile.getPkgNames().iterator();
while (itPkg.hasNext()) {
String pkg = (String) itPkg.next();
ArtifactId id = new ArtifactId(ModuleId.newInstance("", pkg),
ArtifactId id = new ArtifactId(ModuleId.newInstance(BundleInfo.BUNDLE_TYPE, pkg),
PatternMatcher.ANY_EXPRESSION, PatternMatcher.ANY_EXPRESSION,
PatternMatcher.ANY_EXPRESSION);
DefaultExcludeRule rule = new DefaultExcludeRule(id,
ExactOrRegexpPatternMatcher.INSTANCE, OSGI_PACKAGE);
ExactOrRegexpPatternMatcher.INSTANCE, null);
String[] confs = md.getConfigurationsNames();
for (int i = 0; i < confs.length; i++) {
rule.addConfiguration(confs[i]);
@ -288,8 +281,7 @@ public class BundleInfoAdapter {
continue;
}
Map/* <String, String> */osgiAtt = Collections.singletonMap(EXTRA_ATTRIBUTE_NAME, type);
ModuleRevisionId ddmrid = asMrid(name, requirement.getVersion(), osgiAtt);
ModuleRevisionId ddmrid = asMrid(type, name, requirement.getVersion());
DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(ddmrid, false);
String conf = CONF_NAME_DEFAULT;
@ -314,23 +306,18 @@ public class BundleInfoAdapter {
}
private static ModuleRevisionId asMrid(String symbolicNAme, Version v,
Map/* <String, String> */extraAttr) {
return ModuleRevisionId.newInstance("", symbolicNAme, v == null ? null : v.toString(),
extraAttr);
public static ModuleRevisionId asMrid(String type, String name, Version v) {
return ModuleRevisionId.newInstance(type, name, v == null ? null : v.toString());
}
private static ModuleRevisionId asMrid(String symbolicNAme, VersionRange v, Map/*
* <String,
* String>
*/extraAttr) {
public static ModuleRevisionId asMrid(String type, String name, VersionRange v) {
String revision;
if (v == null) {
revision = "[0,)";
} else {
revision = v.toIvyRevision();
}
return ModuleRevisionId.newInstance("", symbolicNAme, revision, extraAttr);
return ModuleRevisionId.newInstance(type, name, revision);
}
public static class ProfileNotFoundException extends RuntimeException {

View File

@ -226,7 +226,7 @@ public class ManifestParser {
return new VersionRange(v);
}
private static Version versionOf(String v) throws NumberFormatException {
private static Version versionOf(String v) throws ParseException {
if (v == null) {
return null;
}

View File

@ -68,7 +68,7 @@ public class OSGiManifestParser implements ModuleDescriptorParser {
} catch (URISyntaxException e) {
throw new RuntimeException("Unsupported repository, resources names are not uris", e);
}
return BundleInfoAdapter.toModuleDescriptor(null, bundleInfo, profileProvider);
return BundleInfoAdapter.toModuleDescriptor(this, null, bundleInfo, profileProvider);
}
public void toIvyFile(InputStream is, Resource res, File destFile, ModuleDescriptor md)

View File

@ -0,0 +1,95 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.ivy.osgi.core;
import java.text.ParseException;
import java.util.Comparator;
import org.apache.ivy.core.IvyContext;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.osgi.util.Version;
import org.apache.ivy.plugins.latest.ArtifactInfo;
import org.apache.ivy.plugins.latest.ComparatorLatestStrategy;
import org.apache.ivy.plugins.version.VersionMatcher;
public class OsgiLatestStrategy extends ComparatorLatestStrategy {
final class MridComparator implements Comparator/* <ModuleRevisionId> */{
public int compare(Object o1, Object o2) {
return compare((ModuleRevisionId) o1, (ModuleRevisionId) o2);
}
public int compare(ModuleRevisionId o1, ModuleRevisionId o2) {
Version v1;
Version v2;
try {
v1 = new Version(o1.getRevision());
v2 = new Version(o2.getRevision());
} catch (ParseException e) {
throw new RuntimeException("Uncomparable versions:" + o1.getRevision() + " and "
+ o2.getRevision() + " (" + e.getMessage() + ")");
}
return v1.compareTo(v2);
}
}
final class ArtifactInfoComparator implements Comparator/* <ArtifactInfo> */{
public int compare(Object o1, Object o2) {
return compare((ArtifactInfo) o1, (ArtifactInfo) o2);
}
public int compare(ArtifactInfo o1, ArtifactInfo o2) {
String rev1 = o1.getRevision();
String rev2 = o2.getRevision();
/*
* The revisions can still be not resolved, so we use the current version matcher to
* know if one revision is dynamic, and in this case if it should be considered greater
* or lower than the other one. Note that if the version matcher compare method returns
* 0, it's because it's not possible to know which revision is greater. In this case we
* consider the dynamic one to be greater, because most of the time it will then be
* actually resolved and a real comparison will occur.
*/
VersionMatcher vmatcher = IvyContext.getContext().getSettings().getVersionMatcher();
ModuleRevisionId mrid1 = ModuleRevisionId.newInstance("", "", rev1);
ModuleRevisionId mrid2 = ModuleRevisionId.newInstance("", "", rev2);
if (vmatcher.isDynamic(mrid1)) {
int c = vmatcher.compare(mrid1, mrid2, mridComparator);
return c >= 0 ? 1 : -1;
} else if (vmatcher.isDynamic(mrid2)) {
int c = vmatcher.compare(mrid2, mrid1, mridComparator);
return c >= 0 ? -1 : 1;
}
return mridComparator.compare(mrid1, mrid2);
}
}
private final Comparator/* <ModuleRevisionId> */mridComparator = new MridComparator();
private final Comparator/* <ArtifactInfo> */artifactInfoComparator = new ArtifactInfoComparator();
public OsgiLatestStrategy() {
setComparator(artifactInfoComparator);
setName("latest-osgi");
}
}

View File

@ -1,235 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.ivy.osgi.core;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.ivy.core.IvyContext;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.plugins.latest.ArtifactInfo;
import org.apache.ivy.plugins.latest.ComparatorLatestStrategy;
import org.apache.ivy.plugins.version.VersionMatcher;
public class OsgiRevisionStrategy extends ComparatorLatestStrategy {
private static final Pattern ALPHA_NUM_REGEX = Pattern.compile("([a-zA-Z])(\\d)");
private static final Pattern NUM_ALPHA_REGEX = Pattern.compile("(\\d)([a-zA-Z])");
private static final Pattern LABEL_REGEX = Pattern.compile("[_\\-\\+]");
/**
* Compares two ModuleRevisionId by their revision. Revisions are compared using an algorithm
* inspired by PHP version_compare one.
*/
final class MridComparator implements Comparator/* <ModuleRevisionId> */{
public int compare(Object o1, Object o2) {
return compare((ModuleRevisionId) o1, (ModuleRevisionId) o2);
}
public int compare(ModuleRevisionId o1, ModuleRevisionId o2) {
String rev1 = o1.getRevision();
String rev2 = o2.getRevision();
String[] outerParts1 = rev1.split("[\\.]");
String[] outerParts2 = rev2.split("[\\.]");
for (int i = 0; i < outerParts1.length && i < outerParts2.length; i++) {
String outerPart1 = outerParts1[i];
String outerPart2 = outerParts2[i];
if (outerPart1.equals(outerPart2)) {
continue;
}
outerPart1 = ALPHA_NUM_REGEX.matcher(outerPart1).replaceAll("$1_$2");
outerPart1 = NUM_ALPHA_REGEX.matcher(outerPart1).replaceAll("$1_$2");
outerPart2 = ALPHA_NUM_REGEX.matcher(outerPart2).replaceAll("$1_$2");
outerPart2 = NUM_ALPHA_REGEX.matcher(outerPart2).replaceAll("$1_$2");
String[] innerParts1 = LABEL_REGEX.split(outerPart1);
String[] innerParts2 = LABEL_REGEX.split(outerPart2);
for (int j = 0; j < innerParts1.length && j < innerParts2.length; j++) {
if (innerParts1[j].equals(innerParts2[j])) {
continue;
}
boolean is1Number = isNumber(innerParts1[j]);
boolean is2Number = isNumber(innerParts2[j]);
if (is1Number && !is2Number) {
return 1;
}
if (is2Number && !is1Number) {
return -1;
}
if (is1Number && is2Number) {
return Long.valueOf(innerParts1[j]).compareTo(Long.valueOf(innerParts2[j]));
}
// both are strings, we compare them taking into account special meaning
Map/* <String, Integer> */meanings = getSpecialMeanings();
Integer sm1 = (Integer) meanings.get(innerParts1[j].toLowerCase(Locale.US));
Integer sm2 = (Integer) meanings.get(innerParts2[j].toLowerCase(Locale.US));
if (sm1 != null) {
sm2 = sm2 == null ? new Integer(0) : sm2;
return sm1.compareTo(sm2);
}
if (sm2 != null) {
return new Integer(0).compareTo(sm2);
}
return innerParts1[j].compareTo(innerParts2[j]);
}
if (i < innerParts1.length) {
return isNumber(innerParts1[i]) ? 1 : -1;
}
if (i < innerParts2.length) {
return isNumber(innerParts2[i]) ? -1 : 1;
}
}
if (outerParts1.length > outerParts2.length) {
return 1;
} else if (outerParts1.length < outerParts2.length) {
return -1;
}
return 0;
}
private boolean isNumber(String str) {
return str.matches("\\d+");
}
}
/**
* Compares two ArtifactInfo by their revision. Revisions are compared using an algorithm
* inspired by PHP version_compare one, unless a dynamic revision is given, in which case the
* version matcher is used to perform the comparison.
*/
final class ArtifactInfoComparator implements Comparator/* <ArtifactInfo> */{
public int compare(Object o1, Object o2) {
return compare((ArtifactInfo) o1, (ArtifactInfo) o2);
}
public int compare(ArtifactInfo o1, ArtifactInfo o2) {
String rev1 = o1.getRevision();
String rev2 = o2.getRevision();
/*
* The revisions can still be not resolved, so we use the current version matcher to
* know if one revision is dynamic, and in this case if it should be considered greater
* or lower than the other one. Note that if the version matcher compare method returns
* 0, it's because it's not possible to know which revision is greater. In this case we
* consider the dynamic one to be greater, because most of the time it will then be
* actually resolved and a real comparison will occur.
*/
VersionMatcher vmatcher = IvyContext.getContext().getSettings().getVersionMatcher();
ModuleRevisionId mrid1 = ModuleRevisionId.newInstance("", "", rev1);
ModuleRevisionId mrid2 = ModuleRevisionId.newInstance("", "", rev2);
if (vmatcher.isDynamic(mrid1)) {
int c = vmatcher.compare(mrid1, mrid2, mridComparator);
return c >= 0 ? 1 : -1;
} else if (vmatcher.isDynamic(mrid2)) {
int c = vmatcher.compare(mrid2, mrid1, mridComparator);
return c >= 0 ? -1 : 1;
}
return mridComparator.compare(mrid1, mrid2);
}
}
public static class SpecialMeaning {
private String name;
private Integer value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
public void validate() {
if (name == null) {
throw new IllegalStateException("a special meaning should have a name");
}
if (value == null) {
throw new IllegalStateException("a special meaning should have a value");
}
}
}
private static final Map/* <String, Integer> */DEFAULT_SPECIAL_MEANINGS;
static {
DEFAULT_SPECIAL_MEANINGS = new HashMap/* <String, Integer> */();
DEFAULT_SPECIAL_MEANINGS.put("dev", new Integer(-1));
DEFAULT_SPECIAL_MEANINGS.put("rc", new Integer(1));
DEFAULT_SPECIAL_MEANINGS.put("final", new Integer(2));
}
private final Comparator/* <ModuleRevisionId> */mridComparator = new MridComparator();
private final Comparator/* <ArtifactInfo> */artifactInfoComparator = new ArtifactInfoComparator();
private Map/* <String, Integer> */specialMeanings = null;
private boolean usedefaultspecialmeanings = true;
public OsgiRevisionStrategy() {
setComparator(artifactInfoComparator);
setName("latest-revision");
}
public void addConfiguredSpecialMeaning(SpecialMeaning meaning) {
meaning.validate();
getSpecialMeanings().put(meaning.getName().toLowerCase(Locale.US), meaning.getValue());
}
public synchronized Map/* <String, Integer> */getSpecialMeanings() {
if (specialMeanings == null) {
specialMeanings = new HashMap/* <String, Integer> */();
if (isUsedefaultspecialmeanings()) {
specialMeanings.putAll(DEFAULT_SPECIAL_MEANINGS);
}
}
return specialMeanings;
}
public boolean isUsedefaultspecialmeanings() {
return usedefaultspecialmeanings;
}
public void setUsedefaultspecialmeanings(boolean usedefaultspecialmeanings) {
this.usedefaultspecialmeanings = usedefaultspecialmeanings;
}
}

View File

@ -31,12 +31,12 @@ import org.apache.ivy.core.cache.CacheResourceOptions;
import org.apache.ivy.core.event.EventManager;
import org.apache.ivy.core.report.ArtifactDownloadReport;
import org.apache.ivy.osgi.obr.xml.OBRXMLParser;
import org.apache.ivy.osgi.repo.RepoDescriptorBasedResolver;
import org.apache.ivy.osgi.repo.AbstractOSGiResolver;
import org.apache.ivy.plugins.repository.Resource;
import org.apache.ivy.plugins.repository.url.URLResource;
import org.xml.sax.SAXException;
public class OBRResolver extends RepoDescriptorBasedResolver {
public class OBRResolver extends AbstractOSGiResolver {
private String repoXmlURL;

View File

@ -179,7 +179,7 @@ public class OBRXMLParser {
Version version;
try {
version = new Version(v);
} catch (NumberFormatException e) {
} catch (ParseException e) {
log(Message.MSG_ERR, "Incorrect resource version: " + v + ". The resource "
+ symbolicname + " is then ignored.");
skip();

View File

@ -93,7 +93,7 @@ public class RequirementAdapter {
}
private void parseCompareFilter(CompareFilter compareFilter, boolean not)
throws UnsupportedFilterException {
throws UnsupportedFilterException, ParseException {
String att = compareFilter.getLeftValue();
if (BundleInfo.PACKAGE_TYPE.equals(att) || BundleInfo.BUNDLE_TYPE.equals(att)
|| "symbolicname".equals(att) || BundleInfo.SERVICE_TYPE.equals(att)) {
@ -116,6 +116,12 @@ public class RequirementAdapter {
name = compareFilter.getRightValue();
} else if ("version".equals(att)) {
String v = compareFilter.getRightValue();
Version version;
try {
version = new Version(v);
} catch (ParseException e) {
throw new ParseException("Ill formed version: " + v, 0);
}
Operator operator = compareFilter.getOperator();
if (not) {
if (operator == Operator.EQUALS) {
@ -136,37 +142,37 @@ public class RequirementAdapter {
throw new UnsupportedFilterException(
"Multiple version matching is not supported");
}
startVersion = new Version(v);
startVersion = version;
startExclusive = false;
endVersion = new Version(v);
endVersion = version;
endExclusive = false;
} else if (operator == Operator.GREATER_OR_EQUAL) {
if (startVersion != null) {
throw new UnsupportedFilterException(
"Multiple version matching is not supported");
}
startVersion = new Version(v);
startVersion = version;
startExclusive = false;
} else if (operator == Operator.GREATER_THAN) {
if (startVersion != null) {
throw new UnsupportedFilterException(
"Multiple version matching is not supported");
}
startVersion = new Version(v);
startVersion = version;
startExclusive = true;
} else if (operator == Operator.LOWER_OR_EQUAL) {
if (endVersion != null) {
throw new UnsupportedFilterException(
"Multiple version matching is not supported");
}
endVersion = new Version(v);
endVersion = version;
endExclusive = false;
} else if (operator == Operator.LOWER_THAN) {
if (endVersion != null) {
throw new UnsupportedFilterException(
"Multiple version matching is not supported");
}
endVersion = new Version(v);
endVersion = version;
endExclusive = true;
}
} else {

View File

@ -195,9 +195,15 @@ public class P2ArtifactParser implements XMLInputParser {
});
}
protected void handleAttributes(Attributes atts) {
protected void handleAttributes(Attributes atts) throws SAXException {
String id = atts.getValue(ID);
Version version = new Version(atts.getValue(VERSION));
Version version;
try {
version = new Version(atts.getValue(VERSION));
} catch (ParseException e) {
throw new SAXException("Incorrect version attribute on artifact '" + id + "': "
+ atts.getValue(VERSION) + " (" + e.getMessage() + ")");
}
String classifier = atts.getValue(CLASSIFIER);
p2Artifact = new P2Artifact(id, version, classifier);

View File

@ -286,11 +286,16 @@ public class P2MetadataParser implements XMLInputParser {
}
protected void handleAttributes(Attributes atts) {
protected void handleAttributes(Attributes atts) throws SAXException {
String id = atts.getValue(ID);
Version version = new Version(atts.getValue(VERSION));
String version = atts.getValue(VERSION);
// Boolean singleton = Boolean.valueOf(atts.getValue(SINGLETON));
bundleInfo = new BundleInfo(id, version);
try {
bundleInfo = new BundleInfo(id, new Version(version));
} catch (ParseException e) {
throw new SAXException("Incorrect version on bundle '" + id + "': " + version
+ " (" + e.getMessage() + ")");
}
}
}
@ -394,10 +399,15 @@ public class P2MetadataParser implements XMLInputParser {
super(PROVIDED);
}
protected void handleAttributes(Attributes atts) {
protected void handleAttributes(Attributes atts) throws SAXException {
namespace = atts.getValue(NAMESPACE);
name = atts.getValue(NAME);
version = new Version(atts.getValue(VERSION));
try {
version = new Version(atts.getValue(VERSION));
} catch (ParseException e) {
throw new SAXException("Incorrect version on provided capability: " + version
+ " (" + e.getMessage() + ")");
}
}
}
@ -536,11 +546,16 @@ public class P2MetadataParser implements XMLInputParser {
super(ARTIFACT);
}
protected void handleAttributes(Attributes atts) {
protected void handleAttributes(Attributes atts) throws SAXException {
String id = atts.getValue(ID);
Version version = new Version(atts.getValue(VERSION));
String version = atts.getValue(VERSION);
String classifier = atts.getValue(CLASSIFIER);
artifact = new P2Artifact(id, version, classifier);
try {
artifact = new P2Artifact(id, new Version(version), classifier);
} catch (ParseException e) {
throw new SAXException("Incorrect version on artifact '" + id + "': " + version
+ " (" + e.getMessage() + ")");
}
}
}

View File

@ -20,6 +20,7 @@ package org.apache.ivy.osgi.repo;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -35,11 +36,15 @@ import java.util.Set;
import org.apache.ivy.core.IvyPatternHelper;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.Configuration;
import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.core.report.DownloadStatus;
import org.apache.ivy.core.report.MetadataArtifactDownloadReport;
import org.apache.ivy.core.resolve.IvyNode;
import org.apache.ivy.core.resolve.ResolveData;
import org.apache.ivy.core.resolve.ResolvedModuleRevision;
import org.apache.ivy.osgi.core.BundleInfo;
@ -54,7 +59,9 @@ import org.apache.ivy.plugins.resolver.util.ResolvedResource;
import org.apache.ivy.plugins.resolver.util.ResourceMDParser;
import org.apache.ivy.util.Message;
public abstract class RepoDescriptorBasedResolver extends BasicResolver {
public abstract class AbstractOSGiResolver extends BasicResolver {
private static final String CAPABILITY_EXTRA_ATTR = "osgi_bundle";
private RepoDescriptor repoDescriptor = null;
@ -109,39 +116,30 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
return repoDescriptor;
}
public boolean isCheckconsistency() {
// since a module can fit a requirement with a different id, no not check anything
public boolean isAllownomd() {
// this a repo based resolver, we always have md
return false;
}
public ResolvedResource findIvyFileRef(DependencyDescriptor dd, ResolveData data) {
ModuleRevisionId mrid = dd.getDependencyRevisionId();
String osgiAtt = mrid.getExtraAttribute(BundleInfoAdapter.EXTRA_ATTRIBUTE_NAME);
String osgiType = mrid.getOrganisation();
if (osgiType == null) {
throw new RuntimeException("Unsupported OSGi module Id: " + mrid.getModuleId());
}
String id = mrid.getName();
Set/* <ModuleDescriptor> */mds = getRepoDescriptor().findModule(osgiAtt, id);
Set/* <ModuleDescriptor> */mds = getRepoDescriptor().findModule(osgiType, id);
if (mds == null || mds.isEmpty()) {
Message.verbose("\t " + id + " not found.");
return null;
}
ResolvedResource[] ret = new ResolvedResource[mds.size()];
int i = 0;
Iterator itMd = mds.iterator();
while (itMd.hasNext()) {
ModuleDescriptor md = (ModuleDescriptor) itMd.next();
MetadataArtifactDownloadReport report = new MetadataArtifactDownloadReport(null);
report.setDownloadStatus(DownloadStatus.NO);
report.setSearched(true);
ResolvedModuleRevision rmr = new ResolvedModuleRevision(this, this, md, report);
MDResolvedResource mdrr = new MDResolvedResource(null, md.getRevision(), rmr);
if (!BundleInfo.BUNDLE_TYPE.equals(osgiAtt)) {
if (data.getVisitData(md.getModuleRevisionId()) != null) {
// already resolved import, no need to go further
return mdrr;
}
}
ret[i++] = mdrr;
ResolvedResource[] ret;
if (BundleInfo.BUNDLE_TYPE.equals(osgiType)) {
ret = findBundle(dd, data, mds);
} else {
ret = findCapability(dd, data, mds);
}
ResolvedResource found = findResource(ret, getDefaultRMDParser(dd.getDependencyId()), mrid,
@ -152,20 +150,97 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
return found;
}
public ResolvedResource[] findBundle(DependencyDescriptor dd, ResolveData data, Set/*
* <
* ModuleDescriptor
* >
*/mds) {
ResolvedResource[] ret = new ResolvedResource[mds.size()];
int i = 0;
Iterator itMd = mds.iterator();
while (itMd.hasNext()) {
ModuleDescriptor md = (ModuleDescriptor) itMd.next();
MetadataArtifactDownloadReport report = new MetadataArtifactDownloadReport(null);
report.setDownloadStatus(DownloadStatus.NO);
report.setSearched(true);
ResolvedModuleRevision rmr = new ResolvedModuleRevision(this, this, md, report);
MDResolvedResource mdrr = new MDResolvedResource(null, md.getRevision(), rmr);
ret[i++] = mdrr;
}
return ret;
}
public ResolvedResource[] findCapability(DependencyDescriptor dd, ResolveData data, Set/*
* <
* ModuleDescriptor
* >
*/mds) {
ResolvedResource[] ret = new ResolvedResource[mds.size()];
int i = 0;
Iterator itMd = mds.iterator();
while (itMd.hasNext()) {
ModuleDescriptor md = (ModuleDescriptor) itMd.next();
IvyNode node = data.getNode(md.getModuleRevisionId());
if (node != null) {
// already resolved import, no need to go further
return new ResolvedResource[] {buildResolvedCapabilityMd(dd, node.getDescriptor())};
}
ret[i++] = buildResolvedCapabilityMd(dd, md);
}
return ret;
}
private MDResolvedResource buildResolvedCapabilityMd(DependencyDescriptor dd,
ModuleDescriptor md) {
String org = dd.getDependencyRevisionId().getOrganisation();
String name = dd.getDependencyRevisionId().getName();
String rev = (String) md.getExtraInfo().get(
BundleInfoAdapter.EXTRA_INFO_EXPORT_PREFIX + name);
ModuleRevisionId capabilityRev = ModuleRevisionId.newInstance(org, name, rev,
Collections.singletonMap(CAPABILITY_EXTRA_ATTR, md.getModuleRevisionId().toString()));
DefaultModuleDescriptor capabilityMd = new DefaultModuleDescriptor(capabilityRev,
"release", new Date());
String useConf = BundleInfoAdapter.CONF_USE_PREFIX + dd.getDependencyRevisionId().getName();
capabilityMd.addConfiguration(BundleInfoAdapter.CONF_DEFAULT);
capabilityMd.addConfiguration(BundleInfoAdapter.CONF_OPTIONAL);
capabilityMd.addConfiguration(BundleInfoAdapter.CONF_TRANSITIVE_OPTIONAL);
capabilityMd.addConfiguration(new Configuration(useConf));
DefaultDependencyDescriptor capabilityDD = new DefaultDependencyDescriptor(
md.getModuleRevisionId(), false);
capabilityDD.addDependencyConfiguration(BundleInfoAdapter.CONF_NAME_DEFAULT,
BundleInfoAdapter.CONF_NAME_DEFAULT);
capabilityDD.addDependencyConfiguration(BundleInfoAdapter.CONF_NAME_OPTIONAL,
BundleInfoAdapter.CONF_NAME_OPTIONAL);
capabilityDD.addDependencyConfiguration(BundleInfoAdapter.CONF_NAME_TRANSITIVE_OPTIONAL,
BundleInfoAdapter.CONF_NAME_TRANSITIVE_OPTIONAL);
capabilityDD.addDependencyConfiguration(useConf, useConf);
capabilityMd.addDependency(capabilityDD);
MetadataArtifactDownloadReport report = new MetadataArtifactDownloadReport(null);
report.setDownloadStatus(DownloadStatus.NO);
report.setSearched(true);
ResolvedModuleRevision rmr = new ResolvedModuleRevision(this, this, capabilityMd, report);
return new MDResolvedResource(null, capabilityMd.getRevision(), rmr);
}
public ResolvedResource findResource(ResolvedResource[] rress, ResourceMDParser rmdparser,
ModuleRevisionId mrid, Date date) {
ResolvedResource found = super.findResource(rress, rmdparser, mrid, date);
String osgiAtt = mrid.getExtraAttribute(BundleInfoAdapter.EXTRA_ATTRIBUTE_NAME);
String osgiType = mrid.getOrganisation();
// for non bundle requirement : log the selected bundle
if (!BundleInfo.BUNDLE_TYPE.equals(osgiAtt)) {
if (!BundleInfo.BUNDLE_TYPE.equals(osgiType)) {
// several candidates with different symbolic name : make an warning about the ambiguity
if (rress.length != 1) {
// several candidates with different symbolic name ?
Map/* <String, List<MDResolvedResource>> */matching = new HashMap();
for (int i = 0; i < rress.length; i++) {
String name = ((MDResolvedResource) rress[i]).getResolvedModuleRevision()
.getId().getName();
.getDescriptor().getExtraAttribute(CAPABILITY_EXTRA_ATTR);
List/* <MDResolvedResource> */list = (List) matching.get(name);
if (list == null) {
list = new ArrayList/* <MDResolvedResource> */();
@ -175,7 +250,7 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
}
if (matching.keySet().size() != 1) {
if (requirementStrategy == RequirementStrategy.first) {
Message.warn("Ambiguity for the '" + osgiAtt + "' requirement "
Message.warn("Ambiguity for the '" + osgiType + "' requirement "
+ mrid.getName() + ";version=" + mrid.getRevision());
Iterator itMatching = matching.entrySet().iterator();
while (itMatching.hasNext()) {
@ -190,7 +265,7 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
}
}
} else if (requirementStrategy == RequirementStrategy.noambiguity) {
Message.error("Ambiguity for the '" + osgiAtt + "' requirement "
Message.error("Ambiguity for the '" + osgiType + "' requirement "
+ mrid.getName() + ";version=" + mrid.getRevision());
Iterator itMatching = matching.entrySet().iterator();
while (itMatching.hasNext()) {
@ -208,7 +283,7 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
}
}
}
Message.info("'" + osgiAtt + "' requirement " + mrid.getName() + ";version="
Message.info("'" + osgiType + "' requirement " + mrid.getName() + ";version="
+ mrid.getRevision() + " satisfied by "
+ ((MDResolvedResource) found).getResolvedModuleRevision().getId().getName()
+ ";" + found.getRevision());
@ -227,9 +302,10 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
protected void checkModuleDescriptorRevision(ModuleDescriptor systemMd,
ModuleRevisionId systemMrid) {
String osgiAtt = systemMrid.getExtraAttribute(BundleInfoAdapter.EXTRA_ATTRIBUTE_NAME);
// only check revision if we're searching for a bundle (package and bundle have different version
if (osgiAtt == null || osgiAtt.equals(BundleInfo.BUNDLE_TYPE)) {
String osgiType = systemMrid.getOrganisation();
// only check revision if we're searching for a bundle (package and bundle have different
// version
if (osgiType == null || osgiType.equals(BundleInfo.BUNDLE_TYPE)) {
super.checkModuleDescriptorRevision(systemMd, systemMrid);
}
}
@ -240,35 +316,28 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
}
protected Collection findNames(Map tokenValues, String token) {
if (BundleInfoAdapter.EXTRA_ATTRIBUTE_NAME.equals(token)) {
return Arrays.asList(new String[] {BundleInfo.BUNDLE_TYPE, BundleInfo.PACKAGE_TYPE,
BundleInfo.SERVICE_TYPE});
}
if (IvyPatternHelper.ORGANISATION_KEY.equals(token)) {
return Collections.singletonList("");
return getRepoDescriptor().getModuleByCapbilities().keySet();
}
String org = (String) tokenValues.get(IvyPatternHelper.ORGANISATION_KEY);
if (org != null && org.length() != 0) {
String osgiType = (String) tokenValues.get(IvyPatternHelper.ORGANISATION_KEY);
if (osgiType == null || osgiType.length() == 0) {
return Collections.EMPTY_LIST;
}
String osgiAtt = (String) tokenValues.get(BundleInfoAdapter.EXTRA_ATTRIBUTE_NAME);
String rev = (String) tokenValues.get(IvyPatternHelper.REVISION_KEY);
if (IvyPatternHelper.MODULE_KEY.equals(token)) {
Map/* <String, Map<String, Set<ModuleDescriptor>>> */moduleByCapbilities = getRepoDescriptor()
.getModuleByCapbilities();
if (osgiAtt != null) {
if (osgiType != null) {
Map/* <String, Set<ModuleDescriptor>> */moduleByCapabilityValue = (Map) moduleByCapbilities
.get(osgiAtt);
.get(osgiType);
if (moduleByCapabilityValue == null) {
return Collections.EMPTY_LIST;
}
Set/* <String> */capabilityValues = new HashSet();
filterCapabilityValues(capabilityValues, moduleByCapbilities, tokenValues, rev);
return capabilityValues;
return moduleByCapabilityValue.keySet();
} else {
Set/* <String> */capabilityValues = new HashSet();
Iterator/* <Map<String, Set<ModuleDescriptor>>> */it = ((Collection) moduleByCapbilities
@ -286,7 +355,7 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
if (IvyPatternHelper.REVISION_KEY.equals(token)) {
String name = (String) tokenValues.get(IvyPatternHelper.MODULE_KEY);
List/* <String> */versions = new ArrayList/* <String> */();
Set/* <ModuleDescriptor> */mds = getRepoDescriptor().findModule(osgiAtt, name);
Set/* <ModuleDescriptor> */mds = getRepoDescriptor().findModule(osgiType, name);
if (mds != null) {
Iterator itMd = mds.iterator();
while (itMd.hasNext()) {
@ -302,11 +371,11 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
if (name == null) {
return Collections.EMPTY_LIST;
}
if (osgiAtt.equals(BundleInfo.PACKAGE_TYPE)) {
if (osgiType.equals(BundleInfo.PACKAGE_TYPE)) {
return Collections.singletonList(BundleInfoAdapter.CONF_USE_PREFIX + name);
}
Set/* <BundleCapabilityAndLocation> */bundleCapabilities = getRepoDescriptor()
.findModule(osgiAtt, name);
.findModule(osgiType, name);
if (bundleCapabilities == null) {
return Collections.EMPTY_LIST;
}
@ -317,7 +386,7 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
Version v;
try {
v = new Version(version);
} catch (NumberFormatException e) {
} catch (ParseException e) {
return Collections.EMPTY_LIST;
}
BundleCapabilityAndLocation found = null;
@ -385,35 +454,32 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
Map/* <String, String> */values = new HashMap/* <String, String> */();
tokenSet.remove(BundleInfoAdapter.EXTRA_ATTRIBUTE_NAME);
String osgiAtt = (String) criteria.get(BundleInfoAdapter.EXTRA_ATTRIBUTE_NAME);
if (osgiAtt == null) {
tokenSet.remove(IvyPatternHelper.ORGANISATION_KEY);
String osgiType = (String) criteria.get(IvyPatternHelper.ORGANISATION_KEY);
if (osgiType == null || osgiType.length() == 0) {
return Collections.EMPTY_SET;
}
values.put(IvyPatternHelper.ORGANISATION_KEY, osgiType);
if (osgiType == null) {
Set/* <Map<String, String>> */tokenValues = new HashSet/* <Map<String, String>> */();
Map/* <String, String> */newCriteria = new HashMap/* <String, String> */(criteria);
newCriteria.put(BundleInfoAdapter.EXTRA_ATTRIBUTE_NAME, BundleInfo.BUNDLE_TYPE);
newCriteria.put(IvyPatternHelper.ORGANISATION_KEY, BundleInfo.BUNDLE_TYPE);
tokenValues.addAll(listTokenValues(tokenSet, newCriteria));
newCriteria = new HashMap/* <String, String> */(criteria);
newCriteria.put(BundleInfoAdapter.EXTRA_ATTRIBUTE_NAME, BundleInfo.PACKAGE_TYPE);
newCriteria.put(IvyPatternHelper.ORGANISATION_KEY, BundleInfo.PACKAGE_TYPE);
tokenValues.addAll(listTokenValues(tokenSet, newCriteria));
newCriteria = new HashMap/* <String, String> */(criteria);
newCriteria.put(BundleInfoAdapter.EXTRA_ATTRIBUTE_NAME, BundleInfo.SERVICE_TYPE);
newCriteria.put(IvyPatternHelper.ORGANISATION_KEY, BundleInfo.SERVICE_TYPE);
tokenValues.addAll(listTokenValues(tokenSet, newCriteria));
return tokenValues;
}
values.put(BundleInfoAdapter.EXTRA_ATTRIBUTE_NAME, osgiAtt);
Set/* <String> */capabilities = getRepoDescriptor().getCapabilityValues(osgiAtt);
Set/* <String> */capabilities = getRepoDescriptor().getCapabilityValues(osgiType);
if (capabilities == null || capabilities.isEmpty()) {
return Collections.EMPTY_SET;
}
tokenSet.remove(IvyPatternHelper.ORGANISATION_KEY);
String org = (String) criteria.get(IvyPatternHelper.ORGANISATION_KEY);
if (org != null && org.length() != 0) {
return Collections.EMPTY_SET;
}
values.put(IvyPatternHelper.ORGANISATION_KEY, "");
tokenSet.remove(IvyPatternHelper.MODULE_KEY);
String module = (String) criteria.get(IvyPatternHelper.MODULE_KEY);
if (module == null) {
@ -433,7 +499,7 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
String rev = (String) criteria.get(IvyPatternHelper.REVISION_KEY);
if (rev == null) {
Set/* <BundleCapabilityAndLocation> */bundleCapabilities = getRepoDescriptor()
.findModule(osgiAtt, module);
.findModule(osgiType, module);
if (bundleCapabilities == null) {
return Collections.EMPTY_SET;
}
@ -453,19 +519,19 @@ public abstract class RepoDescriptorBasedResolver extends BasicResolver {
tokenSet.remove(IvyPatternHelper.CONF_KEY);
String conf = (String) criteria.get(IvyPatternHelper.CONF_KEY);
if (conf == null) {
if (osgiAtt.equals(BundleInfo.PACKAGE_TYPE)) {
if (osgiType.equals(BundleInfo.PACKAGE_TYPE)) {
values.put(IvyPatternHelper.CONF_KEY, BundleInfoAdapter.CONF_USE_PREFIX + module);
return Collections./* <Map<String, String>> */singleton(values);
}
Set/* <BundleCapabilityAndLocation> */bundleCapabilities = getRepoDescriptor()
.findModule(osgiAtt, module);
.findModule(osgiType, module);
if (bundleCapabilities == null) {
return Collections.EMPTY_SET;
}
Version v;
try {
v = new Version(rev);
} catch (NumberFormatException e) {
} catch (ParseException e) {
return Collections.EMPTY_SET;
}
BundleCapabilityAndLocation found = null;

View File

@ -30,6 +30,7 @@ import org.apache.ivy.osgi.core.BundleCapability;
import org.apache.ivy.osgi.core.BundleInfo;
import org.apache.ivy.osgi.core.BundleInfoAdapter;
import org.apache.ivy.osgi.core.ExecutionEnvironmentProfileProvider;
import org.apache.ivy.osgi.core.OSGiManifestParser;
import org.apache.ivy.util.Message;
public class RepoDescriptor {
@ -96,8 +97,8 @@ public class RepoDescriptor {
}
public void addBundle(BundleInfo bundleInfo) {
DefaultModuleDescriptor md = BundleInfoAdapter.toModuleDescriptor(baseUri, bundleInfo,
profileProvider);
DefaultModuleDescriptor md = BundleInfoAdapter.toModuleDescriptor(
OSGiManifestParser.getInstance(), baseUri, bundleInfo, profileProvider);
add(BundleInfo.BUNDLE_TYPE, bundleInfo.getSymbolicName(), md);
Iterator itCapability = bundleInfo.getCapabilities().iterator();
while (itCapability.hasNext()) {

View File

@ -23,10 +23,10 @@ import java.net.URISyntaxException;
import java.text.ParseException;
import org.apache.ivy.core.cache.CacheResourceOptions;
import org.apache.ivy.osgi.repo.RepoDescriptorBasedResolver;
import org.apache.ivy.osgi.repo.AbstractOSGiResolver;
import org.xml.sax.SAXException;
public class UpdateSiteResolver extends RepoDescriptorBasedResolver {
public class UpdateSiteResolver extends AbstractOSGiResolver {
private String url;

View File

@ -177,7 +177,14 @@ public class EclipseUpdateSiteParser {
}
protected void handleAttributes(Attributes atts) throws SAXException {
feature = new EclipseFeature(atts.getValue(ID), new Version(atts.getValue(VERSION)));
String id = atts.getValue(ID);
String version = atts.getValue(VERSION);
try {
feature = new EclipseFeature(id, new Version(version));
} catch (ParseException e) {
throw new SAXException("Incorrect version on the feature '" + id + "': " + version
+ " (" + e.getMessage() + ")");
}
String url = atts.getValue(URL);
if (url != null) {

View File

@ -116,7 +116,14 @@ public class FeatureParser {
}
protected void handleAttributes(Attributes atts) throws SAXException {
feature = new EclipseFeature(atts.getValue(ID), new Version(atts.getValue(VERSION)));
String id = atts.getValue(ID);
String version = atts.getValue(VERSION);
try {
feature = new EclipseFeature(id, new Version(version));
} catch (ParseException e) {
throw new SAXException("Incorrect version on feature '" + id + "': " + version
+ " (" + e.getMessage() + ")");
}
feature.setOS(atts.getValue(OS));
feature.setWS(atts.getValue(WS));
@ -157,8 +164,16 @@ public class FeatureParser {
protected void handleAttributes(Attributes atts) throws SAXException {
plugin = new EclipsePlugin();
plugin.setId(atts.getValue(ID));
plugin.setVersion(new Version(atts.getValue(VERSION)));
String id = atts.getValue(ID);
String version = atts.getValue(VERSION);
plugin.setId(id);
try {
plugin.setVersion(new Version(version));
} catch (ParseException e) {
throw new SAXException("Incorrect version on feature's plugin '" + id + "': "
+ version + " (" + e.getMessage() + ")");
}
plugin.setUnpack(Boolean.valueOf(atts.getValue(UNPACK)).booleanValue());
plugin.setFragment(atts.getValue(FRAGMENT));
plugin.setFilter(atts.getValue(FILTER));
@ -253,9 +268,16 @@ public class FeatureParser {
protected void handleAttributes(Attributes atts) throws SAXException {
require = new Require();
String version = atts.getValue(VERSION);
require.setFeature(atts.getValue(FEATURE));
require.setPlugin(atts.getValue(PLUGIN));
require.setVersion(new Version(atts.getValue(VERSION)));
try {
require.setVersion(new Version(version));
} catch (ParseException e) {
throw new SAXException("Incorrect version on feature's import: " + version + " ("
+ e.getMessage() + ")");
}
require.setMatch(atts.getValue(MATCH));
require.setFilter(atts.getValue(FILTER));
}

View File

@ -1,92 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.ivy.osgi.util;
import java.util.Comparator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ArtifactTokens {
public static final Comparator/* <ArtifactTokens> */ORDER_BY_VERSION_ASC = new OrderByVersion(
true);
public static final Comparator/* <ArtifactTokens> */ORDER_BY_VERSION_DESC = new OrderByVersion(
false);
protected static final Pattern ARTIFACT_TOKEN_REGEX = Pattern
.compile("(.*/)?([\\w\\.]+)[\\-_](\\d*\\.\\d*\\.\\d*)[\\.]?([\\w\\-]+)?");
public final String prefix;
public final String module;
public final Version version;
public final boolean isJar;
public ArtifactTokens(String artifactStr) {
isJar = artifactStr.endsWith(".jar");
artifactStr = (isJar ? artifactStr.substring(0, artifactStr.length() - 4) : artifactStr);
final Matcher matcher = ARTIFACT_TOKEN_REGEX.matcher(artifactStr);
if (matcher.matches()) {
prefix = matcher.group(1);
module = matcher.group(2);
version = new Version(matcher.group(3), matcher.group(4));
} else {
prefix = null;
module = null;
version = null;
}
}
public String toString() {
return (prefix != null ? prefix : "") + module + "-" + version + (isJar ? ".jar" : "");
}
public String toDetailString() {
return "prefix=" + prefix + ", module=" + module + ", version=" + version + ", isJar="
+ isJar;
}
public boolean isValid() {
return (prefix != null) && (module != null) && (version != null);
}
private static class OrderByVersion implements Comparator/* <ArtifactTokens> */{
private final boolean ascending;
public OrderByVersion(boolean ascending) {
this.ascending = ascending;
}
public int compare(Object o1, Object o2) {
return compare((ArtifactTokens) o1, (ArtifactTokens) o2);
}
public int compare(ArtifactTokens a, ArtifactTokens b) {
if (!a.module.equalsIgnoreCase(b.module)) {
throw new IllegalArgumentException("Cannot order different modules by version. A="
+ a + ", B=" + b);
}
final int val = a.version.compareTo(b.version);
return (ascending ? val : -val);
}
}
}

View File

@ -17,6 +17,8 @@
*/
package org.apache.ivy.osgi.util;
import java.text.ParseException;
/**
* Provides OSGi version support.
*/
@ -30,16 +32,31 @@ public class Version implements Comparable/* <Version> */{
private final String qualifier;
public Version(String versionStr, String qualifier) throws NumberFormatException {
public Version(String versionStr, String qualifier) throws ParseException {
this(versionStr + "." + (qualifier != null ? qualifier : ""));
}
public Version(String versionStr) throws NumberFormatException {
final String[] tmp = versionStr.split("[\\.]");
major = Integer.parseInt(tmp[0]);
minor = tmp.length >= 2 ? Integer.parseInt(tmp[1]) : 0;
patch = tmp.length >= 3 ? Integer.parseInt(tmp[2]) : 0;
qualifier = tmp.length == 4 ? tmp[3] : null;
public Version(String versionStr) throws ParseException {
String[] splits = versionStr.split("\\.");
if (splits == null || splits.length == 0 || splits.length > 4) {
throw new ParseException("Ill formed OSGi version", 0);
}
try {
major = Integer.parseInt(splits[0]);
} catch (NumberFormatException e) {
throw new ParseException("Major part of an OSGi version should be an integer", 0);
}
try {
minor = splits.length >= 2 ? Integer.parseInt(splits[1]) : 0;
} catch (NumberFormatException e) {
throw new ParseException("Minor part of an OSGi version should be an integer", 0);
}
try {
patch = splits.length >= 3 ? Integer.parseInt(splits[2]) : 0;
} catch (NumberFormatException e) {
throw new ParseException("Patch part of an OSGi version should be an integer", 0);
}
qualifier = splits.length == 4 ? splits[3] : null;
}
public Version(int major, int minor, int patch, String qualifier) {
@ -49,6 +66,20 @@ public class Version implements Comparable/* <Version> */{
this.qualifier = qualifier;
}
/**
* Build a version from another one while appending an extra qualifier
*
* @param baseVersion
* @param qualifier
*/
public Version(Version baseVersion, String extraQualifier) {
this.major = baseVersion.major;
this.minor = baseVersion.minor;
this.patch = baseVersion.patch;
this.qualifier = baseVersion.qualifier == null ? extraQualifier
: (baseVersion.qualifier + extraQualifier);
}
public String toString() {
return numbersAsString() + (qualifier == null ? "" : "." + qualifier);
}

View File

@ -306,7 +306,7 @@ public class VersionRange {
return startVersion.equals(endVersion);
}
public boolean contains(String versionStr) {
public boolean contains(String versionStr) throws ParseException {
return contains(new Version(versionStr));
}

View File

@ -27,69 +27,50 @@ import junit.framework.TestCase;
import org.apache.ivy.plugins.latest.ArtifactInfo;
public class OsgiRevisionStrategyTest extends TestCase {
public class OsgiLatestStrategyTest extends TestCase {
public void testComparator() {
ArtifactInfo[] revs = toMockAI(new String[] {"0.2a", "0.2_b", "0.2rc1", "0.2-final",
"1.0-dev1", "1.0-dev2", "1.0-alpha1", "1.0-alpha2", "1.0-beta1", "1.0-beta2",
"1.0-gamma", "1.0-rc1", "1.0-rc2", "1.0", "1.0.1", "2.0", "2.0.0", "2.0.0.b006",
"2.0.0.b012", "2.0.0.xyz"});
ArtifactInfo[] revs = toMockAI(new String[] {"0.2.0.a", "0.2.0.b", "0.2.0.final", "1.0",
"1.0.0.gamma", "1.0.0.rc1", "1.0.0.rc2", "1.0.1", "2", "2.0.0.b006", "2.0.0.b012",
"2.0.0.xyz"});
List shuffled = new ArrayList(Arrays.asList(revs));
Collections.shuffle(shuffled);
Collections.sort(shuffled, new OsgiRevisionStrategy().new ArtifactInfoComparator());
Collections.sort(shuffled, new OsgiLatestStrategy().new ArtifactInfoComparator());
assertEquals(Arrays.asList(revs), shuffled);
}
public void testSort() {
ArtifactInfo[] revs = toMockAI(new String[] {"0.2a", "0.2_b", "0.2rc1", "0.2-final",
"1.0-dev1", "1.0-dev2", "1.0-alpha1", "1.0-alpha2", "1.0-beta1", "1.0-beta2",
"1.0-gamma", "1.0-rc1", "1.0-rc2", "1.0", "1.0.1", "2.0"});
ArtifactInfo[] revs = toMockAI(new String[] {"0.2.0.a", "0.2.0.b", "0.2.0.final", "1.0",
"1.0.0.gamma", "1.0.0.rc1", "1.0.0.rc2", "1.0.1", "2", "2.0.0.b006", "2.0.0.b012",
"2.0.0.xyz"});
List shuffled = new ArrayList(Arrays.asList(revs));
ArtifactInfo[] shuffledRevs = (ArtifactInfo[]) shuffled
.toArray(new ArtifactInfo[revs.length]);
OsgiRevisionStrategy latestRevisionStrategy = new OsgiRevisionStrategy();
OsgiLatestStrategy latestRevisionStrategy = new OsgiLatestStrategy();
List sorted = latestRevisionStrategy.sort(shuffledRevs);
assertEquals(Arrays.asList(revs), sorted);
}
public void testFindLatest() {
ArtifactInfo[] revs = toMockAI(new String[] {"0.2a", "0.2_b", "0.2rc1", "0.2-final",
"1.0-dev1", "1.0-dev2", "1.0-alpha1", "1.0-alpha2", "1.0-beta1", "1.0-beta2",
"1.0-gamma", "1.0-rc1", "1.0-rc2", "1.0", "1.0.1", "2.0"});
ArtifactInfo[] revs = toMockAI(new String[] {"0.2.0.a", "0.2.0.b", "0.2.0.rc1",
"0.2.0.final", "1.0.0.dev1", "1.0.0.dev2", "1.0.0.alpha1", "1.0.0.alpha2",
"1.0.0.beta1", "1.0.0.beta2", "1.0.0.gamma", "1.0.0.rc1", "1.0.0.rc2", "1.0",
"1.0.1", "2.0"});
List shuffled = new ArrayList(Arrays.asList(revs));
Collections.shuffle(shuffled);
ArtifactInfo[] shuffledRevs = (ArtifactInfo[]) shuffled
.toArray(new ArtifactInfo[revs.length]);
OsgiRevisionStrategy latestRevisionStrategy = new OsgiRevisionStrategy();
OsgiLatestStrategy latestRevisionStrategy = new OsgiLatestStrategy();
ArtifactInfo latest = latestRevisionStrategy.findLatest(shuffledRevs, new Date());
assertNotNull(latest);
assertEquals("2.0", latest.getRevision());
}
public void testSpecialMeaningComparator() {
ArtifactInfo[] revs = toMockAI(new String[] {"0.1", "0.2-pre", "0.2-dev", "0.2-rc1",
"0.2-final", "0.2-QA", "1.0-dev1"});
List shuffled = new ArrayList(Arrays.asList(revs));
Collections.shuffle(shuffled);
OsgiRevisionStrategy latestRevisionStrategy = new OsgiRevisionStrategy();
OsgiRevisionStrategy.SpecialMeaning specialMeaning = new OsgiRevisionStrategy.SpecialMeaning();
specialMeaning.setName("pre");
specialMeaning.setValue(new Integer(-2));
latestRevisionStrategy.addConfiguredSpecialMeaning(specialMeaning);
specialMeaning = new OsgiRevisionStrategy.SpecialMeaning();
specialMeaning.setName("QA");
specialMeaning.setValue(new Integer(4));
latestRevisionStrategy.addConfiguredSpecialMeaning(specialMeaning);
Collections.sort(shuffled, latestRevisionStrategy.new ArtifactInfoComparator());
assertEquals(Arrays.asList(revs), shuffled);
}
private static class MockArtifactInfo implements ArtifactInfo {
private long _lastModified;

View File

@ -48,34 +48,35 @@ import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.osgi.core.BundleInfo;
import org.apache.ivy.osgi.core.BundleInfoAdapter;
import org.apache.ivy.osgi.core.ManifestParser;
import org.apache.ivy.osgi.repo.RepoDescriptorBasedResolver.RequirementStrategy;
import org.apache.ivy.osgi.core.OSGiManifestParser;
import org.apache.ivy.osgi.repo.AbstractOSGiResolver.RequirementStrategy;
import org.apache.ivy.plugins.resolver.DependencyResolver;
import org.apache.ivy.plugins.resolver.DualResolver;
import org.apache.ivy.plugins.resolver.FileSystemResolver;
public class OBRResolverTest extends TestCase {
private static final ModuleRevisionId MRID_TEST_BUNDLE = ModuleRevisionId.newInstance("",
"org.apache.ivy.osgi.testbundle", "1.2.3", BundleInfoAdapter.OSGI_BUNDLE);
private static final ModuleRevisionId MRID_TEST_BUNDLE = ModuleRevisionId.newInstance(
BundleInfo.BUNDLE_TYPE, "org.apache.ivy.osgi.testbundle", "1.2.3");
private static final ModuleRevisionId MRID_TEST_BUNDLE_IMPORTING = ModuleRevisionId
.newInstance("", "org.apache.ivy.osgi.testbundle.importing", "3.2.1",
BundleInfoAdapter.OSGI_BUNDLE);
.newInstance(BundleInfo.BUNDLE_TYPE, "org.apache.ivy.osgi.testbundle.importing",
"3.2.1");
private static final ModuleRevisionId MRID_TEST_BUNDLE_IMPORTING_VERSION = ModuleRevisionId
.newInstance("", "org.apache.ivy.osgi.testbundle.importing.version", "3.2.1",
BundleInfoAdapter.OSGI_BUNDLE);
.newInstance(BundleInfo.BUNDLE_TYPE,
"org.apache.ivy.osgi.testbundle.importing.version", "3.2.1");
private static final ModuleRevisionId MRID_TEST_BUNDLE_IMPORTING_OPTIONAL = ModuleRevisionId
.newInstance("", "org.apache.ivy.osgi.testbundle.importing.optional", "3.2.1",
BundleInfoAdapter.OSGI_BUNDLE);
.newInstance(BundleInfo.BUNDLE_TYPE,
"org.apache.ivy.osgi.testbundle.importing.optional", "3.2.1");
private static final ModuleRevisionId MRID_TEST_BUNDLE_USE = ModuleRevisionId.newInstance("",
"org.apache.ivy.osgi.testbundle.use", "2.2.2", BundleInfoAdapter.OSGI_BUNDLE);
private static final ModuleRevisionId MRID_TEST_BUNDLE_USE = ModuleRevisionId.newInstance(
BundleInfo.BUNDLE_TYPE, "org.apache.ivy.osgi.testbundle.use", "2.2.2");
private static final ModuleRevisionId MRID_TEST_BUNDLE_EXPORTING_AMBIGUITY = ModuleRevisionId
.newInstance("", "org.apache.ivy.osgi.testbundle.exporting.ambiguity", "3.3.3",
BundleInfoAdapter.OSGI_BUNDLE);
.newInstance(BundleInfo.BUNDLE_TYPE,
"org.apache.ivy.osgi.testbundle.exporting.ambiguity", "3.3.3");
private IvySettings settings;
@ -146,20 +147,20 @@ public class OBRResolverTest extends TestCase {
}
public void testSimpleResolve() throws Exception {
ModuleRevisionId mrid = ModuleRevisionId.newInstance("", "org.apache.ivy.osgi.testbundle",
"1.2.3", BundleInfoAdapter.OSGI_BUNDLE);
ModuleRevisionId mrid = ModuleRevisionId.newInstance(BundleInfo.BUNDLE_TYPE, "org.apache.ivy.osgi.testbundle",
"1.2.3");
genericTestResolveDownload(bundleResolver, mrid);
}
public void testSimpleUrlResolve() throws Exception {
ModuleRevisionId mrid = ModuleRevisionId.newInstance("", "org.apache.ivy.osgi.testbundle",
"1.2.3", BundleInfoAdapter.OSGI_BUNDLE);
ModuleRevisionId mrid = ModuleRevisionId.newInstance(BundleInfo.BUNDLE_TYPE, "org.apache.ivy.osgi.testbundle",
"1.2.3");
genericTestResolveDownload(bundleUrlResolver, mrid);
}
public void testResolveDual() throws Exception {
ModuleRevisionId mrid = ModuleRevisionId.newInstance("", "org.apache.ivy.osgi.testbundle",
"1.2.3", BundleInfoAdapter.OSGI_BUNDLE);
ModuleRevisionId mrid = ModuleRevisionId.newInstance(BundleInfo.BUNDLE_TYPE, "org.apache.ivy.osgi.testbundle",
"1.2.3");
genericTestResolveDownload(dualResolver, mrid);
}
@ -282,7 +283,8 @@ public class OBRResolverTest extends TestCase {
+ jarName));
BundleInfo bundleInfo = ManifestParser.parseManifest(in.getManifest());
bundleInfo.setUri(new File("test/test-repo/bundlerepo/" + jarName).toURI());
DefaultModuleDescriptor md = BundleInfoAdapter.toModuleDescriptor(null, bundleInfo, null);
DefaultModuleDescriptor md = BundleInfoAdapter.toModuleDescriptor(
OSGiManifestParser.getInstance(), null, bundleInfo, null);
ResolveReport resolveReport = ivy.resolve(md,
new ResolveOptions().setConfs(new String[] {conf}).setOutputReport(false));
assertFalse("resolve failed " + resolveReport.getAllProblemMessages(),
@ -313,7 +315,8 @@ public class OBRResolverTest extends TestCase {
+ jarName));
BundleInfo bundleInfo = ManifestParser.parseManifest(in.getManifest());
bundleInfo.setUri(new File("test/test-repo/bundlerepo/" + jarName).toURI());
DefaultModuleDescriptor md = BundleInfoAdapter.toModuleDescriptor(null, bundleInfo, null);
DefaultModuleDescriptor md = BundleInfoAdapter.toModuleDescriptor(
OSGiManifestParser.getInstance(), null, bundleInfo, null);
ResolveReport resolveReport = ivy.resolve(md,
new ResolveOptions().setConfs(new String[] {conf}).setOutputReport(false));
assertTrue(resolveReport.hasError());

View File

@ -37,7 +37,7 @@ import org.apache.ivy.core.resolve.ResolvedModuleRevision;
import org.apache.ivy.core.search.ModuleEntry;
import org.apache.ivy.core.search.OrganisationEntry;
import org.apache.ivy.core.settings.IvySettings;
import org.apache.ivy.osgi.core.BundleInfoAdapter;
import org.apache.ivy.osgi.core.BundleInfo;
import org.apache.ivy.plugins.resolver.DependencyResolver;
public class UpdateSiteResolverTest extends TestCase {
@ -82,13 +82,18 @@ public class UpdateSiteResolverTest extends TestCase {
public void testListOrganization() throws Exception {
OrganisationEntry[] orgs = resolver.listOrganisations();
assertEquals(1, orgs.length);
assertEquals("", orgs[0].getOrganisation());
assertEquals(2, orgs.length);
assertTrue((orgs[0].getOrganisation().equals(BundleInfo.BUNDLE_TYPE) && orgs[1]
.getOrganisation().equals(BundleInfo.PACKAGE_TYPE))
|| (orgs[0].getOrganisation().equals(BundleInfo.PACKAGE_TYPE) && orgs[1]
.getOrganisation().equals(BundleInfo.BUNDLE_TYPE)));
}
public void testListModules() throws Exception {
ModuleEntry[] modules = resolver.listModules(new OrganisationEntry(resolver, ""));
assertEquals(65, modules.length);
ModuleEntry[] modules = resolver.listModules(new OrganisationEntry(resolver, BundleInfo.BUNDLE_TYPE));
assertEquals(3, modules.length);
modules = resolver.listModules(new OrganisationEntry(resolver, BundleInfo.PACKAGE_TYPE));
assertEquals(64, modules.length);
}
private void genericTestResolveDownload(DependencyResolver resolver, ModuleRevisionId mrid)
@ -124,8 +129,8 @@ public class UpdateSiteResolverTest extends TestCase {
}
public void testResolve() throws Exception {
ModuleRevisionId mrid = ModuleRevisionId.newInstance("", "org.apache.ivy",
"2.0.0.final_20090108225011", BundleInfoAdapter.OSGI_BUNDLE);
ModuleRevisionId mrid = ModuleRevisionId.newInstance(BundleInfo.BUNDLE_TYPE,
"org.apache.ivy", "2.0.0.final_20090108225011");
genericTestResolveDownload(resolver, mrid);
}
}

View File

@ -1,74 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.ivy.osgi.util;
import junit.framework.TestCase;
public class ArtifactTokensTest extends TestCase {
public void testGoodMatching() {
final String repoResource = "test/test-ivy/osgi/eclipse/plugins/org.eclipse.datatools.connectivity.ui_1.0.1.v200808121010";
final ArtifactTokens tokens = new ArtifactTokens(repoResource);
assertEquals("test/test-ivy/osgi/eclipse/plugins/", tokens.prefix);
assertEquals("org.eclipse.datatools.connectivity.ui", tokens.module);
assertEquals("1.0.1", tokens.version.numbersAsString());
assertEquals("v200808121010", tokens.version.qualifier());
assertFalse(tokens.isJar);
}
public void testGoodMatching2() {
final String repoResource = "test/test-ivy/osgi/eclipse/plugins/org.eclipse.datatools.connectivity.ui_1.0.1";
final ArtifactTokens tokens = new ArtifactTokens(repoResource);
assertEquals("test/test-ivy/osgi/eclipse/plugins/", tokens.prefix);
assertEquals("org.eclipse.datatools.connectivity.ui", tokens.module);
assertEquals("1.0.1", tokens.version.numbersAsString());
assertEquals("", tokens.version.qualifier());
assertFalse(tokens.isJar);
}
public void testGoodMatching3() {
final String repoResource = "test/test-ivy/osgi/eclipse/plugins/org.myorg.module.one_3.21.100.v20070530";
final ArtifactTokens tokens = new ArtifactTokens(repoResource);
assertEquals("test/test-ivy/osgi/eclipse/plugins/", tokens.prefix);
assertEquals("org.myorg.module.one", tokens.module);
assertEquals("3.21.100", tokens.version.numbersAsString());
assertEquals("v20070530", tokens.version.qualifier());
assertFalse(tokens.isJar);
}
public void testGoodMatching4() {
final String repoResource = "test/test-ivy/osgi/eclipse/plugins/org.eclipse.mylyn.tasks.ui_3.0.1.v20080721-2100-e33.jar";
// String repoResource =
// "test/test-ivy/osgi/eclipse/plugins/org.eclipse.mylyn.tasks.ui_3.0.1.v20080721.jar";
final ArtifactTokens tokens = new ArtifactTokens(repoResource);
assertEquals("test/test-ivy/osgi/eclipse/plugins/", tokens.prefix);
assertEquals("org.eclipse.mylyn.tasks.ui", tokens.module);
assertEquals("3.0.1", tokens.version.numbersAsString());
assertEquals("v20080721-2100-e33", tokens.version.qualifier());
assertTrue(tokens.isJar);
}
public void testBadMatching() {
final String repoResource = "test/test-ivy/osgi/eclipse/plugins/fake";
final ArtifactTokens tokens = new ArtifactTokens(repoResource);
assertNull(tokens.prefix);
assertNull(tokens.module);
assertNull(tokens.version);
}
}

View File

@ -17,11 +17,13 @@
*/
package org.apache.ivy.osgi.util;
import java.text.ParseException;
import junit.framework.TestCase;
public class VersionTest extends TestCase {
public void testParsing() {
public void testParsing() throws Exception {
Version v;
v = new Version("1");
@ -41,7 +43,7 @@ public class VersionTest extends TestCase {
assertEquals("abc", v.qualifier());
}
public void testCompareTo() {
public void testCompareTo() throws Exception {
assertTrue(new Version("1.2.3").compareTo(new Version("1.2.3")) == 0);
assertTrue(new Version("1.2.3").compareTo(new Version("1.2.2")) > 0);