You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by at...@apache.org on 2009/12/03 09:55:23 UTC

svn commit: r886708 - in /incubator/aries/trunk/jmx/jmx-core/src: main/java/org/apache/aries/jmx/codec/ main/java/org/apache/aries/jmx/framework/ test/java/org/apache/aries/jmx/codec/ test/java/org/apache/aries/jmx/framework/

Author: atk
Date: Thu Dec  3 08:55:18 2009
New Revision: 886708

URL: http://svn.apache.org/viewvc?rev=886708&view=rev
Log:
ARIES-31 Implement BundleStateMBean

Added:
    incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleData.java   (with props)
    incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleEventData.java   (with props)
    incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleState.java   (with props)
    incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleStateMBeanHandler.java   (with props)
    incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/
    incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleDataTest.java   (with props)
    incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleEventDataTest.java   (with props)
    incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateMBeanHandlerTest.java   (with props)
    incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateTest.java   (with props)

Added: incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleData.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleData.java?rev=886708&view=auto
==============================================================================
--- incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleData.java (added)
+++ incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleData.java Thu Dec  3 08:55:18 2009
@@ -0,0 +1,444 @@
+/**
+ *  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.aries.jmx.codec;
+
+import static org.apache.aries.jmx.util.FrameworkUtils.getBundleDependencies;
+import static org.apache.aries.jmx.util.FrameworkUtils.getBundleExportedPackages;
+import static org.apache.aries.jmx.util.FrameworkUtils.getBundleImportedPackages;
+import static org.apache.aries.jmx.util.FrameworkUtils.getBundleState;
+import static org.apache.aries.jmx.util.FrameworkUtils.getDependentBundles;
+import static org.apache.aries.jmx.util.FrameworkUtils.getFragmentIds;
+import static org.apache.aries.jmx.util.FrameworkUtils.getHostIds;
+import static org.apache.aries.jmx.util.FrameworkUtils.getRegisteredServiceIds;
+import static org.apache.aries.jmx.util.FrameworkUtils.getServicesInUseByBundle;
+import static org.apache.aries.jmx.util.FrameworkUtils.isBundlePendingRemoval;
+import static org.apache.aries.jmx.util.FrameworkUtils.isBundleRequiredByOthers;
+import static org.apache.aries.jmx.util.TypeUtils.toLong;
+import static org.apache.aries.jmx.util.TypeUtils.toPrimitive;
+import static org.osgi.jmx.framework.BundleStateMBean.BUNDLE_TYPE;
+import static org.osgi.jmx.framework.BundleStateMBean.EXPORTED_PACKAGES;
+import static org.osgi.jmx.framework.BundleStateMBean.FRAGMENT;
+import static org.osgi.jmx.framework.BundleStateMBean.FRAGMENTS;
+import static org.osgi.jmx.framework.BundleStateMBean.HEADERS;
+import static org.osgi.jmx.framework.BundleStateMBean.HEADERS_TYPE;
+import static org.osgi.jmx.framework.BundleStateMBean.HEADER_TYPE;
+import static org.osgi.jmx.framework.BundleStateMBean.HOSTS;
+import static org.osgi.jmx.framework.BundleStateMBean.IDENTIFIER;
+import static org.osgi.jmx.framework.BundleStateMBean.IMPORTED_PACKAGES;
+import static org.osgi.jmx.framework.BundleStateMBean.KEY;
+import static org.osgi.jmx.framework.BundleStateMBean.LAST_MODIFIED;
+import static org.osgi.jmx.framework.BundleStateMBean.LOCATION;
+import static org.osgi.jmx.framework.BundleStateMBean.PERSISTENTLY_STARTED;
+import static org.osgi.jmx.framework.BundleStateMBean.REGISTERED_SERVICES;
+import static org.osgi.jmx.framework.BundleStateMBean.REMOVAL_PENDING;
+import static org.osgi.jmx.framework.BundleStateMBean.REQUIRED;
+import static org.osgi.jmx.framework.BundleStateMBean.REQUIRED_BUNDLES;
+import static org.osgi.jmx.framework.BundleStateMBean.REQUIRING_BUNDLES;
+import static org.osgi.jmx.framework.BundleStateMBean.SERVICES_IN_USE;
+import static org.osgi.jmx.framework.BundleStateMBean.START_LEVEL;
+import static org.osgi.jmx.framework.BundleStateMBean.STATE;
+import static org.osgi.jmx.framework.BundleStateMBean.SYMBOLIC_NAME;
+import static org.osgi.jmx.framework.BundleStateMBean.VALUE;
+import static org.osgi.jmx.framework.BundleStateMBean.VERSION;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.JMRuntimeException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.osgi.framework.Bundle;
+import org.osgi.jmx.framework.BundleStateMBean;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.startlevel.StartLevel;
+
+/**
+ * <p>
+ * <tt>BundleData</tt> represents BundleData Type @see {@link BundleStateMBean#BUNDLE_TYPE}. It is a codec for the
+ * <code>CompositeData</code> representing an OSGi BundleData.
+ * </p>
+ * 
+ * @version $Rev$ $Date$
+ */
+public class BundleData {
+
+    /**
+     * @see BundleStateMBean#EXPORTED_PACKAGES_ITEM
+     */
+    private String[] exportedPackages;
+
+    /**
+     * @see BundleStateMBean#FRAGMENT_ITEM
+     */
+    private boolean fragment;
+
+    /**
+     * @see BundleStateMBean#FRAGMENTS_ITEM
+     */
+    private long[] fragments;
+
+    /**
+     * @see BundleStateMBean#HEADER_TYPE
+     */
+    private List<Header> headers = new ArrayList<Header>();
+
+    /**
+     * @see BundleStateMBean#HOSTS_ITEM
+     */
+    private long[] hosts;
+
+    /**
+     * @see BundleStateMBean#IDENTIFIER_ITEM
+     */
+    private long identifier;
+
+    /**
+     * @see BundleStateMBean#IMPORTED_PACKAGES_ITEM
+     */
+    private String[] importedPackages;
+
+    /**
+     * @see BundleStateMBean#LAST_MODIFIED_ITEM
+     */
+    private long lastModified;
+
+    /**
+     * @see BundleStateMBean#LOCATION_ITEM
+     */
+    private String location;
+
+    /**
+     * @see BundleStateMBean#PERSISTENTLY_STARTED_ITEM
+     */
+    private boolean persistentlyStarted;
+
+    /**
+     * @see BundleStateMBean#REGISTERED_SERVICES_ITEM
+     */
+    private long[] registeredServices;
+
+    /**
+     * @see BundleStateMBean#REMOVAL_PENDING_ITEM
+     */
+    private boolean removalPending;
+
+    /**
+     * @see BundleStateMBean#REQUIRED_ITEM
+     */
+    private boolean required;
+
+    /**
+     * @see BundleStateMBean#REQUIRED_BUNDLES_ITEM
+     */
+    private long[] requiredBundles;
+
+    /**
+     * @see BundleStateMBean#REQUIRING_BUNDLES_ITEM
+     */
+    private long[] requiringBundles;
+
+    /**
+     * @see BundleStateMBean#SERVICES_IN_USE_ITEM
+     */
+    private long[] servicesInUse;
+
+    /**
+     * @see BundleStateMBean#START_LEVEL_ITEM
+     */
+    private int bundleStartLevel;
+
+    /**
+     * @see BundleStateMBean#STATE_ITEM
+     */
+    private String state;
+
+    /**
+     * @see BundleStateMBean#SYMBOLIC_NAME_ITEM
+     */
+    private String symbolicName;
+
+    /**
+     * @see BundleStateMBean#VERSION_ITEM
+     */
+    private String version;
+
+    private BundleData() {
+        super();
+    }
+
+    @SuppressWarnings("unchecked")
+    public BundleData(Bundle bundle, PackageAdmin packageAdmin, StartLevel startLevel) {
+        if (bundle == null) {
+            throw new IllegalArgumentException("Argument bundle cannot be null");
+        }
+        if (packageAdmin == null || startLevel == null) {
+            throw new IllegalArgumentException("Arguments PackageAdmin / startLevel cannot be null");
+        }
+        this.exportedPackages = getBundleExportedPackages(bundle, packageAdmin);
+        this.fragment = (PackageAdmin.BUNDLE_TYPE_FRAGMENT == packageAdmin.getBundleType(bundle));
+        this.fragments = getFragmentIds(bundle, packageAdmin);
+        Dictionary<String, String> bundleHeaders = bundle.getHeaders();
+        Enumeration<String> keys = bundleHeaders.keys();
+        while (keys.hasMoreElements()) {
+            String key = keys.nextElement();
+            headers.add(new Header(key, bundleHeaders.get(key)));
+        }
+        this.hosts = getHostIds(bundle, packageAdmin);
+        this.identifier = bundle.getBundleId();
+        this.importedPackages = getBundleImportedPackages(bundle, packageAdmin);
+        this.lastModified = bundle.getLastModified();
+        this.location = bundle.getLocation();
+        this.persistentlyStarted = startLevel.isBundlePersistentlyStarted(bundle);
+        this.registeredServices = getRegisteredServiceIds(bundle);
+        this.removalPending = isBundlePendingRemoval(bundle, packageAdmin);
+        this.required = isBundleRequiredByOthers(bundle, packageAdmin);
+        this.requiredBundles = getBundleDependencies(bundle, packageAdmin);
+        this.requiringBundles = getDependentBundles(bundle, packageAdmin);
+        this.servicesInUse = getServicesInUseByBundle(bundle);
+        this.bundleStartLevel = startLevel.getBundleStartLevel(bundle);
+        this.state = getBundleState(bundle);
+        this.symbolicName = bundle.getSymbolicName();
+        this.version = bundle.getVersion().toString();
+    }
+
+    /**
+     * Returns CompositeData representing a BundleData complete state typed by {@link BundleStateMBean#BUNDLE_TYPE}
+     * 
+     * @return
+     */
+    public CompositeData toCompositeData() {
+        CompositeData result = null;
+        Map<String, Object> items = new HashMap<String, Object>();
+        items.put(EXPORTED_PACKAGES, this.exportedPackages);
+        items.put(FRAGMENT, this.fragment);
+        items.put(FRAGMENTS, toLong(this.fragments));
+        items.put(HOSTS, toLong(this.hosts));
+        items.put(IDENTIFIER, this.identifier);
+        items.put(IMPORTED_PACKAGES, this.importedPackages);
+        items.put(LAST_MODIFIED, this.lastModified);
+        items.put(LOCATION, this.location);
+        items.put(PERSISTENTLY_STARTED, this.persistentlyStarted);
+        items.put(REGISTERED_SERVICES, toLong(this.registeredServices));
+        items.put(REMOVAL_PENDING, this.removalPending);
+        items.put(REQUIRED, this.required);
+        items.put(REQUIRED_BUNDLES, toLong(this.requiredBundles));
+        items.put(REQUIRING_BUNDLES, toLong(this.requiringBundles));
+        items.put(SERVICES_IN_USE, toLong(this.servicesInUse));
+        items.put(START_LEVEL, this.bundleStartLevel);
+        items.put(STATE, this.state);
+        items.put(SYMBOLIC_NAME, this.symbolicName);
+        items.put(VERSION, this.version);
+        TabularData headerTable = new TabularDataSupport(HEADERS_TYPE);
+        for (Header header : this.headers) {
+            headerTable.put(header.toCompositeData());
+        }
+        items.put(HEADERS, headerTable);
+        try {
+            result = new CompositeDataSupport(BUNDLE_TYPE, items);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Failed to create CompositeData for BundleData [" + this.identifier
+                    + "]", e);
+        }
+        return result;
+    }
+
+    /**
+     * Constructs a <code>BundleData</code> object from the given <code>CompositeData</code>
+     * 
+     * @param compositeData
+     * @return
+     * @throws IlleglArgumentException
+     *             if compositeData is null or not of type {@link BundleStateMBean#BUNDLE_TYPE}
+     */
+    @SuppressWarnings("unchecked")
+    public static BundleData from(CompositeData compositeData) throws IllegalArgumentException {
+        if (compositeData == null) {
+            throw new IllegalArgumentException("Argument compositeData cannot be null");
+        }
+        if (!compositeData.getCompositeType().equals(BUNDLE_TYPE)) {
+            throw new IllegalArgumentException("Invalid CompositeType [" + compositeData.getCompositeType() + "]");
+        }
+        BundleData bundleData = new BundleData();
+        bundleData.exportedPackages = (String[]) compositeData.get(EXPORTED_PACKAGES);
+        bundleData.fragment = (Boolean) compositeData.get(FRAGMENT);
+        bundleData.fragments = toPrimitive((Long[]) compositeData.get(FRAGMENTS));
+        bundleData.hosts = toPrimitive((Long[]) compositeData.get(HOSTS));
+        bundleData.identifier = (Long) compositeData.get(IDENTIFIER);
+        bundleData.importedPackages = (String[]) compositeData.get(IMPORTED_PACKAGES);
+        bundleData.lastModified = (Long) compositeData.get(LAST_MODIFIED);
+        bundleData.location = (String) compositeData.get(LOCATION);
+        bundleData.persistentlyStarted = (Boolean) compositeData.get(PERSISTENTLY_STARTED);
+        bundleData.registeredServices = toPrimitive((Long[]) compositeData.get(REGISTERED_SERVICES));
+        bundleData.removalPending = (Boolean) compositeData.get(REMOVAL_PENDING);
+        bundleData.required = (Boolean) compositeData.get(REQUIRED);
+        bundleData.requiredBundles = toPrimitive((Long[]) compositeData.get(REQUIRED_BUNDLES));
+        bundleData.requiringBundles = toPrimitive((Long[]) compositeData.get(REQUIRING_BUNDLES));
+        bundleData.servicesInUse = toPrimitive((Long[]) compositeData.get(SERVICES_IN_USE));
+        bundleData.bundleStartLevel = (Integer) compositeData.get(START_LEVEL);
+        bundleData.state = (String) compositeData.get(STATE);
+        bundleData.symbolicName = (String) compositeData.get(SYMBOLIC_NAME);
+        bundleData.version = (String) compositeData.get(VERSION);
+        TabularData headerTable = (TabularData) compositeData.get(HEADERS);
+        Collection<CompositeData> headerData = (Collection<CompositeData>) headerTable.values();
+        for (CompositeData headerRow : headerData) {
+            bundleData.headers.add(Header.from(headerRow));
+        }
+        return bundleData;
+    }
+
+    public String[] getExportedPackages() {
+        return exportedPackages;
+    }
+
+    public boolean isFragment() {
+        return fragment;
+    }
+
+    public long[] getFragments() {
+        return fragments;
+    }
+
+    public List<Header> getHeaders() {
+        return headers;
+    }
+
+    public long[] getHosts() {
+        return hosts;
+    }
+
+    public long getIdentifier() {
+        return identifier;
+    }
+
+    public String[] getImportedPackages() {
+        return importedPackages;
+    }
+
+    public long getLastModified() {
+        return lastModified;
+    }
+
+    public String getLocation() {
+        return location;
+    }
+
+    public boolean isPersistentlyStarted() {
+        return persistentlyStarted;
+    }
+
+    public long[] getRegisteredServices() {
+        return registeredServices;
+    }
+
+    public boolean isRemovalPending() {
+        return removalPending;
+    }
+
+    public boolean isRequired() {
+        return required;
+    }
+
+    public long[] getRequiredBundles() {
+        return requiredBundles;
+    }
+
+    public long[] getRequiringBundles() {
+        return requiringBundles;
+    }
+
+    public long[] getServicesInUse() {
+        return servicesInUse;
+    }
+
+    public int getBundleStartLevel() {
+        return bundleStartLevel;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public String getSymbolicName() {
+        return symbolicName;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    /*
+     * Represents key/value pair in BundleData headers
+     */
+    public static class Header {
+
+        private String key;
+        private String value;
+
+        public String getKey() {
+            return key;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        private Header() {
+            super();
+        }
+
+        public Header(String key, String value) {
+            this.key = key;
+            this.value = value;
+        }
+
+        public CompositeData toCompositeData() throws JMRuntimeException {
+            CompositeData result = null;
+            Map<String, Object> items = new HashMap<String, Object>();
+            items.put(KEY, key);
+            items.put(VALUE, value);
+            try {
+                result = new CompositeDataSupport(HEADER_TYPE, items);
+            } catch (OpenDataException e) {
+                throw new JMRuntimeException("Failed to create CompositeData for header [" + key + ":" + value + "] - "
+                        + e.getMessage());
+            }
+            return result;
+        }
+
+        public static Header from(CompositeData compositeData) {
+            if (compositeData == null) {
+                throw new IllegalArgumentException("Argument compositeData cannot be null");
+            }
+            if (!compositeData.getCompositeType().equals(HEADER_TYPE)) {
+                throw new IllegalArgumentException("Invalid CompositeType [" + compositeData.getCompositeType() + "]");
+            }
+            Header header = new Header();
+            header.key = (String) compositeData.get(KEY);
+            header.value = (String) compositeData.get(VALUE);
+            return header;
+        }
+    }
+}

Propchange: incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleData.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleData.java
------------------------------------------------------------------------------
    svn:keywords = Revision Date

Added: incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleEventData.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleEventData.java?rev=886708&view=auto
==============================================================================
--- incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleEventData.java (added)
+++ incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleEventData.java Thu Dec  3 08:55:18 2009
@@ -0,0 +1,137 @@
+/**
+ *  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.aries.jmx.codec;
+
+import static org.osgi.jmx.framework.BundleStateMBean.BUNDLE_EVENT_TYPE;
+import static org.osgi.jmx.framework.BundleStateMBean.EVENT;
+import static org.osgi.jmx.framework.BundleStateMBean.IDENTIFIER;
+import static org.osgi.jmx.framework.BundleStateMBean.LOCATION;
+import static org.osgi.jmx.framework.BundleStateMBean.SYMBOLIC_NAME;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.OpenDataException;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.jmx.framework.BundleStateMBean;
+
+/**
+ * <p>
+ * <tt>BundleEventData</tt> represents BundleEvent Type @see {@link BundleStateMBean#BUNDLE_EVENT_TYPE}. It is a codec
+ * for the <code>CompositeData</code> representing an OSGi BundleEvent.
+ * </p>
+ * 
+ * @version $Rev$ $Date$
+ */
+public class BundleEventData {
+
+    /**
+     * @see BundleStateMBean#IDENTIFIER_ITEM
+     */
+    private long bundleId;
+
+    /**
+     * @see BundleStateMBean#LOCATION_ITEM
+     */
+    private String location;
+
+    /**
+     * @see BundleStateMBean#SYMBOLIC_NAME_ITEM
+     */
+    private String bundleSymbolicName;
+
+    /**
+     * @see BundleStateMBean#EVENT_ITEM
+     */
+    private int eventType;
+
+    private BundleEventData() {
+        super();
+    }
+
+    public BundleEventData(BundleEvent bundleEvent) {
+        this.eventType = bundleEvent.getType();
+        Bundle bundle = bundleEvent.getBundle();
+        this.bundleId = bundle.getBundleId();
+        this.location = bundle.getLocation();
+        this.bundleSymbolicName = bundle.getSymbolicName();
+    }
+
+    /**
+     * Returns CompositeData representing a BundleEvent typed by {@link BundleStateMBean#BUNDLE_EVENT_TYPE}
+     * 
+     * @return
+     */
+    public CompositeData toCompositeData() {
+        CompositeData result = null;
+        Map<String, Object> items = new HashMap<String, Object>();
+        items.put(IDENTIFIER, this.bundleId);
+        items.put(SYMBOLIC_NAME, this.bundleSymbolicName);
+        items.put(LOCATION, this.location);
+        items.put(EVENT, this.eventType);
+        try {
+            result = new CompositeDataSupport(BUNDLE_EVENT_TYPE, items);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Failed to create CompositeData for BundleEvent for Bundle ["
+                    + this.bundleId + "]", e);
+        }
+        return result;
+    }
+
+    /**
+     * Returns a <code>BundleEventData</code> representation of the given compositeData
+     * 
+     * @param compositeData
+     * @return
+     * @throws IllegalArgumentException
+     *             if the compositeData is null or incorrect type
+     */
+    public static BundleEventData from(CompositeData compositeData) throws IllegalArgumentException {
+        BundleEventData eventData = new BundleEventData();
+        if (compositeData == null) {
+            throw new IllegalArgumentException("Argument compositeData cannot be null");
+        }
+        if (!compositeData.getCompositeType().equals(BUNDLE_EVENT_TYPE)) {
+            throw new IllegalArgumentException("Invalid CompositeType [" + compositeData.getCompositeType() + "]");
+        }
+        eventData.bundleId = (Long) compositeData.get(IDENTIFIER);
+        eventData.bundleSymbolicName = (String) compositeData.get(SYMBOLIC_NAME);
+        eventData.eventType = (Integer) compositeData.get(EVENT);
+        eventData.location = (String) compositeData.get(LOCATION);
+        return eventData;
+    }
+
+    public long getBundleId() {
+        return bundleId;
+    }
+
+    public String getLocation() {
+        return location;
+    }
+
+    public String getBundleSymbolicName() {
+        return bundleSymbolicName;
+    }
+
+    public int getEventType() {
+        return eventType;
+    }
+}

Propchange: incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleEventData.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/codec/BundleEventData.java
------------------------------------------------------------------------------
    svn:keywords = Revision Date

Added: incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleState.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleState.java?rev=886708&view=auto
==============================================================================
--- incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleState.java (added)
+++ incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleState.java Thu Dec  3 08:55:18 2009
@@ -0,0 +1,350 @@
+/**
+ *  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.aries.jmx.framework;
+
+import static org.apache.aries.jmx.util.FrameworkUtils.getBundleDependencies;
+import static org.apache.aries.jmx.util.FrameworkUtils.getBundleExportedPackages;
+import static org.apache.aries.jmx.util.FrameworkUtils.getBundleImportedPackages;
+import static org.apache.aries.jmx.util.FrameworkUtils.getBundleState;
+import static org.apache.aries.jmx.util.FrameworkUtils.getDependentBundles;
+import static org.apache.aries.jmx.util.FrameworkUtils.getFragmentIds;
+import static org.apache.aries.jmx.util.FrameworkUtils.getHostIds;
+import static org.apache.aries.jmx.util.FrameworkUtils.getRegisteredServiceIds;
+import static org.apache.aries.jmx.util.FrameworkUtils.getServicesInUseByBundle;
+import static org.apache.aries.jmx.util.FrameworkUtils.isBundlePendingRemoval;
+import static org.apache.aries.jmx.util.FrameworkUtils.isBundleRequiredByOthers;
+import static org.apache.aries.jmx.util.FrameworkUtils.resolveBundle;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.ObjectName;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.aries.jmx.Logger;
+import org.apache.aries.jmx.codec.BundleData;
+import org.apache.aries.jmx.codec.BundleEventData;
+import org.apache.aries.jmx.codec.BundleData.Header;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.jmx.framework.BundleStateMBean;
+import org.osgi.service.log.LogService;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.startlevel.StartLevel;
+
+/**
+ * Implementation of <code>BundleStateMBean</code> which emits JMX <code>Notification</code>
+ * on <code>Bundle</code> state changes
+ * 
+ * @version $Rev$ $Date$
+ */
+public class BundleState extends NotificationBroadcasterSupport implements BundleStateMBean, MBeanRegistration {
+
+    protected Logger logger;
+    protected BundleContext bundleContext;
+    protected PackageAdmin packageAdmin;
+    protected StartLevel startLevel;
+
+    protected ExecutorService eventDispatcher;
+    protected BundleListener bundleListener;
+    private AtomicInteger notificationSequenceNumber = new AtomicInteger(1);
+    private Lock lock = new ReentrantLock();
+    private AtomicInteger registrations = new AtomicInteger(0);
+
+    // notification type description
+    public static String BUNDLE_EVENT = "org.osgi.bundle.event";
+
+    public BundleState(BundleContext bundleContext, PackageAdmin packageAdmin, StartLevel startLevel, Logger logger) {
+        this.bundleContext = bundleContext;
+        this.packageAdmin = packageAdmin;
+        this.startLevel = startLevel;
+        this.logger = logger;
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getExportedPackages(long)
+     */
+    public String[] getExportedPackages(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return getBundleExportedPackages(bundle, packageAdmin);
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getFragments(long)
+     */
+    public long[] getFragments(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return getFragmentIds(bundle, packageAdmin);
+    }
+
+    /**
+     *  @see org.osgi.jmx.framework.BundleStateMBean#getHeaders(long)
+     */
+    @SuppressWarnings("unchecked")
+    public TabularData getHeaders(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        List<Header> headers = new ArrayList<Header>();
+        Dictionary<String, String> bundleHeaders = bundle.getHeaders();
+        Enumeration<String> keys = bundleHeaders.keys();
+        while (keys.hasMoreElements()) {
+            String key = keys.nextElement();
+            headers.add(new Header(key, bundleHeaders.get(key)));
+        }
+        TabularData headerTable = new TabularDataSupport(HEADERS_TYPE);
+        for (Header header : headers) {
+            headerTable.put(header.toCompositeData());
+        }
+        return headerTable;
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getHosts(long)
+     */
+    public long[] getHosts(long fragmentId) throws IOException, IllegalArgumentException {
+        Bundle fragment = resolveBundle(bundleContext, fragmentId);
+        return getHostIds(fragment, packageAdmin);
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getImportedPackages(long)
+     */
+    public String[] getImportedPackages(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return getBundleImportedPackages(bundle, packageAdmin);
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getLastModified(long)
+     */
+    public long getLastModified(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return bundle.getLastModified();
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getLocation(long)
+     */
+    public String getLocation(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return bundle.getLocation();
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getRegisteredServices(long)
+     */
+    public long[] getRegisteredServices(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return getRegisteredServiceIds(bundle);
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getRequiredBundles(long)
+     */
+    public long[] getRequiredBundles(long bundleIdentifier) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleIdentifier);
+        return getBundleDependencies(bundle, packageAdmin);
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getRequiringBundles(long)
+     */
+    public long[] getRequiringBundles(long bundleIdentifier) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleIdentifier);
+        return getDependentBundles(bundle, packageAdmin);
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getServicesInUse(long)
+     */
+    public long[] getServicesInUse(long bundleIdentifier) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleIdentifier);
+        return getServicesInUseByBundle(bundle);
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getStartLevel(long)
+     */
+    public int getStartLevel(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return startLevel.getBundleStartLevel(bundle);
+    }
+
+    /** 
+     * @see org.osgi.jmx.framework.BundleStateMBean#getState(long)
+     */
+    public String getState(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return getBundleState(bundle);
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getSymbolicName(long)
+     */
+    public String getSymbolicName(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return bundle.getSymbolicName();
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#getVersion(long)
+     */
+    public String getVersion(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return bundle.getVersion().toString();
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#isFragment(long)
+     */
+    public boolean isFragment(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return (PackageAdmin.BUNDLE_TYPE_FRAGMENT == packageAdmin.getBundleType(bundle));
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#isPersistentlyStarted(long)
+     */
+    public boolean isPersistentlyStarted(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return startLevel.isBundlePersistentlyStarted(bundle);
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#isRemovalPending(long)
+     */
+    public boolean isRemovalPending(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return isBundlePendingRemoval(bundle, packageAdmin);
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#isRequired(long)
+     */
+    public boolean isRequired(long bundleId) throws IOException, IllegalArgumentException {
+        Bundle bundle = resolveBundle(bundleContext, bundleId);
+        return isBundleRequiredByOthers(bundle, packageAdmin);
+    }
+
+    /**
+     * @see org.osgi.jmx.framework.BundleStateMBean#listBundles()
+     */
+    public TabularData listBundles() throws IOException {
+        Bundle[] containerBundles = bundleContext.getBundles();
+        List<BundleData> bundleDatas = new ArrayList<BundleData>();
+        for (Bundle containerBundle : containerBundles) {
+            bundleDatas.add(new BundleData(containerBundle, packageAdmin, startLevel));
+        }
+        TabularData bundleTable = new TabularDataSupport(BUNDLES_TYPE);
+        for (BundleData bundleData : bundleDatas) {
+            bundleTable.put(bundleData.toCompositeData());
+        }
+        return bundleTable;
+    }
+
+    /**
+     * @see javax.management.NotificationBroadcasterSupport#getNotificationInfo()
+     */
+    public MBeanNotificationInfo[] getNotificationInfo() {
+        String[] types = new String[] { BUNDLE_EVENT };
+        String name = Notification.class.getName();
+        String description = "A BundleEvent issued from the Framework describing a bundle lifecycle change";
+        MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description);
+        return new MBeanNotificationInfo[] { info };
+    }
+
+    /**
+     * @see javax.management.MBeanRegistration#postDeregister()
+     */
+    public void postDeregister() {
+        if (registrations.decrementAndGet() < 1) {
+            bundleContext.removeBundleListener(bundleListener);
+            eventDispatcher.shutdown();
+        }
+    }
+
+    /**
+     * @see javax.management.MBeanRegistration#postRegister(java.lang.Boolean)
+     */
+    public void postRegister(Boolean registrationDone) {
+            if (registrationDone && registrations.incrementAndGet() == 1) {
+                eventDispatcher = Executors.newSingleThreadExecutor();
+                bundleContext.addBundleListener(bundleListener);
+            } 
+    }
+
+    /**
+     * @see javax.management.MBeanRegistration#preDeregister()
+     */
+    public void preDeregister() throws Exception {
+        // No action
+    }
+
+    /**
+     * @see javax.management.MBeanRegistration#preRegister(javax.management.MBeanServer, javax.management.ObjectName)
+     */
+    public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
+        lock.lock();
+        try {
+            if (bundleListener == null) {
+                bundleListener = new BundleListener() {
+                    public void bundleChanged(BundleEvent event) {
+                        final Notification notification = new Notification(EVENT, OBJECTNAME, notificationSequenceNumber
+                                .getAndIncrement());
+                        try {
+                            notification.setUserData(new BundleEventData(event).toCompositeData());
+                            eventDispatcher.submit(new Runnable() {
+                                public void run() {
+                                    sendNotification(notification);
+                                }
+                            });
+                        } catch (Exception e) {
+                            logger.log(LogService.LOG_WARNING, "Exception occured on JMX Notification dispatch for event ["
+                                    + event + "]", e);
+                        }
+                    }
+                };
+            }
+        } finally {
+            lock.unlock();
+        }  
+        return name;
+    }
+
+    /*
+     * Returns the ExecutorService used to dispatch Notifications
+     */
+    public ExecutorService getEventDispatcher() {
+        return eventDispatcher;
+    }
+    
+}

Propchange: incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleState.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleState.java
------------------------------------------------------------------------------
    svn:keywords = Revision Date

Added: incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleStateMBeanHandler.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleStateMBeanHandler.java?rev=886708&view=auto
==============================================================================
--- incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleStateMBeanHandler.java (added)
+++ incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleStateMBeanHandler.java Thu Dec  3 08:55:18 2009
@@ -0,0 +1,115 @@
+/**
+ *  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.aries.jmx.framework;
+
+import static org.osgi.jmx.framework.BundleStateMBean.OBJECTNAME;
+
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+
+import org.apache.aries.jmx.Logger;
+import org.apache.aries.jmx.MBeanHandler;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.jmx.framework.BundleStateMBean;
+import org.osgi.service.log.LogService;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.startlevel.StartLevel;
+
+/**
+ * <p>
+ * Implementation of <code>MBeanHandler</code> which manages the <code>BundleState</code>
+ * MBean implementation
+ * @see MBeanHandler
+ * </p> 
+ *
+ * @version $Rev$ $Date$
+ */
+public class BundleStateMBeanHandler implements MBeanHandler {
+
+    private Logger logger;
+    private String name;
+    private StandardMBean mbean;
+    private BundleContext bundleContext;
+    private ServiceReference packageAdminRef;
+    private ServiceReference startLevelRef;
+    
+    
+    public BundleStateMBeanHandler(BundleContext bundleContext, Logger logger) {
+        this.bundleContext = bundleContext;
+        this.logger = logger;
+        this.name = OBJECTNAME;
+    }
+    
+    /**
+     * @see org.apache.aries.jmx.MBeanHandler#open()
+     */
+    public void open() {
+        packageAdminRef = bundleContext.getServiceReference(PackageAdmin.class.getName());
+        PackageAdmin packageAdmin = (PackageAdmin) bundleContext.getService(packageAdminRef);
+        startLevelRef = bundleContext.getServiceReference(StartLevel.class.getName());
+        StartLevel startLevel = (StartLevel) bundleContext.getService(startLevelRef);
+        BundleStateMBean bundleStateMBean = new BundleState(bundleContext, packageAdmin, startLevel, logger);
+        try {
+            mbean = new RegistrableStandardEmitterMBean(bundleStateMBean, BundleStateMBean.class);
+        } catch (NotCompliantMBeanException e) {
+            logger.log(LogService.LOG_ERROR, "Failed to instantiate MBean for " + BundleStateMBean.class.getName(), e);
+        }
+    }
+    
+    /**
+     * @see org.apache.aries.jmx.MBeanHandler#getMbean()
+     */
+    public StandardMBean getMbean() {
+       return mbean;
+    }
+    
+
+    /**
+     * @see org.apache.aries.jmx.MBeanHandler#getName()
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @see org.apache.aries.jmx.MBeanHandler#close()
+     */
+    public void close() {
+        if (packageAdminRef != null) {
+            try {
+                bundleContext.ungetService(packageAdminRef);
+            } catch (RuntimeException e) {
+                logger.log(LogService.LOG_WARNING, "Exception occured during cleanup", e);
+            }
+            packageAdminRef = null;
+        }
+        if (startLevelRef != null) {
+            try {
+                bundleContext.ungetService(startLevelRef);
+            } catch (RuntimeException e) {
+                logger.log(LogService.LOG_WARNING, "Exception occured during cleanup", e);
+            }
+            startLevelRef = null;
+        }
+    }
+
+   
+
+   
+
+}

Propchange: incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleStateMBeanHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/aries/trunk/jmx/jmx-core/src/main/java/org/apache/aries/jmx/framework/BundleStateMBeanHandler.java
------------------------------------------------------------------------------
    svn:keywords = Revision Date

Added: incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleDataTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleDataTest.java?rev=886708&view=auto
==============================================================================
--- incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleDataTest.java (added)
+++ incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleDataTest.java Thu Dec  3 08:55:18 2009
@@ -0,0 +1,238 @@
+/**
+ *  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.aries.jmx.codec;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.osgi.jmx.framework.BundleStateMBean.BUNDLE_TYPE;
+import static org.osgi.jmx.framework.BundleStateMBean.EXPORTED_PACKAGES;
+import static org.osgi.jmx.framework.BundleStateMBean.FRAGMENT;
+import static org.osgi.jmx.framework.BundleStateMBean.FRAGMENTS;
+import static org.osgi.jmx.framework.BundleStateMBean.HEADERS;
+import static org.osgi.jmx.framework.BundleStateMBean.HEADERS_TYPE;
+import static org.osgi.jmx.framework.BundleStateMBean.HEADER_TYPE;
+import static org.osgi.jmx.framework.BundleStateMBean.HOSTS;
+import static org.osgi.jmx.framework.BundleStateMBean.IDENTIFIER;
+import static org.osgi.jmx.framework.BundleStateMBean.IMPORTED_PACKAGES;
+import static org.osgi.jmx.framework.BundleStateMBean.KEY;
+import static org.osgi.jmx.framework.BundleStateMBean.LAST_MODIFIED;
+import static org.osgi.jmx.framework.BundleStateMBean.LOCATION;
+import static org.osgi.jmx.framework.BundleStateMBean.PERSISTENTLY_STARTED;
+import static org.osgi.jmx.framework.BundleStateMBean.REGISTERED_SERVICES;
+import static org.osgi.jmx.framework.BundleStateMBean.REMOVAL_PENDING;
+import static org.osgi.jmx.framework.BundleStateMBean.REQUIRED;
+import static org.osgi.jmx.framework.BundleStateMBean.REQUIRED_BUNDLES;
+import static org.osgi.jmx.framework.BundleStateMBean.REQUIRING_BUNDLES;
+import static org.osgi.jmx.framework.BundleStateMBean.SERVICES_IN_USE;
+import static org.osgi.jmx.framework.BundleStateMBean.START_LEVEL;
+import static org.osgi.jmx.framework.BundleStateMBean.STATE;
+import static org.osgi.jmx.framework.BundleStateMBean.SYMBOLIC_NAME;
+import static org.osgi.jmx.framework.BundleStateMBean.VALUE;
+import static org.osgi.jmx.framework.BundleStateMBean.VERSION;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.aries.jmx.codec.BundleData;
+import org.apache.aries.jmx.codec.BundleData.Header;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.packageadmin.RequiredBundle;
+import org.osgi.service.startlevel.StartLevel;
+
+/**
+ * 
+ *
+ * @version $Rev$ $Date$
+ */
+public class BundleDataTest {
+
+    
+    @Test
+    public void testToCompositeData() throws Exception {
+        
+        Bundle bundle = mock(Bundle.class);
+        BundleContext context = mock(BundleContext.class);
+        PackageAdmin packageAdmin = mock(PackageAdmin.class);
+        StartLevel startLevel = mock(StartLevel.class);
+        
+        Bundle b1 = mock(Bundle.class);
+        when(b1.getSymbolicName()).thenReturn("b1");
+        when(b1.getBundleId()).thenReturn(new Long(44));
+        Bundle b2 = mock(Bundle.class);
+        when(b2.getSymbolicName()).thenReturn("b2");
+        when(b2.getBundleId()).thenReturn(new Long(55));
+        Bundle b3 = mock(Bundle.class);
+        when(b3.getSymbolicName()).thenReturn("b3");
+        when(b3.getBundleId()).thenReturn(new Long(66));
+        when(context.getBundles()).thenReturn(new Bundle[] { bundle, b1, b2, b3 });
+      
+        when(bundle.getSymbolicName()).thenReturn("test");
+        when(bundle.getVersion()).thenReturn(Version.emptyVersion);
+        when(bundle.getBundleId()).thenReturn(new Long(1));
+        when(bundle.getBundleContext()).thenReturn(context);
+        when(bundle.getLastModified()).thenReturn(new Long(12345));
+        when(bundle.getLocation()).thenReturn("location");
+        
+        //headers
+        Dictionary<String, String> headers = new Hashtable<String, String>();
+        headers.put(Constants.BUNDLE_SYMBOLICNAME, "test");
+        headers.put(Constants.BUNDLE_VERSION, "0.0.0");
+        when(bundle.getHeaders()).thenReturn(headers);
+        
+        //exported packages
+        ExportedPackage exported = mock(ExportedPackage.class);
+        when(exported.getName()).thenReturn("org.apache.aries.jmx");
+        when(exported.getVersion()).thenReturn(new Version("1.0.0"));
+        when(packageAdmin.getExportedPackages(bundle)).thenReturn(new ExportedPackage[] { exported });
+        
+        //imported packages
+        ExportedPackage ep1 = mock(ExportedPackage.class);
+        when(ep1.getImportingBundles()).thenReturn(new Bundle[] { bundle, b2, b3 });
+        when(ep1.getName()).thenReturn("org.apache.aries.jmx.b1");
+        when(ep1.getVersion()).thenReturn(Version.emptyVersion);
+        ExportedPackage ep2 = mock(ExportedPackage.class);
+        when(ep2.getImportingBundles()).thenReturn(new Bundle[] { bundle, b3 });
+        when(ep2.getName()).thenReturn("org.apache.aries.jmx.b2");
+        when(ep2.getVersion()).thenReturn(Version.parseVersion("2.0.1"));
+  
+        when(packageAdmin.getExportedPackages(b1)).thenReturn(new ExportedPackage[] { ep1 });
+        when(packageAdmin.getExportedPackages(b2)).thenReturn(new ExportedPackage[] { ep2 });
+        when(packageAdmin.getExportedPackages(b3)).thenReturn(null);
+        
+        //required bundles
+        RequiredBundle rb1 = mock(RequiredBundle.class);
+        when(rb1.getBundle()).thenReturn(b1);
+        when(rb1.getRequiringBundles()).thenReturn(new Bundle[] { bundle, b2 });
+        RequiredBundle rb2 = mock(RequiredBundle.class);
+        when(rb2.getBundle()).thenReturn(b2);
+        when(rb2.getRequiringBundles()).thenReturn(new Bundle[] { b1 });
+        RequiredBundle rb3 = mock(RequiredBundle.class);
+        when(rb3.getBundle()).thenReturn(b3);
+        when(rb3.getRequiringBundles()).thenReturn(new Bundle[] { bundle, b1, b2 });
+        
+        when(packageAdmin.getRequiredBundles("b1")).thenReturn(new RequiredBundle[] { rb1 });
+        when(packageAdmin.getRequiredBundles("b2")).thenReturn(new RequiredBundle[] { rb2 });
+        when(packageAdmin.getRequiredBundles("b3")).thenReturn(new RequiredBundle[] { rb3 });
+        
+        //services in use
+        ServiceReference s1 = mock(ServiceReference.class);
+        when(s1.getProperty(Constants.SERVICE_ID)).thenReturn(new Long(15));
+        ServiceReference s2 = mock(ServiceReference.class);
+        when(s2.getProperty(Constants.SERVICE_ID)).thenReturn(new Long(16));
+        ServiceReference s3 = mock(ServiceReference.class);
+        when(s3.getProperty(Constants.SERVICE_ID)).thenReturn(new Long(17));
+        
+        when(bundle.getServicesInUse()).thenReturn(new ServiceReference[] { s1, s2, s3 });
+        
+        BundleData b = new BundleData(bundle, packageAdmin, startLevel);
+        CompositeData compositeData = b.toCompositeData();
+        
+        assertEquals("test", compositeData.get(SYMBOLIC_NAME));
+        assertEquals("0.0.0", (String) compositeData.get(VERSION));
+        TabularData headerTable = (TabularData) compositeData.get(HEADERS);
+        assertEquals(2, headerTable.values().size());
+        assertArrayEquals(new String[] { "org.apache.aries.jmx;1.0.0"} , (String[]) compositeData.get(EXPORTED_PACKAGES));
+        assertArrayEquals(new String[] { "org.apache.aries.jmx.b1;0.0.0" , "org.apache.aries.jmx.b2;2.0.1"}, (String[]) compositeData.get(IMPORTED_PACKAGES));
+        assertArrayEquals(new Long[] { new Long(44), new Long(66) }, (Long[]) compositeData.get(REQUIRED_BUNDLES));
+        assertArrayEquals(new Long[] { new Long(15), new Long(16), new Long(17) },(Long[]) compositeData.get(SERVICES_IN_USE));
+        assertEquals("UNKNOWN", compositeData.get(STATE)); //default no return stub
+        assertEquals(0,((Long[]) compositeData.get(HOSTS)).length);
+        assertEquals(0, ((Long[]) compositeData.get(FRAGMENTS)).length);
+        
+    }
+
+   
+    @Test
+    public void testFromCompositeData() throws Exception {
+
+        Map<String, Object> items = new HashMap<String, Object>();
+        items.put(EXPORTED_PACKAGES, new String[] { "org.apache.aries.jmx;1.0.0"});
+        items.put(FRAGMENT, false);
+        items.put(FRAGMENTS, new Long[0]);
+        items.put(HOSTS, new Long[0]);
+        items.put(IDENTIFIER, new Long(3));
+        items.put(IMPORTED_PACKAGES, new String[] { "org.apache.aries.jmx.b1;0.0.0" , "org.apache.aries.jmx.b2;2.0.1"});
+        items.put(LAST_MODIFIED, new Long(8797));
+        items.put(LOCATION, "");
+        items.put(PERSISTENTLY_STARTED, false);
+        items.put(REGISTERED_SERVICES, new Long[0]);
+        items.put(REMOVAL_PENDING, false);
+        items.put(REQUIRED, true);
+        items.put(REQUIRED_BUNDLES, new Long[] { new Long(44), new Long(66) });
+        items.put(REQUIRING_BUNDLES, new Long[0]);
+        items.put(SERVICES_IN_USE, new Long[] { new Long(15), new Long(16), new Long(17) });
+        items.put(START_LEVEL, 1);
+        items.put(STATE, "ACTIVE");
+        items.put(SYMBOLIC_NAME, "test");
+        items.put(VERSION, "0.0.0");
+        TabularData headerTable = new TabularDataSupport(HEADERS_TYPE);
+        headerTable.put(new Header("a", "a").toCompositeData());
+        headerTable.put(new Header("b", "b").toCompositeData());
+        items.put(HEADERS, headerTable);
+        CompositeData compositeData = new CompositeDataSupport(BUNDLE_TYPE, items);
+        
+        BundleData b = BundleData.from(compositeData);
+        
+        assertEquals("test", b.getSymbolicName());
+        assertEquals("0.0.0", b.getVersion());
+        assertEquals(2, b.getHeaders().size());
+        assertArrayEquals(new String[] { "org.apache.aries.jmx;1.0.0"} , b.getExportedPackages());
+        assertArrayEquals(new String[] { "org.apache.aries.jmx.b1;0.0.0" , "org.apache.aries.jmx.b2;2.0.1"}, b.getImportedPackages());
+        assertArrayEquals(new long[] { 44, 66 }, b.getRequiredBundles());
+        assertArrayEquals(new long[] { 15, 16, 17 }, b.getServicesInUse());
+        assertEquals("ACTIVE", b.getState()); //default no return stub
+        assertEquals(0, b.getHosts().length);
+        assertEquals(0, b.getFragments().length);
+    }
+
+    @Test
+    public void testHeaderToCompositeData() throws Exception{
+        
+        Header h1 = new Header("a", "b");
+        CompositeData compositeData = h1.toCompositeData();
+       
+        assertEquals("a", compositeData.get(KEY));
+        assertEquals("b", compositeData.get(VALUE));
+        
+    }
+    
+    @Test
+    public void testHeaderFromCompositeData() throws Exception {
+        
+        CompositeData compositeData = new CompositeDataSupport(HEADER_TYPE, new String[] { KEY, VALUE } , new String [] { "c", "d" });
+        Header header = Header.from(compositeData);
+        assertEquals("c", header.getKey());
+        assertEquals("d", header.getValue());
+        
+    }
+}

Propchange: incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleDataTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleDataTest.java
------------------------------------------------------------------------------
    svn:keywords = Revision Date

Added: incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleEventDataTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleEventDataTest.java?rev=886708&view=auto
==============================================================================
--- incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleEventDataTest.java (added)
+++ incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleEventDataTest.java Thu Dec  3 08:55:18 2009
@@ -0,0 +1,86 @@
+/**
+ *  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.aries.jmx.codec;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+import static org.osgi.jmx.framework.BundleStateMBean.BUNDLE_EVENT_TYPE;
+import static org.osgi.jmx.framework.BundleStateMBean.EVENT;
+import static org.osgi.jmx.framework.BundleStateMBean.IDENTIFIER;
+import static org.osgi.jmx.framework.BundleStateMBean.LOCATION;
+import static org.osgi.jmx.framework.BundleStateMBean.SYMBOLIC_NAME;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+
+/**
+ * 
+ *
+ * @version $Rev$ $Date$
+ */
+public class BundleEventDataTest {
+
+   
+    @Test
+    public void testToCompositeData() throws Exception {
+
+        BundleEvent event = mock(BundleEvent.class);
+        Bundle bundle = mock(Bundle.class);
+        when(event.getBundle()).thenReturn(bundle);
+        when(bundle.getSymbolicName()).thenReturn("test");
+        when(bundle.getBundleId()).thenReturn(new Long(4));
+        when(bundle.getLocation()).thenReturn("location");
+        when(event.getType()).thenReturn(BundleEvent.INSTALLED);
+        
+        BundleEventData eventData = new BundleEventData(event);
+        CompositeData eventCompositeData = eventData.toCompositeData();
+        
+        assertEquals(new Long(4), (Long) eventCompositeData.get(IDENTIFIER));
+        assertEquals("test", (String) eventCompositeData.get(SYMBOLIC_NAME));
+        assertEquals(new Integer(BundleEvent.INSTALLED),  (Integer) eventCompositeData.get(EVENT));
+        assertEquals("location",  (String) eventCompositeData.get(LOCATION));
+        
+    }
+
+    
+    @Test
+    public void testFrom() throws Exception {
+
+        Map<String, Object> items = new HashMap<String, Object>();
+        items.put(IDENTIFIER, new Long(7));
+        items.put(SYMBOLIC_NAME, "t");
+        items.put(LOCATION, "l");
+        items.put(EVENT, BundleEvent.RESOLVED);
+
+        CompositeData compositeData = new CompositeDataSupport(BUNDLE_EVENT_TYPE, items);
+        BundleEventData event = BundleEventData.from(compositeData);
+        
+        assertEquals(7, event.getBundleId());
+        assertEquals("t", event.getBundleSymbolicName());
+        assertEquals("l", event.getLocation());
+        assertEquals(BundleEvent.RESOLVED, event.getEventType());
+            
+    }
+
+}

Propchange: incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleEventDataTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/codec/BundleEventDataTest.java
------------------------------------------------------------------------------
    svn:keywords = Revision Date

Added: incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateMBeanHandlerTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateMBeanHandlerTest.java?rev=886708&view=auto
==============================================================================
--- incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateMBeanHandlerTest.java (added)
+++ incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateMBeanHandlerTest.java Thu Dec  3 08:55:18 2009
@@ -0,0 +1,64 @@
+/**
+ *  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.aries.jmx.framework;
+
+import static org.junit.Assert.*;
+
+import org.apache.aries.jmx.Logger;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.startlevel.StartLevel;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * 
+ *
+ * @version $Rev$ $Date$
+ */
+public class BundleStateMBeanHandlerTest {
+
+    
+    @Test
+    public void testOpenAndClose() throws Exception {
+        
+        BundleContext context = mock(BundleContext.class);
+        Logger logger = mock(Logger.class);
+        
+        ServiceReference packageAdminRef = mock(ServiceReference.class);
+        PackageAdmin packageAdmin = mock(PackageAdmin.class);
+        when(context.getServiceReference(PackageAdmin.class.getName())).thenReturn(packageAdminRef);
+        when(context.getService(packageAdminRef)).thenReturn(packageAdmin);
+        ServiceReference startLevelRef = mock(ServiceReference.class);
+        StartLevel startLevel = mock(StartLevel.class);
+        when(context.getServiceReference(StartLevel.class.getName())).thenReturn(startLevelRef);
+        when(context.getService(startLevelRef)).thenReturn(startLevel);
+        
+        BundleStateMBeanHandler handler = new BundleStateMBeanHandler(context, logger);
+        handler.open();
+        
+        assertNotNull(handler.getMbean());
+        
+        handler.close();
+        verify(context).ungetService(packageAdminRef);
+        verify(context).ungetService(startLevelRef);
+        
+    }
+
+}

Propchange: incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateMBeanHandlerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateMBeanHandlerTest.java
------------------------------------------------------------------------------
    svn:keywords = Revision Date

Added: incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateTest.java?rev=886708&view=auto
==============================================================================
--- incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateTest.java (added)
+++ incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateTest.java Thu Dec  3 08:55:18 2009
@@ -0,0 +1,188 @@
+/**
+ *  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.aries.jmx.framework;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.atMost;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.osgi.jmx.framework.BundleStateMBean.OBJECTNAME;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+
+import org.apache.aries.jmx.Logger;
+import org.apache.aries.jmx.codec.BundleEventData;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.startlevel.StartLevel;
+
+
+public class BundleStateTest {
+
+    @Test
+    public void testNotificationsForBundleEvents() throws Exception {
+        
+        BundleContext context = mock(BundleContext.class);
+        PackageAdmin admin = mock(PackageAdmin.class);
+        StartLevel startLevel = mock(StartLevel.class);
+        Logger logger = mock(Logger.class);
+        
+        //holder for Notifications captured
+        final List<Notification> received = new LinkedList<Notification>();
+        
+        BundleState bundleState = new BundleState(context, admin, startLevel, logger);
+        
+        Bundle b1 = mock(Bundle.class);
+        when(b1.getBundleId()).thenReturn(new Long(9));
+        when(b1.getSymbolicName()).thenReturn("bundle");
+        when(b1.getLocation()).thenReturn("file:/location");
+        
+        BundleEvent installedEvent = mock(BundleEvent.class);
+        when(installedEvent.getBundle()).thenReturn(b1);
+        when(installedEvent.getType()).thenReturn(BundleEvent.INSTALLED);
+       
+        BundleEvent resolvedEvent = mock(BundleEvent.class);
+        when(resolvedEvent.getBundle()).thenReturn(b1);
+        when(resolvedEvent.getType()).thenReturn(BundleEvent.RESOLVED);
+        
+        MBeanServer server = mock(MBeanServer.class);
+        
+        //setup for notification
+        ObjectName objectName = new ObjectName(OBJECTNAME);
+        bundleState.preRegister(server, objectName);
+        bundleState.postRegister(true);
+        
+        //add NotificationListener to receive the events
+        bundleState.addNotificationListener(new NotificationListener() {
+            public void handleNotification(Notification notification, Object handback) {
+               received.add(notification);
+            }
+        }, null, null);
+        
+        // capture the BundleListener registered with BundleContext to issue BundleEvents
+        ArgumentCaptor<BundleListener> argument = ArgumentCaptor.forClass(BundleListener.class);        
+        verify(context).addBundleListener(argument.capture());
+        
+        //send events
+        BundleListener listener = argument.getValue();
+        listener.bundleChanged(installedEvent);
+        listener.bundleChanged(resolvedEvent);
+        
+        //shutdown dispatcher via unregister callback 
+        bundleState.postDeregister();
+        //check the BundleListener is cleaned up
+        verify(context).removeBundleListener(listener);
+        
+        ExecutorService dispatcher = bundleState.getEventDispatcher();
+        assertTrue(dispatcher.isShutdown());
+        dispatcher.awaitTermination(2, TimeUnit.SECONDS);
+        assertTrue(dispatcher.isTerminated());
+        
+        assertEquals(2, received.size());
+        Notification installed = received.get(0);
+        assertEquals(1, installed.getSequenceNumber());
+        CompositeData installedCompositeData = (CompositeData) installed.getUserData();
+        BundleEventData installedData = BundleEventData.from(installedCompositeData);
+        assertEquals("bundle", installedData.getBundleSymbolicName());
+        assertEquals(9, installedData.getBundleId());
+        assertEquals("file:/location", installedData.getLocation());
+        assertEquals(BundleEvent.INSTALLED, installedData.getEventType());
+        
+        Notification resolved = received.get(1);
+        assertEquals(2, resolved.getSequenceNumber());
+        CompositeData resolvedCompositeData = (CompositeData) resolved.getUserData();
+        BundleEventData resolvedData = BundleEventData.from(resolvedCompositeData);
+        assertEquals("bundle", resolvedData.getBundleSymbolicName());
+        assertEquals(9, resolvedData.getBundleId());
+        assertEquals("file:/location", resolvedData.getLocation());
+        assertEquals(BundleEvent.RESOLVED, resolvedData.getEventType());
+        
+    }
+    
+    @Test
+    public void testLifeCycleOfNotificationSupport() throws Exception {
+        
+        BundleContext context = mock(BundleContext.class);
+        PackageAdmin admin = mock(PackageAdmin.class);
+        StartLevel startLevel = mock(StartLevel.class);
+        Logger logger = mock(Logger.class);
+        
+        BundleState bundleState = new BundleState(context, admin, startLevel, logger);
+        
+        MBeanServer server1 = mock(MBeanServer.class);
+        MBeanServer server2 = mock(MBeanServer.class);
+
+        ObjectName objectName = new ObjectName(OBJECTNAME);
+        bundleState.preRegister(server1, objectName);
+        bundleState.postRegister(true);
+        
+        // capture the BundleListener registered with BundleContext
+        ArgumentCaptor<BundleListener> argument = ArgumentCaptor.forClass(BundleListener.class);        
+        verify(context).addBundleListener(argument.capture());
+        assertEquals(1, argument.getAllValues().size());
+        
+        BundleListener listener = argument.getValue();
+        assertNotNull(listener);
+        
+        ExecutorService dispatcher = bundleState.getEventDispatcher();
+        
+        //do registration with another server
+        bundleState.preRegister(server2, objectName);
+        bundleState.postRegister(true);
+        
+        // check no more actions on BundleContext
+        argument = ArgumentCaptor.forClass(BundleListener.class);        
+        verify(context, atMost(1)).addBundleListener(argument.capture());
+        assertEquals(1, argument.getAllValues().size());
+        
+        //do one unregister
+        bundleState.postDeregister();
+        
+        //verify bundleListener not invoked
+        verify(context, never()).removeBundleListener(listener);
+        assertFalse(dispatcher.isShutdown());
+        
+        //do second unregister and check cleanup
+        bundleState.postDeregister();
+        verify(context).removeBundleListener(listener);
+        assertTrue(dispatcher.isShutdown());
+        dispatcher.awaitTermination(2, TimeUnit.SECONDS);
+        assertTrue(dispatcher.isTerminated());
+        
+      
+        
+    }
+}

Propchange: incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/aries/trunk/jmx/jmx-core/src/test/java/org/apache/aries/jmx/framework/BundleStateTest.java
------------------------------------------------------------------------------
    svn:keywords = Revision Date