changeset 541:86e7f31bcd0c

Introducing RequestReceiver interface. This is the last major piece of the command-channel puzzle. A RequestReceiver is the entity on agent-side which will act on, and respond to, incoming requests. Any bundle loaded as part of the agent can use the new ReceiverRegistry class to make a receiver implementation available in the framework. Clients sending a request must ensure they specify a receiver in order for the request to be handled properly by the agent. reviewed-by: neugens review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-August/002683.html PR924
author Jon VanAlten <jon.vanalten@redhat.com>
date Thu, 16 Aug 2012 17:57:28 -0400
parents 1b323d4b416f
children f04463bcfa11
files agent/command/src/main/java/com/redhat/thermostat/agent/command/ReceiverRegistry.java agent/command/src/main/java/com/redhat/thermostat/agent/command/RequestReceiver.java agent/command/src/main/java/com/redhat/thermostat/agent/command/internal/Activator.java agent/command/src/main/java/com/redhat/thermostat/agent/command/internal/ConfigurationServerContext.java agent/command/src/main/java/com/redhat/thermostat/agent/command/internal/PingReceiver.java agent/command/src/main/java/com/redhat/thermostat/agent/command/internal/ServerHandler.java agent/command/src/test/java/com/redhat/thermostat/agent/command/internal/ConfigurationServerContextTest.java agent/command/src/test/java/com/redhat/thermostat/agent/command/internal/RequestDecoderTest.java client/command/src/main/java/com/redhat/thermostat/client/command/cli/PingCommand.java common/command/src/main/java/com/redhat/thermostat/common/command/Request.java common/command/src/test/java/com/redhat/thermostat/common/command/RequestTest.java common/core/src/main/java/com/redhat/thermostat/common/cli/CommandRegistryImpl.java
diffstat 12 files changed, 152 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/main/java/com/redhat/thermostat/agent/command/ReceiverRegistry.java	Thu Aug 16 17:57:28 2012 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat 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, or (at your
+ * option) any later version.
+ *
+ * Thermostat 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 Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.agent.command;
+
+import org.osgi.framework.BundleContext;
+
+import com.redhat.thermostat.common.utils.ServiceRegistry;
+
+public class ReceiverRegistry {
+
+    private ServiceRegistry<RequestReceiver> proxy;
+
+    public ReceiverRegistry(BundleContext context) {
+        proxy = new ServiceRegistry<RequestReceiver>(context, RequestReceiver.class.getName());
+    }
+
+    public void registerReceiver(RequestReceiver receiver) {
+        proxy.registerService(receiver, receiver.getClass().getName());
+    }
+
+    public RequestReceiver getReceiver(String clazz) {
+        return proxy.getService(clazz);
+    }
+
+    public void unregisterReceivers() {
+        proxy.unregisterAll();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/main/java/com/redhat/thermostat/agent/command/RequestReceiver.java	Thu Aug 16 17:57:28 2012 -0400
@@ -0,0 +1,10 @@
+package com.redhat.thermostat.agent.command;
+
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Response;
+
+public interface RequestReceiver {
+
+    public Response receive(Request request);
+
+}
--- a/agent/command/src/main/java/com/redhat/thermostat/agent/command/internal/Activator.java	Thu Aug 16 17:57:26 2012 -0400
+++ b/agent/command/src/main/java/com/redhat/thermostat/agent/command/internal/Activator.java	Thu Aug 16 17:57:28 2012 -0400
@@ -44,28 +44,28 @@
 import org.osgi.framework.ServiceRegistration;
 
 import com.redhat.thermostat.agent.command.ConfigurationServer;
+import com.redhat.thermostat.agent.command.ReceiverRegistry;
 
 public class Activator implements BundleActivator {
 
     private static final Logger logger = Logger.getLogger(Activator.class.getSimpleName());
 
-    private ConfigurationServerImpl confServer;
-    private ServiceRegistration registration;
-
-    public Activator() {
-        confServer = new ConfigurationServerImpl(new ConfigurationServerContext());
-    }
+    private ServiceRegistration confServerRegistration;
+    private ReceiverRegistry receivers;
 
     @Override
     public void start(BundleContext context) throws Exception {    
         logger.log(Level.INFO, "activating thermostat-agent-confserver");
-        registration = context.registerService(ConfigurationServer.class.getName(), confServer, null);
+        receivers = new ReceiverRegistry(context);
+        receivers.registerReceiver(new PingReceiver());
+        ConfigurationServerImpl confServer = new ConfigurationServerImpl(new ConfigurationServerContext(context));
+        confServerRegistration = context.registerService(ConfigurationServer.class.getName(), confServer, null);
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        if (registration != null) {
-            registration.unregister();
+        if (confServerRegistration != null) {
+            confServerRegistration.unregister();
         }
     }
 
--- a/agent/command/src/main/java/com/redhat/thermostat/agent/command/internal/ConfigurationServerContext.java	Thu Aug 16 17:57:26 2012 -0400
+++ b/agent/command/src/main/java/com/redhat/thermostat/agent/command/internal/ConfigurationServerContext.java	Thu Aug 16 17:57:28 2012 -0400
@@ -46,17 +46,21 @@
 import org.jboss.netty.channel.group.ChannelGroup;
 import org.jboss.netty.channel.group.DefaultChannelGroup;
 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+import org.osgi.framework.BundleContext;
 
+import com.redhat.thermostat.agent.command.ReceiverRegistry;
 import com.redhat.thermostat.common.command.ConfigurationCommandContext;
 
 class ConfigurationServerContext implements ConfigurationCommandContext {
 
     private final ServerBootstrap bootstrap;
     private final ChannelGroup channels;
+    private final BundleContext context;
 
-    ConfigurationServerContext() {
+    ConfigurationServerContext(BundleContext context) {
         bootstrap = createBootstrap();
         channels = createChannelGroup();
+        this.context = context;
     }
 
     @Override
@@ -93,7 +97,7 @@
             ChannelPipeline pipeline = Channels.pipeline();
             pipeline.addLast("decoder", new RequestDecoder());
             pipeline.addLast("encoder", new ResponseEncoder());
-            pipeline.addLast("handler", new ServerHandler());
+            pipeline.addLast("handler", new ServerHandler(new ReceiverRegistry(context)));
             return pipeline;
         }
         
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/command/src/main/java/com/redhat/thermostat/agent/command/internal/PingReceiver.java	Thu Aug 16 17:57:28 2012 -0400
@@ -0,0 +1,15 @@
+package com.redhat.thermostat.agent.command.internal;
+
+import com.redhat.thermostat.agent.command.RequestReceiver;
+import com.redhat.thermostat.common.command.Request;
+import com.redhat.thermostat.common.command.Response;
+import com.redhat.thermostat.common.command.Response.ResponseType;
+
+public class PingReceiver implements RequestReceiver {
+
+    @Override
+    public Response receive(Request request) {
+        return new Response(ResponseType.PONG);
+    }
+
+}
--- a/agent/command/src/main/java/com/redhat/thermostat/agent/command/internal/ServerHandler.java	Thu Aug 16 17:57:26 2012 -0400
+++ b/agent/command/src/main/java/com/redhat/thermostat/agent/command/internal/ServerHandler.java	Thu Aug 16 17:57:28 2012 -0400
@@ -47,6 +47,8 @@
 import org.jboss.netty.channel.MessageEvent;
 import org.jboss.netty.channel.SimpleChannelHandler;
 
+import com.redhat.thermostat.agent.command.ReceiverRegistry;
+import com.redhat.thermostat.agent.command.RequestReceiver;
 import com.redhat.thermostat.common.command.Request;
 import com.redhat.thermostat.common.command.Response;
 import com.redhat.thermostat.common.command.Request.RequestType;
@@ -54,13 +56,25 @@
 
 class ServerHandler extends SimpleChannelHandler {
 
+    private ReceiverRegistry receivers;
+
+    public ServerHandler(ReceiverRegistry receivers) {
+        this.receivers = receivers;
+    }
+
     private static final Logger logger = Logger.getLogger(ServerHandler.class.getName());
 
     @Override
     public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
         Request request = (Request) e.getMessage();
         logger.info("Request received: " + request.getType().toString());
-        Response response = doRequest(request);
+        RequestReceiver receiver = receivers.getReceiver(request.getReceiver());
+        Response response = null;
+        if (receiver != null) {
+            response = receiver.receive(request);
+        } else {
+            response = new Response(ResponseType.ERROR);
+        }
         Channel channel = ctx.getChannel();
         if (channel.isConnected()) {
             logger.info("Sending response: " + response.getType().toString());
@@ -80,7 +94,7 @@
     private Response doRequest(Request request) {
         Response response = new Response(ResponseType.ERROR);
         switch ((RequestType) request.getType()) {
-        case PING:
+        case RESPONSE_EXPECTED:
             response = new Response(ResponseType.PONG);
             break;
         default:
--- a/agent/command/src/test/java/com/redhat/thermostat/agent/command/internal/ConfigurationServerContextTest.java	Thu Aug 16 17:57:26 2012 -0400
+++ b/agent/command/src/test/java/com/redhat/thermostat/agent/command/internal/ConfigurationServerContextTest.java	Thu Aug 16 17:57:28 2012 -0400
@@ -39,6 +39,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
 
 import org.jboss.netty.bootstrap.Bootstrap;
 import org.jboss.netty.channel.ChannelHandler;
@@ -47,6 +48,7 @@
 import org.jboss.netty.channel.group.ChannelGroup;
 import org.junit.Before;
 import org.junit.Test;
+import org.osgi.framework.BundleContext;
 
 import com.redhat.thermostat.agent.command.internal.ConfigurationServerContext;
 import com.redhat.thermostat.agent.command.internal.RequestDecoder;
@@ -59,7 +61,8 @@
 
     @Before
     public void setUp() {
-        ctx = new ConfigurationServerContext();
+        BundleContext bCtx = mock(BundleContext.class);
+        ctx = new ConfigurationServerContext(bCtx);
     }
 
     @Test
--- a/agent/command/src/test/java/com/redhat/thermostat/agent/command/internal/RequestDecoderTest.java	Thu Aug 16 17:57:26 2012 -0400
+++ b/agent/command/src/test/java/com/redhat/thermostat/agent/command/internal/RequestDecoderTest.java	Thu Aug 16 17:57:28 2012 -0400
@@ -53,7 +53,7 @@
 import static org.mockito.Mockito.mock;
 
 public class RequestDecoderTest {
-    private static final byte[] PING = "PING".getBytes();
+    private static final byte[] TYPE = RequestType.RESPONSE_EXPECTED.toString().getBytes();
 
     private Channel channel;
     private RequestDecoder decoder;
@@ -67,12 +67,12 @@
     @Test
     public void testDecode() {
         ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
-        buffer.writeInt(PING.length);
-        buffer.writeBytes(PING);
+        buffer.writeInt(TYPE.length);
+        buffer.writeBytes(TYPE);
 
         Request request = (Request) decoder.decode(null, channel, buffer);
 
-        assertTrue(RequestType.PING == (RequestType) request.getType());
+        assertTrue(RequestType.RESPONSE_EXPECTED == (RequestType) request.getType());
     }
 
     @Test
@@ -80,8 +80,8 @@
         String parmName = "parameter";
         String parmValue = "hello";
         ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
-        buffer.writeInt(PING.length);
-        buffer.writeBytes(PING);
+        buffer.writeInt(TYPE.length);
+        buffer.writeBytes(TYPE);
         buffer.writeInt(1);
         buffer.writeInt(parmName.getBytes().length);
         buffer.writeInt(parmValue.getBytes().length);
--- a/client/command/src/main/java/com/redhat/thermostat/client/command/cli/PingCommand.java	Thu Aug 16 17:57:26 2012 -0400
+++ b/client/command/src/main/java/com/redhat/thermostat/client/command/cli/PingCommand.java	Thu Aug 16 17:57:28 2012 -0400
@@ -118,7 +118,8 @@
         }
         int port = df.getStorage().getConfigListenPort(targetHostRef);
         InetSocketAddress target = new InetSocketAddress(targetHostRef.getHostName(), port);
-        Request ping = new Request(RequestType.PING, target);
+        Request ping = new Request(RequestType.RESPONSE_EXPECTED, target);
+        ping.setReceiver("com.redhat.thermostat.agent.command.internal.PingReceiver");
         final Semaphore responseBarrier = new Semaphore(0);
         ping.addListener(new PongListener(out, responseBarrier));
 
--- a/common/command/src/main/java/com/redhat/thermostat/common/command/Request.java	Thu Aug 16 17:57:26 2012 -0400
+++ b/common/command/src/main/java/com/redhat/thermostat/common/command/Request.java	Thu Aug 16 17:57:28 2012 -0400
@@ -47,7 +47,9 @@
 public class Request implements Message {
 
     public enum RequestType implements MessageType {
-        PING;
+        NO_RESPONSE_EXPECTED,
+        RESPONSE_EXPECTED,
+        MULTIPART_RESPONSE_EXPECTED;
     }
 
     private final RequestType type;
@@ -55,6 +57,8 @@
     private final SocketAddress target;
     private final Collection<RequestResponseListener> listeners;
 
+    private static final String RECEIVER = "receiver";
+
     public Request(RequestType type, SocketAddress target) {
         this.type = type;
         parameters = new TreeMap<>();
@@ -79,6 +83,14 @@
         return parameters.keySet();
     }
 
+    public void setReceiver(String clazz) {
+        setParameter(RECEIVER, clazz);
+    }
+
+    public String getReceiver() {
+        return getParameter(RECEIVER);
+    }
+
     public SocketAddress getTarget() {
         return target;
     }
--- a/common/command/src/test/java/com/redhat/thermostat/common/command/RequestTest.java	Thu Aug 16 17:57:26 2012 -0400
+++ b/common/command/src/test/java/com/redhat/thermostat/common/command/RequestTest.java	Thu Aug 16 17:57:28 2012 -0400
@@ -64,9 +64,9 @@
 
     @Test
     public void testGetTypeAndTarget() {
-        Request request = new Request(RequestType.PING, new InetSocketAddress(HOST, PORT));
+        Request request = new Request(RequestType.RESPONSE_EXPECTED, new InetSocketAddress(HOST, PORT));
         RequestType type = (RequestType) request.getType();
-        assertEquals(RequestType.PING, type);
+        assertEquals(RequestType.RESPONSE_EXPECTED, type);
 
         InetSocketAddress target = (InetSocketAddress) request.getTarget();
         assertEquals(PORT, target.getPort());
@@ -75,7 +75,7 @@
 
     @Test
     public void testAddListener() {
-        Request request = new Request(RequestType.PING, new InetSocketAddress(HOST, PORT));
+        Request request = new Request(RequestType.RESPONSE_EXPECTED, new InetSocketAddress(HOST, PORT));
         RequestResponseListener listener1 = new RequestResponseListenerImpl();
         RequestResponseListener listener2 = new RequestResponseListenerImpl();
         request.addListener(listener1);
@@ -88,7 +88,7 @@
 
     @Test
     public void testRemoveListener() {
-        Request request = new Request(RequestType.PING, new InetSocketAddress(HOST, PORT));
+        Request request = new Request(RequestType.RESPONSE_EXPECTED, new InetSocketAddress(HOST, PORT));
         RequestResponseListener listener1 = new RequestResponseListenerImpl();
         RequestResponseListener listener2 = new RequestResponseListenerImpl();
         request.addListener(listener1);
--- a/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandRegistryImpl.java	Thu Aug 16 17:57:26 2012 -0400
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandRegistryImpl.java	Thu Aug 16 17:57:28 2012 -0400
@@ -43,6 +43,11 @@
 
 import com.redhat.thermostat.common.utils.ServiceRegistry;
 
+/**
+ * This class mainly wraps around a ServiceRegistry object, handling the additional
+ * non-osgi-specific task of enable/disable of Command objects as they are registered
+ * or unregistered.
+ */
 public class CommandRegistryImpl implements CommandRegistry {
 
     private BundleContext context;