/** * 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.wiring; import static org.junit.Assert.assertEquals; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Set; import javax.management.ObjectName; import javax.management.openmbean.CompositeData; import javax.management.openmbean.TabularData; import org.apache.aries.jmx.AbstractIntegrationTest; import org.apache.aries.jmx.codec.PropertyData; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.CoreOptions; import org.ops4j.pax.exam.Option; import org.osgi.framework.Bundle; import org.osgi.framework.Constants; import org.osgi.framework.wiring.BundleCapability; import org.osgi.framework.wiring.BundleRequirement; import org.osgi.framework.wiring.BundleRevision; import org.osgi.framework.wiring.BundleRevisions; import org.osgi.framework.wiring.BundleWire; import org.osgi.framework.wiring.BundleWiring; import org.osgi.jmx.framework.wiring.BundleWiringStateMBean; public class BundleWiringStateMBeanTest extends AbstractIntegrationTest { private BundleWiringStateMBean brsMBean; private Bundle bundleA; @Configuration public Option[] configuration() { return CoreOptions.options( // new VMOption( "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000" ), // new TimeoutOption( 0 ), jmxRuntime(), bundlea(), bundleb(), fragmentc(), bundled() ); } @Before public void doSetUp() throws Exception { brsMBean = getMBean(BundleWiringStateMBean.OBJECTNAME, BundleWiringStateMBean.class); bundleA = getBundleByName("org.apache.aries.jmx.test.bundlea"); } @Test public void testObjectName() throws Exception { Set<ObjectName> names = mbeanServer.queryNames(new ObjectName(BundleWiringStateMBean.OBJECTNAME + ",*"), null); assertEquals(1, names.size()); ObjectName name = names.iterator().next(); Hashtable<String, String> props = name.getKeyPropertyList(); assertEquals(context().getProperty(Constants.FRAMEWORK_UUID), props.get("uuid")); assertEquals(context().getBundle(0).getSymbolicName(), props.get("framework")); } @Test public void testGetCurrentRevisionDeclaredRequirements() throws Exception { Bundle a = getBundleByName("org.apache.aries.jmx.test.bundlea"); BundleRevision br = (BundleRevision) a.adapt(BundleRevision.class); List<BundleRequirement> requirements = br.getDeclaredRequirements(BundleRevision.PACKAGE_NAMESPACE); CompositeData[] jmxRequirements = brsMBean.getCurrentRevisionDeclaredRequirements(a.getBundleId(), BundleRevision.PACKAGE_NAMESPACE); Assert.assertEquals(requirements.size(), jmxRequirements.length); Map<Map<String, Object>, Map<String, String>> expectedRequirements = requirementsToMap(requirements); Map<Map<String, Object>, Map<String, String>> actualRequirements = jmxCapReqToMap(jmxRequirements); Assert.assertEquals(expectedRequirements, actualRequirements); } @Test public void testGetCurrentRevisionDeclaredCapabilities() throws Exception { BundleRevision br = (BundleRevision) bundleA.adapt(BundleRevision.class); List<BundleCapability> capabilities = br.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE); CompositeData[] jmxCapabilities = brsMBean.getCurrentRevisionDeclaredCapabilities(bundleA.getBundleId(), BundleRevision.PACKAGE_NAMESPACE); Assert.assertEquals(capabilities.size(), jmxCapabilities.length); Map<Map<String, Object>, Map<String, String>> expectedCapabilities = capabilitiesToMap(capabilities); Map<Map<String, Object>, Map<String, String>> actualCapabilities = jmxCapReqToMap(jmxCapabilities); Assert.assertEquals(expectedCapabilities, actualCapabilities); } @Test public void testGetRevisionsDeclaredRequirements() throws Exception { BundleRevisions revisions = (BundleRevisions) bundleA.adapt(BundleRevisions.class); Assert.assertEquals("Precondition", 1, revisions.getRevisions().size()); TabularData jmxRequirementsTable = brsMBean.getRevisionsDeclaredRequirements(bundleA.getBundleId(), BundleRevision.PACKAGE_NAMESPACE); Assert.assertEquals(1, jmxRequirementsTable.size()); List<BundleRequirement> requirements = ((BundleRevision) revisions.getRevisions().iterator().next()).getDeclaredRequirements(BundleRevision.PACKAGE_NAMESPACE); CompositeData jmxRevRequirements = (CompositeData) jmxRequirementsTable.values().iterator().next(); CompositeData[] jmxRequirements = (CompositeData[]) jmxRevRequirements.get(BundleWiringStateMBean.REQUIREMENTS); Map<Map<String, Object>, Map<String, String>> expectedRequirements = requirementsToMap(requirements); Map<Map<String, Object>, Map<String, String>> actualRequirements = jmxCapReqToMap(jmxRequirements); Assert.assertEquals(expectedRequirements, actualRequirements); } @Test public void testGetRevisionsDeclaredCapabilities() throws Exception { BundleRevisions revisions = (BundleRevisions) bundleA.adapt(BundleRevisions.class); Assert.assertEquals("Precondition", 1, revisions.getRevisions().size()); TabularData jmxCapabilitiesTable = brsMBean.getRevisionsDeclaredCapabilities(bundleA.getBundleId(), BundleRevision.PACKAGE_NAMESPACE); Assert.assertEquals(1, jmxCapabilitiesTable.size()); List<BundleCapability> capabilities = ((BundleRevision) revisions.getRevisions().iterator().next()).getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE); CompositeData jmxRevCapabilities = (CompositeData) jmxCapabilitiesTable.values().iterator().next(); CompositeData[] jmxCapabilities = (CompositeData[]) jmxRevCapabilities.get(BundleWiringStateMBean.CAPABILITIES); Map<Map<String, Object>, Map<String, String>> expectedCapabilities = capabilitiesToMap(capabilities); Map<Map<String, Object>, Map<String, String>> actualCapabilities = jmxCapReqToMap(jmxCapabilities); Assert.assertEquals(expectedCapabilities, actualCapabilities); } @Test public void testGetCurrentWiring() throws Exception { CompositeData jmxWiring = brsMBean.getCurrentWiring(bundleA.getBundleId(), BundleRevision.PACKAGE_NAMESPACE); Assert.assertEquals(BundleWiringStateMBean.BUNDLE_WIRING_TYPE, jmxWiring.getCompositeType()); Assert.assertEquals(bundleA.getBundleId(), jmxWiring.get(BundleWiringStateMBean.BUNDLE_ID)); BundleWiring bw = (BundleWiring) bundleA.adapt(BundleWiring.class); assertBundleWiring(bw, jmxWiring); } @Test public void testRevisionsWiring() throws Exception { TabularData jmxWiringTable = brsMBean.getRevisionsWiring(bundleA.getBundleId(), BundleRevision.PACKAGE_NAMESPACE); Assert.assertEquals(1, jmxWiringTable.size()); CompositeData jmxWiring = (CompositeData) jmxWiringTable.values().iterator().next(); Assert.assertEquals(BundleWiringStateMBean.BUNDLE_WIRING_TYPE, jmxWiring.getCompositeType()); Assert.assertEquals(bundleA.getBundleId(), jmxWiring.get(BundleWiringStateMBean.BUNDLE_ID)); BundleWiring bw = (BundleWiring) bundleA.adapt(BundleWiring.class); assertBundleWiring(bw, jmxWiring); } private void assertBundleWiring(BundleWiring bundleWiring, CompositeData jmxWiring) { CompositeData[] jmxCapabilities = (CompositeData[]) jmxWiring.get(BundleWiringStateMBean.CAPABILITIES); List<BundleCapability> capabilities = bundleWiring.getCapabilities(BundleRevision.PACKAGE_NAMESPACE); Assert.assertEquals(capabilities.size(), jmxCapabilities.length); Map<Map<String, Object>, Map<String, String>> expectedCapabilities = capabilitiesToMap(capabilities); Map<Map<String, Object>, Map<String, String>> actualCapabilities = jmxCapReqToMap(jmxCapabilities); Assert.assertEquals(expectedCapabilities, actualCapabilities); CompositeData[] jmxRequirements = (CompositeData[]) jmxWiring.get(BundleWiringStateMBean.REQUIREMENTS); List<BundleRequirement> requirements = bundleWiring.getRequirements(BundleRevision.PACKAGE_NAMESPACE); Assert.assertEquals(requirements.size(), jmxRequirements.length); Map<Map<String, Object>, Map<String, String>> expectedRequirements = requirementsToMap(requirements); Map<Map<String, Object>, Map<String, String>> actualRequirements = jmxCapReqToMap(jmxRequirements); Assert.assertEquals(expectedRequirements, actualRequirements); List<BundleWire> requiredWires = bundleWiring.getRequiredWires(BundleRevision.PACKAGE_NAMESPACE); CompositeData[] jmxRequiredWires = (CompositeData[]) jmxWiring.get(BundleWiringStateMBean.REQUIRED_WIRES); Assert.assertEquals(requiredWires.size(), jmxRequiredWires.length); Set<List<Object>> expectedRequiredWires = new HashSet<List<Object>>(); for (BundleWire wire : requiredWires) { List<Object> data = new ArrayList<Object>(); data.add(wire.getCapability().getRevision().getBundle().getBundleId()); data.add(wire.getCapability().getAttributes()); data.add(wire.getCapability().getDirectives()); data.add(wire.getRequirement().getRevision().getBundle().getBundleId()); data.add(wire.getRequirement().getAttributes()); data.add(wire.getRequirement().getDirectives()); expectedRequiredWires.add(data); } Set<List<Object>> actualRequiredWires = new HashSet<List<Object>>(); for (CompositeData wire : jmxRequiredWires) { List<Object> data = new ArrayList<Object>(); data.add(wire.get(BundleWiringStateMBean.PROVIDER_BUNDLE_ID)); // TODO bundle revision id data.add(getJmxAttributes((CompositeData) wire.get(BundleWiringStateMBean.BUNDLE_CAPABILITY))); data.add(getJmxDirectives((CompositeData) wire.get(BundleWiringStateMBean.BUNDLE_CAPABILITY))); data.add(wire.get(BundleWiringStateMBean.REQUIRER_BUNDLE_ID)); data.add(getJmxAttributes((CompositeData) wire.get(BundleWiringStateMBean.BUNDLE_REQUIREMENT))); data.add(getJmxDirectives((CompositeData) wire.get(BundleWiringStateMBean.BUNDLE_REQUIREMENT))); actualRequiredWires.add(data); } Assert.assertEquals(expectedRequiredWires, actualRequiredWires); List<BundleWire> providedWires = bundleWiring.getProvidedWires(BundleRevision.PACKAGE_NAMESPACE); CompositeData[] jmxProvidedWires = (CompositeData []) jmxWiring.get(BundleWiringStateMBean.PROVIDED_WIRES); Assert.assertEquals(providedWires.size(), jmxProvidedWires.length); HashSet<List<Object>> expectedProvidedWires = new HashSet<List<Object>>(); for (BundleWire wire : providedWires) { List<Object> data = new ArrayList<Object>(); data.add(wire.getCapability().getRevision().getBundle().getBundleId()); data.add(wire.getCapability().getAttributes()); data.add(wire.getCapability().getDirectives()); data.add(wire.getRequirement().getRevision().getBundle().getBundleId()); data.add(wire.getRequirement().getAttributes()); data.add(wire.getRequirement().getDirectives()); expectedProvidedWires.add(data); } Set<List<Object>> actualProvidedWires = new HashSet<List<Object>>(); for (CompositeData wire : jmxProvidedWires) { List<Object> data = new ArrayList<Object>(); data.add(wire.get(BundleWiringStateMBean.PROVIDER_BUNDLE_ID)); data.add(getJmxAttributes((CompositeData) wire.get(BundleWiringStateMBean.BUNDLE_CAPABILITY))); data.add(getJmxDirectives((CompositeData) wire.get(BundleWiringStateMBean.BUNDLE_CAPABILITY))); data.add(wire.get(BundleWiringStateMBean.REQUIRER_BUNDLE_ID)); data.add(getJmxAttributes((CompositeData) wire.get(BundleWiringStateMBean.BUNDLE_REQUIREMENT))); data.add(getJmxDirectives((CompositeData) wire.get(BundleWiringStateMBean.BUNDLE_REQUIREMENT))); actualProvidedWires.add(data); } Assert.assertEquals(expectedProvidedWires, actualProvidedWires); } @Test public void testCurrentWiringClosure() throws Exception { TabularData jmxWiringClosure = brsMBean.getCurrentWiringClosure(bundleA.getBundleId(), BundleRevision.PACKAGE_NAMESPACE); CompositeData jmxWiringA = jmxWiringClosure.get(new Object [] {bundleA.getBundleId(), 0}); assertBundleWiring((BundleWiring) bundleA.adapt(BundleWiring.class), jmxWiringA); Bundle b = context().getBundleByName("org.apache.aries.jmx.test.bundleb"); int bRevID = findRevisionID(jmxWiringA, b); CompositeData jmxWiringB = jmxWiringClosure.get(new Object [] {b.getBundleId(), bRevID}); assertBundleWiring((BundleWiring) b.adapt(BundleWiring.class), jmxWiringB); Bundle cm = context().getBundleByName("org.apache.felix.configadmin"); int cmRevID = findRevisionID(jmxWiringA, cm); CompositeData jmxWiringCM = jmxWiringClosure.get(new Object [] {cm.getBundleId(), cmRevID}); assertBundleWiring((BundleWiring) cm.adapt(BundleWiring.class), jmxWiringCM); Bundle sb = context().getBundle(0); int sbRevID = findRevisionID(jmxWiringA, sb); CompositeData jmxWiringSB = jmxWiringClosure.get(new Object [] {sb.getBundleId(), sbRevID}); assertBundleWiring((BundleWiring) sb.adapt(BundleWiring.class), jmxWiringSB); } @Test public void testRevisionsWiringClosure() throws Exception { TabularData jmxWiringClosure = brsMBean.getRevisionsWiringClosure(bundleA.getBundleId(), BundleRevision.PACKAGE_NAMESPACE); CompositeData jmxWiringA = jmxWiringClosure.get(new Object [] {bundleA.getBundleId(), 0}); assertBundleWiring((BundleWiring) bundleA.adapt(BundleWiring.class), jmxWiringA); Bundle b = context().getBundleByName("org.apache.aries.jmx.test.bundleb"); int bRevID = findRevisionID(jmxWiringA, b); CompositeData jmxWiringB = jmxWiringClosure.get(new Object [] {b.getBundleId(), bRevID}); assertBundleWiring((BundleWiring) b.adapt(BundleWiring.class), jmxWiringB); Bundle cm = context().getBundleByName("org.apache.felix.configadmin"); int cmRevID = findRevisionID(jmxWiringA, cm); CompositeData jmxWiringCM = jmxWiringClosure.get(new Object [] {cm.getBundleId(), cmRevID}); assertBundleWiring((BundleWiring) cm.adapt(BundleWiring.class), jmxWiringCM); Bundle sb = context().getBundle(0); int sbRevID = findRevisionID(jmxWiringA, sb); CompositeData jmxWiringSB = jmxWiringClosure.get(new Object [] {sb.getBundleId(), sbRevID}); assertBundleWiring((BundleWiring) sb.adapt(BundleWiring.class), jmxWiringSB); } private int findRevisionID(CompositeData jmxWiring, Bundle bundle) { CompositeData[] requiredWires = (CompositeData []) jmxWiring.get(BundleWiringStateMBean.REQUIRED_WIRES); for (CompositeData req : requiredWires) { if (new Long(bundle.getBundleId()).equals(req.get(BundleWiringStateMBean.PROVIDER_BUNDLE_ID))) { return (Integer) req.get(BundleWiringStateMBean.PROVIDER_BUNDLE_REVISION_ID); } } return -1; } private Map<Map<String, Object>, Map<String, String>> capabilitiesToMap(List<BundleCapability> capabilities) { Map<Map<String, Object>, Map<String, String>> map = new HashMap<Map<String,Object>, Map<String,String>>(); for (BundleCapability cap : capabilities) { map.put(cap.getAttributes(), cap.getDirectives()); } return map; } private Map<Map<String, Object>, Map<String, String>> requirementsToMap(List<BundleRequirement> requirements) { Map<Map<String, Object>, Map<String, String>> map = new HashMap<Map<String,Object>, Map<String,String>>(); for (BundleRequirement req : requirements) { map.put(req.getAttributes(), req.getDirectives()); } return map; } private Map<Map<String, Object>, Map<String, String>> jmxCapReqToMap(CompositeData[] jmxCapabilitiesOrRequirements) { Map<Map<String, Object>, Map<String, String>> actualCapabilities = new HashMap<Map<String,Object>, Map<String,String>>(); for (CompositeData jmxCapReq : jmxCapabilitiesOrRequirements) { Map<String, Object> aMap = getJmxAttributes(jmxCapReq); Map<String, String> dMap = getJmxDirectives(jmxCapReq); actualCapabilities.put(aMap, dMap); } return actualCapabilities; } @SuppressWarnings("unchecked") private Map<String, Object> getJmxAttributes(CompositeData jmxCapReq) { TabularData jmxAttributes = (TabularData) jmxCapReq.get(BundleWiringStateMBean.ATTRIBUTES); Map<String, Object> aMap = new HashMap<String, Object>(); for (CompositeData jmxAttr : (Collection<CompositeData>) jmxAttributes.values()) { PropertyData<Object> pd = PropertyData.from(jmxAttr); Object val = pd.getValue(); if (val instanceof Object[]) { val = Arrays.asList((Object [])val); } aMap.put(pd.getKey(), val); } return aMap; } @SuppressWarnings("unchecked") private Map<String, String> getJmxDirectives(CompositeData jmxCapReq) { TabularData jmxDirectives = (TabularData) jmxCapReq.get(BundleWiringStateMBean.DIRECTIVES); Map<String, String> dMap = new HashMap<String, String>(); for (CompositeData jmxDir : (Collection<CompositeData>) jmxDirectives.values()) { dMap.put((String) jmxDir.get(BundleWiringStateMBean.KEY), (String) jmxDir.get(BundleWiringStateMBean.VALUE)); } return dMap; } }