You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jo...@apache.org on 2012/04/01 09:04:03 UTC
svn commit: r1308023 - in
/geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries:
ApplicationGBean.java BundleGraph.java
Author: johnxiao
Date: Sun Apr 1 07:04:03 2012
New Revision: 1308023
URL: http://svn.apache.org/viewvc?rev=1308023&view=rev
Log:
GERONIMO-6305 Start bundles in EBA according to bundle dependencies
Added:
geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/BundleGraph.java (with props)
Modified:
geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/ApplicationGBean.java
Modified: geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/ApplicationGBean.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/ApplicationGBean.java?rev=1308023&r1=1308022&r2=1308023&view=diff
==============================================================================
--- geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/ApplicationGBean.java (original)
+++ geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/ApplicationGBean.java Sun Apr 1 07:04:03 2012
@@ -20,8 +20,11 @@ import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.apache.aries.application.ApplicationMetadataFactory;
@@ -29,12 +32,13 @@ import org.apache.aries.application.Depl
import org.apache.aries.application.DeploymentMetadata;
import org.apache.aries.application.DeploymentMetadataFactory;
import org.apache.aries.application.management.AriesApplication;
+import org.apache.aries.application.management.AriesApplicationContext.ApplicationState;
import org.apache.aries.application.management.AriesApplicationContextManager;
import org.apache.aries.application.management.AriesApplicationResolver;
import org.apache.aries.application.management.BundleInfo;
import org.apache.aries.application.management.ManagementException;
import org.apache.aries.application.management.ResolverException;
-import org.apache.aries.application.management.AriesApplicationContext.ApplicationState;
+import org.apache.geronimo.aries.BundleGraph.BundleNode;
import org.apache.geronimo.gbean.GBeanLifecycle;
import org.apache.geronimo.gbean.annotation.GBean;
import org.apache.geronimo.gbean.annotation.ParamAttribute;
@@ -51,6 +55,7 @@ import org.osgi.framework.BundleExceptio
import org.osgi.framework.ServiceException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
+import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -70,6 +75,7 @@ public class ApplicationGBean implements
private GeronimoApplication application;
private ApplicationState applicationState;
private Set<Bundle> applicationBundles;
+ private BundleGraph bundleGraph;
public ApplicationGBean(@ParamSpecial(type = SpecialAttributeType.kernel) Kernel kernel,
@ParamSpecial(type = SpecialAttributeType.bundle) Bundle bundle,
@@ -226,7 +232,7 @@ public class ApplicationGBean implements
ServiceReference resolverRef = bundleContext.getServiceReference(AriesApplicationResolver.class.getName());
ServiceReference packageAdminRef = bundleContext.getServiceReference(PackageAdmin.class.getName());
- applicationBundles = new HashSet<Bundle>();
+ applicationBundles = new LinkedHashSet<Bundle>();
try {
resolver = getService(resolverRef, AriesApplicationResolver.class);
@@ -269,9 +275,10 @@ public class ApplicationGBean implements
}
contentBundle = bundleContext.installBundle(bundleInfo.getLocation());
+
applicationBundles.add(contentBundle);
-
}
+
}
} catch (BundleException be) {
for (Bundle bundle : applicationBundles) {
@@ -293,6 +300,7 @@ public class ApplicationGBean implements
applicationState = ApplicationState.INSTALLED;
}
+ @SuppressWarnings("deprecation")
private Bundle findBundleInFramework(PackageAdmin admin, String symbolicName, Version version) {
String exactVersion = "[" + version + "," + version + "]";
Bundle[] bundles = admin.getBundles(symbolicName, exactVersion);
@@ -367,10 +375,22 @@ public class ApplicationGBean implements
}
}
- private void startApplicationBundles() throws BundleException {
+ @SuppressWarnings("deprecation")
+ private void startApplicationBundles() throws Exception {
+
+ PackageAdmin packageAdmin = null;
+ ServiceReference packageAdminRef = bundle.getBundleContext().getServiceReference(PackageAdmin.class.getName());
List<Bundle> bundlesWeStarted = new ArrayList<Bundle>();
+
try {
- for (Bundle b : applicationBundles) {
+
+ packageAdmin = getService(packageAdminRef, PackageAdmin.class);
+ Set<Bundle> sortedBundles = new LinkedHashSet<Bundle>();
+
+ calculateBundleDependencies(packageAdmin);
+ sortedBundles.addAll(bundleGraph.getOrderedBundles());
+
+ for (Bundle b : sortedBundles) {
if (BundleUtils.canStart(b)) {
LOG.debug("Starting {} application bundle.", b);
b.start(Bundle.START_TRANSIENT);
@@ -391,9 +411,75 @@ public class ApplicationGBean implements
}
}
throw be;
+ } finally {
+
+ if (packageAdmin != null) {
+ bundle.getBundleContext().ungetService(packageAdminRef);
+ }
+ }
+ }
+
+
+ @SuppressWarnings("deprecation")
+ private void calculateBundleDependencies(PackageAdmin packageAdmin) throws BundleException {
+ if(! packageAdmin.resolveBundles(applicationBundles.toArray(new Bundle[applicationBundles.size()]))) {
+ throw new BundleException("The bundles in " + application.getApplicationMetadata().getApplicationSymbolicName() +
+ ":" + application.getApplicationMetadata().getApplicationVersion() + " could not be resolved");
+ }
+
+ Map<String, BundleNode> nodesMap = new HashMap<String, BundleNode>();
+
+ for(Bundle currentBundle : applicationBundles) {
+
+ BundleNode currentNode = getBundleNode(currentBundle, nodesMap);
+
+ Bundle[] requiringBundles = getRequiringBundles(currentBundle, packageAdmin);
+ for(Bundle rBundle : requiringBundles) {
+ BundleNode rBundleNode = getBundleNode(rBundle, nodesMap);
+ rBundleNode.getRequiredBundles().add(currentNode);
+ }
+ }
+
+ bundleGraph = new BundleGraph(nodesMap.values());
+ }
+
+ /**
+ * Get the requiring bundles which require the target bundle
+ *
+ * @param targetBundle the target bundle
+ * @param packageAdmin
+ * @return
+ */
+ @SuppressWarnings("deprecation")
+ private Bundle[] getRequiringBundles(Bundle targetBundle, PackageAdmin packageAdmin) {
+ ExportedPackage[] ePackages = packageAdmin.getExportedPackages(targetBundle);
+
+ Set<Bundle> requiringBundles = new HashSet<Bundle>();
+
+ for(ExportedPackage ePackage : ePackages) {
+ Bundle[] importingBundles = ePackage.getImportingBundles();
+ if(importingBundles == null) continue;
+
+ for(Bundle iBundle : importingBundles) {
+ if(! targetBundle.equals(iBundle) && applicationBundles.contains(iBundle)) {
+ requiringBundles.add(iBundle);
+ }
+ }
+ }
+
+ return requiringBundles.toArray(new Bundle[requiringBundles.size()]);
+ }
+
+ private BundleNode getBundleNode(Bundle bundle, Map<String, BundleNode> nodesMap) {
+ BundleNode node = nodesMap.get(bundle.getSymbolicName() + bundle.getVersion());
+ if(node == null) {
+ node = new BundleNode(bundle);
}
+ nodesMap.put(bundle.getSymbolicName() + bundle.getVersion(), node);
+ return node;
}
+
private static long getApplicationStartTimeout() {
String property = System.getProperty("org.apache.geronimo.aries.applicationStartTimeout", String.valueOf(5 * 60 * 1000));
return Long.parseLong(property);
Added: geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/BundleGraph.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/BundleGraph.java?rev=1308023&view=auto
==============================================================================
--- geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/BundleGraph.java (added)
+++ geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/BundleGraph.java Sun Apr 1 07:04:03 2012
@@ -0,0 +1,185 @@
+/**
+ * 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.geronimo.aries;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * The bundle graph, using the class to get the ordered bundles by the dependency relationship among them
+ *
+ * @version $Rev$ $Date$
+ */
+public class BundleGraph {
+ private final Collection<BundleNode> nodes;
+
+ public BundleGraph(Collection<BundleNode> nodes) {
+ this.nodes = nodes;
+
+ }
+
+ /**
+ * Traverse the graph in DFS way
+ *
+ * @param action
+ */
+ public void traverseDFS(TraverseVisitor action) {
+ clearState();
+ for(BundleNode node : nodes) {
+ DFS(node, action);
+ }
+
+ }
+
+ protected void DFS(BundleNode startNode, TraverseVisitor action) {
+ if(startNode.isVisited) return;
+
+ // do action before
+ if(action.isVisitBefore()) {
+ action.doVisit(startNode);
+ }
+
+ startNode.isVisited = true;
+
+ Collection<BundleNode> requiredBundles = startNode.requiredBundles;
+ if(! requiredBundles.isEmpty()) {
+ for(BundleNode rqBundle : requiredBundles) {
+ DFS(rqBundle, action);
+ }
+ }
+
+ // do action after
+ if(! action.isVisitBefore()) {
+ action.doVisit(startNode);
+ }
+ }
+
+ /**
+ * Get the ordered bundles according to the bundle dependencies
+ *
+ * @return
+ */
+ public List<Bundle> getOrderedBundles() {
+ final List<Bundle> result = new ArrayList<Bundle>();
+
+ traverseDFS(new TraverseVisitor() {
+ @Override
+ public void doVisit(BundleNode node) {
+ if(! result.contains(node.value)) {
+ result.add(node.value);
+ }
+ }
+ @Override
+ public boolean isVisitBefore() {
+ return false;
+ }
+ });
+
+ return result;
+ }
+
+ protected void clearState() {
+ for(BundleNode node : nodes) {
+ node.isVisited = false;
+ }
+ }
+ /**
+ * The bundle node in graph
+ *
+ * @version $Rev$ $Date$
+ */
+ public static class BundleNode {
+ private final Bundle value;
+ private final Set<BundleNode> requiredBundles;
+ private boolean isVisited;
+
+ public BundleNode(Bundle value) {
+ this.value = value;
+ requiredBundles = new HashSet<BundleNode>();
+ }
+
+ /**
+ * @return the value
+ */
+ public Bundle getValue() {
+ return value;
+ }
+
+ /**
+ * @return the isVisited
+ */
+ public boolean isVisited() {
+ return isVisited;
+ }
+
+ /**
+ * @return the requiredBundles
+ */
+ public Set<BundleNode> getRequiredBundles() {
+ return requiredBundles;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((value == null) ? 0 : value.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BundleNode other = (BundleNode) obj;
+ if (value == null) {
+ if (other.value != null)
+ return false;
+ } else if (!value.equals(other.value))
+ return false;
+ return true;
+ }
+
+
+ }
+
+ /**
+ * Do some action when traverse the graph
+ *
+ * @version $Rev$ $Date$
+ */
+ public static interface TraverseVisitor {
+ public void doVisit(BundleNode node);
+ public boolean isVisitBefore();
+ }
+}
+
Propchange: geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/BundleGraph.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/BundleGraph.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/server/trunk/plugins/aries/geronimo-aries/src/main/java/org/apache/geronimo/aries/BundleGraph.java
------------------------------------------------------------------------------
svn:mime-type = text/plain