Code Search for Developers
 
 
  

RemoteServiceProvider.java from Texai at Krugle


Show RemoteServiceProvider.java syntax highlighted

/*
 * RemoteServiceProvider.java
 *
 * Created on April 24, 2007, 1:37 PM
 *
 * Description: Provides a remote service provider.
 *
 * Copyright (C) April 24, 2007 Stephen L. Reed, ported to ApacheMQ and derived from
 * substantially the same class written by Vitaly Tsaplin, 2007, http://jmsrmi.sourceforge.net/
 *
 * This program is free software; you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program;
 * if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package org.texai.kb.ejb.jmsrmi;

import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import org.apache.log4j.Logger;
import org.texai.util.TexaiException;


/**
 * @author vtsaplin
 *
 */
public class RemoteServiceProvider implements MessageListener {
  
  /** the logger */
  private static final Logger LOGGER = Logger.getLogger(RemoteServiceProvider.class);
  
  /** the JMS connection factory */
  private ConnectionFactory connectionFactory;
  
  /** the JMS connection */
  private Connection connection;
  
  /** the service destination */
  private Destination serviceDestination;
  
  /** the JMS session */
  private Session session;
  
  /** the message producer */
  private MessageProducer producer;
  
  /** the message consumer */
  private MessageConsumer consumer;
  
  /** the transferred objects cache */
  private final Map<Long, Object> cache;
  
  /** the service */
  private Object service;
  
  /** the method cache */
  private final Map<String, Method> methodDictionary = new HashMap<String, Method>();
  
  /** Creates a new RemoteServiceProvider instance. */
  public RemoteServiceProvider() {
    cache = Collections.synchronizedMap(new WeakHashMap<Long, Object> ());
  }
  
  /** Gets the service.
   *
   * @return the service
   */
  public Object getService() {
    return service;
  }
  
  /** Sets the service.
   *
   * @param service the service
   */
  public void setService(final Object service) {
    //Preconditions
    assert service != null : "service must not be null";
    
    this.service = service;
  }
  
  /** Gets the JMS connection factory
   *
   * @return the JMS connection factory
   */
  public ConnectionFactory getConnectionFactory() {
    return connectionFactory;
  }
  
  /** Sets the JMS connection factory.
   *
   * @param connectionFactory the JMS connection factory
   */
  public void setConnectionFactory(final ConnectionFactory connectionFactory) {
    //Preconditions
    assert connectionFactory != null : "connectionFactory must not be null";
    
    this.connectionFactory = connectionFactory;
  }
  
  /** Gets the service destination.
   *
   * @return the service destination
   */
  public Destination getServiceDestination() {
    return serviceDestination;
  }
  
  /** Sets the service destination.
   *
   * @param serviceDestination the service destination
   */
  public void setServiceDestination(final Destination serviceDestination) {
    this.serviceDestination = serviceDestination;
  }
  
  /** Initializes this remote service provider. */
  public void init() throws Exception {
    try {
      // Create a connection.
      connection = connectionFactory.createConnection();
      connection.start();
      
      // Create a session.
      session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      
      // Create a consumer to receive remote method invocation requests.
      consumer = session.createConsumer(serviceDestination);
      consumer.setMessageListener(this);
      
      // Create a producer for sending returned values and callback invocations.
      producer = session.createProducer(null);
    } catch (final JMSException ex) {
      throw new TexaiException(ex);
    }
  }
  
  /** Cleans up this remote service provider. */
  public void cleanup() throws Exception {
    try {
      consumer.close();
      session.close();
      connection.close();
    } catch (final JMSException ex) {
      throw new TexaiException(ex);
    }
  }
  
  /** Provides a remote listener.
   * @author vtsaplin
   *
   */
  private class RemoteListener implements InvocationHandler {
    
    /** the transfer object id */
    private long id;
    
    /** the destination */
    private Destination destination;
    
