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