Package org.apache.felix.mosgi.jmx.rmiconnector.mx4j.remote.resolver.rmi

Source Code of org.apache.felix.mosgi.jmx.rmiconnector.mx4j.remote.resolver.rmi.RMIResolver

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.   
*/
package org.apache.felix.mosgi.jmx.rmiconnector.mx4j.remote.resolver.rmi;

import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.net.MalformedURLException;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.Remote;
import java.util.Hashtable;
import java.util.Map;

import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnectorServer;
import javax.management.remote.rmi.RMIJRMPServerImpl;
import javax.management.remote.rmi.RMIServer;
import javax.management.remote.rmi.RMIServerImpl;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.osgi.service.log.LogService;

import org.apache.felix.mosgi.jmx.rmiconnector.RmiConnectorActivator;

import org.apache.felix.mosgi.jmx.rmiconnector.mx4j.remote.ConnectionResolver;
import org.apache.felix.mosgi.jmx.agent.mx4j.util.Base64Codec;

/**
* Resolver for RMI/JRMP protocol.
*
* @author <a href="mailto:biorn_steedom@users.sourceforge.net">Simone Bordet</a>
* @version $Revision: 1.1.1.1 $
*/
public class RMIResolver extends ConnectionResolver
{
   private static final String JNDI_CONTEXT = "/jndi/";
   private static final String STUB_CONTEXT = "/stub/";


//********************************************************************************************************************//
// CLIENT METHODS


   public Object lookupClient(JMXServiceURL url, Map environment) throws IOException
   {
      return lookupRMIServerStub(url, environment);
   }

   public Object bindClient(Object client, Map environment) throws IOException
   {
      // JRMP does not need anything special
      return client;
   }

   protected RMIServer lookupRMIServerStub(JMXServiceURL url, Map environment) throws IOException
   {
      String path = url.getURLPath();
      RmiConnectorActivator.log(LogService.LOG_DEBUG,"JMXServiceURL for lookup is: '" + url + "'", null);

      if (path != null)
      {
         if (path.startsWith(JNDI_CONTEXT))
         {
            return lookupStubInJNDI(url, environment);
         }

         return decodeStub(url, environment);
      }

      throw new MalformedURLException("Unsupported lookup " + url);
   }

   private RMIServer lookupStubInJNDI(JMXServiceURL url, Map environment) throws IOException
   {

      String path = url.getURLPath();
      String name = path.substring(JNDI_CONTEXT.length());
      RmiConnectorActivator.log(LogService.LOG_DEBUG,"Looking up RMI stub in JNDI under name " + name, null);

      InitialContext ctx = null;
      try
      {
         ctx = new InitialContext(new Hashtable(environment));
         Object stub = ctx.lookup(name);
         RmiConnectorActivator.log(LogService.LOG_DEBUG,"Found RMI stub in JNDI " + stub, null);
         return narrowRMIServerStub(stub);
      }
      catch (NamingException x)
      {
         RmiConnectorActivator.log(LogService.LOG_DEBUG,"Cannot lookup RMI stub in JNDI", x);
         throw new IOException(x.toString());
      }
      finally
      {
         try
         {
            if (ctx != null) ctx.close();
         }
         catch (NamingException x)
         {
            RmiConnectorActivator.log(LogService.LOG_DEBUG,"Cannot close InitialContext", x);
         }
      }
   }

   protected RMIServer narrowRMIServerStub(Object stub)
   {
      return (RMIServer)stub;
   }

   protected RMIServer decodeStub(JMXServiceURL url, Map environment) throws IOException
   {
      String path = url.getURLPath();
      if (path.startsWith(STUB_CONTEXT))
      {
         byte[] encoded = path.substring(STUB_CONTEXT.length()).getBytes();
         if (!Base64Codec.isArrayByteBase64(encoded)) throw new IOException("Encoded stub form is not a valid Base64 sequence: " + url);
         byte[] decoded = Base64Codec.decodeBase64(encoded);
         ByteArrayInputStream bais = new ByteArrayInputStream(decoded);
         ObjectInputStream ois = null;
         try
         {
            ois = new ObjectInputStream(bais);
            return (RMIServer)ois.readObject();
         }
         catch (ClassNotFoundException x)
         {
            throw new IOException("Cannot decode stub from " + url + ": " + x);
         }
         finally
         {
            if (ois != null) ois.close();
         }
      }
      throw new MalformedURLException("Unsupported binding: " + url);
   }


//********************************************************************************************************************//
// SERVER METHODS


   public Object createServer(JMXServiceURL url, Map environment) throws IOException
   {
      return createRMIServer(url, environment);
   }

   protected RMIServerImpl createRMIServer(JMXServiceURL url, Map environment) throws IOException
   {
      int port = url.getPort();
      RMIClientSocketFactory clientFactory = (RMIClientSocketFactory)environment.get(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE);
      RMIServerSocketFactory serverFactory = (RMIServerSocketFactory)environment.get(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE);
      return new RMIJRMPServerImpl(port, clientFactory, serverFactory, environment);
   }