    /** Creates a new RemoteListener instance.
     *
     * @param id the transfer object id
     * @param destination the destination
     */
    public RemoteListener(final long id, final Destination destination) {
      //Preconditions
      assert destination != null : "destination must not be null";
      
      this.id = id;
      this.destination = destination;
    }
    
    /** Processes a method invocation on a proxy instance and returns the result.
     *
     * @param proxy the proxy instance that the method was invoked on
     * @param method the Method instance corresponding to the interface method invoked on the proxy instance
     * @param args an array of objects containing the values of the arguments passed in the method invocation
     * on the proxy instance, or null if interface method takes no arguments
     */
    public Object invoke(
            final Object proxy,
            final Method method,
            final Object [] args) throws Throwable {
      LOGGER.debug("invoking " + method.getName());
      final RemoteInvocation remoteInvocation = new RemoteInvocation(id, method, args);
      producer.send(destination, session.createObjectMessage(remoteInvocation));
      return null;
    }
  }
  
  /** Passes a message to the listener.
   *
   * @param msg the JMS message
   */
  public void onMessage(final Message msg) {
    LOGGER.debug("onMessage " + msg);
    try {
      if (msg instanceof ObjectMessage) {
        final Object obj = ((ObjectMessage)msg).getObject();
        if (RemoteInvocation.class.equals(obj.getClass())) {
          final RemoteInvocation remoteInvocation = (RemoteInvocation)((ObjectMessage)msg).getObject();
          Object result = null;
          final String methodName = remoteInvocation.getName();
          Method method = methodDictionary.get(methodName);
          if (method == null) {
            for (final Method serviceMethod : service.getClass().getMethods()) {
              if (serviceMethod.getName().equals(methodName)) {
                method = serviceMethod;
                methodDictionary.put(methodName, method);
                break;
              }
            }
          }
          assert method != null : "cannot find service method for " + msg;
          final Object[] args = remoteInvocation.getArgs();
          if (args != null) {
            for (int i = 0; i < args.length; i++) {
              if (RemoteInvocationArgument.class.equals(args[i].getClass())) {
                final RemoteInvocationArgument remoteInvocationArgument = (RemoteInvocationArgument)args[i];
                if (cache.containsKey(remoteInvocationArgument.getID())) {
                  // we use a proxy from the cache
                  args[i] = cache.get(remoteInvocationArgument.getID());
                } else {
                  // create a new proxy for a remote calback method
                  args [i] = Proxy.newProxyInstance(
                          getClass().getClassLoader(),
                          remoteInvocationArgument.getType().getInterfaces(),
                          new RemoteListener(remoteInvocationArgument.getID(), msg.getJMSReplyTo()));
                  
                  // put a newly created proxy to the cache
                  cache.put(remoteInvocationArgument.getID(), args[i]);
                }
              }
            }
          }
          
          // call the method
          try {
            LOGGER.debug("invoking " + methodName);
            result = method.invoke(service, args);
          } catch (IllegalArgumentException ex) {
            throw new TexaiException(ex);
          } catch (InvocationTargetException ex) {
            result = ex.getTargetException();
          } catch (IllegalAccessException ex) {
            throw new TexaiException(ex);
          }
          
          if (result != null) {
            // we send the result of an invocation back to the client
            final RemoteInvocationResult remoteInvocationResult = new RemoteInvocationResult(remoteInvocation.getID(), result);
            producer.send(
                    msg.getJMSReplyTo(),
                    session.createObjectMessage((Serializable)remoteInvocationResult));
          }
        }
      }
    } catch (JMSException ex) {
      throw new TexaiException(ex);
    }
  }
  
}




See more files for this project here

Texai

Texai is an chatbot that intelligently seeks to acquire knowledge and friendly behaviors.

Project homepage: http://sourceforge.net/projects/texai
Programming language(s): Java,Shell Script,XML
License: other

  RemoteInvocation.java
  RemoteInvocationArgument.java
  RemoteInvocationResult.java
  RemoteServiceConsumer.java
  RemoteServiceProvider.java
  RemoteTransferObject.java