[345406]
Fixed bug  - 345406 listBundles performance is really poor 
A new method has been introduced that can serve in case of huge bundle numbers. Application developer can control via mask which data can be retrieved by the MBean
diff --git a/org.eclipse.gemini.mgmt/META-INF/MANIFEST.MF b/org.eclipse.gemini.mgmt/META-INF/MANIFEST.MF
index 4c5d35c..03fab44 100644
--- a/org.eclipse.gemini.mgmt/META-INF/MANIFEST.MF
+++ b/org.eclipse.gemini.mgmt/META-INF/MANIFEST.MF
@@ -6,15 +6,18 @@
 Bundle-Vendor: Oracle
 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 Import-Package: org.osgi.framework;version="1.3.0",
- org.osgi.util.tracker,
+ org.osgi.jmx,
+ org.osgi.jmx.framework,
+ org.osgi.jmx.service.cm,
+ org.osgi.jmx.service.permissionadmin,
+ org.osgi.jmx.service.provisioning,
+ org.osgi.jmx.service.useradmin,
  org.osgi.service.cm,
  org.osgi.service.packageadmin,
  org.osgi.service.permissionadmin,
  org.osgi.service.provisioning,
  org.osgi.service.startlevel,
  org.osgi.service.useradmin,
- org.osgi.jmx.framework,
- org.osgi.jmx.service.cm,
- org.osgi.jmx.service.permissionadmin,
- org.osgi.jmx.service.provisioning,
- org.osgi.jmx.service.useradmin
+ org.osgi.util.tracker
+Bundle-Activator: org.eclipse.gemini.mgmt.Activator
+Bundle-ActivationPolicy: lazy
diff --git a/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/Activator.java b/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/Activator.java
index d17048f..82f3de0 100644
--- a/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/Activator.java
+++ b/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/Activator.java
@@ -29,18 +29,18 @@
 import javax.management.ObjectName;

 import javax.management.StandardMBean;

 

-import org.osgi.framework.BundleActivator;

-import org.osgi.framework.BundleContext;

-import org.osgi.framework.ServiceReference;

 import org.eclipse.gemini.mgmt.cm.ConfigAdminManager;

 import org.eclipse.gemini.mgmt.framework.BundleState;

+import org.eclipse.gemini.mgmt.framework.CustomBundleStateMBean;

 import org.eclipse.gemini.mgmt.framework.Framework;

 import org.eclipse.gemini.mgmt.framework.PackageState;

 import org.eclipse.gemini.mgmt.framework.ServiceState;

 import org.eclipse.gemini.mgmt.permissionadmin.PermissionManager;

 import org.eclipse.gemini.mgmt.provisioning.Provisioning;

 import org.eclipse.gemini.mgmt.useradmin.UserManager;

-import org.osgi.jmx.framework.BundleStateMBean;

+import org.osgi.framework.BundleActivator;

+import org.osgi.framework.BundleContext;

+import org.osgi.framework.ServiceReference;

 import org.osgi.jmx.framework.FrameworkMBean;

 import org.osgi.jmx.framework.PackageStateMBean;

 import org.osgi.jmx.framework.ServiceStateMBean;

