bug 347889

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@3372 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Hugues Malphettes 2011-06-01 09:01:20 +00:00
parent c084756951
commit 71ce6291d2
3 changed files with 62 additions and 40 deletions

View File

@ -2,6 +2,7 @@ jetty-7.4.3-SNAPSHOT
+ 347617 Dynamically install/update/remove OSGi bundles discovered in the contexts folder
+ 347717 start.jar destroys dependent child of --exec
+ JETTY-1342 Recreate selector in change task
+ 347889 OSGi should follow directive visibility:=reexport for META-INF/web-fragments and resources
jetty-7.4.2.v20110526
+ 334443 Improve the ability to specify extra class paths using the Jetty Maven Plugin

View File

@ -13,9 +13,9 @@
package org.eclipse.jetty.osgi.boot.utils.internal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.StringTokenizer;
import org.osgi.framework.Bundle;
@ -31,7 +31,6 @@ import org.osgi.service.startlevel.StartLevel;
/**
* When the PackageAdmin service is activated we can look for the fragments
* attached to this bundle and "activate" them.
*
*/
public class PackageAdminServiceTracker implements ServiceListener
{
@ -124,8 +123,9 @@ public class PackageAdminServiceTracker implements ServiceListener
}
/**
* Returns the fragments and the required-bundles that have a jetty-web annotation attribute
* compatible with the webFragOrAnnotationOrResources.
* Returns the fragments and the required-bundles of a bundle.
* Recursively collect the required-bundles and fragment when the directive visibility:=reexport
* is added to a required-bundle.
* @param bundle
* @param webFragOrAnnotationOrResources
* @return
@ -138,60 +138,50 @@ public class PackageAdminServiceTracker implements ServiceListener
return null;
}
PackageAdmin admin = (PackageAdmin)_context.getService(sr);
LinkedHashMap<String,Bundle> deps = new LinkedHashMap<String,Bundle>();
collectFragmentsAndRequiredBundles(bundle, admin, deps, false);
return deps.values().toArray(new Bundle[deps.size()]);
}
/**
* Returns the fragments and the required-bundles. Collects them transitively when the directive 'visibility:=reexport'
* is added to a required-bundle.
* @param bundle
* @param webFragOrAnnotationOrResources
* @return
*/
protected void collectFragmentsAndRequiredBundles(Bundle bundle, PackageAdmin admin, Map<String,Bundle> deps, boolean onlyReexport)
{
Bundle[] fragments = admin.getFragments(bundle);
//get the required bundles. we can't use the org.osgi.framework.wiring package
//just yet: it is not supported by enough osgi implementations.
List<Bundle> requiredBundles = getRequiredBundles(bundle, admin);
if (fragments != null)
{
Set<String> already = new HashSet<String>();
for (Bundle b : requiredBundles)
{
already.add(b.getSymbolicName());
}
//Also add the bundles required by the fragments.
//this way we can inject onto an existing web-bundle a set of bundles that extend it
for (Bundle f : fragments)
{
List<Bundle> requiredBundlesByFragment = getRequiredBundles(f, admin);
for (Bundle b : requiredBundlesByFragment)
if (!deps.keySet().contains(f.getSymbolicName()))
{
if (already.add(b.getSymbolicName()))
{
requiredBundles.add(b);
}
deps.put(f.getSymbolicName(), f);
collectRequiredBundles(f, admin, deps, onlyReexport);
}
}
}
ArrayList<Bundle> bundles = new ArrayList<Bundle>(
(fragments != null ? fragments.length : 0) +
(requiredBundles != null ? requiredBundles.size() : 0));
if (fragments != null)
{
for (Bundle f : fragments)
{
bundles.add(f);
}
}
if (requiredBundles != null)
{
bundles.addAll(requiredBundles);
}
return bundles.toArray(new Bundle[bundles.size()]);
collectRequiredBundles(bundle, admin, deps, onlyReexport);
}
/**
* A simplistic but good enough parser for the Require-Bundle header.
* Parses the version range attribute and the visibility directive.
*
* @param onlyReexport true to collect resources and web-fragments transitively if and only if the directive visibility is reexport.
* @param bundle
* @return The map of required bundles associated to the value of the jetty-web attribute.
*/
protected List<Bundle> getRequiredBundles(Bundle bundle, PackageAdmin admin)
protected void collectRequiredBundles(Bundle bundle, PackageAdmin admin, Map<String,Bundle> deps, boolean onlyReexport)
{
List<Bundle> res = new ArrayList<Bundle>();
String requiredBundleHeader = (String)bundle.getHeaders().get("Require-Bundle");
if (requiredBundleHeader == null)
{
return res;
return;
}
StringTokenizer tokenizer = new StringTokenizer(requiredBundleHeader, ",");
while (tokenizer.hasMoreTokens())
@ -199,7 +189,13 @@ public class PackageAdminServiceTracker implements ServiceListener
String tok = tokenizer.nextToken().trim();
StringTokenizer tokenizer2 = new StringTokenizer(tok, ";");
String symbolicName = tokenizer2.nextToken().trim();
if (deps.keySet().contains(symbolicName))
{
//was already added. 2 dependencies pointing at the same bundle.
continue;
}
String versionRange = null;
boolean reexport = false;
while (tokenizer2.hasMoreTokens())
{
String next = tokenizer2.nextToken().trim();
@ -214,21 +210,37 @@ public class PackageAdminServiceTracker implements ServiceListener
versionRange = next.substring("bundle-version=".length());
}
}
else if (next.equals("visibility:=reexport"))
{
reexport = true;
}
}
if (!reexport && onlyReexport)
{
return;
}
Bundle[] reqBundles = admin.getBundles(symbolicName, versionRange);
if (reqBundles != null)
if (reqBundles != null && reqBundles.length != 0)
{
Bundle reqBundle = null;
for (Bundle b : reqBundles)
{
if (b.getState() == Bundle.ACTIVE || b.getState() == Bundle.STARTING)
{
res.add(b);
reqBundle = b;
break;
}
}
if (reqBundle == null)
{
//strange? in OSGi with Require-Bundle,
//the dependent bundle is supposed to be active already
reqBundle = reqBundles[0];
}
deps.put(reqBundle.getSymbolicName(),reqBundle);
collectFragmentsAndRequiredBundles(reqBundle, admin, deps, true);
}
}
return res;
}

View File

@ -10,20 +10,27 @@
<name>Jetty :: OSGi :: Example Equinox Tools</name>
<description>Jetty OSGi Example Equinox Tools</description>
<properties>
<forceContextQualifier>v20110513</forceContextQualifier>
<jetty-version>7.4.1.v20110513</jetty-version>
<osgi-version>3.6.0.v20100517</osgi-version>
<osgi-services-version>3.2.100.v20100503</osgi-services-version>
<bundle-symbolic-name>${project.groupId}.equinoxtools</bundle-symbolic-name>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-continuation</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
@ -32,10 +39,12 @@
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
<version>${osgi-version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
<version>${osgi-services-version}</version>
</dependency>
</dependencies>