358447: test raw bundle cases and fix recovery path
diff --git a/org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/PlanDeploymentWithDAGTests.java b/org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/PlanDeploymentWithDAGTests.java
index f9fc08e..f793dc3 100644
--- a/org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/PlanDeploymentWithDAGTests.java
+++ b/org.eclipse.virgo.kernel.deployer.test/src/test/java/org/eclipse/virgo/kernel/deployer/test/PlanDeploymentWithDAGTests.java
@@ -187,7 +187,7 @@
         assertBundlesNotInstalled(this.context.getBundles(), BUNDLE_ONE_SYMBOLIC_NAME);
     }
 
-    @Test    
+    @Test
     // 1a. (@see https://bugs.eclipse.org/bugs/show_bug.cgi?id=365034)
     public void planReferencingAnAlreadyInstalledBundleUndeployBundleFirst() throws Exception {
 
@@ -209,22 +209,22 @@
     @Test
     // 1a. (@see https://bugs.eclipse.org/bugs/show_bug.cgi?id=365034)
     public void planReferencingAnAlreadyInstalledBundleUndeployPlanFirst() throws Exception {
-        
+
         File file = new File("src/test/resources/plan-deployment/simple.bundle.one.jar");
         DeploymentIdentity deploymentId = this.deployer.deploy(file.toURI());
         assertBundlesInstalled(this.context.getBundles(), BUNDLE_ONE_SYMBOLIC_NAME);
-        
+
         DeploymentIdentity deploymentIdentity = this.deployer.deploy(new File("src/test/resources/testunscopednonatomicA.plan").toURI());
         assertNoDuplicatesInstalled(this.context.getBundles(), BUNDLE_ONE_SYMBOLIC_NAME);
         assertBundlesInstalled(this.context.getBundles(), BUNDLE_ONE_SYMBOLIC_NAME);
-        
+
         this.deployer.undeploy(deploymentIdentity);
         assertBundlesInstalled(this.context.getBundles(), BUNDLE_ONE_SYMBOLIC_NAME);
-        
+
         this.deployer.undeploy(deploymentId.getType(), deploymentId.getSymbolicName(), deploymentId.getVersion());
         assertBundlesNotInstalled(this.context.getBundles(), BUNDLE_ONE_SYMBOLIC_NAME);
     }
-    
+
     private void assertNoDuplicatesInstalled(Bundle[] bundles, String bundleOneSymbolicName) {
         List<String> installedBsns = getInstalledBsns(bundles);
         int found = 0;
@@ -581,7 +581,7 @@
         expectPlanAUninstall();
         checkEvents();
     }
-    
+
     @Test
     public void sharedTopLevelBundleResolvedResolvedUninstallPlanUninstallBundle() throws Exception {
         sharedTopLevelBundlePlanResolvedBundleResolved();
@@ -592,7 +592,6 @@
         checkEvents();
     }
 
-
     // twoPlansReferencingASharedBundleActiveActive
 
     @Test
@@ -917,7 +916,7 @@
         expectBundleUninstall();
         checkEvents();
     }
-    
+
     @Test
     public void sharedTopLevelPlanResolvedResolvedUninstallChildPlanUninstallParentPlan() throws Exception {
         sharedTopLevelPlanChildResolvedParentResolved();
@@ -1135,15 +1134,60 @@
         this.bundleId = BUNDLE_ONE_IDENTITY;
         stopPlanB();
         clearEvents();
-        
+
         deployUnscopedNonatomicPlanAParent();
         expectPlanAInstall();
         expectPlanAStart();
         expectSharedPlanStart();
         checkEvents();
     }