@@ -99,7 +99,7 @@
 	public void start(BundleContext bundleContext) throws Exception {

 		this.bundleContext = bundleContext;

 		frameworkName = new ObjectName(FrameworkMBean.OBJECTNAME);

-		bundlesStateName = new ObjectName(BundleStateMBean.OBJECTNAME);

+		bundlesStateName = new ObjectName(CustomBundleStateMBean.OBJECTNAME);

 		serviceStateName = new ObjectName(ServiceStateMBean.OBJECTNAME);

 		packageStateName = new ObjectName(PackageStateMBean.OBJECTNAME);

 		configAdminName = new ObjectName(ConfigurationAdminMBean.OBJECTNAME);

@@ -256,7 +256,7 @@
 		}

 		try {

 			bundleState = new StandardMBean(new BundleState(bundleContext, sl,

-					admin), BundleStateMBean.class);

+					admin), CustomBundleStateMBean.class);

 		} catch (NotCompliantMBeanException e) {

 			log.log(Level.SEVERE,

 					"Unable to create StandardMBean for BundleState", e);

diff --git a/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/framework/BundleState.java b/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/framework/BundleState.java
index a5ecfdd..19d01cd 100644
--- a/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/framework/BundleState.java
+++ b/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/framework/BundleState.java
@@ -39,7 +39,7 @@
 /** 

  * 

  */

-public class BundleState extends Monitor implements BundleStateMBean {

+public class BundleState extends Monitor implements CustomBundleStateMBean {

 	public BundleState(BundleContext bc, StartLevel sl, PackageAdmin admin) {

 		this.bc = bc;

 		this.sl = sl;

@@ -52,12 +52,22 @@
 	 * @see org.osgi.jmx.core.BundleStateMBean#getBundles()

 	 */

 	public TabularData listBundles() throws IOException {

+		return listBundles(CustomBundleStateMBean.DEFAULT);

+	}

+	

+	/* (non-Javadoc)

+	 * @see org.eclipse.gemini.mgmt.framework.CustomBundleStateMBean#listBundles(int)

+	 */

+	public TabularData listBundles(int mask) throws IOException {

+		if (mask < 1 || mask > 1048575) {

+			throw new IllegalArgumentException("Mask out of range!");

+		}

 		try {

 			ArrayList<OSGiBundle> bundles = new ArrayList<OSGiBundle>();

 			for (Bundle bundle : bc.getBundles()) {

 				bundles.add(new OSGiBundle(bc, admin, sl, bundle));

 			}

-			TabularData table = OSGiBundle.tableFrom(bundles);

+			TabularData table = OSGiBundle.tableFrom(bundles, mask);

 			return table;

 		} catch (Throwable e) {

 			e.printStackTrace();

diff --git a/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/framework/CustomBundleStateMBean.java b/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/framework/CustomBundleStateMBean.java
new file mode 100644
index 0000000..1498770
--- /dev/null
+++ b/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/framework/CustomBundleStateMBean.java
@@ -0,0 +1,152 @@
+package org.eclipse.gemini.mgmt.framework;
+
+import java.io.IOException;
+
+import javax.management.openmbean.TabularData;
+
+import org.osgi.jmx.framework.BundleStateMBean;
+
+public interface CustomBundleStateMBean extends BundleStateMBean{
+
+	/**
+	 * Mask for listBundles method, that requires bundle location attribute to be 
+	 * included in the returned data.
+	 * 
+	 */
+	public final static int LOCATION = 1;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle id attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int IDENTIFIER = 2;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle symbolic name attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int SYMBOLIC_NAME = 2 << 1;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle version attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int VERSION = 2 << 2;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle start level attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int START_LEVEL = 2 << 3;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle state attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int STATE = 2 << 4;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle last modified attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int LAST_MODIFIED = 2 << 5;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle persistently started attribute to be 
+	 * included in the returned data. 
+	 */
+	public final static int PERSISTENTLY_STARTED = 2 << 6;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle removal pending attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int REMOVAL_PENDING = 2 << 7;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle required attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int REQUIRED = 2 << 8;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle fragment attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int FRAGMENT = 2 << 9;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle registered services attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int REGISTERED_SERVICES = 2 << 10;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle services in use attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int SERVICES_IN_USE = 2 << 11;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle headers attribute to be 
+	 * included in the returned data. 
+	 */
+	public final static int HEADERS = 2 << 12;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle exported packages attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int EXPORTED_PACKAGES = 2 << 13;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle imported packages attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int IMPORTED_PACKAGES = 2 << 14;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle fragments attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int FRAGMENTS = 2 << 15;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle hosts attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int HOSTS = 2 << 16;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle "requiring bundles" attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int REQUIRING_BUNDLES = 2 << 17;
+	
+	/**
+	 * Mask for listBundles method, that requires bundle "required bundles" attribute to be 
+	 * included in the returned data.
+	 */
+	public final static int REQUIRED_BUNDLES = 2 << 18;
+	
+	/**
+	 * Mask for listBundles method, that returns all available data. Equivalent to listBundles()
+	 */
+	public final static int DEFAULT = LOCATION + IDENTIFIER
+	+ SYMBOLIC_NAME + VERSION + START_LEVEL + STATE + LAST_MODIFIED 
+	+ PERSISTENTLY_STARTED + REMOVAL_PENDING + REQUIRED + FRAGMENT + REGISTERED_SERVICES
+	+ SERVICES_IN_USE + HEADERS + EXPORTED_PACKAGES + IMPORTED_PACKAGES + FRAGMENTS 
+	+ HOSTS + REQUIRING_BUNDLES + REQUIRED_BUNDLES;
+
+	/**
+	 * Answer the bundle state of the system in tabular form depending on the mask.
+	 * 
+	 * Each row of the returned table represents a single bundle. The Tabular
+	 * Data consists of Composite Data that is type by {@link #BUNDLES_TYPE}.
+	 *
+	 * @param mask - representing the information that will be contained in the result
+	 * @return the tabular representation of the bundle state
+	 * @throws IOException
+	 */
+	TabularData listBundles(int mask) throws IOException;
+}
diff --git a/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/framework/codec/OSGiBundle.java b/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/framework/codec/OSGiBundle.java
index f4653fc..73de7ea 100644
--- a/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/framework/codec/OSGiBundle.java
+++ b/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/framework/codec/OSGiBundle.java
@@ -40,6 +40,7 @@
 

 import javax.management.openmbean.CompositeData;

 import javax.management.openmbean.CompositeDataSupport;

+import javax.management.openmbean.CompositeType;

 import javax.management.openmbean.OpenDataException;

 import javax.management.openmbean.TabularData;

 import javax.management.openmbean.TabularDataSupport;

@@ -47,11 +48,14 @@
 import org.osgi.framework.Bundle;

 import org.osgi.framework.BundleContext;

 

+import org.osgi.jmx.Item;

 import org.osgi.jmx.framework.BundleStateMBean;

 import org.osgi.service.packageadmin.PackageAdmin;

 import org.osgi.service.startlevel.StartLevel;

 

 import org.eclipse.gemini.mgmt.codec.Util;

+import org.eclipse.gemini.mgmt.framework.CustomBundleStateMBean;

+

 

 /**

  * <p>

@@ -142,13 +146,17 @@
  * </table>

  */

 public class OSGiBundle {

-

+	

 	private static final String VALUE = "Value";

 

 	private static final String KEY = "Key";

 

 	private static final String[] HEADER_PROPERTY_ITEM_NAMES = new String[] {

 			KEY, VALUE };

+	private BundleContext bc;

+	private PackageAdmin admin;

+	private StartLevel sl;

+	private Bundle b;

 

 	/**

 	 * Construct an OSGiBundle from the encoded CompositeData

@@ -199,18 +207,11 @@
 	 */

 	public OSGiBundle(BundleContext bc, PackageAdmin admin, StartLevel sl,

 			Bundle b) {

-		this(b.getLocation(), b.getBundleId(), b.getSymbolicName(), b

-				.getVersion().toString(), sl.getBundleStartLevel(b),

-				getBundleState(b), b.getLastModified(),

-				isBundlePersistentlyStarted(b, sl),

-				isRequiredBundleRemovalPending(b, bc, admin), isBundleRequired(

-						b, bc, admin), isBundleFragment(b, admin), serviceIds(b

-						.getRegisteredServices()), serviceIds(b

-						.getServicesInUse()), getBundleHeaders(b),

-				getBundleExportedPackages(b, admin), getBundleImportedPackages(

-						b, bc, admin), getBundleFragments(b, admin), Util

-						.bundleIds(admin.getHosts(b)), getDependencies(b,

-						admin), getBundlesRequiring(b, bc, admin));

+		this.bc = bc;

+		this.admin = admin;

+		this.sl = sl;

+		this.b = b;

+

 	}

 

 	/**

@@ -272,17 +273,87 @@
 	 * 

 	 * @param bundles

 	 *            - the list of bundles to represent

+	 * @param mask 

 	 * 

 	 * @return the Tabular data which represents the list of bundles

 	 */

-	public static TabularData tableFrom(ArrayList<OSGiBundle> bundles) {

+	public static TabularData tableFrom(ArrayList<OSGiBundle> bundles, int mask) {

 		TabularDataSupport table = new TabularDataSupport(

-				BundleStateMBean.BUNDLES_TYPE);

+				Item.tabularType("BUNDLES", "A list of bundles",

+						OSGiBundle.computeBundleType(mask), new String[] { BundleStateMBean.IDENTIFIER }));

 		for (OSGiBundle bundle : bundles) {

-			table.put(bundle.asCompositeData());

+			table.put(bundle.asCompositeData(mask));

 		}

 		return table;

 	}

+	

+	private static CompositeType computeBundleType(int mask) {

+		List<Item> bundleTypes = new ArrayList<Item>();

+		if((mask | CustomBundleStateMBean.LOCATION) == mask) {

+		bundleTypes.add(BundleStateMBean.LOCATION_ITEM);

+		}

+//		if((mask | IDENTIFIER) == mask) {

+		bundleTypes.add(BundleStateMBean.IDENTIFIER_ITEM);

+//		}

+		if((mask | CustomBundleStateMBean.SYMBOLIC_NAME) == mask) {

+		bundleTypes.add(BundleStateMBean.SYMBOLIC_NAME_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.VERSION) == mask) {

+		bundleTypes.add(BundleStateMBean.VERSION_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.START_LEVEL) == mask) {

+		bundleTypes.add(BundleStateMBean.START_LEVEL_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.STATE) == mask) {

+		bundleTypes.add(BundleStateMBean.STATE_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.LAST_MODIFIED) == mask) {

+		bundleTypes.add(BundleStateMBean.LAST_MODIFIED_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.PERSISTENTLY_STARTED) == mask) {

+		bundleTypes.add(BundleStateMBean.PERSISTENTLY_STARTED_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.REMOVAL_PENDING) == mask) {

+		bundleTypes.add(BundleStateMBean.REMOVAL_PENDING_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.REQUIRED) == mask) {

+		bundleTypes.add(BundleStateMBean.REQUIRED_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.FRAGMENT) == mask) {

+		bundleTypes.add(BundleStateMBean.FRAGMENT_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.REGISTERED_SERVICES) == mask) {

+		bundleTypes.add(BundleStateMBean.REGISTERED_SERVICES_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.SERVICES_IN_USE) == mask) {

+		bundleTypes.add(BundleStateMBean.SERVICES_IN_USE_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.HEADERS) == mask) {

+		bundleTypes.add(BundleStateMBean.HEADERS_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.EXPORTED_PACKAGES) == mask) {

+		bundleTypes.add(BundleStateMBean.EXPORTED_PACKAGES_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.IMPORTED_PACKAGES) == mask) {

+		bundleTypes.add(BundleStateMBean.IMPORTED_PACKAGES_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.FRAGMENTS) == mask) {

+		bundleTypes.add(BundleStateMBean.FRAGMENTS_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.HOSTS) == mask) {

+		bundleTypes.add(BundleStateMBean.HOSTS_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.REQUIRING_BUNDLES) == mask) {

+		bundleTypes.add(BundleStateMBean.REQUIRING_BUNDLES_ITEM);

+		}

+		if((mask | CustomBundleStateMBean.REQUIRED_BUNDLES) == mask) {

+		bundleTypes.add(BundleStateMBean.REQUIRED_BUNDLES_ITEM);

+		}

+

+		CompositeType currentCompositeType = Item.compositeType("BUNDLE",

+				"This type encapsulates OSGi bundles",bundleTypes.toArray(new Item[]{}));

+		return currentCompositeType;

+	}

 

 	/**

 	 * Answer the TabularData representing the list of bundle headers for a

@@ -334,39 +405,80 @@
 

 	/**

 	 * Answer the receiver encoded as CompositeData

+	 * @param mask 

 	 * 

 	 * @return the CompositeData encoding of the receiver.

 	 */

 	@SuppressWarnings("boxing")

-	public CompositeData asCompositeData() {

+	public CompositeData asCompositeData(int mask) {

 		Map<String, Object> items = new HashMap<String, Object>();

-		items.put(BundleStateMBean.LOCATION, location);

-		items.put(BundleStateMBean.IDENTIFIER, identifier);

-		items.put(BundleStateMBean.SYMBOLIC_NAME, symbolicName);

-		items.put(BundleStateMBean.VERSION, version);

-		items.put(BundleStateMBean.START_LEVEL, startLevel);

-		items.put(BundleStateMBean.STATE, state);

-		items.put(BundleStateMBean.LAST_MODIFIED, lastModified);

-		items.put(BundleStateMBean.PERSISTENTLY_STARTED, persistentlyStarted);

-		items.put(BundleStateMBean.REMOVAL_PENDING, removalPending);

-		items.put(BundleStateMBean.REQUIRED, required);

-		items.put(BundleStateMBean.FRAGMENT, fragment);

+		if((mask | CustomBundleStateMBean.LOCATION) == mask) {

+		items.put(BundleStateMBean.LOCATION, getLocation());

+		}

+//		if((mask | IDENTIFIER) == mask) {

+		items.put(BundleStateMBean.IDENTIFIER, getIdentifier());

+//		}

+		if((mask | CustomBundleStateMBean.SYMBOLIC_NAME) == mask) {

+		items.put(BundleStateMBean.SYMBOLIC_NAME, getSymbolicName());

+		}

+		if((mask | CustomBundleStateMBean.VERSION) == mask) {

+		items.put(BundleStateMBean.VERSION, getVersion());

+		}

+		if((mask | CustomBundleStateMBean.START_LEVEL) == mask) {

+		items.put(BundleStateMBean.START_LEVEL, getStartLevel());

+		}

+		if((mask | CustomBundleStateMBean.STATE) == mask) {

+		items.put(BundleStateMBean.STATE, getState());

+		}

+		if((mask | CustomBundleStateMBean.LAST_MODIFIED) == mask) {

+		items.put(BundleStateMBean.LAST_MODIFIED, getLastModified());

+		}

+		if((mask | CustomBundleStateMBean.PERSISTENTLY_STARTED) == mask) {

+		items.put(BundleStateMBean.PERSISTENTLY_STARTED, isPersistentlyStarted());

+		}

+		if((mask | CustomBundleStateMBean.REMOVAL_PENDING) == mask) {

+		items.put(BundleStateMBean.REMOVAL_PENDING, isRemovalPending());

+		}

+		if((mask | CustomBundleStateMBean.REQUIRED) == mask) {

+		items.put(BundleStateMBean.REQUIRED, isRequired());

+		}

+		if((mask | CustomBundleStateMBean.FRAGMENT) == mask) {

+		items.put(BundleStateMBean.FRAGMENT, isFragment());

+		}

+		if((mask | CustomBundleStateMBean.REGISTERED_SERVICES) == mask) {

 		items.put(BundleStateMBean.REGISTERED_SERVICES,

-				LongArrayFrom(registeredServices));

+				LongArrayFrom(getRegisteredServices()));

+		}

+		if((mask | CustomBundleStateMBean.SERVICES_IN_USE) == mask) {

 		items.put(BundleStateMBean.SERVICES_IN_USE,

-				LongArrayFrom(servicesInUse));

-		items.put(BundleStateMBean.HEADERS, headerTable(headers));

-		items.put(BundleStateMBean.EXPORTED_PACKAGES, exportedPackages);

-		items.put(BundleStateMBean.IMPORTED_PACKAGES, importedPackages);

-		items.put(BundleStateMBean.FRAGMENTS, LongArrayFrom(fragments));

-		items.put(BundleStateMBean.HOSTS, LongArrayFrom(hosts));

+				LongArrayFrom(getServicesInUse()));

+		}

+		if((mask | CustomBundleStateMBean.HEADERS) == mask) {

+		items.put(BundleStateMBean.HEADERS, headerTable(getHeaders()));

+		}

+		if((mask | CustomBundleStateMBean.EXPORTED_PACKAGES) == mask) {

+		items.put(BundleStateMBean.EXPORTED_PACKAGES, getExportedPackages());

+		}

+		if((mask | CustomBundleStateMBean.IMPORTED_PACKAGES) == mask) {

+		items.put(BundleStateMBean.IMPORTED_PACKAGES, getImportedPackages());

+		}

+		if((mask | CustomBundleStateMBean.FRAGMENTS) == mask) {

+		items.put(BundleStateMBean.FRAGMENTS, LongArrayFrom(getFragments()));

+		}

+		if((mask | CustomBundleStateMBean.HOSTS) == mask) {

+		items.put(BundleStateMBean.HOSTS, LongArrayFrom(getHosts()));

+		}

+		if((mask | CustomBundleStateMBean.REQUIRING_BUNDLES) == mask) {

 		items.put(BundleStateMBean.REQUIRING_BUNDLES,

-				LongArrayFrom(requiringBundles));

+				LongArrayFrom(getRequiringBundles()));

+		}

+		if((mask | CustomBundleStateMBean.REQUIRED_BUNDLES) == mask) {

 		items.put(BundleStateMBean.REQUIRED_BUNDLES,

-				LongArrayFrom(requiredBundles));

+				LongArrayFrom(getRequiredBundles()));

+		}

 

 		try {

-			return new CompositeDataSupport(BundleStateMBean.BUNDLE_TYPE, items);

+			return new CompositeDataSupport(OSGiBundle.computeBundleType(mask), items);

 		} catch (OpenDataException e) {

 			throw new IllegalStateException("Cannot form bundle open data", e);

 		}

@@ -378,6 +490,9 @@
 	 * 

 	 */

 	public String[] getExportedPackages() {

+		if (exportedPackages == null) {

+			exportedPackages = getBundleExportedPackages(b, admin); 

+		}

 		return exportedPackages;

 	}

 

@@ -386,6 +501,9 @@
 	 *         bundle as a host

 	 */

 	public long[] getFragments() {

+		if (fragments == null) {

+			fragments = getBundleFragments(b, admin);			

+		}

 		return fragments;

 	}

 

@@ -393,6 +511,9 @@
 	 * @return the map of headers for this bundle

 	 */

 	public Map<String, String> getHeaders() {

+		if (headers == null) {

+			headers = getBundleHeaders(b);

+		}

 		return headers;

 	}

 

@@ -400,6 +521,9 @@
 	 * @return list of identifiers of the bundles which host this fragment

 	 */

 	public long[] getHosts() {

+		if (hosts == null) {

+			hosts = Util.bundleIds(admin.getHosts(b));

+		}

 		return hosts;

 	}

 

@@ -407,6 +531,9 @@
 	 * @return the identifier of this bundle

 	 */

 	public long getIdentifier() {

+		if (identifier == 0) {

+			identifier = b.getBundleId();

+		}

 		return identifier;

 	}

 

@@ -415,6 +542,9 @@
 	 *         <packageName>;<version>

 	 */

 	public String[] getImportedPackages() {

+		if (importedPackages == null) {

+			importedPackages = getBundleImportedPackages(b, bc, admin);

+		}

 		return importedPackages;

 	}

 

@@ -422,6 +552,9 @@
 	 * @return the last modified time of this bundle

 	 */

 	public long getLastModified() {

+		if (lastModified == 0) {

+			lastModified = b.getLastModified();

+		}

 		return lastModified;

 	}

 

@@ -429,6 +562,9 @@
 	 * @return the name of this bundle

 	 */

 	public String getLocation() {

+		if (location == null) {

+			location = b.getLocation();

+		}

 		return location;

 	}

 

@@ -436,6 +572,9 @@
 	 * @return the list of identifiers of the services registered by this bundle

 	 */

 	public long[] getRegisteredServices() {

+		if (registeredServices == null) {

+			registeredServices = serviceIds(b.getRegisteredServices());

+		}

 		return registeredServices;

 	}

 

@@ -443,6 +582,9 @@
 	 * @return the list of identifiers of bundles required by this bundle

 	 */

 	public long[] getRequiredBundles() {

+		if (requiredBundles == null) {

+			requiredBundles = getDependencies(b,admin);

+		}

 		return requiredBundles;

 	}

 

@@ -450,6 +592,9 @@
 	 * @return the list of identifiers of bundles which require this bundle

 	 */

 	public long[] getRequiringBundles() {

+		if (requiringBundles == null) {

+			requiringBundles = getBundlesRequiring(b, bc, admin);

+		}

 		return requiringBundles;

 	}

 

@@ -457,6 +602,9 @@
 	 * @return the list of identifiers of services in use by this bundle

 	 */

 	public long[] getServicesInUse() {

+		if (servicesInUse == null) {

+			servicesInUse = serviceIds(b.getServicesInUse());

+		}

 		return servicesInUse;

 	}

 

@@ -464,6 +612,9 @@
 	 * @return the start level of this bundle

 	 */

 	public int getStartLevel() {

+		if (startLevel == 0) {

+			startLevel = sl.getBundleStartLevel(b);

+		}

 		return startLevel;

 	}

 

@@ -471,6 +622,9 @@
 	 * @return the state of this bundle

 	 */

 	public String getState() {

+		if (state == null) {

+			state = getBundleState(b);

+		}

 		return state;

 	}

 

@@ -478,6 +632,9 @@
 	 * @return the symbolic name of this bundle

 	 */

 	public String getSymbolicName() {

+		if (symbolicName == null) {

+			symbolicName = b.getSymbolicName();

+		}

 		return symbolicName;

 	}

 

@@ -485,6 +642,9 @@
 	 * @return the version of this bundle

 	 */

 	public String getVersion() {

+		if (version == null) {

+			version = b.getVersion().toString();

+		}

 		return version;

 	}

 

@@ -492,6 +652,9 @@
 	 * @return true if this bundle represents a fragment

 	 */

 	public boolean isFragment() {

+		if (fragment == null) {

+			fragment = isBundleFragment(b, admin);

+		}

 		return fragment;

 	}

 

@@ -499,6 +662,9 @@
 	 * @return true if this bundle is persistently started

 	 */

 	public boolean isPersistentlyStarted() {

+		if (persistentlyStarted == null) {

+			persistentlyStarted = isBundlePersistentlyStarted(b, sl);

+		}

 		return persistentlyStarted;

 	}

 

@@ -506,6 +672,9 @@
 	 * @return true if this bundle is pending removal

 	 */

 	public boolean isRemovalPending() {

+		if (removalPending == null) {

+			isRequiredBundleRemovalPending(b, bc, admin);

+		}

 		return removalPending;

 	}

 

@@ -513,6 +682,9 @@
 	 * @return true if this bundle is required

 	 */

 	public boolean isRequired() {

+		if (required == null) {

+			required = isBundleRequired(b, bc, admin);

+		}

 		return required;

 	}

 

@@ -529,7 +701,7 @@
 	}

 

 	private String[] exportedPackages;

-	private boolean fragment;

+	private Boolean fragment;

 	private long[] fragments;

 	private Map<String, String> headers;

 	private long[] hosts;

@@ -537,10 +709,10 @@
 	private String[] importedPackages;

 	private long lastModified;

 	private String location;

-	private boolean persistentlyStarted;

+	private Boolean persistentlyStarted;

 	private long[] registeredServices;

-	private boolean removalPending;

-	private boolean required;

+	private Boolean removalPending;

+	private Boolean required;

 	private long[] requiredBundles;

 	private long[] requiringBundles;

 	private long[] servicesInUse;