Mercurial > hg > release > thermostat-0.4
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
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;