Moved org.apache.felix.jmood to trunk
git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@438973 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.jmood/pom.xml b/org.apache.felix.jmood/pom.xml
new file mode 100644
index 0000000..e51ae2e
--- /dev/null
+++ b/org.apache.felix.jmood/pom.xml
@@ -0,0 +1,90 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>felix</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>osgi-bundle</packaging>
+ <name>JMood JMX Management Agent</name>
+ <artifactId>${groupId}.jmood</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.apache.felix.framework</artifactId>
+ <version>${pom.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>${pom.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <version>${pom.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix.plugins</groupId>
+ <artifactId>maven-osgi-plugin</artifactId>
+ <version>${pom.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <osgiManifest >
+ <bundleName>${name}</bundleName>
+ <bundleActivator>${artifactId}.Activator</bundleActivator>
+ <bundleDescription>JMood management agent</bundleDescription>
+ <bundleSymbolicName>${artifactId}</bundleSymbolicName>
+ <exportPackage>
+ <!-- TODO -->
+ </exportPackage>
+ <!--Automatic resolution includes not available, unused, mx4j stuff-->
+ <importPackage>
+ org.osgi.framework, org.osgi.util.tracker, org.osgi.service.log, org.osgi.service.packageadmin, org.osgi.service.startlevel, org.osgi.service.permissionadmin, org.osgi.service.useradmin, org.osgi.service.cm, javax.management, javax.management.remote
+ </importPackage>
+ </osgiManifest>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <!--
+ Current tests are (unfinished) integration tests, and need
+ to have the bundle available, so there's a chicken-egg problem there. Temporal workaround: omit tests in pom
+ -->
+
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </reporting>
+</project>
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/Activator.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/Activator.java
new file mode 100644
index 0000000..328f6ac
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/Activator.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.URL;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.ExportException;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.Properties;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+
+import org.apache.felix.jmood.core.CoreController;
+import org.apache.felix.jmood.core.Framework;
+import org.apache.felix.jmood.utils.ObjectNames;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+public class Activator implements BundleActivator{
+ private Properties props;
+ private String agentPropsPath="/agent.properties";
+ private static final String IS_POLICY_EMBEDDED="policy.embedded";
+ private static final String JAVA_SECURITY_POLICY="java.security.policy";
+ private MBeanServer server;
+ private JMXConnectorServer connectorServer;
+ private int rmiRegistryPort = 1199;
+ private AgentContext ac;
+ private static final String connectoServerOname="RemotingService:type=ConnectorServer, subtype=RMIConnectorServer, provider=JRE";
+ private CompendiumController compendium;
+ private Registry rmiRegistry;
+
+
+ public void start(BundleContext context) throws Exception {
+ this.ac=new AgentContext(context);
+ this.ac.debug("starting");
+ try{
+ this.server=this.getMBeanServer();
+ }
+ catch (Exception e){
+ this.ac.error("unexpected error", e);
+ throw e;
+ }
+ this.ac.debug("got platform mbeanserver");
+ this.compendium = new CompendiumController(this.server,this.ac);
+ this.props = this.loadProperties();
+ this.ac.debug("props loaded");
+ //TODO Enable this when Felix has security support.RMI Serialization doesn't work well without it. In Equinox, it works fine
+ //this.setSecurityManager();
+ //ac.debug("security manager set");
+ this.ac.debug("registering mbeans");
+ this.registerMBeans();
+ this.initRMIConn();
+ this.ac.debug("rmi connection initialised and mbeans registered");
+ this.ac.debug("agent started");
+ }
+ public void stop(BundleContext context) throws Exception {
+ this.ac.debug("stopping");
+ this.stopRMIConn();
+ this.ac.closeTrackers();
+ this.unregisterMBeans();
+ this.ac.debug("done");
+ }
+ private void setSecurityManager() throws Exception{
+ //TODO check this when we add permission admin support to the bundle
+ //It caused StackOverFlow the second time the framework was run(?)
+
+ if (System.getSecurityManager() != null) {
+ return;
+ }
+ try {
+ this.ac.debug("Security manager does not exist");
+ if (this.props.getProperty(IS_POLICY_EMBEDDED).equalsIgnoreCase("true")){
+ this.ac.debug("Policy is embedded, copying it to filesystem...");
+ String policyName=this.props.getProperty(JAVA_SECURITY_POLICY);
+ //The policy is in the file system and should be copied...
+ File file=this.ac.getBundleContext().getDataFile(policyName);
+ if (file.exists()) {
+ this.ac.debug("trying to delete file...");
+ boolean deleted=file.delete();
+ if(!deleted) {
+ this.ac.error("Could not delete existing policy file");
+ } else {
+ this.ac.debug("successfully deleted");
+ }
+ file=this.ac.getBundleContext().getDataFile(policyName);
+ file.createNewFile();
+ this.ac.debug("new file created");
+ }
+
+ FileOutputStream o=new FileOutputStream (file);
+ InputStream i=this.ac.getBundleContext().getBundle().getResource("/"+policyName).openStream();
+ byte [] buffer=new byte [1024];
+ while (i.read(buffer)!=-1){
+ o.write(buffer);
+ }
+ i.close();
+ o.flush();
+ o.close();
+
+ System.setProperty(JAVA_SECURITY_POLICY, file.getAbsolutePath());
+ }
+ else{
+ System.setProperty(JAVA_SECURITY_POLICY, this.props.getProperty(JAVA_SECURITY_POLICY));
+ }
+ System.setSecurityManager(new SecurityManager());
+
+ }catch(Exception e){
+ this.ac.error("Unexpected exception", e);
+ }
+ this.ac.debug("Security policy: "+System.getProperty(JAVA_SECURITY_POLICY));
+ this.ac.debug("Security manager toString(): "+System.getSecurityManager().toString());
+
+ }
+
+ private Properties loadProperties() throws Exception{
+ Properties props = new Properties();
+ URL u=this.ac.getBundleContext().getBundle().getResource(this.agentPropsPath);
+ props.load(u.openStream());
+ return props;
+ }
+
+ /**
+ * A getter method for retrieving the context of this bundle
+ * @return BundleContext the bundle context for this bundle
+ * @throws InstanceNotFoundException
+ */
+
+ private void initRMIConn() throws IOException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException, MalformedObjectNameException, NullPointerException, InstanceNotFoundException {
+ Thread t=new Thread(){
+ public void run() {
+ try {
+ rmiRegistry=LocateRegistry.createRegistry(rmiRegistryPort);
+ } catch (RemoteException e) {
+ ac.warning(e.getMessage()+"\n"+"Possibly some other framework already running, skipping RMI registry creation");
+ return;
+ }
+ }
+ };
+ t.setName("RMIREGISTRY");
+ t.setContextClassLoader(this.getClass().getClassLoader());
+ t.start();
+ InetAddress[] addresses=InetAddress.getAllByName(InetAddress.getLocalHost().getCanonicalHostName());
+ //Do not attach the agent to the loopback address
+ InetAddress address=null;
+ for (int i = 0; i < addresses.length; i++) {
+ if (!addresses[i].isLoopbackAddress()) {
+ address=addresses[i];
+ break;
+ }
+ }
+ if (address==null){
+ StringBuffer msg=new StringBuffer("java.net.InetAddress could not find non-localhost IP. \n");
+ msg.append(" Is there any network interface available? Are you using Linux?. \n")
+ .append("If you are using debian-based distros, try editing the /etc/hosts file so that it does not contain")
+ .append(" something like '127.0.0.1 ${hostname}'");
+ this.ac.warning(msg.toString());
+ address=InetAddress.getLocalHost();
+ }
+ JMXServiceURL url = new JMXServiceURL(
+ "service:jmx:rmi:///jndi/rmi://"+address.getHostName()+":"
+ + this.rmiRegistryPort + "/server");
+ this.ac.debug(url.toString());
+ this.connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(
+ url, null,this.server);
+
+ this.server.registerMBean(this.connectorServer, new ObjectName(connectoServerOname));
+ this.connectorServer.start();
+ }
+ private void stopRMIConn() throws Exception {
+ this.connectorServer.stop();
+ UnicastRemoteObject.unexportObject(this.rmiRegistry, true);
+ this.server.unregisterMBean(new ObjectName(connectoServerOname));
+
+ }
+
+ private void registerMBeans() throws Exception{
+ this.server.registerMBean(new CoreController(this.ac), new ObjectName(ObjectNames.CORE_CONTROLLER));
+ this.server.registerMBean(new Framework(this.ac), new ObjectName(ObjectNames.FRAMEWORK));
+ this.compendium.initController();
+ this.ac.debug("mbeans registered");
+
+
+ }
+ private void unregisterMBeans() throws Exception{
+ this.server.unregisterMBean(new ObjectName(ObjectNames.CORE_CONTROLLER));
+ this.server.unregisterMBean(new ObjectName(ObjectNames.FRAMEWORK));
+ this.compendium.dispose();
+ }
+ private MBeanServer getMBeanServer() throws Exception{
+ String jvm=System.getProperty("java.version"); //1.5.0 or higher
+ this.ac.debug("java version is: "+jvm);
+ String[] s=jvm.split("\\.");
+ if(Integer.parseInt(s[1])<5){//In this way it should also work with Mustang
+ return MBeanServerFactory.createMBeanServer();
+ } else {
+ Class clazz =
+ Class.forName("java.lang.management.ManagementFactory");
+ Method m=clazz.getDeclaredMethod("getPlatformMBeanServer", new Class[0]);
+ return (MBeanServer) m.invoke(null,(Object[]) null);
+ }
+ }
+
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/AgentConstants.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/AgentConstants.java
new file mode 100644
index 0000000..7eea844
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/AgentConstants.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood;
+
+
+public interface AgentConstants {
+ public static final String FRAMEWORK_NOTIFICATION_TYPE =
+ "osgi.framework.framework";
+ public static final String USER_ADMIN_NOTIFICATION_TYPE = "osgi.useradmin";
+ public static final String SERVICE_NOTIFICATION_TYPE =
+ "osgi.framework.service";
+ public static final String LOG_NOTIFICATION_TYPE = "osgi.log";
+ public static final String USER = "User";
+ public static final String GROUP = "Group";
+ public static final String ROLE = "Role";
+
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/AgentContext.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/AgentContext.java
new file mode 100644
index 0000000..3377ad1
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/AgentContext.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood;
+
+
+import org.apache.felix.jmood.core.ServiceNotAvailableException;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogReaderService;
+import org.osgi.service.log.LogService;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.permissionadmin.PermissionAdmin;
+import org.osgi.service.startlevel.StartLevel;
+import org.osgi.service.useradmin.UserAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+
+
+/**
+ *
+ *
+ */public class AgentContext {
+ private BundleContext context;
+ private ServiceTracker logTracker;
+ private ServiceTracker logReaderTracker;
+ private ServiceTracker startLevelTracker;
+ private ServiceTracker packageAdminTracker;
+ private ServiceTracker permissionAdminTracker;
+ private ServiceTracker userAdminTracker;
+ private ServiceTracker configAdminTracker;
+
+ private int loglevel;
+ public static final int DEBUG=0;
+ public static final int INFO=1;
+ public static final int WARNING=2;
+ public static final int ERROR=3;
+ public AgentContext(BundleContext context) throws Exception{
+ super();
+ this.context=context;
+ this.setTrackers();
+ }
+
+ ///////////////////////////////////////////////////////////////
+ //////////////////LOGGING/////////////////////////////////////
+ ///////////////////////////////////////////////////////////////
+ public void debug(String s){
+ if(this.loglevel==DEBUG) System.out.println("DEBUG: JMOOD. "+s);
+ }
+ public void info(String s){
+ if(this.loglevel<=INFO) System.out.println("INFO: JMOOD. "+s);
+ }
+ public void warning (String s){
+ if(this.loglevel<=WARNING) System.out.println("WARNING: JMOOD. "+s);
+ }
+ public void error(String s){
+ if(this.loglevel<=ERROR) System.out.println("ERROR: JMOOD. "+s);
+ }
+ public void error(String s, Exception e){
+ if(this.loglevel<=ERROR) {
+ System.out.println("ERROR: JMOOD. "+s);
+ e.printStackTrace();
+ }
+ }
+ public int getLoglevel() {
+ return loglevel;
+ }
+ public void setLoglevel(int level) {
+ this.loglevel=level;
+ }
+ //////////////////////////////////////////////////////////////
+ ///////////////////CONTEXT AND SERVICES//////////////////////
+ public BundleContext getBundleContext() {
+ return context;
+ }
+ public LogService getLogservice() {
+ int count = logTracker.getTrackingCount();
+ switch (count) {
+ case 0 :
+ return null;
+ //FUTURE WORK when there is more than one log service available, select "the best"
+ case 1 :
+ default :
+ return (LogService) logTracker.getService();
+ }
+ }
+ public StartLevel getStartLevel() throws ServiceNotAvailableException {
+ int count = startLevelTracker.getTrackingCount();
+ switch (count) {
+ case 0 :
+ throw new ServiceNotAvailableException("No start level service available");
+ case 1 :
+ default :
+ return (StartLevel) startLevelTracker.getService();
+ }
+ }
+ public PackageAdmin getPackageadmin() throws ServiceNotAvailableException{
+ int count = packageAdminTracker.getTrackingCount();
+ switch (count) {
+ case 0 :
+ throw new ServiceNotAvailableException("No package admin available");
+ case 1 :
+ default :
+ return (PackageAdmin) packageAdminTracker.getService();
+ }
+
+ }
+ public PermissionAdmin getPermissionadmin() {
+ int count = permissionAdminTracker.getTrackingCount();
+ switch (count) {
+ case 0 :
+ return null;
+ case 1 :
+ default :
+ return (PermissionAdmin) permissionAdminTracker.getService();
+ }
+ }
+ public UserAdmin getUserAdmin() {
+ int count = userAdminTracker.getTrackingCount();
+ switch (count) {
+ case 0 :
+ return null;
+ case 1 :
+ default :
+ return (UserAdmin) userAdminTracker.getService();
+ }
+ }
+ public ConfigurationAdmin getConfigurationAdmin() {
+ int count = configAdminTracker.getTrackingCount();
+ switch (count) {
+ case 0 :
+ return null;
+ case 1 :
+ default :
+ return (ConfigurationAdmin) configAdminTracker.getService();
+ }
+ }
+ //////////////////////////////////////////////////////////////////////
+ //////////////////PRIVATE////////////////////////////////////////////
+ private void setTrackers() {
+ try {
+ logTracker =
+ new ServiceTracker(
+ context,
+ context.createFilter(
+ "(objectClass=" + LogService.class.getName() + ")"),
+ null);
+ logReaderTracker =
+ new ServiceTracker(
+ context,
+ context.createFilter(
+ "(objectClass=" + LogReaderService.class.getName() + ")"),
+ null);
+ startLevelTracker =
+ new ServiceTracker(
+ context,
+ context.createFilter(
+ "(objectClass=" + StartLevel.class.getName() + ")"),
+ null);
+ packageAdminTracker =
+ new ServiceTracker(
+ context,
+ context.createFilter(
+ "(objectClass=" + PackageAdmin.class.getName() + ")"),
+ null);
+ permissionAdminTracker =
+ new ServiceTracker(
+ context,
+ context.createFilter(
+ "(objectClass=" + PermissionAdmin.class.getName() + ")"),
+ null);
+ userAdminTracker=new ServiceTracker(context, context.createFilter("(objectClass=" + UserAdmin.class.getName() + ")"), null);
+ configAdminTracker=new ServiceTracker(context, context.createFilter("(objectClass=" + ConfigurationAdmin.class.getName() + ")"), null);
+
+ } catch (InvalidSyntaxException e) {
+ warning("INVALID FILTER ");
+ }
+
+
+
+ logTracker.open();
+ logReaderTracker.open();
+ startLevelTracker.open();
+ packageAdminTracker.open();
+ permissionAdminTracker.open();
+ userAdminTracker.open();
+ configAdminTracker.open();
+ }
+ void closeTrackers() {
+ logTracker.close();
+ logReaderTracker.close();
+ startLevelTracker.close();
+ packageAdminTracker.close();
+ permissionAdminTracker.close();
+ userAdminTracker.close();
+ configAdminTracker.close();
+
+
+ }
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/CompendiumController.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/CompendiumController.java
new file mode 100644
index 0000000..eba0ccb
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/CompendiumController.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+
+import org.apache.felix.jmood.compendium.ConfigAdminManager;
+import org.apache.felix.jmood.compendium.ConfigAdminManagerMBean;
+import org.apache.felix.jmood.compendium.LogManager;
+import org.apache.felix.jmood.compendium.LogManagerMBean;
+import org.apache.felix.jmood.compendium.UserManager;
+import org.apache.felix.jmood.compendium.UserManagerMBean;
+import org.apache.felix.jmood.utils.ObjectNames;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+import org.osgi.service.useradmin.UserAdmin;
+
+
+/**
+ * This class will control the life-cycle of MBeans related to OSGi Compendium
+ * Services
+ *
+ *
+ */
+public class CompendiumController {
+
+ private AgentContext ac;
+
+ private ServiceListener sl;
+
+ private Vector svcs;
+
+ private MBeanServer server;
+
+ public CompendiumController(MBeanServer server, AgentContext ac) {
+ super();
+ this.ac = ac;
+ this.server = server;
+ svcs = new Vector();
+ svcs.add(ConfigurationAdmin.class.getName());
+ svcs.add(UserAdmin.class.getName());
+ svcs.add(LogService.class.getName());
+ sl = new ServiceListener() {
+ public void serviceChanged(ServiceEvent event) {
+ processServiceEvent(event);
+ }
+ };
+ }
+
+ public void initController() {
+ try {
+ if (ac.getConfigurationAdmin() != null) {
+ ConfigAdminManagerMBean ca = new ConfigAdminManager(ac);
+ server
+ .registerMBean(ca, new ObjectName(
+ ObjectNames.CM_SERVICE));
+ }
+ if (ac.getLogservice() != null) {
+ LogManagerMBean lm = new LogManager(ac);
+ server.registerMBean(lm,
+ new ObjectName(ObjectNames.LOG_SERVICE));
+ }
+ if (ac.getUserAdmin() != null) {
+ UserManagerMBean um = new UserManager(ac);
+ server
+ .registerMBean(um, new ObjectName(
+ ObjectNames.UA_SERVICE));
+ }
+ } catch (InstanceAlreadyExistsException e) {
+ ac.error("Unexpected error", e);
+ } catch (MBeanRegistrationException e) {
+ ac.error("Unexpected error", e);
+ } catch (NotCompliantMBeanException e) {
+ ac.error("Unexpected error", e);
+ } catch (MalformedObjectNameException e) {
+ ac.error("Unexpected error", e);
+ } catch (NullPointerException e) {
+ ac.error("Unexpected error", e);
+ }
+ ac.getBundleContext().addServiceListener(sl);
+
+ }
+
+ public void dispose() {
+ ac.getBundleContext().removeServiceListener(sl);
+ try {
+ Iterator it = server.queryNames(
+ new ObjectName(ObjectNames.COMPENDIUM + ":*"), null)
+ .iterator();
+ while (it.hasNext())
+ server.unregisterMBean((ObjectName) it.next());
+
+ } catch (MalformedObjectNameException e) {
+ ac.error("Unexpected error", e);
+ } catch (NullPointerException e) {
+ ac.error("Unexpected error", e);
+ } catch (InstanceNotFoundException e) {
+ ac.error("Unexpected error", e);
+ } catch (MBeanRegistrationException e) {
+ ac.error("Unexpected error", e);
+ }
+ }
+
+ private void processServiceEvent(ServiceEvent event) {
+ String[] svs = (String[]) event.getServiceReference().getProperty(
+ Constants.OBJECTCLASS);
+ // Check if this event comes from an OSGi compendium service
+ for (int i = 0; i < svs.length; i++) {
+ if (svcs.contains(svs[i])) {
+ if (event.getType() == ServiceEvent.REGISTERED
+ || event.getType() == ServiceEvent.UNREGISTERING)
+ handleEvent(event.getServiceReference(), svs[i], event
+ .getType());
+ }
+ }
+
+ }
+
+ private void handleEvent(ServiceReference serviceReference,
+ String iService, int eType) {
+ try {
+
+ if (iService.equals(ConfigurationAdmin.class.getName())) {
+ switch (eType) {
+ case ServiceEvent.REGISTERED:
+ ConfigAdminManagerMBean ca = new ConfigAdminManager(ac);
+ server.registerMBean(ca, new ObjectName(
+ ObjectNames.CM_SERVICE));
+ break;
+ case ServiceEvent.UNREGISTERING:
+ server.unregisterMBean(new ObjectName(
+ ObjectNames.CM_SERVICE));
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (iService.equals(LogService.class.getName())) {
+ switch (eType) {
+ case ServiceEvent.REGISTERED:
+ LogManagerMBean lm = new LogManager(ac);
+ server.registerMBean(lm, new ObjectName(
+ ObjectNames.LOG_SERVICE));
+ break;
+ case ServiceEvent.UNREGISTERING:
+ server.unregisterMBean(new ObjectName(
+ ObjectNames.LOG_SERVICE));
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (iService.equals(UserAdmin.class.getName())) {
+ switch (eType) {
+ case ServiceEvent.REGISTERED:
+ UserManagerMBean um = new UserManager(ac);
+ server.registerMBean(um, new ObjectName(
+ ObjectNames.UA_SERVICE));
+ break;
+ case ServiceEvent.UNREGISTERING:
+ server.unregisterMBean(new ObjectName(
+ ObjectNames.UA_SERVICE));
+ break;
+ default:
+ break;
+ }
+ }
+ } catch (InstanceAlreadyExistsException e) {
+ ac.error("Unexpected error", e);
+ } catch (MBeanRegistrationException e) {
+ ac.error("Unexpected error", e);
+ } catch (NotCompliantMBeanException e) {
+ ac.error("Unexpected error", e);
+ } catch (MalformedObjectNameException e) {
+ ac.error("Unexpected error", e);
+ } catch (NullPointerException e) {
+ ac.error("Unexpected error", e);
+ } catch (InstanceNotFoundException e) {
+ ac.error("Unexpected error", e);
+ }
+ }
+
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/ConfigAdminManager.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/ConfigAdminManager.java
new file mode 100644
index 0000000..2a01db4
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/ConfigAdminManager.java
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.compendium;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.ObjectName;
+
+import org.apache.felix.jmood.AgentContext;
+import org.apache.felix.jmood.utils.ObjectNames;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+//import es.upm.dit.osgi.management.agent.AgentConstants;
+/**
+ * This is the main class of the config admin module. As such, it is responsible for controlling all the issues related to it. This class implements
+ * the ConfigAdminManagerMXBean which defines its management interface. It creates a ConfigurationDelegate object for each available
+ * Configuration object.
+ *
+ */
+public class ConfigAdminManager extends NotificationBroadcasterSupport
+ implements MBeanRegistration, ConfigAdminManagerMBean{
+ /*NOTE: The spec says that ConfigurationException's should be used by management systems
+ * in order to inform a human manager in a suitable way. However, this is not possible unless we implement the service
+ * because nowhere in the spec is there a way of accesing those exceptions (unless the implementation of the cm chooses to log the exception, which is not even suggested in the spec)
+ */
+ private MBeanServer server;
+ private AgentContext ac;
+ private ConfigurationAdmin cadmin;
+ public ConfigAdminManager(AgentContext ac) {
+ this.ac=ac;
+
+ }
+ /**
+ * This is called before the module is loaded. It initializes the module.
+ * @see javax.management.MBeanRegistration#preRegister(javax.management.MBeanServer, javax.management.ObjectName)
+ */
+ public ObjectName preRegister(MBeanServer server, ObjectName name)
+ throws Exception {
+ this.server = server;
+ return name;
+ }
+
+ /**
+ * @see javax.management.MBeanRegistration#postRegister(java.lang.Boolean)
+ */
+ public void postRegister(Boolean registrationDone) {}
+ /**
+ * @see javax.management.MBeanRegistration#preDeregister()
+ */
+ public void preDeregister() throws Exception {
+ //Remove the service
+ //and remove all mbeans from this module...
+ unregisterMBeans();
+ }
+ /**
+ * @see javax.management.MBeanRegistration#postDeregister()
+ */
+ public void postDeregister() {}
+
+ /**
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#listConfigurations(java.lang.String)
+ */
+
+ public String[] listConfigurations(String filter) throws Exception {
+ ConfigurationAdmin cad=ac.getConfigurationAdmin();
+ Configuration[] confs = null;
+ if (cad!= null) {
+ confs = cad.listConfigurations(filter);
+ refresh();
+ if (confs == null)
+ return null;
+ }
+ String[] result = new String[confs.length];
+ for (int i = 0; i < confs.length; i++)
+ result[i] = this.getObjectName(confs[i]);
+ return result;
+ }
+
+ /**
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#getConfiguration(java.lang.String)
+ */
+ public String getConfiguration(String pid) throws Exception {
+ //FIXME this should not be invoked
+ //if created, the configuration is attached to the management agent's location
+ ac.debug("ConfigAdmin, getting config for pid: "+pid);
+ if (pid.contains(":")) throw new IllegalArgumentException("pid not compliant with jmx. Please remove ':' from the pid");
+ ConfigurationAdmin cad=ac.getConfigurationAdmin();
+ if (cad != null) {
+ Configuration config = cad.getConfiguration(pid);
+ refresh();
+ return this.getObjectName(config);
+
+ } else
+ return null;
+ }
+
+ /**
+ * This method gets a configuration object related to a pid and a bundle location
+ * @param pid Persistent ID
+ * @param location Bundle location of the service
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#getConfiguration(java.lang.String, java.lang.String)
+ */
+ public String getConfiguration(String pid, String location)
+ throws Exception {
+ //":" is reserved in objectnames, as a work around we do not permit pids containing it
+ if (pid.contains(":")) throw new IllegalArgumentException("pid not compliant with jmx. Please remove ':' from the pid");
+ ConfigurationAdmin cad=ac.getConfigurationAdmin();
+ if (cad != null) {
+ Configuration config = cad.getConfiguration(pid, location);
+ refresh();
+ return this.getObjectName(config);
+ } else
+ return null;
+ }
+ /**
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#createFactoryConfiguration(java.lang.String)
+ */
+ public String createFactoryConfiguration(String pid) throws Exception {
+ ConfigurationAdmin cad=ac.getConfigurationAdmin();
+ if (cad != null) {
+ Configuration conf = cad.createFactoryConfiguration(pid);
+ refresh();
+ return this.getObjectName(conf);
+ } else
+ return null;
+ }
+
+ /**
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#createFactoryConfiguration(java.lang.String, java.lang.String)
+ */
+ public String createFactoryConfiguration(String pid, String location)
+ throws Exception {
+ ConfigurationAdmin cad=ac.getConfigurationAdmin();
+ if (cad != null) {
+ Configuration conf = cad.createFactoryConfiguration(pid, location);
+ refresh();
+ return this.getObjectName(conf);
+ } else
+ return null;
+ }
+ /**
+ * Delete the configurations identified by the LDAP filter
+ * @param filter LDAP String representing the configurations that want to be deleted
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#deleteConfigurations(java.lang.String)
+ */
+ public void deleteConfigurations(String filter) throws Exception {
+ ConfigurationAdmin cad=ac.getConfigurationAdmin();
+ Configuration[] confs = null;
+ if (cad!= null) {
+ confs = cad.listConfigurations(filter);
+ }
+ if (confs != null)
+ for (int i = 0; i < confs.length; i++) {
+ confs[i].delete();
+ }
+ refresh();
+ }
+
+ /**
+ * Removes a property from all the configurations selected by an LDAP expression
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#removePropertyFromConfigurations(java.lang.String, java.lang.String)
+ */
+ public void removePropertyFromConfigurations(String filter, String name)
+ throws Exception {
+ ConfigurationAdmin cad=ac.getConfigurationAdmin();
+ Configuration[] confs = null;
+ if (cad != null) {
+ confs = cad.listConfigurations(filter);
+ }
+ if (confs != null)
+ for (int i = 0; i < confs.length; i++) {
+ Dictionary dic = confs[i].getProperties();
+ Enumeration keys = dic.keys();
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+ if (key.equals(name)) {
+ dic.remove(key);
+ try {
+ confs[i].update(dic);
+ } catch (IOException e) {
+ ac.error("Unexpected exception", (Exception)e);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Updates or adds a property to configurations selected by an LDAP expression
+ * Arrays and vectors not supported
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#addPropertyToConfigurations(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void addPropertyToConfigurations(
+ String filter,
+ String name,
+ String value,
+ String type)
+ throws Exception {
+ if (isValidType(type)) {
+ ConfigurationAdmin cad=ac.getConfigurationAdmin();
+ Configuration[] confs = null;
+ if (cad != null) {
+ confs = cad.listConfigurations(filter);
+ }
+ if (confs != null)
+ for (int i = 0; i < confs.length; i++) {
+ Dictionary dic = confs[i].getProperties();
+ dic.put(name, castValueToType(type, value));
+ try {
+ confs[i].update(dic);
+ } catch (IOException e) {
+ ac.error("Unexpected exception", (Exception)e);
+ }
+ }
+ }
+ }
+
+ /**
+ *
+ * Validate that the value type is supported
+ * @param type
+ */
+ protected static boolean isValidType(String type) {
+ String[] validTypes =
+ {
+ "String",
+ "Integer",
+ "Long",
+ "Float",
+ "Double",
+ "Byte",
+ "Short",
+ "Character",
+ "Boolean",
+ "BigInteger",
+ "BigDecimal" };
+ for (int i = 0; i < validTypes.length; i++) {
+ if (validTypes[i].equalsIgnoreCase(type))
+ return true;
+ }
+ return false;
+ }
+ protected static Object castValueToType(String type, String value) {
+ value = value.equals("") ? null : value;
+ if (type.equals("String")) {
+ return value == null ? new String() : new String(value);
+ } else if (type.equals("Integer")) {
+ return value == null ? new Integer(0) : new Integer(value);
+ } else if (type.equals("Long")) {
+ return value == null ? new Long(0) : new Long(value);
+ } else if (type.equals("Float")) {
+ return value == null ? new Float(0) : new Float(value);
+ } else if (type.equals("Double")) {
+ return value == null ? new Double(0) : new Double(value);
+ } else if (type.equals("Byte")) {
+ return value == null ? new Byte("0") : new Byte(value);
+ } else if (type.equals("Short")) {
+ return value == null ? new Short("0") : new Short(value);
+ } else if (type.equals("BigInteger")) {
+ return value == null ? new BigInteger("0") : new BigInteger(value);
+ } else if (type.equals("BigDecimal")) {
+ return value == null ? new BigDecimal(0) : new BigDecimal(value);
+ } else if (type.equals("Character")) {
+ return value == null
+ ? new Character('a')
+ : new Character(value.charAt(0));
+ } else if (type.equals("Boolean")) {
+ return value == null ? new Boolean(false) : new Boolean(value);
+ } else {
+ // Unsupported type
+ return null;
+ }
+ }
+ private void registerMBeans() throws Exception{
+ ConfigurationAdmin cad=ac.getConfigurationAdmin();
+ if (cad==null) {
+ ac.debug("could not add any conf mbean, conf admin not available");
+ return;
+ }
+ ac.debug("creating mbeans for existing config objects");
+ Configuration[] confs = null;
+ //confs contains the new config objects
+ //The old ones are in configObjects, whose key is the object name.
+ confs = cad.listConfigurations(null);
+ if (confs!=null) {
+ ac.debug("Existing conf objects: ");
+ for(int i=0;i<confs.length;i++) {
+ ac.debug("\t"+confs[i].getPid());
+ //now we add the new ones
+ String oname = this.getObjectName(confs[i]);
+ server.registerMBean(
+ new ConfigurationDelegate(confs[i], ac),
+ new ObjectName(oname));
+ ac.debug("Succesfully registered? "+!server.queryMBeans(new ObjectName(oname), null).isEmpty());
+ }
+ }
+
+ }
+ public synchronized void refresh() throws Exception {
+ //Extremely innefficient but KISS
+ unregisterMBeans();
+ registerMBeans();
+ }
+ public boolean isAvailable() {
+ return ac.getConfigurationAdmin()==null?false:true;
+ }
+ private void unregisterMBeans() throws MalformedObjectNameException, NullPointerException, InstanceNotFoundException, MBeanRegistrationException{
+ Set set =
+ server.queryNames(
+ new ObjectName(ObjectNames.ALL_CM_OBJECT),
+ null);
+ Iterator it = set.iterator();
+ while (it.hasNext()) {
+ ObjectName oname=(ObjectName) it.next();
+ ac.debug("Unregistering config mbean: "+oname);
+ server.unregisterMBean(oname);
+ }
+ }
+
+ private String getObjectName(Configuration configuration) {
+ StringBuffer posfix = new StringBuffer();
+ posfix.append("pid=" + configuration.getPid());
+ if (configuration.getFactoryPid() != null)
+ posfix.append(
+ ",isFactory=true,FactoryPid=" + configuration.getFactoryPid());
+ else
+ posfix.append(",isFactory=false");
+ String oname = ObjectNames.CM_OBJECT + posfix.toString();
+ return oname;
+ }
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/ConfigAdminManagerMBean.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/ConfigAdminManagerMBean.java
new file mode 100644
index 0000000..f4a2bf3
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/ConfigAdminManagerMBean.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.compendium;
+
+
+public interface ConfigAdminManagerMBean {
+ /**
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#listConfigurations(java.lang.String)
+ */
+ public abstract String[] listConfigurations(String filter)
+ throws Exception;
+ /**
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#getConfiguration(java.lang.String)
+ */
+ public abstract String getConfiguration(String pid) throws Exception;
+ /**
+ * This method gets a configuration object related to a pid and a bundle location
+ * @param pid Persistent ID
+ * @param location Bundle location of the service
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#getConfiguration(java.lang.String, java.lang.String)
+ */
+ public abstract String getConfiguration(String pid, String location)
+ throws Exception;
+ /**
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#createFactoryConfiguration(java.lang.String)
+ */
+ public abstract String createFactoryConfiguration(String pid)
+ throws Exception;
+ /**
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#createFactoryConfiguration(java.lang.String, java.lang.String)
+ */
+ public abstract String createFactoryConfiguration(
+ String pid,
+ String location)
+ throws Exception;
+ /**
+ * Delete the configurations identified by the LDAP filter
+ * @param filter LDAP String representing the configurations that want to be deleted
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#deleteConfigurations(java.lang.String)
+ */
+ public abstract void deleteConfigurations(String filter) throws Exception;
+ /**
+ * Removes a property from all the configurations selected by an LDAP expression
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#removePropertyFromConfigurations(java.lang.String, java.lang.String)
+ */
+ public abstract void removePropertyFromConfigurations(
+ String filter,
+ String name)
+ throws Exception;
+ /**
+ * Updates or adds a property to configurations selected by an LDAP expression
+ * Arrays and vectors not supported
+ * @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#addPropertyToConfigurations(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+ */
+ public abstract void addPropertyToConfigurations(
+ String filter,
+ String name,
+ String value,
+ String type)
+ throws Exception;
+ public abstract void refresh() throws Exception;
+ public abstract boolean isAvailable() throws Exception;
+}
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/ConfigurationDelegate.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/ConfigurationDelegate.java
new file mode 100644
index 0000000..02c2b3f
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/ConfigurationDelegate.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.compendium;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.felix.jmood.AgentContext;
+import org.osgi.service.cm.Configuration;
+
+
+public class ConfigurationDelegate implements MBeanRegistration, ConfigurationDelegateMBean {
+ private Configuration configuration;
+ private MBeanServer server;
+ private ObjectName oname;
+ private AgentContext ac;
+ public ConfigurationDelegate(Configuration configuration, AgentContext ac){
+ this.configuration=configuration;
+ this.ac=ac;
+ }
+
+ /**
+ * @see org.osgi.service.cm.Configuration#getPid()
+ */
+ public String getPid() {
+
+ return configuration.getPid();
+ }
+
+ /**
+ * @see org.osgi.service.cm.Configuration#getProperties()
+ */
+ public Hashtable getProperties() {
+ Dictionary dic=configuration.getProperties();
+ Enumeration keys=dic.keys();
+ Hashtable properties=new Hashtable();
+ while(keys.hasMoreElements()) {
+ Object key=keys.nextElement();
+ properties.put(key, dic.get(key));
+ }
+ return properties;
+ }
+
+ /**
+ * @see org.osgi.service.cm.Configuration#update(java.util.Dictionary)
+ *hashtable is a dictionary!
+ */
+ public void update(Hashtable properties) throws IOException {
+ configuration.update(properties);
+ }
+
+ /**
+ * @see org.osgi.service.cm.Configuration#delete()
+ */
+ public void delete() throws Exception {
+ server.unregisterMBean(oname);
+ configuration.delete();
+ }
+
+ /**
+ * @see org.osgi.service.cm.Configuration#getFactoryPid()
+ */
+ public String getFactoryPid() {
+ return configuration.getFactoryPid();
+ }
+
+ /**
+ * @see org.osgi.service.cm.Configuration#update()
+ */
+ public void update() throws IOException {
+ configuration.update();
+ }
+
+ /**
+ * @see org.osgi.service.cm.Configuration#setBundleLocation(java.lang.String)
+ */
+ public void setBundleLocation(String bundleLocation) {
+ configuration.setBundleLocation(bundleLocation);
+ }
+
+ /**
+ * @see org.osgi.service.cm.Configuration#getBundleLocation()
+ */
+ public String getBundleLocation() {
+ return configuration.getBundleLocation();
+ }
+ /**
+ * @see javax.management.MBeanRegistration#postDeregister()
+ */
+ public void postDeregister() {
+ }
+
+ /**
+ * @see javax.management.MBeanRegistration#postRegister(java.lang.Boolean)
+ */
+ public void postRegister(Boolean registrationDone) {
+ }
+
+ /**
+ * @see javax.management.MBeanRegistration#preDeregister()
+ */
+ public void preDeregister() throws Exception {
+ }
+
+ /**
+ * @see javax.management.MBeanRegistration#preRegister(javax.management.MBeanServer, javax.management.ObjectName)
+ */
+ public ObjectName preRegister(MBeanServer server, ObjectName name)
+ throws Exception {
+ this.oname=name;
+ this.server=server;
+ return name;
+ }
+
+ /**
+ * @see org.apache.felix.jmood.compendium.ConfigurationDelegateMBean#getProperty(java.lang.String)
+ */
+ public String getProperty(String key) throws Exception {
+ Object result= configuration.getProperties().get(key);
+ if (result==null) return null;
+ if (result instanceof String) return (String) result;
+ else return result.toString();
+ }
+
+ /**
+ * @see org.apache.felix.jmood.compendium.ConfigurationDelegateMBean#setProperty(java.lang.String, java.lang.String)
+ */
+ public void setProperty(String key, String value, String type) throws Exception {
+ if (ConfigAdminManager.isValidType(type)) {
+ Dictionary dic = configuration.getProperties();
+ dic.put(key, ConfigAdminManager.castValueToType(type, value));
+ try {
+ configuration.update(dic);
+ } catch (IOException e) {
+ ac.error("Unexpected exception", (Exception)e);
+ }
+ }
+ }
+ public void deleteProperty(String key) throws Exception{
+ Dictionary dic = configuration.getProperties();
+ Enumeration keys = dic.keys();
+ while (keys.hasMoreElements()) {
+ String k = (String) keys.nextElement();
+ if (k.equals(key)) {
+ dic.remove(k);
+ configuration.update(dic);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/ConfigurationDelegateMBean.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/ConfigurationDelegateMBean.java
new file mode 100644
index 0000000..8724cce
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/ConfigurationDelegateMBean.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.compendium;
+import java.util.Hashtable;
+
+public interface ConfigurationDelegateMBean {
+ /* (no Javadoc)
+ * @see org.osgi.service.cm.Configuration#getPid()
+ */
+ public abstract String getPid() throws Exception;
+ /* (no Javadoc)
+ * @see org.osgi.service.cm.Configuration#getProperties()
+ */
+ public abstract Hashtable getProperties() throws Exception;
+ /* (no Javadoc)
+ * @see org.osgi.service.cm.Configuration#update(java.util.Dictionary)
+ *hashtable is a dictionary!
+ */
+ public abstract void update(Hashtable properties) throws Exception;
+ /* (no Javadoc)
+ * @see org.osgi.service.cm.Configuration#delete()
+ */
+ public abstract void delete() throws Exception;
+ /* (no Javadoc)
+ * @see org.osgi.service.cm.Configuration#getFactoryPid()
+ */
+ public abstract String getFactoryPid() throws Exception;
+ /* (no Javadoc)
+ * @see org.osgi.service.cm.Configuration#update()
+ */
+ public abstract void update() throws Exception;
+ /* (no Javadoc)
+ * @see org.osgi.service.cm.Configuration#setBundleLocation(java.lang.String)
+ */
+ public abstract void setBundleLocation(String bundleLocation) throws Exception;
+ /* (no Javadoc)
+ * @see org.osgi.service.cm.Configuration#getBundleLocation()
+ */
+ public abstract String getBundleLocation() throws Exception;
+ /* (no Javadoc)
+ * @see org.apache.felix.jmood.modules.configadmin.ConfigurationDelegateMXBean#getProperty(java.lang.String)
+ */
+ public abstract String getProperty(String key) throws Exception;
+ /* (no Javadoc)
+ * @see org.apache.felix.jmood.modules.configadmin.ConfigurationDelegateMXBean#setProperty(java.lang.String, java.lang.String)
+ */
+ public abstract void setProperty(String key, String value, String type)
+ throws Exception;
+ public abstract void deleteProperty(String key) throws Exception;
+}
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/LogManager.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/LogManager.java
new file mode 100644
index 0000000..5e181ed
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/LogManager.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.compendium;
+
+import java.util.*;
+import javax.management.*;
+import javax.management.openmbean.*;
+
+import org.apache.felix.jmood.AgentConstants;
+import org.apache.felix.jmood.AgentContext;
+import org.apache.felix.jmood.utils.*;
+import org.osgi.framework.*;
+import org.osgi.service.log.*;
+
+
+/**
+ *
+ * This class enables remote management of
+ * org.osgi.service.log.LogReaderService It enables the operator to read
+ * the system log.
+ */
+// FUTURE WORK: limitations of Log manager: if the service appears or
+// disappears, and/or there ismore than one service available, correct
+// functioning is not guaranteed. A New manager should be branched for each
+// available log service, and info should be merged to expose it afterwards.
+// FUTURE WORK: Log Listener should be an anonymous class
+// FUTURE WORK: Add persistence to the log manager
+public class LogManager extends NotificationBroadcasterSupport implements
+ LogListener, MBeanRegistration, LogManagerMBean {
+ private LogReaderService logReader = null;
+
+ private ServiceReference[] refs;
+
+ private LogService log = null;
+
+ private String[][] Log;
+
+ private static final int DefaultLogLevel = 0;
+
+ private int LogLevel;
+
+ private Vector entryVector;
+
+ private static int sequenceNumber = 0;
+
+ private AgentContext ac;
+
+ private ServiceRegistration registration;
+
+ // FUTURE WORK: add persistence to sequence numbers
+ public LogManager(AgentContext ac) {
+ this.ac = ac;
+ }
+
+ public void setLogLevel(int level) {
+ // FUTURE WORK This setting only affects to the agent. Extend it to the
+ // service. This is implementation dependent.
+ this.LogLevel = level;
+ }
+
+ public int getLogLevel() {
+ return LogLevel;
+ }
+
+ public CompositeData[] getLog() {
+ if (entryVector == null) {
+ return null;
+ } else {
+ try {
+
+ CompositeData[] value = new CompositeData[entryVector.size()];
+ for (int i = 0; i < entryVector.size(); i++) {
+ value[i] = OSGi2JMXCodec
+ .encodeLogEntry((LogEntry) entryVector.elementAt(i));
+ }
+ return value;
+ } catch (Exception e) {
+ ac.error("Unexpected exception", e);
+ return null;
+ }
+ }
+
+ }
+
+ /**
+ * This method exposes the attribute LogFromReader for remote management.
+ * The main difference with the log attribute is that the later uses the
+ * level configuration specified by the log level attribute and as a
+ * drawback does not include log entries registered before the log manager
+ * was started.
+ *
+ * @return
+ */
+ public String[] getLogMessages() {
+ if (entryVector == null)
+ return null;
+ String[] msgs = new String[entryVector.size()];
+ for (int i = 0; i < msgs.length; i++) {
+ LogEntry entry = (LogEntry) entryVector.elementAt(i);
+ msgs[i] = "BUNDLE " + entry.getBundle().getBundleId() + " ("
+ + entry.getBundle().getLocation() + "): LEVEL="
+ + this.getLevelAsString(entry.getLevel()) + "; MESSAGE="
+ + entry.getMessage();
+ }
+ return msgs;
+
+ }
+
+ /**
+ * @see javax.management.MBeanRegistration#postDeregister()
+ *
+ */
+ public void postDeregister() {
+ }
+
+ /**
+ * @see javax.management.MBeanRegistration#postRegister(java.lang.Boolean)
+ * @param registrationDone
+ */
+ public void postRegister(Boolean registrationDone) {
+ }
+
+ /**
+ * @see javax.management.MBeanRegistration#preDeregister()
+ * @throws java.lang.Exception
+ */
+ public void preDeregister() throws Exception {
+ registration.unregister();
+ }
+
+ /**
+ * @see javax.management.MBeanRegistration#preRegister(javax.management.MBeanServer,
+ * javax.management.ObjectName)
+ * @param server
+ * @param name
+ * @return
+ * @throws java.lang.Exception
+ */
+ public ObjectName preRegister(MBeanServer server, ObjectName name) {
+ this.entryVector = new Vector();
+ this.LogLevel = DefaultLogLevel;
+ registration=ac.getBundleContext().registerService(LogListener.class.getName(), this, null);
+ return name;
+ }
+
+ /**
+ * @see org.osgi.service.log.LogListener#logged(org.osgi.service.log.LogEntry)
+ * @param arg0
+ */
+ public void logged(LogEntry entry) {
+ if (entry.getLevel() >= this.LogLevel) {
+ this.notifyLogEntry(entry);
+ entryVector.add(entry);
+ }
+
+ }
+
+ private void notifyLogEntry(LogEntry entry) {
+ // TEST: See if user data are correctly received. This we cannot do with
+ // MC4J
+ String Level = this.getLevelAsString(entry.getLevel());
+ try {
+ ObjectName source = new ObjectName(ObjectNames.LOG_SERVICE);
+ String message = "Log entry added: Bundle "
+ + entry.getBundle().getLocation() + " with id "
+ + entry.getBundle().getBundleId()
+ + " has added a new log entry of level " + Level
+ + ". The message is: " + entry.getMessage();
+ Notification notification = new Notification(
+ AgentConstants.LOG_NOTIFICATION_TYPE, source,
+ sequenceNumber++, message);
+ // User data is CompositeData with the info of the log entry
+
+ CompositeData userData = OSGi2JMXCodec.encodeLogEntry(entry);
+
+ // Before using composite data, we used a simple string array:
+ /*
+ * String[] userData = new String[4]; userData[0] =
+ * entry.getBundle().getLocation(); userData[1] = new
+ * Long(entry.getBundle().getBundleId()).toString(); userData[2] =
+ * Level; userData[3] = entry.getMessage();
+ */
+
+ notification.setUserData(userData);
+ sendNotification(notification);
+ } catch (Exception e) {
+ ac.error("Unexpected exception", e);
+ }
+ }
+
+ private String getLevelAsString(int level) {
+ String Level;
+ switch (level) {
+ case LogService.LOG_DEBUG:
+ Level = "DEBUG";
+ break;
+ case LogService.LOG_WARNING:
+ Level = "WARNING";
+ break;
+ case LogService.LOG_INFO:
+ Level = "INFO";
+ break;
+ case LogService.LOG_ERROR:
+ Level = "ERROR";
+ break;
+ default:
+ Level = "UserDefined: " + level;
+ break;
+ }
+ return Level;
+
+ }
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/LogManagerMBean.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/LogManagerMBean.java
new file mode 100644
index 0000000..cfdabc1
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/LogManagerMBean.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.compendium;
+
+import javax.management.openmbean.CompositeData;
+
+public interface LogManagerMBean {
+ //FUTURE WORK: add persistence to sequence numbers
+ public abstract void setLogLevel(int level) throws Exception;
+ public abstract int getLogLevel() throws Exception;
+ public abstract CompositeData[] getLog() throws Exception;
+ /**
+ * This method exposes the attribute LogFromReader for remote management. The main difference with the log attribute is that the later
+ * uses the level configuration specified by the log level attribute and as a drawback does not include log entries registered before the log manager was started.
+ * @return
+ */
+ public abstract String[] getLogMessages() throws Exception;
+}
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/UserManager.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/UserManager.java
new file mode 100644
index 0000000..9ea2556
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/UserManager.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.compendium;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+
+import org.apache.felix.jmood.AgentConstants;
+import org.apache.felix.jmood.AgentContext;
+import org.apache.felix.jmood.utils.OSGi2JMXCodec;
+import org.apache.felix.jmood.utils.ObjectNames;
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdminEvent;
+import org.osgi.service.useradmin.UserAdminListener;
+
+/**
+ * User manager for the gateway. This mbean provides access to the user admin
+ * functionality.
+ *
+ *
+ */
+public class UserManager extends NotificationBroadcasterSupport implements
+ MBeanRegistration, UserManagerMBean {
+ private AgentContext ac;
+
+ private UserManager um;
+
+ public UserManager(AgentContext ac) {
+ this.ac = ac;
+ this.um = this;
+ }
+
+ private static long sequenceNumber = 0;
+
+ /**
+ * Creates a role of the specified type, case insensitive, with the
+ * specified name
+ *
+ * @param name
+ * @param type
+ * @throws Exception
+ */
+ public void createRole(String name, String type) throws Exception {
+ int t = -1;
+ if (type.equalsIgnoreCase(AgentConstants.GROUP))
+ t = Role.GROUP;
+ else if (type.equalsIgnoreCase(AgentConstants.USER))
+ t = Role.USER;
+ else
+ throw new Exception(
+ "Incorrect type name. Valid names: User | Group. Case Insensitive");
+ try {
+ ac.getUserAdmin().createRole(name, t);
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. Could not create Role");
+ }
+ }
+
+ public CompositeData getRole(String name) throws Exception {
+ try {
+ return OSGi2JMXCodec.encodeRole(ac.getUserAdmin().getRole(name));
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. Could not get Role");
+ return null;
+ }
+ }
+
+ public CompositeData getGroup(String groupname) {
+ try {
+ Role group = ac.getUserAdmin().getRole(groupname);
+ if (group.getType() == Role.GROUP)
+ return OSGi2JMXCodec.encodeGroup((Group) group);
+ else
+ return null;
+
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return null;
+ } catch (Exception e) {
+ ac.error("unexpected exception", e);
+ return null;
+ }
+ }
+
+ public CompositeData getUser(String username) throws Exception {
+ try {
+ Role user = ac.getUserAdmin().getRole(username);
+ if (user.getType() == Role.USER)
+ return OSGi2JMXCodec.encodeUser((User) user);
+ else
+ return null;
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return null;
+ }
+
+ }
+
+ public CompositeData getAuthorization(String user) {
+ try {
+ return OSGi2JMXCodec.encodeAuthorization(ac.getUserAdmin()
+ .getAuthorization((User) ac.getUserAdmin().getRole(user)));
+ } catch (Exception e) {
+ ac.error("unexpected exception", e);
+ return null;
+
+ }
+ }
+
+ public String[] getRoles(String filter) throws Exception {
+ try {
+ Role[] roles = ac.getUserAdmin().getRoles(filter);
+ String[] result = new String[roles.length];
+ for (int i = 0; i < roles.length; i++) {
+ result[i] = roles[i].getName();
+ }
+ return result;
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return null;
+ }
+
+ }
+
+ public String getUser(String key, String value) {
+ try {
+ return ac.getUserAdmin().getUser(key, value).getName();
+
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return null;
+ }
+ }
+
+ public boolean removeRole(String name) {
+ try {
+ return ac.getUserAdmin().removeRole(name);
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return false;
+ }
+ }
+
+ public String[] getRoles() throws Exception {
+ try {
+ Role[] roles = ac.getUserAdmin().getRoles(null);
+ String[] result = new String[roles.length];
+ for (int i = 0; i < roles.length; i++) {
+ result[i] = roles[i].getName();
+ }
+ return result;
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return null;
+ }
+ }
+
+ public String[] getGroups() throws Exception {
+ try {
+ Role[] roles = ac.getUserAdmin().getRoles(null);
+ Vector tmp = new Vector();
+ int j = 0;
+ for (int i = 0; i < roles.length; i++) {
+ if (roles[i].getType() == Role.GROUP) {
+ j++;
+ tmp.add(roles[i].getName());
+ }
+ }
+ if (j == 0)
+ return new String[0];
+ else {
+ String[] result = new String[j];
+ tmp.copyInto(result);
+ return result;
+ }
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return null;
+ }
+
+ }
+
+ public String[] getUsers() throws Exception {
+ try {
+ Role[] roles = ac.getUserAdmin().getRoles(null);
+ Vector tmp = new Vector();
+ int j = 0;
+ for (int i = 0; i < roles.length; i++) {
+ if (roles[i].getType() == Role.USER) {
+ j++;
+ tmp.add(roles[i].getName());
+ }
+ }
+ if (j == 0)
+ return new String[0];
+ else {
+ String[] result = new String[j];
+ tmp.copyInto(result);
+ return result;
+ }
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return null;
+ }
+
+ }
+
+ public String[] getMembers(String groupname) {
+ try {
+ Group group = (Group) ac.getUserAdmin().getRole(groupname);
+ Role[] members = group.getMembers();
+ if (members == null)
+ return null;
+ String[] names = new String[members.length];
+ for (int i = 0; i < members.length; i++) {
+ names[i] = members[i].getName();
+ }
+ return names;
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return null;
+ }
+ }
+
+ public String[] getRequiredMembers(String groupname) {
+ try {
+ Group group = (Group) ac.getUserAdmin().getRole(groupname);
+ Role[] members = group.getRequiredMembers();
+ if (members == null)
+ return null;
+ String[] names = new String[members.length];
+ for (int i = 0; i < members.length; i++) {
+ names[i] = members[i].getName();
+ }
+ return names;
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return null;
+ }
+
+ }
+
+ public boolean addMember(String groupname, String rolename) {
+ try {
+ Role group = ac.getUserAdmin().getRole(groupname);
+ Role role = ac.getUserAdmin().getRole(rolename);
+ if (!(group.getType() == Role.GROUP))
+ return false;
+ return ((Group) group).addMember(role);
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return false;
+ }
+ }
+
+ public boolean addRequiredMember(String groupname, String rolename) {
+ try {
+ Role group = ac.getUserAdmin().getRole(groupname);
+ Role role = ac.getUserAdmin().getRole(rolename);
+ if (!(group.getType() == Role.GROUP))
+ return false;
+ return ((Group) group).addRequiredMember(role);
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return false;
+ }
+
+ }
+
+ public boolean removeMember(String groupname, String rolename) {
+ try {
+ Role group = ac.getUserAdmin().getRole(groupname);
+ Role role = ac.getUserAdmin().getRole(rolename);
+ if (!(group.getType() == Role.GROUP))
+ return false;
+ return ((Group) group).removeMember(role);
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return false;
+ }
+ }
+
+ public String[] getImpliedRoles(String username) throws Exception {
+ try {
+ Role role = ac.getUserAdmin().getRole(username);
+ if (role.getType() == Role.USER && role instanceof User) {
+ return ac.getUserAdmin().getAuthorization((User) role)
+ .getRoles();
+ } else
+ return null;
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return null;
+ }
+ }
+
+ public void addProperty(String key, Object value, String rolename)
+ throws IllegalArgumentException {
+ try {
+ if (value instanceof Byte[]) {
+ Byte[] ByteValue = (Byte[]) value;
+ byte[] primitive = new byte[ByteValue.length];
+ for (int i = 0; i < ByteValue.length; i++)
+ primitive[i] = ByteValue[i].byteValue();
+ value = primitive;
+ } else if (!(value instanceof String) && !(value instanceof byte[]))
+ throw new IllegalArgumentException(
+ "Credentials can only be byte[] or String");
+ Role role = ac.getUserAdmin().getRole(rolename);
+ role.getProperties().put(key, value);
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ }
+
+ }
+
+ public void removeProperty(String key, String rolename) {
+ try {
+ Role role = ac.getUserAdmin().getRole(rolename);
+ role.getProperties().remove(key);
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ }
+
+ }
+
+ public void addCredential(String key, Object value, String username)
+ throws IllegalArgumentException {
+ try {
+ if (value instanceof Byte[]) {
+ Byte[] ByteValue = (Byte[]) value;
+ byte[] primitive = new byte[ByteValue.length];
+ for (int i = 0; i < ByteValue.length; i++)
+ primitive[i] = ByteValue[i].byteValue();
+ value = primitive;
+ } else if (!(value instanceof String) && !(value instanceof byte[]))
+ throw new IllegalArgumentException(
+ "Credentials can only be byte[] or String");
+ User user = (User) ac.getUserAdmin().getRole(username);
+ user.getCredentials().put(key, value);
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ }
+
+ }
+
+ public void removeCredential(String key, String username) {
+ try {
+ User user = (User) ac.getUserAdmin().getRole(username);
+ user.getCredentials().remove(key);
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ } catch (Exception e) {
+ ac.error("unexpected exception", e);
+ }
+ }
+
+ public Hashtable getProperties(String rolename) {
+ try {
+ Role role = ac.getUserAdmin().getRole(rolename);
+ Dictionary dic = role.getProperties();
+ Hashtable props = new Hashtable();
+ Enumeration keys = dic.keys();
+ while (keys.hasMoreElements()) {
+ Object key = keys.nextElement();
+ props.put(key, dic.get(key));
+ }
+ return props;
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return null;
+ }
+ }
+
+ public Hashtable getCredentials(String username) {
+ try {
+ User user = (User) ac.getUserAdmin().getRole(username);
+ Dictionary dic = user.getCredentials();
+ Hashtable credentials = new Hashtable();
+ Enumeration keys = dic.keys();
+ while (keys.hasMoreElements()) {
+ Object key = keys.nextElement();
+ credentials.put(key, dic.get(key));
+ }
+ return credentials;
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ return null;
+ }
+
+ }
+
+ // /////////////////////MBEANREGISTRATION
+ // METHODS///////////////////////////////////////////////////
+ public void postDeregister() {
+ }
+
+ public void postRegister(Boolean registrationDone) {
+ }
+
+ public void preDeregister() throws Exception {
+ }
+
+ /**
+ * @see javax.management.MBeanRegistration#preRegister(javax.management.MBeanServer,
+ * javax.management.ObjectName)
+ * @param server
+ * @param name
+ * @return
+ * @throws java.lang.Exception
+ */
+ public ObjectName preRegister(MBeanServer server, ObjectName name)
+ throws Exception {
+ ac.getBundleContext().registerService(
+ UserAdminListener.class.getName(), new UserAdminListener() {
+ public void roleChanged(UserAdminEvent e) {
+ um.notifyUserAdminEvent(e);
+ }
+ }, null);
+ try {
+ ac.getUserAdmin().removeRole(AgentConstants.USER);
+ } catch (NullPointerException npe) {
+ ac.debug("UserAdmin not available. ");
+ }
+ return name;
+
+ }
+
+ // ///////PRIVATE METHODS//////////////////////////
+ private void notifyUserAdminEvent(UserAdminEvent event) {
+ String typedesc = null;
+ switch (event.getType()) {
+ case UserAdminEvent.ROLE_CREATED:
+ typedesc = "created";
+ break;
+ case UserAdminEvent.ROLE_CHANGED:
+ typedesc = "changed";
+ break;
+ case UserAdminEvent.ROLE_REMOVED:
+ typedesc = "removed";
+ break;
+ }
+ try {
+ ObjectName source = new ObjectName(ObjectNames.UA_SERVICE);
+ String message = "User Admin event: Role "
+ + event.getRole().getName() + typedesc;
+ Notification notification = new Notification(
+ AgentConstants.USER_ADMIN_NOTIFICATION_TYPE, source,
+ sequenceNumber++, message);
+ CompositeData userData = OSGi2JMXCodec.encodeUserAdminEvent(event);
+ notification.setUserData(userData);
+ sendNotification(notification);
+ } catch (Exception e) {
+ ac.error("Unexpected exception", e);
+ }
+ }
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/UserManagerMBean.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/UserManagerMBean.java
new file mode 100644
index 0000000..910fb4f
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/compendium/UserManagerMBean.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.compendium;
+
+import java.util.Hashtable;
+
+import javax.management.openmbean.CompositeData;
+
+public interface UserManagerMBean {
+ /**
+ * Creates a role of the specified type, case insensitive, with the specified name
+ * @param name
+ * @param type
+ * @throws Exception
+ */
+ public abstract void createRole(String name, String type) throws Exception;
+ public abstract CompositeData getRole(String name) throws Exception;
+ public abstract CompositeData getGroup(String groupname) throws Exception;
+ public abstract CompositeData getUser(String username) throws Exception;
+ public abstract CompositeData getAuthorization(String user) throws Exception;
+ public abstract String[] getRoles(String filter) throws Exception;
+ public abstract String getUser(String key, String value) throws Exception;
+ public abstract boolean removeRole(String name) throws Exception;
+ public abstract String[] getRoles() throws Exception;
+ public abstract String[] getGroups() throws Exception;
+ public abstract String[] getUsers() throws Exception;
+ public abstract String[] getMembers(String groupname) throws Exception;
+ public abstract String[] getRequiredMembers(String groupname) throws Exception;
+ public abstract boolean addMember(String groupname, String rolename) throws Exception;
+ public abstract boolean addRequiredMember(
+ String groupname,
+ String rolename) throws Exception;
+ public abstract boolean removeMember(String groupname, String rolename) throws Exception;
+ public abstract String[] getImpliedRoles(String username) throws Exception;
+ public abstract void addProperty(String key, Object value, String rolename) throws Exception;
+ public abstract void removeProperty(String key, String rolename) throws Exception;
+ public abstract void addCredential(String key,Object value, String username) throws Exception;
+ public abstract void removeCredential(String key, String username) throws Exception;
+ public abstract Hashtable getProperties(String rolename) throws Exception;
+ public abstract Hashtable getCredentials(String username) throws Exception;
+}
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/BundleNotAvailableException.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/BundleNotAvailableException.java
new file mode 100644
index 0000000..06e9ec5
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/BundleNotAvailableException.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+
+public class BundleNotAvailableException extends Exception {
+
+ public BundleNotAvailableException() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ public BundleNotAvailableException(String message) {
+ super(message);
+ // TODO Auto-generated constructor stub
+ }
+
+ public BundleNotAvailableException(String message, Throwable cause) {
+ super(message, cause);
+ // TODO Auto-generated constructor stub
+ }
+
+ public BundleNotAvailableException(Throwable cause) {
+ super(cause);
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/CoreController.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/CoreController.java
new file mode 100644
index 0000000..af81b1b
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/CoreController.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.apache.felix.jmood.AgentContext;
+import org.apache.felix.jmood.utils.InstrumentationSupport;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.startlevel.StartLevel;
+
+
+public class CoreController implements CoreControllerMBean {
+ private AgentContext ac;
+
+ public CoreController(AgentContext ac) {
+ super();
+ this.ac = ac;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#startBundle(java.lang.String)
+ */
+ public void startBundle(String bundleSymbolicName) throws BundleException,
+ BundleNotAvailableException {
+ String[] s = bundleSymbolicName.split(";");
+ long id = InstrumentationSupport.getBundleId(bundleSymbolicName, ac);
+ ac.getBundleContext().getBundle(id).start();
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#batchStartBundles(java.lang.String[])
+ */
+ public void batchStartBundles(String[] bundleSymbolicNames)
+ throws BundleException, BundleNotAvailableException {
+ if (bundleSymbolicNames == null)
+ throw new IllegalArgumentException(
+ "Array of bundles cannot be null");
+ for (int i = 0; i < bundleSymbolicNames.length; i++) {
+ this.startBundle(bundleSymbolicNames[i]);
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#stopBundle(java.lang.String)
+ */
+ public void stopBundle(String bundleSymbolicName) throws BundleException,
+ BundleNotAvailableException {
+ long id = InstrumentationSupport.getBundleId(bundleSymbolicName, ac);
+ ac.getBundleContext().getBundle(id).stop();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#batchStopBundles(java.lang.String[])
+ */
+ public void batchStopBundles(String[] bundleSymbolicNames)
+ throws BundleException, BundleNotAvailableException {
+ if (bundleSymbolicNames == null)
+ throw new IllegalArgumentException(
+ "Array of bundles cannot be null");
+ for (int i = 0; i < bundleSymbolicNames.length; i++) {
+ this.stopBundle(bundleSymbolicNames[i]);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#updateBundle(java.lang.String)
+ */
+ public void updateBundle(String bundleSymbolicName) throws BundleException,
+ BundleNotAvailableException {
+ long id = InstrumentationSupport.getBundleId(bundleSymbolicName, ac);
+ ac.getBundleContext().getBundle(id).update();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#batchUpdateBundles(java.lang.String[])
+ */
+ public void batchUpdateBundles(String[] bundleSymbolicNames)
+ throws BundleException, BundleNotAvailableException {
+ if (bundleSymbolicNames == null)
+ throw new IllegalArgumentException(
+ "Array of bundles cannot be null");
+ for (int i = 0; i < bundleSymbolicNames.length; i++) {
+ this.updateBundle(bundleSymbolicNames[i]);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#updateBundleFromUrl(java.lang.String,
+ * java.lang.String)
+ */
+ public void updateBundleFromUrl(String bundleSymbolicName, String url)
+ throws BundleException, BundleNotAvailableException,
+ MalformedURLException, IOException {
+ long id = InstrumentationSupport.getBundleId(bundleSymbolicName, ac);
+ ac.getBundleContext().getBundle(id).update((new URL(url)).openStream());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#batchUpdateBundleFromUrl(java.lang.String[],
+ * java.lang.String[])
+ */
+ public void batchUpdateBundleFromUrl(String[] bundleSymbolicNames,
+ String[] urls) throws BundleException, BundleNotAvailableException,
+ MalformedURLException, IOException {
+ if (bundleSymbolicNames == null || urls == null)
+ throw new IllegalArgumentException("arguments cannot be null");
+ if (urls.length != bundleSymbolicNames.length)
+ throw new IllegalArgumentException(
+ "Each bundle needs a corresponding url");
+ for (int i = 0; i < bundleSymbolicNames.length; i++) {
+ this.updateBundleFromUrl(bundleSymbolicNames[i], urls[i]);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#installBundle(java.lang.String)
+ */
+ public void installBundle(String bundleLocation) throws BundleException {
+ ac.getBundleContext().installBundle(bundleLocation);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#batchInstallBundle(java.lang.String[])
+ */
+ public void batchInstallBundle(String[] bundleLocations)
+ throws BundleException {
+ for (int i = 0; i < bundleLocations.length; i++) {
+ this.installBundle(bundleLocations[i]);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#setBundleStartLevel(java.lang.String,
+ * int)
+ */
+ public void setBundleStartLevel(String bundleSymbolicName, int newlevel)
+ throws BundleNotAvailableException, ServiceNotAvailableException {
+ StartLevel sl = ac.getStartLevel();
+ if (sl == null) {
+ ac.debug("tried to modify startlevel, but no service found");
+ throw new ServiceNotAvailableException(
+ "Start Level service not available");
+ }
+ long id = InstrumentationSupport.getBundleId(bundleSymbolicName, ac);
+ ac.getStartLevel().setBundleStartLevel(
+ ac.getBundleContext().getBundle(id), newlevel);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#batchSetBundleStartLevel(java.lang.String[],
+ * int[])
+ */
+ public void batchSetBundleStartLevel(String[] bundleSymbolicNames,
+ int[] newlevels) {
+ if (bundleSymbolicNames == null || newlevels == null)
+ throw new IllegalArgumentException("arguments cannot be null");
+ if (newlevels.length != bundleSymbolicNames.length)
+ throw new IllegalArgumentException(
+ "Each bundle needs a corresponding new level");
+ for (int i = 0; i < newlevels.length; i++) {
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#refreshPackages(java.lang.String[])
+ */
+ public void refreshPackages(String[] bundleSymbolicNames)
+ throws BundleNotAvailableException, ServiceNotAvailableException {
+ if (bundleSymbolicNames == null)
+ throw new IllegalArgumentException("argument cannot be null");
+ Bundle[] bundles = new Bundle[bundleSymbolicNames.length];
+ for (int i = 0; i < bundles.length; i++) {
+ long id = InstrumentationSupport.getBundleId(
+ bundleSymbolicNames[i], ac);
+ bundles[i] = ac.getBundleContext().getBundle(id);
+ if (bundles[i] == null)
+ throw new BundleNotAvailableException(
+ "could not get bundle whose id" + id);
+ }
+ ac.getPackageadmin().refreshPackages(bundles);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#resolveBundles(java.lang.String[])
+ */
+ public void resolveBundles(String[] bundleSymbolicNames)
+ throws BundleNotAvailableException, ServiceNotAvailableException {
+ if (bundleSymbolicNames == null)
+ throw new IllegalArgumentException("argument cannot be null");
+ Bundle[] bundles = new Bundle[bundleSymbolicNames.length];
+ for (int i = 0; i < bundles.length; i++) {
+ long id = InstrumentationSupport.getBundleId(
+ bundleSymbolicNames[i], ac);
+ bundles[i] = ac.getBundleContext().getBundle(id);
+ if (bundles[i] == null)
+ throw new BundleNotAvailableException(
+ "could not get bundle whose id" + id);
+ }
+ ac.getPackageadmin().resolveBundles(bundles);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#setPlatformStartLevel(int)
+ */
+ public void setPlatformStartLevel(int newlevel)
+ throws ServiceNotAvailableException {
+ ac.getStartLevel().setStartLevel(newlevel);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#getPlatformStartLevel()
+ */
+ public int getPlatformStartLevel() throws ServiceNotAvailableException {
+ return ac.getStartLevel().getStartLevel();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#setInitialBundleStartLevel(int)
+ */
+ public void setInitialBundleStartLevel(int newlevel)
+ throws ServiceNotAvailableException {
+ ac.getStartLevel().setInitialBundleStartLevel(newlevel);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#getInitialBundleStartLevel()
+ */
+ public int getInitialBundleStartLevel() throws ServiceNotAvailableException {
+ return ac.getStartLevel().getInitialBundleStartLevel();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#restartFramework()
+ */
+ public void restartFramework() throws NotImplementedException {
+ try {
+ ac.getBundleContext().getBundle(0).update();
+ } catch (BundleException be) {
+ throw new NotImplementedException(
+ "Restarting not implemented in this framework", be);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#shutdownFramework()
+ */
+ public void shutdownFramework() throws NotImplementedException {
+ try {
+ ac.getBundleContext().getBundle(0).stop();
+ } catch (BundleException be) {
+ throw new NotImplementedException(
+ "Shutting down not implemented in this framework", be);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.CoreControllerMBean#updateFramework()
+ */
+ public void updateFramework() throws NotImplementedException {
+ // TODO
+ throw new NotImplementedException(
+ "Feature not implemented for this framework");
+ }
+
+ public void uninstallBundle(String bundleSymbolicName)
+ throws BundleNotAvailableException, BundleException {
+ if (bundleSymbolicName == null)
+ throw new IllegalArgumentException("argument cannot be null");
+ String[] s = bundleSymbolicName.split(";");
+ long id = InstrumentationSupport.getBundleId(bundleSymbolicName, ac);
+ ac.getBundleContext().getBundle(id).uninstall();
+
+ }
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/CoreControllerMBean.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/CoreControllerMBean.java
new file mode 100644
index 0000000..85e8fca
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/CoreControllerMBean.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+import org.osgi.framework.BundleException;
+
+/**
+ * The CoreController mbean provides mechanisms to exert control over the
+ * framework. For many operations, it provides a batch mechanism to avoid
+ * excessive message passing when interacting remotely.
+ *
+ */
+public interface CoreControllerMBean {
+
+ public abstract void startBundle(String bundleSymbolicName)
+ throws BundleException, BundleNotAvailableException;
+
+ public abstract void batchStartBundles(String[] bundleSymbolicNames)
+ throws BundleException, BundleNotAvailableException;
+
+ public abstract void stopBundle(String bundleSymbolicName)
+ throws BundleException, BundleNotAvailableException;
+
+ public abstract void batchStopBundles(String[] bundleSymbolicNames)
+ throws BundleException, BundleNotAvailableException;
+
+ public abstract void updateBundle(String bundleSymbolicName)
+ throws BundleException, BundleNotAvailableException;
+
+ public abstract void uninstallBundle(String bundleSymbolicName)
+ throws BundleNotAvailableException, BundleException;
+
+ public abstract void batchUpdateBundles(String[] bundleSymbolicNames)
+ throws BundleException, BundleNotAvailableException;
+
+ public abstract void updateBundleFromUrl(String bundleSymbolicName,
+ String url) throws BundleException, BundleNotAvailableException,
+ MalformedURLException, IOException;
+
+ public abstract void batchUpdateBundleFromUrl(String[] bundleSymbolicNames,
+ String[] urls) throws BundleException, BundleNotAvailableException,
+ MalformedURLException, IOException;
+
+ public abstract void installBundle(String bundleLocation)
+ throws BundleException;
+
+ public abstract void batchInstallBundle(String[] bundleLocations)
+ throws BundleException;
+
+ public abstract void setBundleStartLevel(String bundleSymbolicName,
+ int newlevel) throws BundleNotAvailableException,
+ ServiceNotAvailableException;
+
+ public abstract void batchSetBundleStartLevel(String[] bundleSymbolicNames,
+ int[] newlevels);
+
+ public abstract void refreshPackages(String[] bundleSymbolicNames)
+ throws BundleNotAvailableException, ServiceNotAvailableException;
+
+ public abstract void resolveBundles(String[] bundleSymbolicNames)
+ throws BundleNotAvailableException, ServiceNotAvailableException;
+
+ public abstract void setPlatformStartLevel(int newlevel) throws ServiceNotAvailableException;
+
+ public abstract int getPlatformStartLevel() throws ServiceNotAvailableException;
+
+ /**
+ *
+ * @param newlevel
+ * @throws ServiceNotAvailableException if StartLevel service not available, or RuntimeMBeanException that wraps an IllegalArgumentException, as specified
+ * by the Start Level service.
+ */
+ public abstract void setInitialBundleStartLevel(int newlevel) throws ServiceNotAvailableException;
+
+ public abstract int getInitialBundleStartLevel() throws ServiceNotAvailableException;
+
+ public abstract void restartFramework() throws NotImplementedException;
+
+ public abstract void shutdownFramework() throws NotImplementedException;
+
+ public abstract void updateFramework() throws NotImplementedException;
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/Framework.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/Framework.java
new file mode 100644
index 0000000..8d1a242
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/Framework.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+
+import org.apache.felix.jmood.AgentContext;
+import org.apache.felix.jmood.core.instrumentation.BundleInfo;
+import org.apache.felix.jmood.core.instrumentation.FrameworkSnapshot;
+import org.apache.felix.jmood.core.instrumentation.PackageInfo;
+import org.apache.felix.jmood.core.instrumentation.ServiceInfo;
+import org.apache.felix.jmood.utils.InstrumentationSupport;
+import org.apache.felix.jmood.utils.ObjectNames;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+public class Framework implements FrameworkMBean, MBeanRegistration {
+ private MBeanRegistrator registrator;
+
+ private AgentContext ac;
+
+ private FrameworkSnapshot snapshot;
+
+ public Framework(AgentContext ac) {
+ super();
+ this.ac = ac;
+ snapshot = new FrameworkSnapshot(ac);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.FrameworkMBean#getBundles()
+ */
+ public BundleInfo[] getBundles() {
+ snapshot.refreshSnapshot();
+ return snapshot.getAllBundles();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.FrameworkMBean#getServiceInfo()
+ */
+ public ServiceInfo[] getServiceInfo() throws InvalidSyntaxException {
+ snapshot.refreshSnapshot();
+ return snapshot.getAllServiceInfo();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.jmood.core.FrameworkMBean#getPackageInfo()
+ */
+ public PackageInfo[] getPackageInfo() throws ServiceNotAvailableException {
+ snapshot.refreshSnapshot();
+ return snapshot.getAllPackageInfo();
+ }
+
+ public Hashtable getProperties() {
+ Hashtable props = new Hashtable();
+ // We do not cache it just in case some value changes (although
+ // unlikely)
+ props.put(Constants.FRAMEWORK_VERSION, ac.getBundleContext()
+ .getProperty(Constants.FRAMEWORK_VERSION));
+ props.put(Constants.FRAMEWORK_VENDOR, ac.getBundleContext()
+ .getProperty(Constants.FRAMEWORK_VENDOR));
+ props.put(Constants.FRAMEWORK_LANGUAGE, ac.getBundleContext()
+ .getProperty(Constants.FRAMEWORK_LANGUAGE));
+ props.put(Constants.FRAMEWORK_OS_NAME, ac.getBundleContext()
+ .getProperty(Constants.FRAMEWORK_OS_NAME));
+ props.put(Constants.FRAMEWORK_OS_VERSION, ac.getBundleContext()
+ .getProperty(Constants.FRAMEWORK_OS_VERSION));
+ props.put(Constants.FRAMEWORK_PROCESSOR, ac.getBundleContext()
+ .getProperty(Constants.FRAMEWORK_PROCESSOR));
+ String bootdel = ac.getBundleContext().getProperty(
+ Constants.FRAMEWORK_BOOTDELEGATION);
+ if (bootdel != null)
+ props.put(Constants.FRAMEWORK_BOOTDELEGATION, bootdel);
+ String execenv = ac.getBundleContext().getProperty(
+ Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
+ if (execenv != null)
+ props.put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, execenv);
+ String syspkgs = ac.getBundleContext().getProperty(
+ Constants.FRAMEWORK_SYSTEMPACKAGES);
+ if (syspkgs != null)
+ props.put(Constants.FRAMEWORK_SYSTEMPACKAGES, syspkgs);
+ return props;
+ }
+
+ public String getProperty(String key) {
+ return ac.getBundleContext().getProperty(key);
+ }
+
+ public ObjectName preRegister(MBeanServer server, ObjectName name)
+ throws Exception {
+ registrator = new MBeanRegistrator(server, ac);
+ return name;
+ }
+
+ public void postRegister(Boolean registrationDone) {
+ registrator.init();
+ }
+
+ public void preDeregister() throws Exception {
+ registrator.dispose();
+
+ }
+
+ public void postDeregister() {
+ }
+}
+ class MBeanRegistrator {
+ private MBeanServer server;
+
+ private AgentContext ac;
+
+ private FrameworkListener fl;
+
+ private BundleListener bl;
+
+ private ServiceListener sl;
+
+ protected MBeanRegistrator(MBeanServer server, AgentContext ac) {
+ this.server = server;
+ this.ac=ac;
+
+ fl = new FrameworkListener() {
+ public void frameworkEvent(FrameworkEvent event) {
+ if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
+ // We cannot know which are the affected packages, just refresh all
+ //However, registering mbeans is expensive, as it involves reflection
+ //TODO improve this
+ unregisterPackageMBeans();
+ registerPackageMBeans();
+ unregisterBundleMBeans();
+ registerBundleMBeans();
+ }
+ }
+ };
+ bl = new BundleListener() {
+ public void bundleChanged(BundleEvent event) {
+ switch (event.getType()){
+ case BundleEvent.INSTALLED:
+ registerBundleMBean(event.getBundle());
+ break;
+ case BundleEvent.UNINSTALLED:
+ //Ignore: uninstalled bundles are not removed until refreshed
+ break;
+ case BundleEvent.UPDATED:
+ //Ignore Update
+ break;
+ default: //nothing todo for the rest of the events
+ break;
+ }
+ }
+ };
+ sl = new ServiceListener() {
+ public void serviceChanged(ServiceEvent event) {
+ switch (event.getType()) {
+ case ServiceEvent.UNREGISTERING:
+ unregisterServiceMBean(event.getServiceReference());
+ break;
+ case ServiceEvent.REGISTERED:
+ registerServiceMBean(event.getServiceReference());
+ break;
+ default://nothing todo if MODIFIED
+ break;
+ }
+ }
+ };
+ }
+ protected void init(){
+ registerBundleMBeans();
+ registerServiceMBeans();
+ registerPackageMBeans();
+ ac.getBundleContext().addFrameworkListener(fl);
+ ac.getBundleContext().addBundleListener(bl);
+ ac.getBundleContext().addServiceListener(sl);
+ }
+ protected void dispose() {
+ ac.getBundleContext().removeFrameworkListener(fl);
+ ac.getBundleContext().removeBundleListener(bl);
+ ac.getBundleContext().removeServiceListener(sl);
+ unregisterBundleMBeans();
+ unregisterServiceMBeans();
+ unregisterPackageMBeans();
+ }
+ private void unregisterBundleMBeans(){
+ try {
+ Set bundles = server.queryNames(new ObjectName(
+ ObjectNames.ALLBUNDLES), null);
+ for (Iterator iter = bundles.iterator(); iter.hasNext();) {
+ ObjectName oname = (ObjectName) iter.next();
+ server.unregisterMBean(oname);
+ }
+
+ } catch (MalformedObjectNameException mone) {
+ ac.error("unexpected error:", mone);
+ } catch (NullPointerException npe) {
+ //No registered bundle mbeans
+ } catch (InstanceNotFoundException infe) {
+ ac.error("unexpected error:", infe);
+ } catch (MBeanRegistrationException mre) {
+ ac.error("unexpected error:", mre);
+ }
+ }
+
+ private void unregisterServiceMBeans(){
+ try {
+ Set services = server.queryNames(new ObjectName(
+ ObjectNames.ALLSERVICES), null);
+ for (Iterator iter = services.iterator(); iter.hasNext();) {
+ ObjectName oname = (ObjectName) iter.next();
+ server.unregisterMBean(oname);
+ }
+ } catch (MalformedObjectNameException mone) {
+ ac.error("unexpected error:", mone);
+ } catch (NullPointerException npe) {
+ //No registered service mbeans
+ } catch (InstanceNotFoundException infe) {
+ ac.error("unexpected error:", infe);
+ } catch (MBeanRegistrationException mre) {
+ ac.error("unexpected error:", mre);
+ }
+
+ }
+ private void unregisterPackageMBeans(){
+ try {
+ Set pkgs = server.queryNames(new ObjectName(
+ ObjectNames.ALLPACKAGES), null);
+ for (Iterator iter = pkgs.iterator(); iter.hasNext();) {
+ ObjectName oname = (ObjectName) iter.next();
+ server.unregisterMBean(oname);
+ }
+ } catch (MalformedObjectNameException mone) {
+ ac.error("unexpected error:", mone);
+ } catch (NullPointerException npe) {
+ //No registered package mbeans
+ } catch (InstanceNotFoundException infe) {
+ ac.error("unexpected error:", infe);
+ } catch (MBeanRegistrationException mre) {
+ ac.error("unexpected error:", mre);
+ }
+
+ }
+ private void unregisterServiceMBean(ServiceReference service){
+ try {
+ server.unregisterMBean(new ObjectName(ObjectNames.SERVICE+service.getProperty(Constants.SERVICE_ID)));
+ } catch (InstanceNotFoundException infe) {
+ ac.error("Unexpected error", infe);
+ } catch (MBeanRegistrationException mre) {
+ ac.error("Unexpected error", mre);
+ } catch (MalformedObjectNameException mone) {
+ ac.error("Unexpected error", mone);
+ }
+ }
+ private void registerBundleMBean(Bundle bundle){
+ try {
+ server.registerMBean(new ManagedBundle(bundle, ac),
+ new ObjectName(ObjectNames.BUNDLE
+ + InstrumentationSupport
+ .getSymbolicName(bundle)));
+ ac.debug("registered mbean for "
+ + bundle.getSymbolicName());
+
+ } catch (InstanceAlreadyExistsException iaee) {
+ ac.error("unexpected error:", iaee);
+ } catch (MBeanRegistrationException mre) {
+ ac.error("unexpected error:", mre);
+ } catch (NotCompliantMBeanException ncme) {
+ ac.error("unexpected error:", ncme);
+ } catch (MalformedObjectNameException mone) {
+ ac.error("unexpected error:", mone);
+ } catch (NullPointerException npe) {
+ ac.error("unexpected error:", npe);
+ }
+ }
+ private void registerBundleMBeans(){
+ Bundle[] bundles = ac.getBundleContext().getBundles();
+ for (int i = 0; i < bundles.length; i++) {
+ registerBundleMBean(bundles[i]);
+ }
+ }
+ private void registerServiceMBean(ServiceReference service){
+ try {
+ server.registerMBean(new ManagedService(service),
+ new ObjectName(ObjectNames.SERVICE
+ + service.getProperty(
+ Constants.SERVICE_ID)));
+ ac.debug("registed mbean for "
+ + service.getProperty(
+ Constants.SERVICE_ID));
+ } catch (InstanceAlreadyExistsException iaee) {
+ ac.error("unexpected error:", iaee);
+ } catch (MBeanRegistrationException mre) {
+ ac.error("unexpected error:", mre);
+ } catch (NotCompliantMBeanException ncme) {
+ ac.error("unexpected error:", ncme);
+ } catch (MalformedObjectNameException mone) {
+ ac.error("unexpected error:", mone);
+ } catch (NullPointerException npe) {
+ ac.error("unexpected error:", npe);
+ }
+
+ }
+ private void registerServiceMBeans(){
+ try {
+ ServiceReference[] services=ac.getBundleContext().getServiceReferences(null, null);
+ if (services != null) {
+ for (int i = 0; i < services.length; i++) {
+ registerServiceMBean(services[i]);
+ }
+ } else
+ ac.debug("no services found");
+ } catch (InvalidSyntaxException ie) {
+ ac.error("unexpected error:", ie);
+ }
+ }
+ private void registerPackageMBeans(){
+ try {
+ ExportedPackage[] pkgs=ac.getPackageadmin().getExportedPackages((Bundle)null);
+ if (pkgs != null) {
+ for (int i = 0; i < pkgs.length; i++) {
+ try {
+ server.registerMBean(new ManagedPackage(pkgs[i]),
+ new ObjectName(ObjectNames.PACKAGE
+ + InstrumentationSupport.getPackageName(pkgs[i])));
+ ac.debug("registed mbean for " + InstrumentationSupport.getPackageName(pkgs[i]));
+
+ } catch (InstanceAlreadyExistsException iaee) {
+ ac.error("unexpected error:", iaee);
+ } catch (MBeanRegistrationException mre) {
+ ac.error("unexpected error:", mre);
+ } catch (NotCompliantMBeanException ncme) {
+ ac.error("unexpected error:", ncme);
+ } catch (MalformedObjectNameException mone) {
+ ac.error("unexpected error:", mone);
+ } catch (NullPointerException npe) {
+ ac.error("unexpected error:", npe);
+ }
+ }
+ } else
+ ac.debug("no packages found");
+ } catch (ServiceNotAvailableException se) {
+ ac.error("No package admin available", se);
+ }
+ }
+ }
+
+
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/FrameworkMBean.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/FrameworkMBean.java
new file mode 100644
index 0000000..d71552d
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/FrameworkMBean.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+
+import java.util.Hashtable;
+
+import javax.management.MBeanRegistration;
+
+import org.apache.felix.jmood.core.instrumentation.BundleInfo;
+import org.apache.felix.jmood.core.instrumentation.PackageInfo;
+import org.apache.felix.jmood.core.instrumentation.ServiceInfo;
+import org.osgi.framework.InvalidSyntaxException;
+
+
+/**
+ * This mbean provides access to the basic framework information:
+ * <ul>
+ * <li><code>BundleInfo</code></li>
+ * <li><code>PackageInfo</code></li>
+ * <li><code>ServiceInfo</code></li>
+ * </ul>
+ *
+ * The idea underlying this is to provide both a reasonably fast way to access
+ * all the framework information, avoiding too much message-passing overhead, while at the same time provide console-friendly
+ * information.
+ * <p>
+ * Internally, implementations of Info objects include references to each other,
+ * so that with getBundleInfo() you get information, indirectly, of all the services
+ * and packages.
+ * </p>
+ * <p>
+ * This mbean also dynamically registers mbeans representing those objects
+ * to ease-up direct usage by generic JMX mgmt consoles (such as Jconsole)
+ * that are not aware of the data types used. While CompositeDataTypes could
+ * be used (as in former JMood implementations), they are too cumbersome to use
+ * and place too much dependency on JMX.
+ * </p>
+ *
+ * @see org.apache.felix.jmood.core.instrumentation.BundleInfo
+ * @see org.apache.felix.jmood.core.instrumentation.PackageInfo
+ * @see org.apache.felix.jmood.core.instrumentation.ServiceInfo
+ *
+ */
+public interface FrameworkMBean {
+
+ public abstract BundleInfo[] getBundles();
+
+ public abstract ServiceInfo[] getServiceInfo()
+ throws InvalidSyntaxException;
+
+ public abstract PackageInfo[] getPackageInfo()
+ throws ServiceNotAvailableException;
+ /**
+ * This hashtable contains the framework properties:
+ * <ul>
+ * <li><code>FRAMEWORK_VERSION</code></li>
+ * <li><code>FRAMEWORK_VENDOR</code></li>
+ * <li><code>FRAMEWORK_LANGUAGE</code></li>
+ * <li><code>FRAMEWORK_OS_NAME</code></li>
+ * <li><code>FRAMEWORK_OS_VERSION</code></li>
+ * <li><code>FRAMEWORK_PROCESSOR</code></li>
+ * </ul><p>Plus, if available:</p><ul>
+ * <li><code>FRAMEWORK_BOOTDELEGATION</code></li>
+ * <li><code>FRAMEWORK_EXECUTIONENVIRONMENT</code></li>
+ * <li><code>FRAMEWORK_SYSTEMPACKAGES</code></li>
+ * </ul>
+ * For any other properties, we suggest to use the getProperty(String key)
+ * @return
+ * @see org.osgi.framework.Constants
+ */
+ public abstract Hashtable getProperties();
+ /**
+ *
+ * @param key
+ * @return return the property value or null if undefined. System properties are also
+ * searched for if the property is not found in the framework properties
+ */
+ public String getProperty(String key);
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedBundle.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedBundle.java
new file mode 100644
index 0000000..4ceb2e3
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedBundle.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.apache.felix.jmood.AgentContext;
+import org.apache.felix.jmood.utils.InstrumentationSupport;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.service.packageadmin.RequiredBundle;
+
+/**
+ * This class implements the MBean interface. In order to obtain
+ * the string representation of bundles, services and packages
+ * it uses the CoreUtils static methods.
+ * @see org.apache.felix.jmood.utils.InstrumentationSupport
+ *
+ */
+public class ManagedBundle implements ManagedBundleMBean {
+ private Bundle bundle;
+ private AgentContext ac;
+ public ManagedBundle(Bundle bundle, AgentContext ac) {
+ super();
+ this.bundle=bundle;
+ this.ac=ac;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getBundleId()
+ */
+ public long getBundleId() {
+ return bundle.getBundleId();
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getExportedPackages()
+ */
+ public String[] getExportedPackages() throws ServiceNotAvailableException{
+ return InstrumentationSupport.getPackageNames(ac.getPackageadmin().getExportedPackages(bundle));
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getFragments()
+ */
+ public String[] getFragments() throws ServiceNotAvailableException{
+ return InstrumentationSupport.getSymbolicNames(ac.getPackageadmin().getFragments(bundle));
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getHeaders()
+ */
+ public Hashtable getHeaders() {
+ Hashtable ht=new Hashtable();
+ Enumeration keys=bundle.getHeaders().keys();
+ while(keys.hasMoreElements()) {
+ Object key=keys.nextElement();
+ ht.put(key, bundle.getHeaders().get(key));
+ }
+ return ht;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getHosts()
+ */
+ public String[] getHosts() throws ServiceNotAvailableException{
+ return InstrumentationSupport.getSymbolicNames(ac.getPackageadmin().getHosts(bundle));
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getImportedPackages()
+ */
+ public String[] getImportedPackages() throws ServiceNotAvailableException {
+ return InstrumentationSupport.getPackageNames(InstrumentationSupport.getImportedPackages(bundle, ac));
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getLastModified()
+ */
+ public long getLastModified() {
+ return bundle.getLastModified();
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getRegisteredServices()
+ */
+ public String[] getRegisteredServices() {
+ return InstrumentationSupport.getServiceNames(bundle.getRegisteredServices());
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getRequiredBundles()
+ */
+ public String[] getBundleDependencies() throws ServiceNotAvailableException{
+ Bundle[] required=InstrumentationSupport.getBundleDependencies(bundle, ac);
+ return InstrumentationSupport.getSymbolicNames(required);
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getRequiringBundles()
+ */
+ public String[] getRequiringBundles() throws ServiceNotAvailableException {
+ return InstrumentationSupport.getSymbolicNames(InstrumentationSupport.getRequiringBundles(bundle, ac));
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getServicesInUse()
+ */
+ public String[] getServicesInUse() {
+ return InstrumentationSupport.getServiceNames(bundle.getServicesInUse());
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getStartLevel()
+ */
+ public int getStartLevel() throws ServiceNotAvailableException {
+ return ac.getStartLevel().getBundleStartLevel(bundle);
+ }
+ public void setStartLevel(int level) throws ServiceNotAvailableException{
+ ac.getStartLevel().setBundleStartLevel(this.bundle, level);
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getState()
+ */
+ public String getState() {
+ return InstrumentationSupport.getState(bundle.getState());
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#getSymbolicName()
+ */
+ public String getSymbolicName() {
+ return bundle.getSymbolicName();
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#isBundlePersistentlyStarted()
+ */
+ public boolean isBundlePersistentlyStarted() throws ServiceNotAvailableException {
+ try{
+ return ac.getStartLevel().isBundlePersistentlyStarted(bundle);
+ } catch (NullPointerException npe){
+ ac.error("npe", npe);
+ throw npe;
+ }
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#isFragment()
+ */
+ public boolean isFragment() throws ServiceNotAvailableException{
+ return InstrumentationSupport.isFragment(bundle, ac);
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#isRemovalPending()
+ */
+ public boolean isRemovalPending() throws ServiceNotAvailableException{
+ RequiredBundle r=InstrumentationSupport.getRequiredBundle(bundle, ac);
+ if(r==null) return false;
+ return r.isRemovalPending();
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedBundleMBean#isRequired()
+ */
+ public boolean isRequired() throws ServiceNotAvailableException{
+ return InstrumentationSupport.isBundleRequired(bundle, ac);
+ }
+ public void start() throws BundleException {
+ bundle.start();
+
+ }
+ public void stop() throws BundleException {
+ bundle.stop();
+ }
+ public void update() throws BundleException {
+ bundle.update();
+
+ }
+ public void updateFromUrl(String url) throws MalformedURLException, BundleException, IOException {
+ //TODO should we use url handler service?
+ bundle.update(new URL(url).openStream());
+
+ }
+ public void refreshBundle() throws BundleNotAvailableException, ServiceNotAvailableException {
+ CoreController c=new CoreController(ac);
+ String[] b={bundle.getSymbolicName()};
+ c.refreshPackages(b);
+
+ }
+ public void resolveBundle() throws BundleNotAvailableException, ServiceNotAvailableException {
+ CoreController c=new CoreController(ac);
+ String[] b={bundle.getSymbolicName()};
+ c.resolveBundles(b);
+ }
+ public void uninstall() throws BundleException {
+ bundle.uninstall();
+
+ }
+
+
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedBundleMBean.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedBundleMBean.java
new file mode 100644
index 0000000..f909d56
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedBundleMBean.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Hashtable;
+
+import org.osgi.framework.BundleException;
+public interface ManagedBundleMBean {
+
+ public abstract long getBundleId();
+
+ public abstract String[] getExportedPackages() throws ServiceNotAvailableException;
+
+ public abstract String[] getFragments() throws ServiceNotAvailableException;
+
+ public abstract Hashtable getHeaders();
+
+ public abstract String[] getHosts() throws ServiceNotAvailableException;
+
+ public abstract String[] getImportedPackages() throws ServiceNotAvailableException;
+
+ public abstract long getLastModified();
+
+ public abstract String[] getRegisteredServices();
+
+ public abstract String[] getBundleDependencies() throws ServiceNotAvailableException;
+
+ public abstract String[] getRequiringBundles() throws ServiceNotAvailableException;
+
+ public abstract String[] getServicesInUse();
+
+ public abstract int getStartLevel() throws ServiceNotAvailableException;
+
+ public abstract String getState();
+
+ public abstract String getSymbolicName();
+
+ public abstract boolean isBundlePersistentlyStarted() throws ServiceNotAvailableException;
+
+ public abstract boolean isFragment() throws ServiceNotAvailableException;
+
+ public abstract boolean isRemovalPending() throws ServiceNotAvailableException;
+
+ public abstract boolean isRequired() throws ServiceNotAvailableException;
+
+ public abstract void start() throws BundleException;
+
+ public abstract void stop() throws BundleException;
+
+ public abstract void update() throws BundleException;
+
+ public abstract void uninstall() throws BundleException;
+
+ public abstract void updateFromUrl(String url) throws MalformedURLException, BundleException, IOException;
+
+ public abstract void refreshBundle() throws BundleNotAvailableException, ServiceNotAvailableException;
+
+ public abstract void resolveBundle() throws BundleNotAvailableException, ServiceNotAvailableException;
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedPackage.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedPackage.java
new file mode 100644
index 0000000..3021f69
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedPackage.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+
+import org.apache.felix.jmood.core.instrumentation.PackageInfo;
+import org.apache.felix.jmood.utils.InstrumentationSupport;
+import org.osgi.service.packageadmin.ExportedPackage;
+
+public class ManagedPackage implements ManagedPackageMBean {
+ private ExportedPackage pkg;
+ public ManagedPackage(ExportedPackage pkg) {
+ super();
+ this.pkg=pkg;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedPackageMBean#getExportingBundle()
+ */
+ public String getExportingBundle() {
+ return InstrumentationSupport.getSymbolicName(pkg.getExportingBundle());
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedPackageMBean#getImportingBundles()
+ */
+ public String[] getImportingBundles() {
+ return InstrumentationSupport.getSymbolicNames(pkg.getImportingBundles());
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedPackageMBean#getName()
+ */
+ public String getName() {
+ return pkg.getName();
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedPackageMBean#getVersion()
+ */
+ public String getVersion() {
+ return pkg.getVersion().toString();
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedPackageMBean#isRemovalPending()
+ */
+ public boolean isRemovalPending() {
+ return pkg.isRemovalPending();
+ }
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedPackageMBean.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedPackageMBean.java
new file mode 100644
index 0000000..c3700ac
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedPackageMBean.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+public interface ManagedPackageMBean {
+
+ /**
+ *
+ * @return the symbolic name of the exporting bundle
+ */
+ public abstract String getExportingBundle();
+
+ /**
+ *
+ * @return the symbolic names of the importing bundles
+ */
+ public abstract String[] getImportingBundles();
+
+ /**
+ *
+ * @return the package name
+ */
+ public abstract String getName();
+
+ /**
+ *
+ * @return the package version
+ */
+ public abstract String getVersion();
+
+ /**
+ *
+ * @return <code>true</code> if the associated package is being exported
+ * by a bundle that has been updated or uninstalled.
+ * @see org.osgi.service.packageadmin.ExportedPackage
+ */
+ public abstract boolean isRemovalPending();
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedService.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedService.java
new file mode 100644
index 0000000..d6f2883
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedService.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+
+import java.util.Hashtable;
+
+import org.apache.felix.jmood.core.instrumentation.ServiceInfo;
+import org.apache.felix.jmood.utils.InstrumentationSupport;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+public class ManagedService implements ManagedServiceMBean {
+ private ServiceReference svc;
+ public ManagedService(ServiceReference svc) {
+ super();
+ this.svc=svc;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedServiceMBean#getBundle()
+ */
+ public String getBundle() {
+ return InstrumentationSupport.getSymbolicName(svc.getBundle());
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedServiceMBean#getProperties()
+ */
+ public Hashtable getProperties() {
+ String[] keys=svc.getPropertyKeys();
+ Hashtable ht=new Hashtable();
+ for (int i = 0; i < keys.length; i++) {
+ ht.put(keys[i], svc.getProperty(keys[i]));
+ }
+ return ht;
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.jmood.core.ManagedServiceMBean#getUsingBundles()
+ */
+ public String[] getUsingBundles() {
+ return InstrumentationSupport.getSymbolicNames(svc.getUsingBundles());
+ }
+ public String[] getServiceInterfaces(){
+ return (String[]) svc.getProperty(Constants.OBJECTCLASS);
+ }
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedServiceMBean.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedServiceMBean.java
new file mode 100644
index 0000000..e8c1dd7
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ManagedServiceMBean.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+
+import java.util.Hashtable;
+public interface ManagedServiceMBean {
+
+ /**
+ *
+ * @return The registering bundle symbolic name
+ */
+ public abstract String getBundle();
+
+ /**
+ *
+ * @return a hashtable containing the same properties contained in
+ * the dictionary object used when registering the service. These include
+ * the standard mandatory service.id and objectClass properties as
+ * defined in the <i>org.osgi.framework.Constants</i> interface
+ * @see org.osgi.framework.Constants
+ */
+ public abstract Hashtable getProperties();
+
+ /**
+ *
+ * @return the symbolic names of the bundles using the service
+ */
+ public abstract String[] getUsingBundles();
+
+ public String[] getServiceInterfaces();
+
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/NotImplementedException.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/NotImplementedException.java
new file mode 100644
index 0000000..62d51f5
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/NotImplementedException.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+public class NotImplementedException extends Exception {
+
+ public NotImplementedException() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ public NotImplementedException(String message) {
+ super(message);
+ // TODO Auto-generated constructor stub
+ }
+
+ public NotImplementedException(String message, Throwable cause) {
+ super(message, cause);
+ // TODO Auto-generated constructor stub
+ }
+
+ public NotImplementedException(Throwable cause) {
+ super(cause);
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ServiceNotAvailableException.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ServiceNotAvailableException.java
new file mode 100644
index 0000000..9a0b3d8
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/ServiceNotAvailableException.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+
+public class ServiceNotAvailableException extends Exception {
+
+ public ServiceNotAvailableException() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ public ServiceNotAvailableException(String message) {
+ super(message);
+ // TODO Auto-generated constructor stub
+ }
+
+ public ServiceNotAvailableException(String message, Throwable cause) {
+ super(message, cause);
+ // TODO Auto-generated constructor stub
+ }
+
+ public ServiceNotAvailableException(Throwable cause) {
+ super(cause);
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/instrumentation/BundleInfo.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/instrumentation/BundleInfo.java
new file mode 100644
index 0000000..855bcd4
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/instrumentation/BundleInfo.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core.instrumentation;
+
+import java.io.Serializable;
+import java.util.Hashtable;
+public class BundleInfo implements Serializable {
+
+ //mgmt attributes
+ private int startLevel;
+ private String state;
+ private ServiceInfo[] registeredServices;
+ private ServiceInfo[] servicesInUse;
+ private Hashtable headers;
+ private long bundleId;
+ private PackageInfo[] exportedPackages;
+ private PackageInfo[] importedPackages;
+ private BundleInfo[] fragments;
+ private BundleInfo[] hosts;
+ private BundleInfo[] requiredBundles;
+ private BundleInfo[] requiringBundles;
+ private long lastModified;
+ private String symbolicName;
+ //private String version; //Included in the headers except for required bundles
+ private boolean bundlePersistentlyStarted;
+ private boolean removalPending;
+ private boolean required;
+ private boolean fragment;
+// private R4Permission[] permissions;//TODO This should include conditional permz as well as regular ones
+// private R4Configuration[] configurations; //TODO
+
+ public BundleInfo() {
+ }
+
+
+ ////////////GETTERS'n'SETTERS////////////////////////
+ public boolean isFragment() {
+ return fragment;
+ }
+
+
+ protected void setFragment(boolean fragment) {
+ this.fragment = fragment;
+ }
+
+
+ public long getLastModified() {
+ return lastModified;
+ }
+
+
+ protected void setLastModified(long lastModified) {
+ this.lastModified = lastModified;
+ }
+
+
+ public boolean isRequired() {
+ return required;
+ }
+
+
+ protected void setRequired(boolean required) {
+ this.required = required;
+ }
+ public long getBundleId() {
+ return bundleId;
+ }
+ protected void setBundleId(long bundleId) {
+ this.bundleId = bundleId;
+ }
+ public boolean isBundlePersistentlyStarted() {
+ return bundlePersistentlyStarted;
+ }
+ protected void setBundlePersistentlyStarted(boolean bundlePersistentlyStarted) {
+ this.bundlePersistentlyStarted = bundlePersistentlyStarted;
+ }
+ public PackageInfo[] getExportedPackages() {
+ return exportedPackages;
+ }
+ protected void setExportedPackages(PackageInfo[] exportedPackages) {
+ this.exportedPackages = exportedPackages;
+ }
+ public BundleInfo[] getFragments() {
+ return fragments;
+ }
+ protected void setFragments(BundleInfo[] fragments) {
+ this.fragments = fragments;
+ }
+ public Hashtable getHeaders() {
+ return headers;
+ }
+ protected void setHeaders(Hashtable headers) {
+ this.headers = headers;
+ }
+ public BundleInfo[] getHosts() {
+ return hosts;
+ }
+ protected void setHosts(BundleInfo[] hosts) {
+ this.hosts = hosts;
+ }
+ public PackageInfo[] getImportedPackages() {
+ return importedPackages;
+ }
+ protected void setImportedPackages(PackageInfo[] importedPackages) {
+ this.importedPackages = importedPackages;
+ }
+ public ServiceInfo[] getRegisteredServices() {
+ return registeredServices;
+ }
+ protected void setRegisteredServices(ServiceInfo[] registeredServices) {
+ this.registeredServices = registeredServices;
+ }
+ public boolean isRemovalPending() {
+ return removalPending;
+ }
+ protected void setRemovalPending(boolean removalPending) {
+ this.removalPending = removalPending;
+ }
+ public BundleInfo[] getRequiredBundles() {
+ return requiredBundles;
+ }
+ protected void setRequiredBundles(BundleInfo[] requiredBundles) {
+ this.requiredBundles = requiredBundles;
+ }
+ public BundleInfo[] getRequiringBundles() {
+ return requiringBundles;
+ }
+ protected void setRequiringBundles(BundleInfo[] requiringBundles) {
+ this.requiringBundles = requiringBundles;
+ }
+ public ServiceInfo[] getServicesInUse() {
+ return servicesInUse;
+ }
+ protected void setServicesInUse(ServiceInfo[] servicesInUse) {
+ this.servicesInUse = servicesInUse;
+ }
+ public int getStartLevel() {
+ return startLevel;
+ }
+ protected void setStartLevel(int startLevel) {
+ this.startLevel = startLevel;
+ }
+ public String getState() {
+ return state;
+ }
+ protected void setState(String state) {
+ this.state = state;
+ }
+ public String getSymbolicName() {
+ return symbolicName;
+ }
+ protected void setSymbolicName(String symbolicName) {
+ this.symbolicName = symbolicName;
+ }
+
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/instrumentation/FrameworkSnapshot.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/instrumentation/FrameworkSnapshot.java
new file mode 100644
index 0000000..a0145f6
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/instrumentation/FrameworkSnapshot.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core.instrumentation;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.apache.felix.jmood.AgentContext;
+import org.apache.felix.jmood.core.ServiceNotAvailableException;
+import org.apache.felix.jmood.utils.InstrumentationSupport;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.ExportedPackage;
+
+public class FrameworkSnapshot {
+ private Hashtable bundles = new Hashtable(); //<Long, BundleInfo>
+
+ private Hashtable services = new Hashtable();//<Long, ServiceInfo>
+
+ private Hashtable packages = new Hashtable();//<String, PackageInfo>
+
+ private AgentContext ac;
+
+ private long timestamp;
+
+ public FrameworkSnapshot(AgentContext ac) {
+ super();
+ this.ac = ac;
+ this.populate();
+ }
+
+ public long getShotTime() {
+ return timestamp;
+ }
+
+ public void refreshSnapshot() {
+ bundles = new Hashtable();
+ services = new Hashtable();
+ packages = new Hashtable();
+ this.populate();
+ ac.debug("factory-bundles found: " + bundles.size());
+ ac.debug("factory-services found: " + services.size());
+ ac.debug("factory-packages found: " + packages.size());
+
+ }
+
+ public BundleInfo[] getAllBundles() {
+ Enumeration b = bundles.elements();
+ BundleInfo[] binfo = new BundleInfo[bundles.size()];
+ for (int i = 0; i < binfo.length; i++) {
+ binfo[i] = (BundleInfo) b.nextElement();
+ }
+ return binfo;
+ }
+
+ public ServiceInfo[] getAllServiceInfo() {
+ Enumeration s = services.elements();
+ ServiceInfo[] sinfo = new ServiceInfo[services.size()];
+ for (int i = 0; i < sinfo.length; i++) {
+ sinfo[i] = (ServiceInfo) s.nextElement();
+ }
+ return sinfo;
+ }
+
+ public PackageInfo[] getAllPackageInfo() {
+ Enumeration p = packages.elements();
+ PackageInfo[] pinfo = new PackageInfo[packages.size()];
+ for (int i = 0; i < pinfo.length; i++) {
+ pinfo[i] = (PackageInfo) p.nextElement();
+ }
+ return pinfo;
+ }
+
+ // ///////////PRIVATE METHODS//////////////////////////
+
+ private void populate() {
+ Bundle[] bundles = ac.getBundleContext().getBundles();
+ BundleInfo[] binfo = new BundleInfo[bundles.length];
+ for (int i = 0; i < binfo.length; i++) {
+ binfo[i] = getBundleInfo(bundles[i]);
+ }
+ this.timestamp = System.currentTimeMillis();
+ }
+
+private BundleInfo getBundleInfo(Bundle bundle) {
+ if (bundle==null) return null;
+ ac.debug("creating R4 bundleinfo: "+bundle.getSymbolicName());
+ Long key = new Long(bundle.getBundleId());
+ if (bundles.containsKey(key))
+ return (BundleInfo) bundles.get(key);
+ BundleInfo b = new BundleInfo();
+ b.setBundleId(bundle.getBundleId());
+ bundles.put(key, b);
+ try{
+ b.setFragments(this.getFragments(bundle));
+ b.setHeaders(InstrumentationSupport.getHashtable(bundle.getHeaders()));
+ b.setLastModified(bundle.getLastModified());
+ b.setRegisteredServices(this.getSvcsInfo(bundle.getRegisteredServices()));
+ b.setBundlePersistentlyStarted(InstrumentationSupport.isBundlePersistentlyStarted(bundle, ac));
+ b.setStartLevel(InstrumentationSupport.getBundleStartLevel(bundle, ac));
+ b.setExportedPackages(this.getPkgInfo(InstrumentationSupport.getExportedPackages(bundle, ac)));
+ b.setFragment(InstrumentationSupport.isFragment(bundle, ac));
+ b.setRequired(InstrumentationSupport.isBundleRequired(bundle, ac));
+ b.setRemovalPending(InstrumentationSupport.isRequiredBundleRemovalPending(bundle, ac));
+ b.setRequiredBundles(this.getBundleDependencies(bundle));
+ b.setRequiringBundles(this.getBInfos(InstrumentationSupport.getRequiringBundles(bundle, ac)));
+ b.setImportedPackages(this.getImportedPackages(bundle));
+ }catch(ServiceNotAvailableException sae){
+ //Not needed, since they are default values, placed for clarity
+ b.setBundlePersistentlyStarted(false);
+ b.setStartLevel(-1);
+ b.setExportedPackages(null);
+ b.setFragment(false);
+ b.setRequired(false);
+ b.setRemovalPending(false);
+ b.setRequiredBundles(null);
+ b.setRequiringBundles(null);
+ b.setImportedPackages(null);
+ ac.warning(sae.getMessage());
+ }
+ b.setServicesInUse(this.getSvcsInfo(bundle.getServicesInUse()));
+ b.setState(InstrumentationSupport.getState(bundle.getState()));
+ b.setSymbolicName(bundle.getSymbolicName());
+ return b;
+ } private ServiceInfo getServiceInfo(ServiceReference svc) {
+ if (svc == null)
+ return null;
+ ac.debug("Creating R4service for service id "
+ + svc.getProperty(Constants.SERVICE_ID));
+ Long key = (Long) svc.getProperty(Constants.SERVICE_ID);
+ if (services.containsKey(key))
+ return (ServiceInfo) services.get(key);
+ ServiceInfo s = new ServiceInfo();
+ services.put(key, s);
+
+ // now we set the atts
+ s.setBundle(this.getBundleInfo(svc.getBundle()));
+ Bundle[] using = svc.getUsingBundles();
+ if (using != null) {
+ BundleInfo[] r4Using = new BundleInfo[using.length];
+ for (int i = 0; i < r4Using.length; i++) {
+ r4Using[i] = getBundleInfo(using[i]);
+ }
+ s.setUsingBundles(r4Using);
+ }
+ Hashtable props = new Hashtable();//<String, Object>
+ String[] keys=svc.getPropertyKeys();
+ for (int i=0; i<keys.length;i++) {
+ props.put(keys[i], svc.getProperty(keys[i]));
+ }
+ s.setProperties(props);
+ return s;
+
+ }
+
+ private PackageInfo getPackageInfo(ExportedPackage pkg) {
+ if (pkg == null)
+ return null;
+ ac.debug("Creating PackageInfo for package " + pkg.getName());
+ String key = pkg.getName();
+ if (packages.containsKey(key))
+ return (PackageInfo) packages.get(key);
+ PackageInfo p = new PackageInfo();
+ packages.put(key, p);
+ p.setExportingBundle(getBundleInfo(pkg.getExportingBundle()));
+ Bundle[] importing = pkg.getImportingBundles();
+ if (importing != null) {
+ BundleInfo[] r4importing = new BundleInfo[importing.length];
+ for (int i = 0; i < r4importing.length; i++) {
+ r4importing[i] = getBundleInfo(importing[i]);
+ }
+ p.setImportingBundles(r4importing);
+ }
+ p.setName(pkg.getName());
+ p.setRemovalPending(pkg.isRemovalPending());
+ p.setVersion(pkg.getVersion().toString());
+ return p;
+ }
+
+ private BundleInfo[] getFragments(Bundle bundle) throws ServiceNotAvailableException{
+ Bundle[] fragments = ac.getPackageadmin().getFragments(bundle);
+ if (fragments == null)
+ return null;
+ BundleInfo[] r4fragments = new BundleInfo[fragments.length];
+ for (int i = 0; i < fragments.length; i++) {
+ r4fragments[i] = getBundleInfo(fragments[i]);
+ }
+ return r4fragments;
+ }
+
+ private ServiceInfo[] getSvcsInfo(ServiceReference[] svcs) {
+ if (svcs == null)
+ return null;
+ ServiceInfo[] r4svcs = new ServiceInfo[svcs.length];
+ for (int i = 0; i < svcs.length; i++) {
+ r4svcs[i] = getServiceInfo(svcs[i]);
+ }
+ return r4svcs;
+ }
+
+ private PackageInfo[] getImportedPackages(Bundle bundle) throws ServiceNotAvailableException {
+ return this.getPkgInfo(InstrumentationSupport.getImportedPackages(bundle, ac));
+ }
+
+ private PackageInfo[] getPkgInfo(ExportedPackage[] pkgs) {
+ if (pkgs == null)
+ return null;
+ PackageInfo[] r4pkgs = new PackageInfo[pkgs.length];
+ for (int i = 0; i < pkgs.length; i++) {
+ r4pkgs[i] = getPackageInfo(pkgs[i]);
+ }
+ return r4pkgs;
+ }
+
+
+ private BundleInfo[] getBundleDependencies(Bundle bundle) throws ServiceNotAvailableException {
+ Bundle[] required = InstrumentationSupport.getBundleDependencies(bundle, ac);
+ return this.getBInfos(required);
+ }
+ private BundleInfo[] getBInfos(Bundle[] bundles){
+ if(bundles==null) return null;
+ BundleInfo[] info = new BundleInfo[bundles.length];
+ for (int i = 0; i < info.length; i++) {
+ info[i] = getBundleInfo(bundles[i]);
+ }
+ return info;
+
+ }
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/instrumentation/PackageInfo.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/instrumentation/PackageInfo.java
new file mode 100644
index 0000000..dfbd4b7
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/instrumentation/PackageInfo.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core.instrumentation;
+
+import java.io.Serializable;
+
+public class PackageInfo implements Serializable{
+ private BundleInfo exportingBundle;
+ private BundleInfo [] importingBundles;
+ private String name;
+ private String version;
+ private boolean removalPending;
+
+ public PackageInfo() {
+ super();
+ }
+
+ public BundleInfo getExportingBundle() {
+ return exportingBundle;
+ }
+
+ protected void setExportingBundle(BundleInfo exportingBundle) {
+ this.exportingBundle = exportingBundle;
+ }
+
+ public BundleInfo[] getImportingBundles() {
+ return importingBundles;
+ }
+
+ protected void setImportingBundles(BundleInfo[] importingBundles) {
+ this.importingBundles = importingBundles;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ protected void setName(String name) {
+ this.name = name;
+ }
+
+ public boolean isRemovalPending() {
+ return removalPending;
+ }
+
+ protected void setRemovalPending(boolean removalPending) {
+ this.removalPending = removalPending;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ protected void setVersion(String version) {
+ this.version = version;
+ }
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/instrumentation/ServiceInfo.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/instrumentation/ServiceInfo.java
new file mode 100644
index 0000000..4ea7feb
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/core/instrumentation/ServiceInfo.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core.instrumentation;
+
+import java.io.Serializable;
+import java.util.Hashtable;
+
+public class ServiceInfo implements Serializable{
+ private BundleInfo bundle;
+ private BundleInfo[] usingBundles;
+ private Hashtable properties;
+ public ServiceInfo() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+ public BundleInfo getBundle() {
+ return bundle;
+ }
+ protected void setBundle(BundleInfo bundle) {
+ this.bundle = bundle;
+ }
+ public Hashtable getProperties() {
+ return properties;
+ }
+ protected void setProperties(Hashtable properties) {
+ this.properties = properties;
+ }
+ public BundleInfo[] getUsingBundles() {
+ return usingBundles;
+ }
+ protected void setUsingBundles(BundleInfo[] usingBundles) {
+ this.usingBundles = usingBundles;
+ }
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/CompositeDataItemNames.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/CompositeDataItemNames.java
new file mode 100644
index 0000000..0e1dde6
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/CompositeDataItemNames.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.utils;
+
+public interface CompositeDataItemNames {
+ public static final String BUNDLE_ID="BundleId";
+ public static final String BUNDLE_LOCATION="BundleLocation";
+ public static final String EVENT_TYPE="Type";
+ public static final String ENCODED_SERVICE="Service";
+ public static final String ENCODED_EXCEPTION="Throwable";
+ public static final String ENCODED_ROLE="Role";
+ public static final String OBJECT_CLASS="objectClass";
+ public static final String CLASSNAME="ClassName";
+ public static final String FILENAME="FileName";
+ public static final String LINE_NUMBER="LineNumber";
+ public static final String METHOD_NAME="MethodName";
+ public static final String IS_NATIVE_METHOD="isNativeMethod";
+ public static final String EXCEPTION_MESSAGE="Message";
+ public static final String STACK_TRACE="StackTrace";
+ public static final String KEYS_FOR_STRING_VALUES="KeysForStringValues";
+ public static final String KEYS_FOR_BYTEARRAY_VALUES="KeysForByteArrayValues";
+ public static final String STRING_VALUES="StringValues";
+ public static final String BYTEARRAY_VALUES="ByteArrayValues";
+ public static final String ENCODED_CREDENTIALS="credentials";
+ public static final String ROLE_NAME="name";
+ public static final String ROLE_TYPE="type";
+ public static final String ROLE_ENCODED_PROPERTIES="properties";
+ public static final String ENCODED_USER="User";
+ public static final String GROUP_MEMBERS="members";
+ public static final String GROUP_REQUIRED_MEMBERS="requiredMembers";
+ public static final String USER_NAME="UserName";
+ public static final String ROLE_NAMES="RoleNames";
+ public static final String LOG_LEVEL="Level";
+ public static final String LOG_MESSAGE="Message";
+ public static final String LOG_TIME="Time";
+ public static final String[] AUTHORIZATION={USER_NAME,ROLE_NAMES};
+ public static final String[] BUNDLE_EVENT={BUNDLE_ID,BUNDLE_LOCATION, EVENT_TYPE};
+ public static final String[] SERVICE_EVENT={ENCODED_SERVICE, EVENT_TYPE};
+ public static final String[] USER_EVENT={EVENT_TYPE, ENCODED_ROLE, ENCODED_SERVICE};
+ public static final String[] FRAMEWORK_EVENT={BUNDLE_ID,BUNDLE_LOCATION, ENCODED_EXCEPTION,EVENT_TYPE };
+ public static final String[] SERVICE={BUNDLE_ID,BUNDLE_LOCATION,OBJECT_CLASS};
+ public static final String[] STACK_TRACE_ELEMENT={CLASSNAME,FILENAME,LINE_NUMBER,METHOD_NAME,IS_NATIVE_METHOD};
+ public static final String[] EXCEPTION={EXCEPTION_MESSAGE,STACK_TRACE};
+ public static final String[] ROLE_PROPERTIES={KEYS_FOR_STRING_VALUES,KEYS_FOR_BYTEARRAY_VALUES,STRING_VALUES,BYTEARRAY_VALUES};
+ public static final String[] USER_CREDENTIALS=ROLE_PROPERTIES;
+ public static final String[] USER={ENCODED_ROLE,ENCODED_CREDENTIALS};
+ public static final String[] ROLE={ROLE_NAME,ROLE_TYPE,ROLE_ENCODED_PROPERTIES};
+ public static final String[] GROUP={ENCODED_USER,GROUP_MEMBERS,GROUP_REQUIRED_MEMBERS};
+ public static final String[] LOG_ENTRY={BUNDLE_ID,BUNDLE_LOCATION, ENCODED_EXCEPTION,LOG_LEVEL,LOG_MESSAGE,ENCODED_SERVICE,LOG_TIME};
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/InstrumentationSupport.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/InstrumentationSupport.java
new file mode 100644
index 0000000..efa9af5
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/InstrumentationSupport.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.utils;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.apache.felix.jmood.AgentContext;
+import org.apache.felix.jmood.core.BundleNotAvailableException;
+import org.apache.felix.jmood.core.ServiceNotAvailableException;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.packageadmin.RequiredBundle;
+
+
+/**
+ * This class contains helper methods
+ *
+ *
+ */
+public class InstrumentationSupport {
+ private AgentContext ac;
+ public InstrumentationSupport(AgentContext ac){
+ this.ac=ac;
+ }
+ /**
+ * <p>For each BundleInfo, this method returns the symbolic name String, which we define as the concatenation of
+ * the getSymbolicName of the <code>Bundle</code> interface and the bundle version as specified
+ * in the bundle header. Both parts are divided by a semicolon. An example would be:</p>
+ * <p>
+ * <code>com.acme.foo;1.0.0</code>
+ * </p>
+ * @param bundles The <code>Bundle</code> array to be converted
+ * @return The String array
+ * @see org.osgi.framework.Bundle#getSymbolicName()
+ */
+ public static String[] getSymbolicNames(Bundle[] bundles) {
+ if(bundles==null) return null;
+ String[] names=new String[bundles.length];
+ for (int i = 0; i < names.length; i++) {
+ names[i]=getSymbolicName(bundles[i]);
+ }
+ return names;
+ }
+ public static String getSymbolicName(Bundle bundle){
+ return bundle.getSymbolicName()+";"+bundle.getHeaders().get(Constants.BUNDLE_VERSION);
+
+ }
+
+ /**
+ * <p>
+ *
+ * OSGi exported packages can be uniquely identified by the tuple (packageName, packageVersion).
+ * This methods returns a String array representing those packages with the following syntax:
+ * </p>
+ * <p>
+ * <i>packageName</i>;<i>packageVersion</i>
+ * </p><p>
+ * where packageName is as returned by the method <i>getName()</i> and packageVersion as returned by the method <i>getVersion()</i>
+ * in package admin's <code>ExportedPackage</code> class.
+ * </p>
+ * @param packages The <code>ExportedPackage</code> array to be converted
+ * @return The String array
+ * @see org.osgi.service.packageadmin.ExportedPackage
+ */
+ public static String[] getPackageNames(ExportedPackage[] packages) {
+ if (packages==null) return null;
+ String[] names=new String[packages.length];
+ for (int i = 0; i < names.length; i++) {
+ names[i]=getPackageName(packages[i]);
+ }
+ return names;
+
+ }
+ public static String getPackageName(ExportedPackage pkg) {
+ return pkg.getName()+";"+pkg.getVersion().toString();
+ }
+
+
+ /**
+ * <p>
+ * OSGi Services can be registered under more than one interface (objectClass in
+ * the spec). Services have a mandatory unique service id (as defined in the SERVICE_ID property of the org.osgi.framework.Constants interface), during their lifetime (i.e, until they are
+ * garbage collected). To show this information in a consistent way, we use the following String representation
+ * of the service:
+ * </p>
+ * <p>
+ * <i>objectClass1</i>[;<i>objectClass2</i>[;<i>objectClass3</i>...]]:<i>service.id</i>
+ * </p><p>
+ * where objectClass1..objectClassN are the elements of the mandatory objectClass array
+ * included in the service property dictionary (and set by the framework at registration time. The property name is defined in <code>org.osgi.framework.Constants#OBJECTCLASS</code>
+ * </p>
+ * @param services The <code>ServiceReference</code> array to be converted
+ * @return The String array
+ * @see org.osgi.framework.Constants#OBJECTCLASS
+ * @see org.osgi.framework.Constants#SERVICE_ID
+ * @see org.osgi.framework.ServiceReference
+ */
+ public static String[] getServiceNames(ServiceReference[] services) {
+ if(services==null) return null;
+ String[] names=new String[services.length];
+ for (int i = 0; i < names.length; i++) {
+ String[] objectClass=(String[])services[i].getProperty(Constants.OBJECTCLASS);
+ //We asume that the framework always returns a non-empty, non-null array.
+ StringBuffer sb=new StringBuffer(objectClass[0]);
+ for (int j = 1; j < objectClass.length; j++) {
+ sb.append(";");
+ sb.append(objectClass[j]);
+ }
+ sb.append(services[i].getProperty(Constants.SERVICE_ID));
+ names[i]=sb.toString();
+ }
+ return names;
+ }
+ public static ExportedPackage[] getImportedPackages(Bundle bundle, AgentContext ac) throws ServiceNotAvailableException {
+ Vector imported = new Vector();
+ Bundle[] allBundles = ac.getBundleContext().getBundles();
+ for (int i=0; i<allBundles.length;i++) {
+ Bundle b=allBundles[i];
+ ExportedPackage[] eps=ac.getPackageadmin()
+ .getExportedPackages(b);
+ if(eps==null) continue;
+ exported: for (int j=0;j<eps.length;j++) {
+ ExportedPackage ep = eps[j];
+ Bundle[] imp=ep.getImportingBundles();
+ if(imp==null) continue;
+ for (int k=0;k<imp.length;k++) {
+ Bundle b2 =imp[k];
+ if (b2.getBundleId() == bundle.getBundleId()) {
+ imported.add(ep);
+ continue exported;
+ }
+ }
+ }
+ }
+ if (imported.size() == 0)
+ return null;
+ else return (ExportedPackage[])imported.toArray(new ExportedPackage[imported.size()]);
+
+ }
+ public static Bundle[] getRequiringBundles(Bundle bundle, AgentContext ac) throws ServiceNotAvailableException{
+ if (bundle==null) throw new IllegalArgumentException("Bundle argument should not be null");
+ if (bundle.getSymbolicName()==null) return null;
+ RequiredBundle[] required=ac.getPackageadmin().getRequiredBundles(bundle.getSymbolicName());
+ if (required==null) return null;
+ RequiredBundle b=null;
+ for (int i=0;i<required.length;i++) {
+ if(bundle.getBundleId()==required[i].getBundle().getBundleId()) {
+ b=required[i];
+ break;
+ }
+ }
+ if(b==null) {
+ ac.error(InstrumentationSupport.class.getName()+": required bundle should not be null!!!!", new Exception());
+ return null;
+ }
+ return b.getRequiringBundles();
+ }
+ public static Bundle[] getBundleDependencies(Bundle bundle, AgentContext ac) throws ServiceNotAvailableException{
+ Bundle[] all=ac.getBundleContext().getBundles();
+ Vector required=new Vector();
+ for (int i = 0; i < all.length; i++) {
+ Bundle[] requiring=getRequiringBundles(all[i], ac);
+ if (requiring==null) continue;
+ for (int j = 0; j < requiring.length; j++) {
+ //If the solicited bundle is requiring the bundle all[i] we mark it as required
+ if (requiring[j].getBundleId()==bundle.getBundleId()) required.add(all[i]);
+ }
+ }
+ if (required.size()==0) return null;
+ return (Bundle[])required.toArray(new Bundle[required.size()]);
+ }
+ public static boolean isBundleRequired(Bundle bundle, AgentContext ac) throws ServiceNotAvailableException {
+ if (getRequiredBundle(bundle, ac)==null) return false;
+ return true;
+ }
+ public static boolean isRequiredBundleRemovalPending(Bundle bundle, AgentContext ac)throws ServiceNotAvailableException{
+ RequiredBundle r=getRequiredBundle(bundle, ac);
+ if (r==null) return false;
+ return r.isRemovalPending();
+ }
+ public static RequiredBundle getRequiredBundle(Bundle bundle, AgentContext ac)throws ServiceNotAvailableException{
+ RequiredBundle[] required=ac.getPackageadmin().getRequiredBundles(bundle.getSymbolicName());
+ if(required==null) return null;
+ for (int i = 0; i < required.length; i++) {
+ if (required[i].getBundle().getBundleId()==bundle.getBundleId()) return required[i];
+ }
+ return null;
+ }
+ public static String getState(int state) {
+ switch (state) {
+ case Bundle.ACTIVE:
+ return "ACTIVE";
+ case Bundle.INSTALLED:
+ return "INSTALLED";
+ case Bundle.RESOLVED:
+ return "RESOLVED";
+ case Bundle.STARTING:
+ return "STARTING";
+ case Bundle.STOPPING:
+ return "STOPPING";
+ case Bundle.UNINSTALLED:
+ return "UNINSTALLED";
+ }
+ return null;
+ }
+ public static boolean isBundlePersistentlyStarted(Bundle bundle, AgentContext ac)throws ServiceNotAvailableException{
+ // BUG in KNOPFLERFISH: isPersistentlyStarted throws NPE if called
+ // on System bundle
+ // Workaround: system bundle should always be persistently started, return true
+ if (bundle.getBundleId()==0) return true;
+ else
+ return ac.getStartLevel().isBundlePersistentlyStarted(bundle);
+ // End workaround
+ }
+
+ public static int getBundleStartLevel(Bundle bundle, AgentContext ac) throws ServiceNotAvailableException {
+ return ac.getStartLevel().getBundleStartLevel(bundle);
+ }
+
+ public static ExportedPackage[] getExportedPackages(Bundle bundle, AgentContext ac) throws ServiceNotAvailableException{
+ return ac.getPackageadmin().getExportedPackages(bundle);
+ }
+
+ public static boolean isFragment(Bundle bundle, AgentContext ac) throws ServiceNotAvailableException{
+ if(ac.getPackageadmin().getBundleType(bundle)==PackageAdmin.BUNDLE_TYPE_FRAGMENT) return true;
+ return false;
+ }
+ public static Hashtable getHashtable(Dictionary dic){
+ Hashtable ht = new Hashtable();
+ for (Enumeration keys = dic.keys(); keys.hasMoreElements();) {
+ Object key = keys.nextElement();
+ // Not inmutable, but unlikely to change
+ ht.put(key, dic.get(key));
+ }
+ return ht;
+ }
+ public static long getBundleId(String symbolicName, AgentContext ac) throws BundleNotAvailableException{
+ if(symbolicName==null) throw new IllegalArgumentException("Symbolic name cannot be null");
+ String [] s=symbolicName.split(";");
+ if(s==null||s.length==0) throw new BundleNotAvailableException("Could not find bundle identified by "+symbolicName);
+ Bundle[] bundles=ac.getBundleContext().getBundles();
+ long id=-1;
+ Vector candidates=new Vector();
+ for(int i=0;i<bundles.length;i++) {
+ //First find all bundles with symbolicName
+ String name=bundles[i].getSymbolicName();
+ if(name==null) continue;
+ if (s[0].equals(name)){
+ candidates.add(new Long(bundles[i].getBundleId()));
+ }
+ }
+ //now search the one that matches the version
+ for(int i=0; i< candidates.size();i++){
+ long cId=((Long)candidates.elementAt(i)).longValue();
+ Bundle c=ac.getBundleContext().getBundle(cId);
+ String version=(String)c.getHeaders().get(Constants.BUNDLE_VERSION);
+ if(s.length==1){//no version available
+ ac.debug("no version available for "+symbolicName);
+ if(candidates.size()>1) throw new BundleNotAvailableException("could not distinguish among multiple candidates");
+ if(candidates.size()==1) {
+ id=cId;
+ break;
+ }
+ }
+ if (version.equals(s[1])) id=cId;
+ }
+ if(id==-1) throw new BundleNotAvailableException("No " + symbolicName+ "installed");
+ return id;
+ }
+
+
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/OSGi2JMXCodec.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/OSGi2JMXCodec.java
new file mode 100644
index 0000000..a9b414d
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/OSGi2JMXCodec.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.utils;
+import java.util.*;
+import javax.management.openmbean.*;
+import org.osgi.service.useradmin.*;
+import org.osgi.service.log.*;
+import org.osgi.framework.*;
+
+/**
+ * This class's task is to be in charge of all needed type conversions
+ * inside the management agent. This involves translating osgi-defined types
+ * to jmx's open types. It implements methods for obtaining open instances.
+ * This class implements the singleton pattern.
+ *
+ */
+//TODO this class is only used by log and useradmin mbeans, should be just remove it?
+public class OSGi2JMXCodec {
+ public static CompositeData encodeBundleEvent(BundleEvent event) throws Exception{
+ if(event==null) return null;
+ String[] itemNames=CompositeDataItemNames.BUNDLE_EVENT;
+ Object[] itemValues=new Object [3];
+ itemValues[0]=new Integer((int)event.getBundle().getBundleId());
+ itemValues[1]=event.getBundle().getLocation();
+ itemValues[2]=new Integer(event.getType());
+ return new CompositeDataSupport(
+ OSGiTypes.BUNDLEEVENT,
+ itemNames,
+ itemValues);
+ }
+ public static CompositeData encodeServiceEvent(ServiceEvent event) throws Exception{
+ if(event==null) return null;
+ String[] itemNames=CompositeDataItemNames.SERVICE_EVENT;
+ Object[] itemValues=new Object[2];
+ itemValues[0]=encodeService(event.getServiceReference());
+ itemValues[1]=new Integer(event.getType());
+ return new CompositeDataSupport(
+ OSGiTypes.SERVICEEVENT,
+ itemNames,
+ itemValues);
+
+ }
+ public static CompositeData encodeFrameworkEvent(FrameworkEvent event) throws Exception{
+ if(event==null) return null;
+ String[] itemNames=CompositeDataItemNames.FRAMEWORK_EVENT;
+ Object[] itemValues=new Object[4];
+ itemValues[0]=new Integer((int)event.getBundle().getBundleId());
+ itemValues[1]=event.getBundle().getLocation();
+ if (event.getThrowable()==null) itemValues[2]=null;
+ else itemValues[2]=encodeException(event.getThrowable());
+ itemValues[3]=new Integer(event.getType());
+ return new CompositeDataSupport(
+ OSGiTypes.FRAMEWORKEVENT,
+ itemNames,
+ itemValues);
+
+ }
+ public static CompositeData encodeUserAdminEvent(UserAdminEvent event) throws Exception{
+ //type: better as a String or as a number? for the moment number.
+ //FUTURE WORK Enable some bulk methods in most used parts: optimization issue
+ if(event==null) return null;
+ String [] itemNames =CompositeDataItemNames.USER_EVENT;
+ Object[] itemValues=new Object[3];
+ itemValues[0]=new Integer(event.getType());
+ itemValues[1]=encodeRole(event.getRole());
+ itemValues[2]=encodeService(event.getServiceReference());
+ return new CompositeDataSupport(
+ OSGiTypes.USERADMINEVENT,
+ itemNames,
+ itemValues);
+ }
+ public static CompositeData[] encodeLog(Enumeration enumeration) throws Exception{
+ if(enumeration==null) return null;
+ Vector vector=new Vector();
+ while(enumeration.hasMoreElements()){
+ vector.add(encodeLogEntry((LogEntry)enumeration.nextElement()));
+ }
+ CompositeData[] value=new CompositeData[vector.size()];
+ vector.copyInto(value);
+ return value;
+ }
+ public static CompositeData encodeUser(User user) throws Exception {
+ if(user==null) return null;
+ String[] itemNames = CompositeDataItemNames.USER;
+ Object[] itemValues = new Object[2];
+ itemValues[0] = encodeRole((Role)user);
+ itemValues[1] =
+ OSGi2JMXCodec.encodeUserCredentials(user.getCredentials());
+ return new CompositeDataSupport(
+ OSGiTypes.USER,
+ itemNames,
+ itemValues);
+ }
+ public static CompositeData encodeRole(Role role) throws Exception {
+ if (role==null) return null;
+ Object[] itemValues = new Object[3];
+ itemValues[0] = role.getName();
+ itemValues[1] = new Integer(role.getType());
+ itemValues[2] =
+ OSGi2JMXCodec.encodeRoleProperties(role.getProperties());
+ CompositeData cdata =
+ new CompositeDataSupport(
+ OSGiTypes.ROLE,
+ CompositeDataItemNames.ROLE,
+ itemValues);
+ return cdata;
+ }
+ public static CompositeData encodeGroup(Group group) throws Exception {
+ if(group==null) return null;
+ String[] itemNames = CompositeDataItemNames.GROUP;
+ Object[] itemValues = new Object[3];
+ itemValues[0] = encodeUser((User)group);
+ Role[] members = group.getMembers();
+ String[] membersNames;
+ if (members!=null){
+ membersNames = new String[members.length];
+ for (int i = 0; i < members.length; i++)
+ membersNames[i] = members[i].getName();
+ }
+ else{
+ membersNames=new String[0];
+ }
+ itemValues[1] = membersNames;
+ Role[] requiredMembers = group.getRequiredMembers();
+ String [] requiredMembersNames;
+ if(requiredMembers!=null){
+ requiredMembersNames = new String[requiredMembers.length];
+ for (int i = 0; i < requiredMembers.length; i++)
+ requiredMembersNames[i] = requiredMembers[i].getName();
+ }else requiredMembersNames=new String[0];
+ itemValues[2] = requiredMembersNames;
+ return new CompositeDataSupport(OSGiTypes.GROUP, itemNames, itemValues);
+ }
+ public static CompositeData encodeAuthorization(Authorization authorization)
+ throws Exception {
+ if(authorization==null) return null;
+ Object[] itemValues = new Object[2];
+ String[] itemNames = CompositeDataItemNames.AUTHORIZATION;
+ itemValues[0] = authorization.getName();
+ itemValues[1] = authorization.getRoles();
+ return new CompositeDataSupport(
+ OSGiTypes.AUTHORIZATION,
+ itemNames,
+ itemValues);
+ }
+ public static CompositeData encodeLogEntry(LogEntry entry)
+ throws Exception {
+ if (entry==null) return null;
+ String[] itemNames = CompositeDataItemNames.LOG_ENTRY;
+ Object[] itemValues = new Object[7];
+ itemValues[0] = new Integer((int) entry.getBundle().getBundleId());
+ itemValues[1] =entry.getBundle().getLocation();
+ itemValues[2] = OSGi2JMXCodec.encodeException(entry.getException());
+ itemValues[3] = new Integer(entry.getLevel());
+ itemValues[4] = entry.getMessage();
+ itemValues[5] =
+ OSGi2JMXCodec.encodeService(entry.getServiceReference());
+ itemValues[6] = new Integer((int) entry.getTime());
+ return new CompositeDataSupport(
+ OSGiTypes.LOGENTRY,
+ itemNames,
+ itemValues);
+ }
+ public static CompositeData encodeRoleProperties(Dictionary RoleProperties)
+ throws Exception {
+ if (RoleProperties==null) return null;
+ if(RoleProperties.isEmpty()) return null;
+ Enumeration propkeys= RoleProperties.keys();
+ Vector byteKeys=new Vector();
+ Vector byteValues=new Vector();
+ Vector StringKeys=new Vector();
+ Vector StringValues=new Vector();
+ while(propkeys.hasMoreElements()){
+ Object key=propkeys.nextElement();
+ Object value= RoleProperties.get(key);
+ if ( value instanceof byte[] ) {
+ byteKeys.add(key);
+ byteValues.add(value);
+ }
+ else if (value instanceof String) {
+ StringKeys.add(key);
+ StringValues.add(value);
+ }
+ }
+ Byte[][] bvalues=new Byte[byteValues.size()][];
+ for(int i=0; i<byteValues.size();i++){
+ byte[] array=(byte[])byteValues.elementAt(i);
+ bvalues[i]=OSGi2JMXCodec.byte2Byte(array);
+ }
+ Object[] propsItemValues = new Object[4];
+ String[] bkeys = new String[byteKeys.size()];
+ byteKeys.copyInto(bkeys);
+ //byteValues.copyInto(bvalues);
+ String[] skeys = new String[StringKeys.size()];
+ StringKeys.copyInto(skeys);
+ String[] svalues = new String[StringValues.size()];
+ StringValues.copyInto(svalues);
+ propsItemValues[1] = bkeys;
+ propsItemValues[3] = bvalues;
+ propsItemValues[0] =skeys;
+ propsItemValues[2]=svalues;
+ return new CompositeDataSupport(
+ OSGiTypes.ROLEPROPERTIES,
+ CompositeDataItemNames.ROLE_PROPERTIES,
+ propsItemValues);
+ }
+ public static CompositeData encodeUserCredentials(Dictionary credentials)
+ throws Exception {
+ if (credentials==null) return null;
+ if(credentials.isEmpty())return null;
+ String[] itemNames = CompositeDataItemNames.USER_CREDENTIALS;
+ //For the moment, user credentials and role properties have the same structure...
+ CompositeData cdata=OSGi2JMXCodec.encodeRoleProperties(credentials);
+ Object[] values=cdata.getAll(CompositeDataItemNames.USER_CREDENTIALS);
+ return new CompositeDataSupport(
+ OSGiTypes.USERCREDENTIALS,
+ itemNames,
+ values);
+ }
+ public static CompositeData encodeService(ServiceReference service)
+ throws Exception {
+ if(service==null) return null;
+ Object[] itemValues = new Object[3];
+ String[] itemNames = CompositeDataItemNames.SERVICE;
+ int id;
+ String[] objectClass;
+ String BundleLocation;
+ if(service==null){
+ id=-1;
+ objectClass=new String[1];
+ objectClass[0]="No service related to this log entry";
+ BundleLocation="none";
+ }else {
+ id=(int) service.getBundle().getBundleId();
+ objectClass= (String[])service.getProperty(itemNames[1]);
+ BundleLocation=service.getBundle().getLocation();
+ }
+ itemValues[0] = new Integer(id);
+ itemValues[1] =BundleLocation;
+ itemValues[2] =objectClass;
+ return new CompositeDataSupport(
+ OSGiTypes.SERVICE,
+ itemNames,
+ itemValues);
+ }
+ public static CompositeData encodeException(Throwable throwable)
+ throws Exception {
+ if (throwable==null) return null;
+ Object[] itemValues = new Object[2];
+ String[] itemNames = CompositeDataItemNames.EXCEPTION;
+ String message;
+ if (throwable==null) message="This log entry has not an associated exception";
+ else message= throwable.getMessage();
+ itemValues[0] =message;
+ StackTraceElement[] stack=throwable.getStackTrace();
+ if(stack==null) itemValues[1]=null;
+ else{
+ CompositeData[] cstack=new CompositeData[stack.length];
+ for (int i=0;i<stack.length;i++) cstack[i]=encodeStackTraceElement(stack[i]);
+ itemValues[1]=cstack;
+ }
+ return new CompositeDataSupport(
+ OSGiTypes.EXCEPTION,
+ itemNames,
+ itemValues);
+ }
+ public static CompositeData encodeStackTraceElement(StackTraceElement element) throws Exception{
+ Object[] itemValues = new Object[5];
+ String[] itemNames = CompositeDataItemNames.STACK_TRACE_ELEMENT;
+ itemValues[0]=element.getClassName();
+ itemValues[1]=element.getFileName();
+ itemValues[2]=new Integer(element.getLineNumber());
+ itemValues[3]=element.getMethodName();
+ itemValues[4]=new Boolean(element.isNativeMethod());
+ return new CompositeDataSupport(
+ OSGiTypes.STACKTRACE_ELEMENT,
+ itemNames,
+ itemValues);
+ }
+ public static byte[] Byte2byte(Byte[] bytes){
+ byte[] result=new byte[ bytes.length];
+ for(int i=0;i<bytes.length;i++) result[i]=bytes[i].byteValue();
+ return result;
+ }
+ public static Byte[] byte2Byte(byte[] bytes){
+ Byte[] result=new Byte[ bytes.length];
+ for(int i=0;i<bytes.length;i++) result[i]=new Byte(bytes[i]);
+ return result;
+
+ }
+}
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/OSGiTypes.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/OSGiTypes.java
new file mode 100644
index 0000000..196cef9
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/OSGiTypes.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.utils;
+import javax.management.openmbean.*;
+/**
+ * This class defines open types in a static way for the management agent. An open type instance defines the structure of an open data.
+ * For more information on open types and open data see jmx specification.
+ *
+ */
+public class OSGiTypes {
+ public final static CompositeType USER;
+ public final static CompositeType ROLE;
+ public final static CompositeType GROUP;
+ public final static CompositeType USERADMINEVENT;
+ public final static CompositeType AUTHORIZATION;
+ public final static CompositeType LOGENTRY;
+ public final static CompositeType ROLEPROPERTIES;
+ public final static CompositeType USERCREDENTIALS;
+ public final static CompositeType SERVICE;
+ public final static CompositeType EXCEPTION;
+ public final static CompositeType BUNDLEEVENT;
+ public final static CompositeType SERVICEEVENT;
+ public final static CompositeType FRAMEWORKEVENT;
+ public final static CompositeType STACKTRACE_ELEMENT;
+ protected static OpenType[] DICTIONARYITEMTYPES = null;
+ //protected static String[] RoleItemNames = null;
+ //protected static String[] RolePropertiesItemNames = null;
+
+ static {
+ try {
+ DICTIONARYITEMTYPES = new OpenType[4];
+ DICTIONARYITEMTYPES[0] = new ArrayType(1, SimpleType.STRING);
+ DICTIONARYITEMTYPES[1] = new ArrayType(1, SimpleType.STRING);
+ DICTIONARYITEMTYPES[2] = new ArrayType(1, SimpleType.STRING);
+ DICTIONARYITEMTYPES[3] = new ArrayType(2, SimpleType.BYTE);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ STACKTRACE_ELEMENT=createStackTraceElementType();
+ ROLEPROPERTIES = createRolePropertiesType();
+ USERCREDENTIALS = createUserCredentialsType();
+ SERVICE = createServiceType();
+ EXCEPTION = createExceptionType();
+ ROLE = createRoleType();
+ USER = createUserType();
+ GROUP = createGroupType();
+ AUTHORIZATION = createAuthorizationType();
+ LOGENTRY = createLogEntryType();
+ USERADMINEVENT=createUserAdminEventType();
+ BUNDLEEVENT=createBundleEventType();
+ SERVICEEVENT=createServiceEventType();
+ FRAMEWORKEVENT=createFrameworkEventType();
+ }
+ private static CompositeType createBundleEventType(){
+ String description="This type encapsulates OSGi bundle events";
+ String[] itemNames=CompositeDataItemNames.BUNDLE_EVENT;
+ OpenType[] itemTypes=new OpenType[3];
+ String[] itemDescriptions=new String[3];
+ /* itemNames[0]="BundleId";
+ itemNames[1]="BundleLocation";
+ itemNames[2]="Type";*/
+ itemTypes[0]=SimpleType.INTEGER;
+ itemTypes[1]=SimpleType.STRING;
+ itemTypes[2]=SimpleType.INTEGER;
+ itemDescriptions[0]="The ID of the bundle that generated this event";
+ itemDescriptions[1]="The location of the bundle that generated this event";
+ itemDescriptions[2]="The type of the event: {INSTALLED=1, STARTED=2, STOPPED=4, UPDATED=8, UNINSTALLED=16}";
+ try {
+ return new CompositeType(
+ "BundleEvent",
+ description,
+ itemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ }
+ private static CompositeType createServiceEventType(){
+ String description="This type encapsulates OSGi service events";
+ String[] itemNames=CompositeDataItemNames.SERVICE_EVENT;
+ OpenType[] itemTypes=new OpenType[2];
+ String[] itemDescriptions=new String[2];
+ /*itemNames[0]="Service";
+ itemNames[1]="Type";
+ */
+ itemTypes[0]=SERVICE;
+ itemTypes[1]=SimpleType.INTEGER;
+ itemDescriptions[0]="The service associated with this event";
+ itemDescriptions[1]="The type of the event: {REGISTERED=1, MODIFIED=2 UNREGISTERING=3}";
+ try {
+ return new CompositeType(
+ "ServiceEvent",
+ description,
+ itemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ }
+ private static CompositeType createFrameworkEventType(){
+ String description="This type encapsulates OSGi framework events";
+ String[] itemNames=CompositeDataItemNames.FRAMEWORK_EVENT;
+ OpenType[] itemTypes=new OpenType[4];
+ String[] itemDescriptions=new String[4];
+ /*itemNames[0]="BundleId";
+ itemNames[1] ="BundleLocation";
+ itemNames[2]="Throwable";
+ itemNames[3]="Type";
+ */
+ itemTypes[0]=SimpleType.INTEGER;
+ itemTypes[1]=SimpleType.STRING;
+ itemTypes[2]= EXCEPTION;
+ itemTypes[3]=SimpleType.INTEGER;
+ itemDescriptions[0]="The id of the bundle that os related to this event";
+ itemDescriptions[1]="The location of the bundle that os related to this event";
+ itemDescriptions[2]="The associated exception";
+ itemDescriptions[3]="The type of the event: {STARTED=1, ERROR=2, PACKAGES_REFRESHED=4, STARTLEVEL_CHANGED=8}";
+ try {
+ return new CompositeType(
+ "FrameworkEvent",
+ description,
+ itemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ private static CompositeType createUserAdminEventType(){
+ String description="This type encapsulates OSGi user admin events";
+ String[] itemNames=CompositeDataItemNames.USER_EVENT;
+ OpenType[] itemTypes=new OpenType[3];
+ String[] itemDescriptions=new String[3];
+ /*itemNames[0]="Type";
+ itemNames[1]="Role";
+ itemNames[2]="Service";
+ */
+ itemTypes[0]=SimpleType.INTEGER;
+ itemTypes[1]=ROLE;
+ itemTypes[2]=SERVICE;
+ itemDescriptions[0]="The type of the event: {ROLE_CREATED= 1, ROLE_CHANGED=2, ROLE_REMOVED=4}";
+ itemDescriptions[1]="The role associated with this event";
+ itemDescriptions[2]="The UserAdmin service associated with this event. In some gateways, there might be more than one service available.";
+ try {
+ return new CompositeType(
+ "UserAdminEvent",
+ description,
+ itemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ private static CompositeType createServiceType() {
+ String description =
+ "The mapping of the service information for log entries";
+ String[] ServiceItemNames = CompositeDataItemNames.SERVICE;
+ /*ServiceItemNames[0] = "BundleId";
+ ServiceItemNames[1] = "BundleLocation";
+ ServiceItemNames[2] = "objectClass";*/
+ String[] itemDescriptions = new String[3];
+ itemDescriptions[0] =
+ "The id of the bundle which registered the service";
+ itemDescriptions[1] ="The location of the bundle that registered the service";
+ itemDescriptions[2] =
+ "An string array containing the interfaces under which the service has been registered";
+ OpenType[] itemTypes = new OpenType[3];
+ itemTypes[0] = SimpleType.INTEGER;
+ itemTypes[1] =SimpleType.STRING;
+ try {
+ itemTypes[2] = new ArrayType(1, SimpleType.STRING);
+ return new CompositeType(
+ "Service",
+ description,
+ ServiceItemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ private static CompositeType createStackTraceElementType() {
+ //classname,filename,int linenumber,string method name,boolean isNativeMethod
+ String description = "The mapping for of stack trace's elements";
+ String[] itemNames =CompositeDataItemNames.STACK_TRACE_ELEMENT;
+ /*itemNames[0] = "ClassName";
+ itemNames[1]="FileName";
+ itemNames[2]="LineNumber";
+ itemNames[3]="MethodName";
+ itemNames[4]="isNativeMethod";*/
+ String[] itemDescriptions = new String[5];
+ itemDescriptions[0] = "the class where occured";
+ itemDescriptions[1]="the file name";
+ itemDescriptions[2] = "the line number";
+ itemDescriptions[3] = "the method name";
+ itemDescriptions[4] = "True if it is a native method";
+ OpenType[] itemTypes = new OpenType[5];
+ itemTypes[0] = SimpleType.STRING;
+ itemTypes[1] = SimpleType.STRING;
+ itemTypes[2] = SimpleType.INTEGER;
+ itemTypes[3] = SimpleType.STRING;
+ itemTypes[4] = SimpleType.BOOLEAN;
+ try {
+ return new CompositeType(
+ "Exception",
+ description,
+ itemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ private static CompositeType createExceptionType() {
+ String description = "The exception mapping for logging purposes";
+ String[] itemNames = CompositeDataItemNames.EXCEPTION;
+ /*itemNames[0] = "Message";
+ itemNames[1]="StackTrace";*/
+ String[] itemDescriptions = new String[2];
+ itemDescriptions[0] = "The exception's message";
+ itemDescriptions[1]="The exception's stack trace";
+ OpenType[] itemTypes = new OpenType[2];
+ itemTypes[0] = SimpleType.STRING;
+ try {
+ itemTypes[1] = new ArrayType(1, STACKTRACE_ELEMENT);
+ return new CompositeType(
+ "Exception",
+ description,
+ itemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ }
+ private static CompositeType createRolePropertiesType() {
+ String description =
+ "The properties dictionary mapping of a Role. It has four fields: KeysForStringValues, KeysForByteArrayValues, StringValues, ByteArrayValues";
+ String[] RolePropertiesItemNames = CompositeDataItemNames.ROLE_PROPERTIES;
+ /*RolePropertiesItemNames[0] = "KeysForStringValues";
+ RolePropertiesItemNames[1] = "KeysForByteArrayValues";
+ RolePropertiesItemNames[3] = "ByteArrayValues";
+ RolePropertiesItemNames[2] = "StringValues";*/
+ String[] itemDescriptions = new String[4];
+ itemDescriptions[0] =
+ "A string array containing the keys for the properties which are Strings";
+ itemDescriptions[1] =
+ "A string array containing the keys for the properties which are byte[]";
+ itemDescriptions[2] =
+ "A string array containing the values of the properties which are Strings";
+ itemDescriptions[3] =
+ "A 2D-array containing the values of the properties which are byte[]. byte[i] is the i-nth Byte[], whose key is at KeysForByteArrayValues[i]";
+ try {
+ return new CompositeType(
+ "RoleProperties",
+ description,
+ RolePropertiesItemNames,
+ itemDescriptions,
+ DICTIONARYITEMTYPES);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private static CompositeType createUserCredentialsType() {
+ //BUG possibly problems here with indexes which is which. review
+ String description = "The credentials for a user";
+ String[] itemNames = CompositeDataItemNames.USER_CREDENTIALS;
+ /*itemNames[0] = "KeysForStringValues";
+ itemNames[1] = "KeysForByteArrayValues";
+ itemNames[3] = "ByteArrayValues";
+ itemNames[2] = "StringValues";
+ */
+ String[] itemDescriptions = new String[4];
+ itemDescriptions[0] =
+ "A string array containing the keys for the credentials which are Strings";
+ itemDescriptions[1] =
+ "A string array containing the keys for the credentials which are byte[]";
+ itemDescriptions[2] =
+ "A string array containing the values of the credentials which are Strings";
+ itemDescriptions[3] =
+ "A 2D-array containing the values of the credentials which are byte[]. byte[i] is the i-nth Byte[], whose key is at KeysForByteArrayValues[i]";
+ try {
+
+ return new CompositeType(
+ "UserCredentials",
+ description,
+ itemNames,
+ itemDescriptions,
+ OSGiTypes.DICTIONARYITEMTYPES);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private static CompositeType createUserType() {
+ //public CompositeType(String typeName, String description, String[] itemNames, String[] itemDescriptions, OpenType[] itemTypes)
+ String description =
+ "Mapping of org.osgi.service.useradmin.User for remote management purposes. User extends Role";
+ String[] itemNames = CompositeDataItemNames.USER;
+ /*itemNames[0] = "Role";
+ itemNames[1] = "credentials";*/
+ String[] itemDescriptions = new String[2];
+ itemDescriptions[0] = "The role object that is extended by this user object";
+ itemDescriptions[1] = "The credentials for this user";
+ OpenType[] itemTypes = new OpenType[2];
+ itemTypes[0] = ROLE;
+ itemTypes[1] = USERCREDENTIALS;
+ try {
+
+ return new CompositeType(
+ "User",
+ description,
+ itemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ private static CompositeType createRoleType() {
+ createRolePropertiesType();
+ String description =
+ "Mapping of org.osgi.service.useradmin.Role for remote management purposes. User and Group extend Role";
+ String []RoleItemNames = CompositeDataItemNames.ROLE;
+ /*RoleItemNames[0] = "name";
+ RoleItemNames[1] = "type";
+ RoleItemNames[2] = "properties";*/
+ String[] itemDescriptions = new String[3];
+ itemDescriptions[0] =
+ "The name of the role. Can be either a group or a user";
+ itemDescriptions[1] =
+ "An integer representing type of the role: {0=Role,1=user,2=group}";
+ itemDescriptions[2] =
+ "A properties list as defined by org.osgi.service.useradmin.Role";
+ OpenType[] itemTypes = new OpenType[3];
+ itemTypes[0] = SimpleType.STRING;
+ itemTypes[1] = SimpleType.INTEGER;
+ itemTypes[2] = ROLEPROPERTIES;
+ try {
+
+ return new CompositeType(
+ "Role",
+ description,
+ RoleItemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ private static CompositeType createGroupType() {
+ String description =
+ "Mapping of org.osgi.service.useradmin.Group for remote management purposes. Group extends User which in turn extends Role";
+ String[] itemNames = CompositeDataItemNames.GROUP;
+ /*itemNames[0] = "User";
+ itemNames[1] = "members";
+ itemNames[2] = "requiredMembers";
+ */
+ String[] itemDescriptions = new String[3];
+ itemDescriptions[0] = "The user object that is extended by this group object";
+ itemDescriptions[1] = "The members of this group";
+ itemDescriptions[2] = "The required members for this group";
+ OpenType[] itemTypes = new OpenType[3];
+ itemTypes[0] = USER;
+ try {
+ itemTypes[1] = new ArrayType(1, SimpleType.STRING);
+ itemTypes[2] = new ArrayType(1, SimpleType.STRING);
+ return new CompositeType(
+ "Group",
+ description,
+ itemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ private static CompositeType createAuthorizationType() {
+ String description =
+ "An authorization object defines which roles has a user got";
+ String[] itemNames = CompositeDataItemNames.AUTHORIZATION;
+ /*itemNames[0] = "UserName";
+ itemNames[1] = "RoleNames";*/
+ String[] itemDescriptions = new String[2];
+ itemDescriptions[0] = "The user name for this authorization object";
+ itemDescriptions[1] =
+ "The names of the roles encapsulated by this auth object";
+ OpenType[] itemTypes = new OpenType[2];
+ itemTypes[0] = SimpleType.STRING;
+ try {
+ itemTypes[1] = new ArrayType(1, SimpleType.STRING);
+ return new CompositeType(
+ "Authorization",
+ description,
+ itemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ private static CompositeType createLogEntryType() {
+ String description =
+ "A log entry type encapsulates a org.osgi.service.log.LogEntry";
+ String[] itemNames = CompositeDataItemNames.LOG_ENTRY;
+ /*itemNames[0] = "BundleId";
+ itemNames[1] = "BundleLocation";
+ itemNames[2] = "Throwable";
+ itemNames[3] = "Level";
+ itemNames[4] = "Message";
+ itemNames[5] = "ServiceReference";
+ itemNames[6] = "Time";*/
+ String[] itemDescriptions = new String[7];
+ itemDescriptions[0] =
+ "The id for the bundle that generated the log entry";
+ itemDescriptions[1] =
+ "The location of the bundle that generated the log entry";
+ itemDescriptions[2] =
+ "The ExceptionType that caused the error, or null if there was none";
+ itemDescriptions[3] = "The level of entry: DEBUG, INFO, ERROR, WARNING";
+ itemDescriptions[4] = "The log message";
+ itemDescriptions[5] =
+ "The service that generated the log entry, or null if not available";
+ itemDescriptions[6] = "The time at which the exception occurred";
+ OpenType[] itemTypes = new OpenType[7];
+ itemTypes[0] = SimpleType.INTEGER;
+ itemTypes[1]=SimpleType.STRING;
+ itemTypes[2] = EXCEPTION;
+ itemTypes[3] = SimpleType.INTEGER;
+ itemTypes[4] = SimpleType.STRING;
+
+ try {
+ itemTypes[5] = SERVICE;
+ itemTypes[6] = SimpleType.INTEGER;
+ return new CompositeType(
+ "LogEntry",
+ description,
+ itemNames,
+ itemDescriptions,
+ itemTypes);
+ } catch (OpenDataException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+}
diff --git a/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/ObjectNames.java b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/ObjectNames.java
new file mode 100644
index 0000000..0a9b893
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/java/org/apache/felix/jmood/utils/ObjectNames.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.utils;
+
+/**
+ * This interface holds the <code>ObjectName</code>s under which the
+ * core MBeans (<code>CoreControllerMBean</code>, <code>ManagedBundleMBean</code>,
+ * <code>ManagedServiceMBean</code>) and <code>ManagedPackageMBean</code>
+ * Note that service, bundle and package data mbeans are created dynamically
+ * and need a dynamic property to be added to the objectName.
+ *
+ */
+public interface ObjectNames {
+ public static final String CORE= "osgi.core";
+ public static final String COMPENDIUM="osgi.compendium";
+ public static final String CORE_CONTROLLER=CORE+":type=controller";
+ public static final String FRAMEWORK=CORE+":type=framework";
+ public static final String BUNDLE=CORE+":type=bundle, symbolicName=";
+ public static final String SERVICE=CORE+":type=service, service.id=";
+ public static final String CM_SERVICE=COMPENDIUM+":service=cm, type=manager";
+ public static final String CM_OBJECT=COMPENDIUM+":service=cm, type=object,";
+ public static final String LOG_SERVICE = COMPENDIUM+":service=log";
+ public static final String UA_SERVICE = COMPENDIUM+":service=useradmin";
+
+ /**
+ * package mbean object names also contain a version property to
+ * avoid <code>InstanceAlreadyExistsException</code> when two
+ * versions of the same package co-exist.
+ */
+ public static final String PACKAGE=CORE+":type=package, name=";
+ public static final String ALLBUNDLES=CORE+":type=bundle,*";
+ public static final String ALLSERVICES=CORE+":type=service,*";
+ public static final String ALLPACKAGES=CORE+":type=package,*";
+ public static final String ALL_CM_OBJECT=COMPENDIUM+":service=cm, type=object,*";
+
+}
diff --git a/org.apache.felix.jmood/src/main/resources/agent.properties b/org.apache.felix.jmood/src/main/resources/agent.properties
new file mode 100644
index 0000000..baa3218
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/resources/agent.properties
@@ -0,0 +1,2 @@
+java.security.policy=simple.policy
+policy.embedded=true
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/main/resources/simple.policy b/org.apache.felix.jmood/src/main/resources/simple.policy
new file mode 100644
index 0000000..f6bec57
--- /dev/null
+++ b/org.apache.felix.jmood/src/main/resources/simple.policy
@@ -0,0 +1,4 @@
+grant {
+ permission java.security.AllPermission;
+};
+
diff --git a/org.apache.felix.jmood/src/site/site.xml b/org.apache.felix.jmood/src/site/site.xml
new file mode 100644
index 0000000..6a4774b
--- /dev/null
+++ b/org.apache.felix.jmood/src/site/site.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project name="Maven">
+ <bannerLeft>
+ <name>Maven</name>
+ <src>http://maven.apache.org/images/apache-maven-project.png</src>
+ <href>http://maven.apache.org/</href>
+ </bannerLeft>
+ <bannerRight>
+ <src>http://maven.apache.org/images/maven-small.gif</src>
+ </bannerRight>
+ <body>
+ <links>
+ <item name="Apache" href="http://www.apache.org/" />
+ <item name="Maven 1.0" href="http://maven.apache.org/"/>
+ <item name="Maven 2" href="http://maven.apache.org/maven2/"/>
+ </links>
+
+ <menu name="Maven 2.0">
+ <item name="Introduction" href="index.html"/>
+ <item name="Download" href="download.html"/>
+ <item name="Release Notes" href="release-notes.html" />
+ <item name="General Information" href="about.html"/>
+ <item name="For Maven 1.0 Users" href="maven1.html"/>
+ <item name="Road Map" href="roadmap.html" />
+ </menu>
+ ${reports}
+ </body>
+</project>
\ No newline at end of file
diff --git a/org.apache.felix.jmood/src/test/java/org/apache/felix/jmood/FelixLauncher.java b/org.apache.felix.jmood/src/test/java/org/apache/felix/jmood/FelixLauncher.java
new file mode 100644
index 0000000..70e9d5a
--- /dev/null
+++ b/org.apache.felix.jmood/src/test/java/org/apache/felix/jmood/FelixLauncher.java
@@ -0,0 +1,156 @@
+package org.apache.felix.jmood;
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.
+ *
+ */
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.management.MBeanServerConnection;
+
+import org.apache.felix.framework.Felix;
+import org.apache.felix.framework.util.MutablePropertyResolver;
+import org.apache.felix.framework.util.MutablePropertyResolverImpl;
+import org.osgi.framework.Constants;
+public class FelixLauncher {
+
+ private MutablePropertyResolver props;
+ private Felix framework;
+ private List bundles;
+ private List packages;
+ private File cacheDir;
+ public FelixLauncher() {
+ super();
+ cacheDir = new File("./cache");
+ System.out.println(cacheDir.getAbsolutePath());
+ clearCache(cacheDir);
+ cacheDir.mkdir();
+
+ framework = new Felix();
+ Map m=new HashMap();
+ bundles=new ArrayList();
+ packages=new ArrayList();
+
+ props = new MutablePropertyResolverImpl(m);
+ props.put("felix.cache.profiledir", cacheDir.getAbsolutePath());
+
+ }
+ public void addBundle(String url){
+ if (!bundles.contains(url))
+ bundles.add(url);
+ }
+ public void addPackage(String packageName){
+ if(!packages.contains(packageName))
+ packages.add(packageName);
+ }
+ public void start(){
+ StringBuffer autostart=new StringBuffer();
+ for (int i=0; i<bundles.size(); i++){
+ String bundle=(String)bundles.get(i);
+ autostart.append(bundle).append(" ");
+ }
+ props.put("felix.auto.start.1", autostart.toString());
+ StringBuffer spkg=new StringBuffer((String)packages.get(0));
+ packages.remove(0);
+ for (int i=0; i<packages.size(); i++){
+ String pkg=(String)packages.get(i);
+ spkg.append(", "+pkg);
+ }
+
+
+ props.put(Constants.FRAMEWORK_SYSTEMPACKAGES, spkg.toString());
+
+ framework.start(props,null);
+ }
+ public void blockingStart() throws Exception{
+ this.start();
+ int to=0;
+ while(framework.getStatus()!=Felix.RUNNING_STATUS) {
+ Thread.sleep(10);
+ to++;
+ if(to>100) throw new Exception("timeout");
+ }
+
+ }
+ public void shutdown(){
+ framework.shutdown();
+ clearCache(cacheDir);
+ }
+
+ private void clearCache(File cacheDir) {
+ if(!isCache(cacheDir)){
+ System.out.println("not valid cache");
+ return;
+ }
+ File[] files=cacheDir.listFiles();
+ for(int i=0; i<files.length; i++){
+ recursiveDelete(files[i]);
+ }
+ }
+ private void recursiveDelete(File file){
+ if(file.isDirectory()){
+ File[] files=file.listFiles();
+ for(int i=0; i<files.length; i++){
+ File f=files[i];
+ recursiveDelete(f);
+ }
+ }
+ file.delete();
+ }
+ private boolean isCache(File cacheDir){
+ if(!cacheDir.exists()||!cacheDir.isDirectory()) return false;
+ else{
+ String[] names=cacheDir.list();
+ for(int i=0;i<names.length;i++){
+ String name=names[i];
+ if(!name.startsWith("bundle")) return false;
+ }
+ return true;
+ }
+ }
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) throws Exception{
+ FelixLauncher launcher=new FelixLauncher();
+ String jmood="file:target/org.apache.felix.jmood-0.8.0-SNAPSHOT.jar";
+ String jmxintrospector="file:../org.apache.felix.mishell/target/org.apache.felix.mishell-0.8.0-SNAPSHOT.jar";
+ launcher.addBundle(jmood);
+ launcher.addBundle(jmxintrospector);
+ launcher.addPackage("org.osgi.framework");
+ launcher.addPackage("org.osgi.util.tracker");
+ launcher.addPackage("org.osgi.service.log");
+ launcher.addPackage("org.osgi.service.packageadmin");
+ launcher.addPackage("org.osgi.service.startlevel");
+ launcher.addPackage("org.osgi.service.permissionadmin");
+ launcher.addPackage("org.osgi.service.useradmin");
+ launcher.addPackage("org.osgi.service.cm");
+ launcher.addPackage("javax.management");
+ launcher.addPackage("javax.management.remote");
+ launcher.addPackage("javax.script");
+ launcher.start();
+ }
+ public Felix getFramework() {
+ return framework;
+ }
+}
diff --git a/org.apache.felix.jmood/src/test/java/org/apache/felix/jmood/core/BundleMBeanTestCase.java b/org.apache.felix.jmood/src/test/java/org/apache/felix/jmood/core/BundleMBeanTestCase.java
new file mode 100644
index 0000000..1f6908c
--- /dev/null
+++ b/org.apache.felix.jmood/src/test/java/org/apache/felix/jmood/core/BundleMBeanTestCase.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+import java.util.Iterator;
+import java.util.logging.Logger;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.ObjectName;
+
+import org.apache.felix.jmood.core.ManagedBundleMBean;
+import org.apache.felix.jmood.core.ManagedServiceMBean;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+import org.apache.felix.jmood.utils.ObjectNames;
+
+
+public class BundleMBeanTestCase extends TestHarness {
+// private String bname="es.upm.dit.jmood;0.9.0";
+// private static Logger l=Logger.getLogger(BundleMBeanTestCase.class.getPackage().getName());
+// private ObjectName jmood;
+ public BundleMBeanTestCase() throws Exception{
+ super();
+// jmood=new ObjectName(ObjectNames.BUNDLE+bname);
+ }
+ protected void setUp()throws Exception{
+ super.setUp();
+ }
+ protected void tearDown()throws Exception{
+ super.tearDown();
+ }
+ public void testAttributes() throws Exception{
+// super.testAttributes(jmood,ManagedBundleMBean.class);
+// l.finest("testing Start level attribute");
+// getServer().getAttribute(jmood, "StartLevel");
+ }
+ public void testUpdateInvariant()throws Exception{
+ //JMood update should be invariant
+ //TODO Should we refresh?
+// getServer().invoke(jmood,"update",null, null);
+// boolean wait=true;
+// String state=null;
+// for(int i=0;wait&&i<10;i++){
+// try{
+// Thread.sleep(10);
+// state=(String)(getServer().getAttribute(jmood,"State"));
+// wait=state.equals("STOPPING")||state.equals("STARTING");
+// }catch (InstanceNotFoundException e){}
+// }
+// assertTrue("state: "+state,state.equals("ACTIVE"));
+ }
+ public void testServiceMBeans()throws Exception{
+// Iterator it=getServer().queryNames(new ObjectName(ObjectNames.ALLSERVICES), null).iterator();
+// while(it.hasNext()){
+// super.testAttributes((ObjectName) it.next(),ManagedServiceMBean.class);
+// }
+ }
+ public void testBundleMBeans()throws Exception{
+// Iterator it=getServer().queryNames(new ObjectName(ObjectNames.ALLBUNDLES), null).iterator();
+// while(it.hasNext()){
+// super.testAttributes((ObjectName) it.next(),ManagedBundleMBean.class);
+// }
+ }
+ public void testPackageMBeans()throws Exception{
+// //Currently fails for Felix because no package mbeans are registered
+// Iterator it=getServer().queryNames(new ObjectName(ObjectNames.ALLSERVICES), null).iterator();
+// while(it.hasNext()){
+// super.testAttributes((ObjectName) it.next(),ManagedBundleMBean.class);
+// }
+ }
+ public void testUpdate()throws Exception{
+// ManagedBundleMBean bundle=(ManagedBundleMBean)MBeanServerInvocationHandler.newProxyInstance(getServer(), jmood, ManagedBundleMBean.class, false);
+// l.info("Last modified: "+bundle.getSymbolicName());
+ }
+
+}
diff --git a/org.apache.felix.jmood/src/test/java/org/apache/felix/jmood/core/CoreTestCase.java b/org.apache.felix.jmood/src/test/java/org/apache/felix/jmood/core/CoreTestCase.java
new file mode 100644
index 0000000..ca45e90
--- /dev/null
+++ b/org.apache.felix.jmood/src/test/java/org/apache/felix/jmood/core/CoreTestCase.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+import java.util.logging.Logger;
+
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.ObjectName;
+import javax.management.RuntimeMBeanException;
+
+import junit.framework.Assert;
+
+import org.apache.felix.jmood.core.CoreControllerMBean;
+import org.apache.felix.jmood.core.ServiceNotAvailableException;
+import org.osgi.framework.BundleException;
+
+import org.apache.felix.jmood.utils.ObjectNames;
+
+public class CoreTestCase extends TestHarness {
+// CoreControllerMBean core;
+ private static Logger l=Logger.getLogger(CoreTestCase.class.getPackage().getName());
+
+ public CoreTestCase() throws Exception {
+ super();
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+// core = (CoreControllerMBean) MBeanServerInvocationHandler
+// .newProxyInstance(getServer(), new ObjectName(
+// ObjectNames.CORE_CONTROLLER),
+// CoreControllerMBean.class, false);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.startBundle(String)'
+ */
+ public void testStartBundle() {
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.batchStartBundles(String[])'
+ */
+ public void testBatchStartBundles() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.stopBundle(String)'
+ */
+ public void testStopBundle() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.batchStopBundles(String[])'
+ */
+ public void testBatchStopBundles() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.updateBundle(String)'
+ */
+ public void testUpdateBundle() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.batchUpdateBundles(String[])'
+ */
+ public void testBatchUpdateBundles() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.updateBundleFromUrl(String,
+ * String)'
+ */
+ public void testUpdateBundleFromUrl() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.batchUpdateBundleFromUrl(String[],
+ * String[])'
+ */
+ public void testBatchUpdateBundleFromUrl() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.installBundle(String)'
+ */
+ public void testInstallBundle() throws Exception {
+// String[] badUrls= {null, "MiCarro", "http://www.dit.upm.es"};
+// for (int i = 0; i < badUrls.length; i++) {
+// try {
+// core.installBundle(badUrls[i]);
+// assertTrue("Should've thrown bundle exception", false);
+// } catch (BundleException e) {
+// // OK
+// }
+// }
+// String[] goodUrls= {"http://maquina:9000/testing/bundle1.jar", "http://maquina:9000/testing/bundle2.jar"};
+// for (int i = 0; i < goodUrls.length; i++) {
+// core.installBundle(goodUrls[i]);
+// }
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.batchInstallBundle(String[])'
+ */
+ public void testBatchInstallBundle() throws Exception{
+// String[] badUrls= {null, "MiCarro", "http://www.dit.upm.es"};
+// try {
+// core.batchInstallBundle(badUrls);
+// assertTrue("Should've thrown bundle exception", false);
+// } catch (BundleException e) {
+// // OK
+// }
+//
+// String[] goodUrls= {"http://maquina:9000/testing/bundle1.jar", "http://maquina:9000/testing/bundle2.jar"};
+// core.batchInstallBundle(goodUrls);
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.setBundleStartLevel(String,
+ * int)'
+ */
+ public void testSetBundleStartLevel() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.batchSetBundleStartLevel(String[],
+ * int[])'
+ */
+ public void testBatchSetBundleStartLevel() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.refreshPackages(String[])'
+ */
+ public void testRefreshPackages() throws Exception{
+// try {
+// core.refreshPackages(null);
+// }
+// catch(RuntimeMBeanException e) {
+// assertTrue(e.getTargetException() instanceof IllegalArgumentException);
+// }
+// core.refreshPackages(new String[] {"es.upm.dit.jmood;0.9.0"});
+//
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.resolveBundles(String[])'
+ */
+ public void testResolveBundles() throws Exception{
+// try {
+// core.resolveBundles(null);
+// }
+// catch(RuntimeMBeanException e) {
+// assertTrue(e.getTargetException() instanceof IllegalArgumentException);
+// }
+// core.resolveBundles(new String[] {"es.upm.dit.jmood;0.9.0"});
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.setPlatformStartLevel(int)'
+ */
+ public void testSetPlatformStartLevel() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.getPlatformStartLevel()'
+ */
+ public void testGetPlatformStartLevel() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.setInitialBundleStartLevel(int)'
+ */
+ public void testSetInitialBundleStartLevel() throws Exception{
+// int init=core.getInitialBundleStartLevel();
+// l.info("INITIAL BUNDLE STARTLEVEL"+ init);
+// int [] good= {1,10, 3};
+// int [] bad= {-1,0};
+// for (int i = 0; i < good.length; i++) {
+// core.setInitialBundleStartLevel(good[i]);
+// assertEquals(core.getInitialBundleStartLevel(), good[i]);
+// }
+// for (int i = 0; i < bad.length; i++) {
+// try {
+// core.setInitialBundleStartLevel(bad[i]);
+// assertTrue(false);
+// } catch(RuntimeMBeanException e) {
+// assertTrue(e.getTargetException() instanceof IllegalArgumentException);
+// }
+// }
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.getInitialBundleStartLevel()'
+ */
+ public void testGetInitialBundleStartLevel() throws Exception{
+// core.getInitialBundleStartLevel();
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.restartFramework()'
+ */
+ public void testRestartFramework() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.shutdownFramework()'
+ */
+ public void testShutdownFramework() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * Test method for
+ * 'es.upm.dit.osgi.management.agent.core.CoreController.updateFramework()'
+ */
+ public void testUpdateFramework() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/org.apache.felix.jmood/src/test/java/org/apache/felix/jmood/core/TestHarness.java b/org.apache.felix.jmood/src/test/java/org/apache/felix/jmood/core/TestHarness.java
new file mode 100644
index 0000000..4293883
--- /dev/null
+++ b/org.apache.felix.jmood/src/test/java/org/apache/felix/jmood/core/TestHarness.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed 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.felix.jmood.core;
+import junit.framework.TestCase;
+
+import org.apache.felix.jmood.FelixLauncher;
+
+public class TestHarness extends TestCase {
+ private FelixLauncher launcher;
+ protected void setUp() throws Exception {
+ //ISSUE: this is not a unit test, but maven runs it as one
+ //before it builds the jar
+ super.setUp();
+ launcher=new FelixLauncher();
+ String jmood="file:target/org.apache.felix.jmood-0.8.0-SNAPSHOT.jar";
+ launcher.addBundle(jmood);
+ launcher.addPackage("org.osgi.framework");
+ launcher.addPackage("org.osgi.util.tracker");
+ launcher.addPackage("org.osgi.service.log");
+ launcher.addPackage("org.osgi.service.packageadmin");
+ launcher.addPackage("org.osgi.service.startlevel");
+ launcher.addPackage("org.osgi.service.permissionadmin");
+ launcher.addPackage("org.osgi.service.useradmin");
+ launcher.addPackage("org.osgi.service.cm");
+ launcher.addPackage("javax.management");
+ launcher.addPackage("javax.management.remote");
+ launcher.blockingStart();
+ }
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ launcher.shutdown();
+ }
+ public void testDummy() {
+ //to avoid test not found assertion error
+ }
+}