You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2011/10/20 14:28:53 UTC

svn commit: r1186760 - in /sling/trunk/installer/core/src: main/java/org/apache/sling/installer/core/impl/ main/java/org/apache/sling/installer/core/impl/tasks/ test/java/org/apache/sling/installer/core/impl/

Author: cziegeler
Date: Thu Oct 20 12:28:53 2011
New Revision: 1186760

URL: http://svn.apache.org/viewvc?rev=1186760&view=rev
Log:
SLING-2199 : Installer should be able to update itself

Added:
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java   (with props)
Modified:
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleTaskCreator.java
    sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/SystemBundleUpdateTask.java
    sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/MockBundleContext.java

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java?rev=1186760&r1=1186759&r2=1186760&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java Thu Oct 20 12:28:53 2011
@@ -72,6 +72,9 @@ public class OsgiInstallerImpl
     extends Thread
     implements BundleListener, FrameworkListener, OsgiInstaller, ResourceChangeListener {
 
+    /** Internal key for tasks to be executed async. */
+    public static final String ASYNC_TASK_KEY = "EXECUTE TASK ASYNC";
+
     /** The logger */
     private final Logger logger =  LoggerFactory.getLogger(this.getClass());
 
@@ -113,6 +116,8 @@ public class OsgiInstallerImpl
 
     private final InstallListener listener;
 
+    private volatile boolean running = false;
+
     /** Constructor */
     public OsgiInstallerImpl(final BundleContext ctx) {
         this.ctx = ctx;
@@ -141,11 +146,13 @@ public class OsgiInstallerImpl
 
         // wake up sleeping thread
         this.wakeUp();
-        this.logger.debug("Waiting for installer thread to stop");
-        try {
-            this.join();
-        } catch (InterruptedException e) {
-            // we simply ignore this
+        if ( this.running ) {
+            this.logger.debug("Waiting for installer thread to stop");
+            try {
+                this.join();
+            } catch (InterruptedException e) {
+                // we simply ignore this
+            }
         }
 
         // remove file util
@@ -175,59 +182,69 @@ public class OsgiInstallerImpl
 
     @Override
     public void run() {
-        this.init();
-        while (active) {
-            listener.onEvent(new InstallationEvent() {
+        this.running = true;
+        try {
+            this.init();
+            while (active) {
+                listener.onEvent(new InstallationEvent() {
 
-                public TYPE getType() {
-                    return TYPE.STARTED;
-                }
+                    public TYPE getType() {
+                        return TYPE.STARTED;
+                    }
 
-                public Object getSource() {
-                    return null;
-                }
-            });
-            logger.debug("Starting new cycle");
+                    public Object getSource() {
+                        return null;
+                    }
+                });
+                logger.debug("Starting new installer cycle");
 
-            this.mergeNewlyRegisteredResources();
+                this.mergeNewlyRegisteredResources();
 
-            // invoke transformers
-            this.transformResources();
+                // invoke transformers
+                this.transformResources();
 
-            // execute tasks
-            final SortedSet<InstallTask> tasks = this.computeTasks();
-            final boolean tasksCreated = !tasks.isEmpty();
+                // execute tasks
+                final SortedSet<InstallTask> tasks = this.computeTasks();
+                final boolean tasksCreated = !tasks.isEmpty();
 
-            this.executeTasks(tasks);
+                // execute tasks and see if we have to stop processing
+                if ( this.executeTasks(tasks) ) {
 
-            // clean up and save
-            this.cleanupInstallableResources();
+                    // clean up and save
+                    this.cleanupInstallableResources();
 
-            // if we don't have any tasks, we go to sleep
-            if (!tasksCreated) {
-                synchronized ( this.resourcesLock ) {
-  		            // before we go to sleep, check if new resources arrived in the meantime
-                    if ( !this.hasNewResources()) {
-                        // No tasks to execute - wait until new resources are
-                        // registered
-                        logger.debug("No tasks to process, going idle");
-                        listener.onEvent(new InstallationEvent() {
+                    // if we don't have any tasks, we go to sleep
+                    if (!tasksCreated) {
+                        synchronized ( this.resourcesLock ) {
+          		            // before we go to sleep, check if new resources arrived in the meantime
+                            if ( !this.hasNewResources()) {
+                                // No tasks to execute - wait until new resources are
+                                // registered
+                                logger.debug("No tasks to process, going idle");
+                                listener.onEvent(new InstallationEvent() {
 
-                            public TYPE getType() {
-                                return TYPE.SUSPENDED;
-                            }
+                                    public TYPE getType() {
+                                        return TYPE.SUSPENDED;
+                                    }
 
-                            public Object getSource() {
-                                return null;
+                                    public Object getSource() {
+                                        return null;
+                                    }
+                                });
+                                try {
+                                    this.resourcesLock.wait();
+                                } catch (InterruptedException ignore) {}
+                                logger.debug("Notified of new resources, back to work");
                             }
-                        });
-                        try {
-                            this.resourcesLock.wait();
-                        } catch (InterruptedException ignore) {}
-                        logger.debug("Notified of new resources, back to work");
+                        }
                     }
+                } else {
+                    // stop processing
+                    this.active = false;
                 }
             }
+        } finally {
+            this.running = false;
         }
     }
 
@@ -519,15 +536,23 @@ public class OsgiInstallerImpl
     /**
      * Execute all tasks
      */
-    private void executeTasks(final SortedSet<InstallTask> tasks) {
+    private boolean executeTasks(final SortedSet<InstallTask> tasks) {
         if ( !tasks.isEmpty() ) {
 
+            final List<InstallTask> asyncTasks = new ArrayList<InstallTask>();
             final InstallationContext ctx = new InstallationContext() {
 
                 public void addTaskToNextCycle(final InstallTask t) {
-                    logger.debug("adding task to next cycle: {}", t);
-                    synchronized (tasksForNextCycle) {
-                        tasksForNextCycle.add(t);
+                    if ( t.getSortKey().equals(ASYNC_TASK_KEY) ) {
+                        logger.debug("Adding async task: {}", t);
+                        synchronized (asyncTasks) {
+                            asyncTasks.add(t);
+                        }
+                    } else {
+                        logger.debug("Adding task to next cycle: {}", t);
+                        synchronized (tasksForNextCycle) {
+                            tasksForNextCycle.add(t);
+                        }
                     }
                 }
 
@@ -555,8 +580,38 @@ public class OsgiInstallerImpl
                     logger.error("Uncaught exception during task execution!", t);
                 }
             }
+            // save new state
             persistentList.save();
+
+            // let's check if we have async tasks and no other tasks
+            if ( this.active && !asyncTasks.isEmpty() ) {
+                final boolean isEmpty;
+                synchronized ( tasksForNextCycle ) {
+                    isEmpty = tasksForNextCycle.isEmpty();
+                }
+                if ( isEmpty ) {
+                    // compact list and save if required
+                    this.cleanupInstallableResources();
+                    final InstallTask task = asyncTasks.get(0);
+                    final Thread t = new Thread() {
+
+                        @Override
+                        public void run() {
+                            try {
+                                Thread.sleep(2000L);
+                            } catch (final InterruptedException ie) {
+                                // ignore
+                            }
+                            task.execute(ctx);
+                        }
+                    };
+                    t.start();
+                    return false;
+                }
+            }
+
         }
+        return true;
     }
 
     /**

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleTaskCreator.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleTaskCreator.java?rev=1186760&r1=1186759&r2=1186760&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleTaskCreator.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/BundleTaskCreator.java Thu Oct 20 12:28:53 2011
@@ -50,6 +50,8 @@ public class BundleTaskCreator implement
      */
     private final static String FORCE_INSTALL_VERSION = "force.install.version";
 
+    private final static String SPECIAL_ATTR = "sling.osgi.installer.special";
+
     /** The logger */
     private final Logger logger =  LoggerFactory.getLogger(this.getClass());
 
@@ -166,8 +168,9 @@ public class BundleTaskCreator implement
             }
         }
         final String symbolicName = (String)toActivate.getAttribute(Constants.BUNDLE_SYMBOLICNAME);
+        final boolean isInstallerCoreBundle = this.bundleContext.getBundle().getSymbolicName().equals(symbolicName);
 
-		// Uninstall
+        // Uninstall
         final InstallTask result;
 		if (toActivate.getState() == ResourceState.UNINSTALL) {
             // find the info with the exact version
@@ -184,7 +187,13 @@ public class BundleTaskCreator implement
                     logger.debug("Detected downgrad of bundle {}", symbolicName);
                     result = new ChangeStateTask(resourceList, ResourceState.UNINSTALLED);
 	            } else {
-	                result = new BundleRemoveTask(resourceList, this);
+	                // prevent uninstalling the installer itself!
+	                if ( isInstallerCoreBundle ) {
+	                    logger.debug("Prevent completely uninstalling installer bundle {}", symbolicName);
+	                    result = new ChangeStateTask(resourceList, ResourceState.UNINSTALLED);
+	                } else {
+	                    result = new BundleRemoveTask(resourceList, this);
+	                }
 	            }
 		    } else {
 	            logger.debug("Bundle {}:{} is not installed anymore - nothing to remove.", symbolicName,
@@ -219,17 +228,33 @@ public class BundleTaskCreator implement
                                     + " is not installed, bundle with higher version is already installed.");
                     }
 			    } else if (compare == 0 && this.isSnapshot(newVersion)) {
+			        // check if system bundle or installer bundle
+			        if ( isInstallerCoreBundle || Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName) ) {
+			            if ( toActivate.getAttribute(SPECIAL_ATTR) != null ) {
+			                toActivate.setAttribute(SPECIAL_ATTR, null);
+			                result = new ChangeStateTask(resourceList, ResourceState.INSTALLED);
+			                return result;
+                        }
+		                toActivate.setAttribute(SPECIAL_ATTR, "installingsnapshot");
+			        }
 			        // installed, same version but SNAPSHOT
 			        doUpdate = true;
 			    }
                 if (doUpdate) {
 
                     logger.debug("Scheduling update of {}", toActivate);
+                    // check if this is the system bundle
                     if ( Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName) ) {
                         result = new SystemBundleUpdateTask(resourceList, this);
+                        // check if this is a installer update
+                    } else if ( isInstallerCoreBundle ) {
+                        result = new InstallerBundleUpdateTask(resourceList, this);
                     } else {
                         result = new BundleUpdateTask(resourceList, this);
                     }
+                } else if ( compare == 0 && (isInstallerCoreBundle || Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(symbolicName)) ) {
+                    // the installer core bundle / system bundle has been updated, just set state
+                    result = new ChangeStateTask(resourceList, ResourceState.INSTALLED);
                 } else {
                     logger.debug("Nothing to install for {}, same version {} already installed.", toActivate, newVersion);
                     result = new ChangeStateTask(resourceList, ResourceState.IGNORED);

Added: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java?rev=1186760&view=auto
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java (added)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java Thu Oct 20 12:28:53 2011
@@ -0,0 +1,90 @@
+/*
+ * 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.sling.installer.core.impl.tasks;
+
+import org.apache.sling.installer.api.tasks.InstallTask;
+import org.apache.sling.installer.api.tasks.InstallationContext;
+import org.apache.sling.installer.api.tasks.TaskResourceGroup;
+import org.apache.sling.installer.core.impl.AbstractInstallTask;
+import org.apache.sling.installer.core.impl.OsgiInstallerImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Update the installer itself
+ */
+public class InstallerBundleUpdateTask extends AbstractInstallTask {
+
+    private static final String BUNDLE_UPDATE_ORDER = "98-";
+
+    private final BundleTaskCreator creator;
+
+    public InstallerBundleUpdateTask(final TaskResourceGroup r,
+                            final BundleTaskCreator creator) {
+        super(r);
+        this.creator = creator;
+    }
+
+    /**
+     * @see org.apache.sling.installer.api.tasks.InstallTask#execute(org.apache.sling.installer.api.tasks.InstallationContext)
+     */
+    public void execute(final InstallationContext ctx) {
+        final Bundle b = this.creator.getBundleContext().getBundle();
+        final PackageAdmin pa = this.creator.getPackageAdmin();
+
+        ctx.addTaskToNextCycle(new InstallTask(this.getResourceGroup()) {
+
+            private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+            @Override
+            public String getSortKey() {
+                return OsgiInstallerImpl.ASYNC_TASK_KEY;
+            }
+
+            @Override
+            public void execute(final InstallationContext ctx) {
+                try {
+                    b.update(getResource().getInputStream());
+                    ctx.log("Updated bundle {} from resource {}", b, getResource());
+
+                    if ( pa != null ) {
+                        // wait for asynchronous bundle start tasks to finish
+                        try {
+                            Thread.sleep(2000L);
+                        } catch (final InterruptedException ignore) {
+                            // just ignore
+                        }
+
+                        pa.refreshPackages( new Bundle[] { b } );
+                    }
+                    logger.debug("Bundle updated: {}/{}", b.getBundleId(), b.getSymbolicName());
+                } catch (final Exception e) {
+                    logger.warn("Removing failing tasks - unable to retry: " + this, e);
+                }
+            }
+        });
+    }
+
+    @Override
+    public String getSortKey() {
+        return BUNDLE_UPDATE_ORDER + getResource().getEntityId();
+    }
+}
\ No newline at end of file

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/InstallerBundleUpdateTask.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/SystemBundleUpdateTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/SystemBundleUpdateTask.java?rev=1186760&r1=1186759&r2=1186760&view=diff
==============================================================================
--- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/SystemBundleUpdateTask.java (original)
+++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/tasks/SystemBundleUpdateTask.java Thu Oct 20 12:28:53 2011
@@ -21,12 +21,16 @@ package org.apache.sling.installer.core.
 import java.io.IOException;
 import java.io.InputStream;
 
+import org.apache.sling.installer.api.tasks.InstallTask;
 import org.apache.sling.installer.api.tasks.InstallationContext;
+import org.apache.sling.installer.api.tasks.ResourceState;
 import org.apache.sling.installer.api.tasks.TaskResourceGroup;
 import org.apache.sling.installer.core.impl.AbstractInstallTask;
+import org.apache.sling.installer.core.impl.OsgiInstallerImpl;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Update the system bundle from a RegisteredResource.
@@ -45,58 +49,76 @@ public class SystemBundleUpdateTask exte
 
     @Override
     public void execute(final InstallationContext ctx) {
-        // restart system bundle
-        if ( this.getResource() == null ) {
-            this.restartSystemBundleDelayed();
+        final Bundle systemBundle = this.creator.getBundleContext().getBundle(0);
+        // sanity check
+        if ( systemBundle == null ) {
             return;
         }
-        final String symbolicName = (String)getResource().getAttribute(Constants.BUNDLE_SYMBOLICNAME);
-        final Bundle b = this.creator.getMatchingBundle(symbolicName, null);
-        if (b == null) {
-            throw new IllegalStateException("Bundle to update (" + symbolicName + ") not found");
-        }
 
-        InputStream is = null;
-        try {
-            is = getResource().getInputStream();
-            if (is == null) {
-                throw new IllegalStateException(
-                        "RegisteredResource provides null InputStream, cannot update bundle: "
-                        + getResource());
-            }
-            // delayed system bundle update
-            final InputStream backgroundIS = is;
-            is = null;
-            final Thread t = new Thread(new Runnable() {
-
-                /**
-                 * @see java.lang.Runnable#run()
-                 */
-                public void run() {
+        // restart system bundle
+        if ( this.getResource() == null ) {
+            // do an async update
+            ctx.addTaskToNextCycle(new InstallTask(this.getResourceGroup()) {
+
+                private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+                @Override
+                public String getSortKey() {
+                    return OsgiInstallerImpl.ASYNC_TASK_KEY;
+                }
+
+                @Override
+                public void execute(final InstallationContext ctx) {
                     try {
-                        Thread.sleep(800);
-                    } catch(InterruptedException ignored) {
+                        systemBundle.update();
+                    } catch (final BundleException e) {
+                        logger.warn("Updating system bundle failed - unable to retry: " + this, e);
                     }
-                    try {
-                        b.update(backgroundIS);
-                    } catch (final BundleException be) {
-                        getLogger().warn("Unable to update system bundle", be);
-                    } finally {
+                }
+            });
+        } else {
+            InputStream is = null;
+            try {
+                is = getResource().getInputStream();
+                if (is == null) {
+                    throw new IllegalStateException(
+                            "RegisteredResource provides null InputStream, cannot update bundle: "
+                            + getResource());
+                }
+                // delayed system bundle update
+                final InputStream backgroundIS = is;
+                is = null;
+                ctx.addTaskToNextCycle(new InstallTask(this.getResourceGroup()) {
+
+                    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+                    @Override
+                    public String getSortKey() {
+                        return OsgiInstallerImpl.ASYNC_TASK_KEY;
+                    }
+
+                    @Override
+                    public void execute(final InstallationContext ctx) {
                         try {
-                            backgroundIS.close();
-                        } catch (IOException ignore) {}
+                            systemBundle.update(backgroundIS);
+                        } catch (final BundleException e) {
+                            logger.warn("Updating system bundle failed - unable to retry: " + this, e);
+                        } finally {
+                            try {
+                                backgroundIS.close();
+                            } catch (IOException ignore) {}
+                        }
                     }
+                });
+            } catch (final IOException e) {
+                this.getLogger().warn("Removing failing tasks - unable to retry: " + this, e);
+                this.setFinishedState(ResourceState.IGNORED);
+            } finally {
+                if ( is != null ) {
+                    try {
+                        is.close();
+                    } catch (IOException ignore) {}
                 }
-            });
-            t.setDaemon(true);
-            t.start();
-        } catch (final IOException e) {
-            this.getLogger().warn("Removing failing tasks - unable to retry: " + this, e);
-        } finally {
-            if ( is != null ) {
-                try {
-                    is.close();
-                } catch (IOException ignore) {}
             }
         }
     }
@@ -105,31 +127,4 @@ public class SystemBundleUpdateTask exte
     public String getSortKey() {
         return BUNDLE_UPDATE_ORDER + getResource().getURL();
     }
-
-    private void restartSystemBundleDelayed() {
-        final Bundle systemBundle = this.creator.getBundleContext().getBundle(0);
-        // sanity check
-        if ( systemBundle == null ) {
-            return;
-        }
-        final Thread t = new Thread(new Runnable() {
-
-            /**
-             * @see java.lang.Runnable#run()
-             */
-            public void run() {
-                try {
-                    Thread.sleep(800);
-                } catch(InterruptedException ignored) {
-                }
-                try {
-                    systemBundle.update();
-                } catch (final BundleException be) {
-                    getLogger().warn("Unable to refresh system bundle", be);
-                }
-            }
-        });
-        t.setDaemon(true);
-        t.start();
-    }
 }
\ No newline at end of file

Modified: sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/MockBundleContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/MockBundleContext.java?rev=1186760&r1=1186759&r2=1186760&view=diff
==============================================================================
--- sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/MockBundleContext.java (original)
+++ sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/MockBundleContext.java Thu Oct 20 12:28:53 2011
@@ -21,7 +21,10 @@ package org.apache.sling.installer.core.
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URL;
 import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Map;
 
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
@@ -33,6 +36,7 @@ import org.osgi.framework.InvalidSyntaxE
 import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.Version;
 
 public class MockBundleContext implements BundleContext {
 
@@ -127,8 +131,138 @@ public class MockBundleContext implement
     }
 
     public Bundle getBundle() {
-        // TODO Auto-generated method stub
-        return null;
+        return new Bundle() {
+
+            public int getState() {
+                // TODO Auto-generated method stub
+                return 0;
+            }
+
+            public void start(int options) throws BundleException {
+                // TODO Auto-generated method stub
+
+            }
+
+            public void start() throws BundleException {
+                // TODO Auto-generated method stub
+
+            }
+
+            public void stop(int options) throws BundleException {
+                // TODO Auto-generated method stub
+
+            }
+
+            public void stop() throws BundleException {
+                // TODO Auto-generated method stub
+
+            }
+
+            public void update(InputStream input) throws BundleException {
+                // TODO Auto-generated method stub
+
+            }
+
+            public void update() throws BundleException {
+                // TODO Auto-generated method stub
+
+            }
+
+            public void uninstall() throws BundleException {
+                // TODO Auto-generated method stub
+
+            }
+
+            public Dictionary getHeaders() {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public long getBundleId() {
+                // TODO Auto-generated method stub
+                return 0;
+            }
+
+            public String getLocation() {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public ServiceReference[] getRegisteredServices() {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public ServiceReference[] getServicesInUse() {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public boolean hasPermission(Object permission) {
+                // TODO Auto-generated method stub
+                return false;
+            }
+
+            public URL getResource(String name) {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public Dictionary getHeaders(String locale) {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public String getSymbolicName() {
+                return "test-bundle";
+            }
+
+            public Class loadClass(String name) throws ClassNotFoundException {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public Enumeration getResources(String name) throws IOException {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public Enumeration getEntryPaths(String path) {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public URL getEntry(String path) {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public long getLastModified() {
+                // TODO Auto-generated method stub
+                return 0;
+            }
+
+            public Enumeration findEntries(String path, String filePattern,
+                    boolean recurse) {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public BundleContext getBundleContext() {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public Map getSignerCertificates(int signersType) {
+                // TODO Auto-generated method stub
+                return null;
+            }
+
+            public Version getVersion() {
+                // TODO Auto-generated method stub
+                return null;
+            }
+        };
     }
 
     public ServiceReference[] getAllServiceReferences(String clazz,