Bug 184127 NullPointerException when trying to open a file
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/services/resolver/PlatformAdminTest.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/services/resolver/PlatformAdminTest.java
index df2c7b5..7bfbf53 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/services/resolver/PlatformAdminTest.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/services/resolver/PlatformAdminTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2003, 2007 IBM Corporation and others.
+ * Copyright (c) 2003, 2008 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -14,8 +14,8 @@
 import java.util.Hashtable;
 import junit.framework.Test;
 import junit.framework.TestSuite;
-import org.eclipse.osgi.service.resolver.BundleDescription;
-import org.eclipse.osgi.service.resolver.State;
+import org.eclipse.osgi.internal.baseadaptor.StateManager;
+import org.eclipse.osgi.service.resolver.*;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
 
@@ -71,6 +71,87 @@
 			fail("Unexpected error while cloning a BundleDescription", t);
 		}
 	}
+
+	public void testBug184127() throws BundleException {
+		File resolverData = getContext().getDataFile("resolverData");
+		resolverData.mkdirs();
+
+		File stateFile = new File(resolverData, ".state");
+		File lazyFile = new File(resolverData, ".lazy");
+		stateFile.delete();
+		lazyFile.delete();
+		StateManager sm = new StateManager(stateFile, lazyFile, getContext());
+		State systemState = sm.readSystemState();
+		assertNull("SystemState is not null", systemState);
+		systemState = sm.createSystemState();
+
+		Hashtable manifest = new Hashtable();
+		int id = 0;
+		manifest = new Hashtable();
+
+		manifest.clear();
+		manifest.put(Constants.BUNDLE_MANIFESTVERSION, "2");
+		manifest.put(Constants.BUNDLE_SYMBOLICNAME, "a");
+		manifest.put(Constants.BUNDLE_VERSION, "1.0.0");
+		BundleDescription a = systemState.getFactory().createBundleDescription(systemState, manifest, (String) manifest.get(Constants.BUNDLE_SYMBOLICNAME) + "_" + manifest.get(Constants.BUNDLE_VERSION), id++);
+
+		manifest.clear();
+		manifest.put(Constants.BUNDLE_MANIFESTVERSION, "2");
+		manifest.put(Constants.BUNDLE_SYMBOLICNAME, "b");
+		manifest.put(Constants.BUNDLE_VERSION, "1.0.0");
+		manifest.put(Constants.EXPORT_PACKAGE, "b, c");
+		manifest.put(Constants.REQUIRE_BUNDLE, "a");
+		manifest.put(Constants.IMPORT_PACKAGE, "afrag2");
+		BundleDescription b = systemState.getFactory().createBundleDescription(systemState, manifest, (String) manifest.get(Constants.BUNDLE_SYMBOLICNAME) + "_" + manifest.get(Constants.BUNDLE_VERSION), id++);
+
+		manifest.clear();
+		manifest.put(Constants.BUNDLE_MANIFESTVERSION, "2");
+		manifest.put(Constants.BUNDLE_SYMBOLICNAME, "afrag2");
+		manifest.put(Constants.BUNDLE_VERSION, "1.0.0");
+		manifest.put(Constants.EXPORT_PACKAGE, "afrag2");
+		manifest.put(Constants.FRAGMENT_HOST, "a");
+		manifest.put(Constants.IMPORT_PACKAGE, "c");
+		BundleDescription afrag2 = systemState.getFactory().createBundleDescription(systemState, manifest, (String) manifest.get(Constants.BUNDLE_SYMBOLICNAME) + "_" + manifest.get(Constants.BUNDLE_VERSION), id++);
+
+		manifest.clear();
+		manifest.put(Constants.BUNDLE_MANIFESTVERSION, "2");
+		manifest.put(Constants.BUNDLE_SYMBOLICNAME, "afrag1");
+		manifest.put(Constants.BUNDLE_VERSION, "1.0.0");
+		manifest.put(Constants.FRAGMENT_HOST, "a");
+		manifest.put(Constants.IMPORT_PACKAGE, "b");
+		BundleDescription afrag1 = systemState.getFactory().createBundleDescription(systemState, manifest, (String) manifest.get(Constants.BUNDLE_SYMBOLICNAME) + "_" + manifest.get(Constants.BUNDLE_VERSION), id++);
+
+		systemState.addBundle(afrag1);
+		systemState.addBundle(afrag2);
+		systemState.addBundle(a);
+		systemState.addBundle(b);
+
+		systemState.resolve();
+
+		assertTrue("aFrag1 is not resolved", afrag1.isResolved());
+		assertTrue("aFrag2 is not resolved", afrag2.isResolved());
+		assertTrue("a is not resolved", a.isResolved());
+		assertTrue("b is not resolved", b.isResolved());
+
+		try {
+			sm.shutdown(stateFile, lazyFile);
+		} catch (IOException e) {
+			fail("failed to shudown StateManager", e);
+		}
+
+		sm = new StateManager(stateFile, lazyFile, getContext());
+		systemState = sm.readSystemState();
+		assertNotNull("SystemState is null", systemState);
+		b = systemState.getBundle("b", null);
+		ExportPackageDescription[] exports = null;
+		try {
+			exports = b.getExportPackages();
+		} catch (Throwable e) {
+			fail("Unexpected exception getting exports", e);
+		}
+		assertNotNull("exports is null", exports);
+		assertEquals("Wrong number of exports", 2, exports.length);
+	}
 }
 //TODO tests to enable
 //testFragmentUpdateNoVersionChanged()
diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateHelperImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateHelperImpl.java
index 53aea07..d6d453e 100644
--- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateHelperImpl.java
+++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateHelperImpl.java
@@ -233,7 +233,38 @@
 		for (int i = 0; i < toSort.length; i++)
 			if (toSort[i].isResolved())
 				buildReferences(toSort[i], references);
-		return ComputeNodeOrder.computeNodeOrder(toSort, (Object[][]) references.toArray(new Object[references.size()][]));
+		Object[][] cycles = ComputeNodeOrder.computeNodeOrder(toSort, (Object[][]) references.toArray(new Object[references.size()][]));
+		if (cycles.length == 0)
+			return cycles;
+		// fix up host/fragment orders (bug 184127)
+		for (int i = 0; i < cycles.length; i++) {
+			for (int j = 0; j < cycles[i].length; j++) {
+				BundleDescription fragment = (BundleDescription) cycles[i][j];
+				if (fragment.getHost() == null)
+					continue;
+				BundleDescription host = (BundleDescription) fragment.getHost().getSupplier();
+				if (host == null)
+					continue;
+				fixFragmentOrder(host, fragment, toSort);
+			}
+		}
+		return cycles;
+	}
+
+	private void fixFragmentOrder(BundleDescription host, BundleDescription fragment, BundleDescription[] toSort) {
+		int hostIndex = -1;
+		int fragIndex = -1;
+		for (int i = 0; i < toSort.length && (hostIndex == -1 || fragIndex == -1); i++) {
+			if (toSort[i] == host)
+				hostIndex = i;
+			else if (toSort[i] == fragment)
+				fragIndex = i;
+		}
+		if (fragIndex > -1 && fragIndex < hostIndex) {
+			for (int i = fragIndex; i < hostIndex; i++)
+				toSort[i] = toSort[i + 1];
+			toSort[hostIndex] = fragment;
+		}
 	}
 
 	private void buildReferences(BundleDescription description, List references) {