+    
+    // Raw bundle access
+    
+    @Test
+    public void rawBundleStop() throws Exception {
+        deployUnscopedNonatomicPlanA();
+        deploySimpleBundleOne();
+        stopPlanA();
+        Bundle b = getUnderlyingBundle();
+        b.stop();
+        clearEvents();
+
+        startPlanA();
+        stopPlanA();
+        expectPlanAStart();
+        expectBundleStart();
+        expectPlanAStop();
+        // Do not expect bundle stop, since bundle was not stopped via the deployer.
+        checkEvents();
+    }
+
+    @Test
+    public void rawBundleStart() throws Exception {
+        deployUnscopedNonatomicPlanA();
+        deploySimpleBundleOne();
+        stopBundle();
+        Bundle b = getUnderlyingBundle();
+        b.start();
+        Thread.sleep(50);
+        clearEvents();
+        
+        stopPlanA();
+        expectPlanAStop();
+        expectBundleStop(); // since bundle was not started via the deployer
+        checkEvents();
+    }
 
     // helper methods
+    
+    private Bundle getUnderlyingBundle() {
+        for (Bundle bundle : this.context.getBundles()) {
+            if (BUNDLE_ONE_SYMBOLIC_NAME.equals(bundle.getSymbolicName()) && (new Version(BUNDLE_ONE_VERSION)).equals(bundle.getVersion())) {
+                return bundle;
+            }
+        }
+        return null;
+    }
 
     private void checkEvents() {
         waitForAndCheckEventsReceived(this.expectedEventSet, 50L);
@@ -1464,7 +1508,7 @@
     static void assertBundlesActive(Bundle[] bundles, String... bsns) {
         assertBundlesInState(Bundle.ACTIVE, bundles, bsns);
     }
-    
+
     static void assertBundlesResolved(Bundle[] bundles, String... bsns) {
         assertBundlesInState(Bundle.RESOLVED, bundles, bsns);
     }
diff --git a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/PipelinedApplicationDeployer.java b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/PipelinedApplicationDeployer.java
index c9ceb1c..cdc61a0 100644
--- a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/PipelinedApplicationDeployer.java
+++ b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/deployer/core/internal/PipelinedApplicationDeployer.java
@@ -310,18 +310,27 @@
     public void recoverDeployment(URI uri, DeploymentOptions options) throws DeploymentException {
 
         GraphNode<InstallArtifact> installNode = null;
+        boolean shared = false;
         File artifact = new File(uri);
         if (options.getRecoverable() && (!options.getDeployerOwned() || artifact.exists())) {
-            installNode = this.installArtifactGraphInclosure.recoverInstallGraph(determineIdentity(artifact, null), artifact);
+            ArtifactIdentity artifactIdentity = determineIdentity(artifact, null);
+            installNode = findSharedNode(artifactIdentity);
+            if (installNode == null) {
+                installNode = this.installArtifactGraphInclosure.recoverInstallGraph(artifactIdentity, artifact);
+            } else {
+                shared = true;
+            }
         }
 
         if (installNode == null) {
             // Remove the URI from the recovery log.
             this.deploymentListener.undeployed(uri);
         } else {
-            driveInstallPipeline(uri, installNode);
+            if (!shared) {
+                driveInstallPipeline(uri, installNode);
 
-            start(installNode.getValue(), options.getSynchronous());
+                start(installNode.getValue(), options.getSynchronous());
+            }
 
             try {
                 addGraphToModel(uri, installNode);
diff --git a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/AbstractInstallArtifact.java b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/AbstractInstallArtifact.java
index 0389cab..dfe08d4 100644
--- a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/AbstractInstallArtifact.java
+++ b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/AbstractInstallArtifact.java
@@ -657,6 +657,7 @@
     public void setTopLevelDeployed() {
         synchronized (this.monitor) {
             this.isTopLevelDeployed = true;
+            this.isTopLevelActive = true;
         }
     }
 
diff --git a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/bundle/StandardBundleInstallArtifact.java b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/bundle/StandardBundleInstallArtifact.java
index e2297af..62e2441 100644
--- a/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/bundle/StandardBundleInstallArtifact.java
+++ b/org.eclipse.virgo.kernel.deployer/src/main/java/org/eclipse/virgo/kernel/install/artifact/internal/bundle/StandardBundleInstallArtifact.java
@@ -225,7 +225,7 @@
     }
 
     /**
-     * Track the start of the bundle.
+     * Track an unsolicited start of the bundle.
      */
     void trackStart() {
         AbortableSignal signal = createStateMonitorSignal(null);