   public JMXServiceURL bindServer(Object server, JMXServiceURL url, Map environment) throws IOException
   {
      // See javax/management/remote/rmi/package-summary.html

      RMIServerImpl rmiServer = (RMIServerImpl)server;

      RmiConnectorActivator.log(LogService.LOG_DEBUG,"JMXServiceURL for binding is: '" + url + "'",null);

      if (isEncodedForm(url))
      {
         String path = encodeStub(rmiServer, environment);
         return new JMXServiceURL(url.getProtocol(), url.getHost(), url.getPort(), path);
      }

      String jndiURL = parseJNDIForm(url);
      RmiConnectorActivator.log(LogService.LOG_DEBUG,"JMXServiceURL path for binding is: '" + jndiURL + "'", null);

      InitialContext ctx = null;
      try
      {
         ctx = new InitialContext(new Hashtable(environment));
         boolean rebind = Boolean.valueOf((String)environment.get(RMIConnectorServer.JNDI_REBIND_ATTRIBUTE)).booleanValue();
         if (rebind)
            ctx.rebind(jndiURL, rmiServer.toStub());
         else
            ctx.bind(jndiURL, rmiServer.toStub());
         RmiConnectorActivator.log(LogService.LOG_DEBUG,"Bound " + rmiServer + " to " + jndiURL, null);
         return url;
      }
      catch (NamingException x)
      {
         RmiConnectorActivator.log(LogService.LOG_DEBUG,"Cannot bind server " + rmiServer + " to " + jndiURL, x);
         throw new IOException(x.toString());
      }
      finally
      {
         try
         {
            if (ctx != null) ctx.close();
         }
         catch (NamingException x)
         {
            RmiConnectorActivator.log(LogService.LOG_DEBUG,"Cannot close InitialContext", x);
         }
      }
   }

   protected String encodeStub(RMIServerImpl rmiServer, Map environment) throws IOException
   {
      Remote stub = rmiServer.toStub();
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = null;
      try
      {
         oos = new ObjectOutputStream(baos);
         oos.writeObject(stub);
      }
      finally
      {
         if (oos != null) oos.close();
      }
      byte[] bytes = baos.toByteArray();
      byte[] encoded = Base64Codec.encodeBase64(bytes);
      // Since the bytes are base 64 bytes, the encoding in creating the string is not important: any will work
      return STUB_CONTEXT + new String(encoded);
   }

   protected boolean isEncodedForm(JMXServiceURL url)
   {
      String path = url.getURLPath();
      if (path == null || path.length() == 0 || path.equals("/") || path.startsWith(STUB_CONTEXT)) return true;
      return false;
   }

   private String parseJNDIForm(JMXServiceURL url) throws MalformedURLException
   {
      String path = url.getURLPath();
      if (path.startsWith(JNDI_CONTEXT))
      {
         String jndiURL = path.substring(JNDI_CONTEXT.length());
         if (jndiURL == null || jndiURL.length() == 0) throw new MalformedURLException("No JNDI URL specified: " + url);
         return jndiURL;
      }
      throw new MalformedURLException("Unsupported binding: " + url);
   }

   public void unbindServer(Object server, JMXServiceURL url, Map environment) throws IOException
   {
      RmiConnectorActivator.log(LogService.LOG_DEBUG,"JMXServiceURL for unbinding is: '" + url + "'", null);
      // The server was not bound to JNDI (the stub was encoded), just return
      if (isEncodedForm(url))
      {
         destroyServer(server, environment);
         return;
      }

      String jndiURL = parseJNDIForm(url);
      RmiConnectorActivator.log(LogService.LOG_DEBUG,"JMXServiceURL path for binding is: '" + jndiURL + "'",null);

      InitialContext ctx = null;
      try
      {
         ctx = new InitialContext(new Hashtable(environment));
         ctx.unbind(jndiURL);
         RmiConnectorActivator.log(LogService.LOG_DEBUG,"Unbound " + server + " from " + jndiURL, null);
      }
      catch (NamingException x)
      {
         RmiConnectorActivator.log(LogService.LOG_DEBUG,"Cannot unbind server " + server + " to " + jndiURL, x);
         throw new IOException(x.toString());
      }
      finally
      {
         try
         {
            if (ctx != null) ctx.close();
         }
         catch (NamingException x)
         {
            RmiConnectorActivator.log(LogService.LOG_DEBUG,"Cannot close InitialContext", x);
         }
      }
   }

   protected void destroyServer(Object server, Map environment) throws IOException
   {
   }
}
TOP

Related Classes of org.apache.felix.mosgi.jmx.rmiconnector.mx4j.remote.resolver.rmi.RMIResolver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.