blob: 328f6ac0f6d46d87492c7f1b7d2bd04d46509d0a [file] [log] [blame]
/*
* 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);
}
}
}