diff --git a/src/main/java/org/jboss/netty/example/localtime/LocalTimeClient.java b/src/main/java/org/jboss/netty/example/localtime/LocalTimeClient.java new file mode 100644 index 0000000000..f445c49113 --- /dev/null +++ b/src/main/java/org/jboss/netty/example/localtime/LocalTimeClient.java @@ -0,0 +1,124 @@ +/* + * JBoss, Home of Professional Open Source + * + * Copyright 2008, Red Hat Middleware LLC, and individual contributors + * by the @author tags. See the COPYRIGHT.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.localtime; + +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.Executors; + +import org.jboss.netty.bootstrap.ClientBootstrap; +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelFactory; +import org.jboss.netty.channel.ChannelFuture; +import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; + +/** + * Sends a list of continent/city pairs to a {@link LocalTimeServer} to + * get the local times of the specified cities. + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Trustin Lee (tlee@redhat.com) + * + * @version $Rev$, $Date$ + */ +public class LocalTimeClient { + + public static void main(String[] args) throws Exception { + // Print usage if necessary. + if (args.length < 3) { + printUsage(); + return; + } + + // Parse options. + String host = args[0]; + int port = Integer.parseInt(args[1]); + Collection cities = parseCities(args, 2); + if (cities == null) { + return; + } + + // Set up. + ChannelFactory factory = + new NioClientSocketChannelFactory( + Executors.newCachedThreadPool(), + Executors.newCachedThreadPool()); + + ClientBootstrap bootstrap = new ClientBootstrap(factory); + + bootstrap.setPipelineFactory(new LocalTimeClientPipelineFactory()); + bootstrap.setOption("tcpNoDelay", true); + bootstrap.setOption("keepAlive", true); + + // Make a new connection. + ChannelFuture connectFuture = + bootstrap.connect(new InetSocketAddress(host, port)); + + // Wait until the connection is made successfully. + Channel channel = connectFuture.awaitUninterruptibly().getChannel(); + + // Get the handler instance to initiate the request. + LocalTimeClientHandler handler = + channel.getPipeline().get(LocalTimeClientHandler.class); + + // Request and get the response. + List response = handler.getLocalTimes(cities); + // Close the connection. + channel.close().awaitUninterruptibly(); + + // Shut down all thread pools to exit. + factory.releaseExternalResources(); + + // Print the response at last but not least. + Iterator i1 = cities.iterator(); + Iterator i2 = response.iterator(); + while (i1.hasNext()) { + System.out.format("%28s: %s%n", i1.next(), i2.next()); + } + } + + private static void printUsage() { + System.err.println( + "Usage: " + LocalTimeClient.class.getSimpleName() + + " ..."); + System.err.println( + "Example: " + LocalTimeClient.class.getSimpleName() + + " localhost 8080 America/New_York Asia/Seoul"); + } + + private static List parseCities(String[] args, int offset) { + List cities = new ArrayList(); + for (int i = offset; i < args.length; i ++) { + if (!args[i].matches("^[_A-Za-z]+/[_A-Za-z]+$")) { + System.err.println("Syntax error: '" + args[i] + "'"); + printUsage(); + return null; + } + cities.add(args[i].trim()); + } + return cities; + } +} diff --git a/src/main/java/org/jboss/netty/example/localtime/LocalTimeClientHandler.java b/src/main/java/org/jboss/netty/example/localtime/LocalTimeClientHandler.java new file mode 100644 index 0000000000..a8b5272bc5 --- /dev/null +++ b/src/main/java/org/jboss/netty/example/localtime/LocalTimeClientHandler.java @@ -0,0 +1,134 @@ +/* + * JBoss, Home of Professional Open Source + * + * Copyright 2008, Red Hat Middleware LLC, and individual contributors + * by the @author tags. See the COPYRIGHT.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.localtime; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Formatter; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelEvent; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.ChannelPipelineCoverage; +import org.jboss.netty.channel.ChannelStateEvent; +import org.jboss.netty.channel.ExceptionEvent; +import org.jboss.netty.channel.MessageEvent; +import org.jboss.netty.channel.SimpleChannelHandler; +import org.jboss.netty.example.localtime.LocalTimeProtocol.Continent; +import org.jboss.netty.example.localtime.LocalTimeProtocol.LocalTime; +import org.jboss.netty.example.localtime.LocalTimeProtocol.LocalTimes; +import org.jboss.netty.example.localtime.LocalTimeProtocol.Location; +import org.jboss.netty.example.localtime.LocalTimeProtocol.Locations; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Trustin Lee (tlee@redhat.com) + * + * @version $Rev$, $Date$ + */ +@ChannelPipelineCoverage("one") +public class LocalTimeClientHandler extends SimpleChannelHandler { + + private static final Logger logger = Logger.getLogger( + LocalTimeClientHandler.class.getName()); + + // Stateful properties + private volatile Channel channel; + private final BlockingQueue answer = new LinkedBlockingQueue(); + + public List getLocalTimes(Collection cities) { + Locations.Builder builder = Locations.newBuilder(); + + for (String c: cities) { + String[] components = c.split("/"); + builder.addLocation(Location.newBuilder(). + setContinent(Continent.valueOf(components[0].toUpperCase())). + setCity(components[1]).build()); + } + + channel.write(builder.build()); + + LocalTimes localTimes; + for (;;) { + try { + localTimes = answer.take(); + break; + } catch (InterruptedException e) { + // Ignore. + } + } + + List result = new ArrayList(); + for (LocalTime lt: localTimes.getLocalTimeList()) { + result.add( + new Formatter().format( + "%4d-%02d-%02d %02d:%02d:%02d %s", + lt.getYear(), + lt.getMonth(), + lt.getDayOfMonth(), + lt.getHour(), + lt.getMinute(), + lt.getSecond(), + lt.getDayOfWeek().name()).toString()); + } + + return result; + } + + @Override + public void handleUpstream( + ChannelHandlerContext ctx, ChannelEvent e) throws Exception { + if (e instanceof ChannelStateEvent) { + logger.info(e.toString()); + } + super.handleUpstream(ctx, e); + } + + @Override + public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) + throws Exception { + channel = e.getChannel(); + super.channelOpen(ctx, e); + } + + @Override + public void messageReceived( + ChannelHandlerContext ctx, final MessageEvent e) { + answer.offer((LocalTimes) e.getMessage()); + } + + @Override + public void exceptionCaught( + ChannelHandlerContext ctx, ExceptionEvent e) { + logger.log( + Level.WARNING, + "Unexpected exception from downstream.", + e.getCause()); + e.getChannel().close(); + } +} diff --git a/src/main/java/org/jboss/netty/example/localtime/LocalTimeClientPipelineFactory.java b/src/main/java/org/jboss/netty/example/localtime/LocalTimeClientPipelineFactory.java new file mode 100644 index 0000000000..fe6dfe3667 --- /dev/null +++ b/src/main/java/org/jboss/netty/example/localtime/LocalTimeClientPipelineFactory.java @@ -0,0 +1,52 @@ +/* + * JBoss, Home of Professional Open Source + * + * Copyright 2009, Red Hat Middleware LLC, and individual contributors + * by the @author tags. See the COPYRIGHT.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.localtime; + +import static org.jboss.netty.channel.Channels.*; + +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder; +import org.jboss.netty.handler.codec.frame.LengthFieldPrepender; +import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder; +import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Trustin Lee (tlee@redhat.com) + * @version $Rev$, $Date$ + */ +public class LocalTimeClientPipelineFactory implements ChannelPipelineFactory { + + public ChannelPipeline getPipeline() throws Exception { + ChannelPipeline p = pipeline(); + p.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4)); + p.addLast("protobufDecoder", new ProtobufDecoder(LocalTimeProtocol.LocalTimes.getDefaultInstance())); + + p.addLast("frameEncoder", new LengthFieldPrepender(4)); + p.addLast("protobufEncoder", new ProtobufEncoder()); + + p.addLast("handler", new LocalTimeClientHandler()); + return p; + } +} diff --git a/src/main/java/org/jboss/netty/example/localtime/LocalTimeProtocol.java b/src/main/java/org/jboss/netty/example/localtime/LocalTimeProtocol.java index ddc696dc70..50677dc649 100644 --- a/src/main/java/org/jboss/netty/example/localtime/LocalTimeProtocol.java +++ b/src/main/java/org/jboss/netty/example/localtime/LocalTimeProtocol.java @@ -77,6 +77,68 @@ public final class LocalTimeProtocol { } } + public static enum DayOfWeek { + SUNDAY(0, 1), + MONDAY(1, 2), + TUESDAY(2, 3), + WEDNESDAY(3, 4), + THURSDAY(4, 5), + FRIDAY(5, 6), + SATURDAY(6, 7), + ; + + + public final int getNumber() { return value; } + + public static DayOfWeek valueOf(int value) { + switch (value) { + case 1: return SUNDAY; + case 2: return MONDAY; + case 3: return TUESDAY; + case 4: return WEDNESDAY; + case 5: return THURSDAY; + case 6: return FRIDAY; + case 7: return SATURDAY; + default: return null; + } + } + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + return getDescriptor().getValues().get(index); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return org.jboss.netty.example.localtime.LocalTimeProtocol.getDescriptor().getEnumTypes().get(1); + } + + private static final DayOfWeek[] VALUES = { + SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, + }; + public static DayOfWeek valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + return VALUES[desc.getIndex()]; + } + private final int index; + private final int value; + private DayOfWeek(int index, int value) { + this.index = index; + this.value = value; + } + + static { + org.jboss.netty.example.localtime.LocalTimeProtocol.getDescriptor(); + } + } + public static final class Location extends com.google.protobuf.GeneratedMessage { // Use Location.newBuilder() to construct. @@ -708,23 +770,17 @@ public final class LocalTimeProtocol { public boolean hasMonth() { return hasMonth; } public int getMonth() { return month_; } - // required uint32 week = 3; - private boolean hasWeek; - private int week_ = 0; - public boolean hasWeek() { return hasWeek; } - public int getWeek() { return week_; } - // required uint32 dayOfMonth = 4; private boolean hasDayOfMonth; private int dayOfMonth_ = 0; public boolean hasDayOfMonth() { return hasDayOfMonth; } public int getDayOfMonth() { return dayOfMonth_; } - // required uint32 dayOfWeek = 5; + // required .org.jboss.netty.example.localtime.DayOfWeek dayOfWeek = 5; private boolean hasDayOfWeek; - private int dayOfWeek_ = 0; + private org.jboss.netty.example.localtime.LocalTimeProtocol.DayOfWeek dayOfWeek_ = org.jboss.netty.example.localtime.LocalTimeProtocol.DayOfWeek.SUNDAY; public boolean hasDayOfWeek() { return hasDayOfWeek; } - public int getDayOfWeek() { return dayOfWeek_; } + public org.jboss.netty.example.localtime.LocalTimeProtocol.DayOfWeek getDayOfWeek() { return dayOfWeek_; } // required uint32 hour = 6; private boolean hasHour; @@ -748,7 +804,6 @@ public final class LocalTimeProtocol { public final boolean isInitialized() { if (!hasYear) return false; if (!hasMonth) return false; - if (!hasWeek) return false; if (!hasDayOfMonth) return false; if (!hasDayOfWeek) return false; if (!hasHour) return false; @@ -766,14 +821,11 @@ public final class LocalTimeProtocol { if (hasMonth()) { output.writeUInt32(2, getMonth()); } - if (hasWeek()) { - output.writeUInt32(3, getWeek()); - } if (hasDayOfMonth()) { output.writeUInt32(4, getDayOfMonth()); } if (hasDayOfWeek()) { - output.writeUInt32(5, getDayOfWeek()); + output.writeEnum(5, getDayOfWeek().getNumber()); } if (hasHour()) { output.writeUInt32(6, getHour()); @@ -802,17 +854,13 @@ public final class LocalTimeProtocol { size += com.google.protobuf.CodedOutputStream .computeUInt32Size(2, getMonth()); } - if (hasWeek()) { - size += com.google.protobuf.CodedOutputStream - .computeUInt32Size(3, getWeek()); - } if (hasDayOfMonth()) { size += com.google.protobuf.CodedOutputStream .computeUInt32Size(4, getDayOfMonth()); } if (hasDayOfWeek()) { size += com.google.protobuf.CodedOutputStream - .computeUInt32Size(5, getDayOfWeek()); + .computeEnumSize(5, getDayOfWeek().getNumber()); } if (hasHour()) { size += com.google.protobuf.CodedOutputStream @@ -958,9 +1006,6 @@ public final class LocalTimeProtocol { if (other.hasMonth()) { setMonth(other.getMonth()); } - if (other.hasWeek()) { - setWeek(other.getWeek()); - } if (other.hasDayOfMonth()) { setDayOfMonth(other.getDayOfMonth()); } @@ -1018,16 +1063,18 @@ public final class LocalTimeProtocol { setMonth(input.readUInt32()); break; } - case 24: { - setWeek(input.readUInt32()); - break; - } case 32: { setDayOfMonth(input.readUInt32()); break; } case 40: { - setDayOfWeek(input.readUInt32()); + int rawValue = input.readEnum(); + org.jboss.netty.example.localtime.LocalTimeProtocol.DayOfWeek value = org.jboss.netty.example.localtime.LocalTimeProtocol.DayOfWeek.valueOf(rawValue); + if (value == null) { + unknownFields.mergeVarintField(5, rawValue); + } else { + setDayOfWeek(value); + } break; } case 48: { @@ -1083,24 +1130,6 @@ public final class LocalTimeProtocol { return this; } - // required uint32 week = 3; - public boolean hasWeek() { - return result.hasWeek(); - } - public int getWeek() { - return result.getWeek(); - } - public Builder setWeek(int value) { - result.hasWeek = true; - result.week_ = value; - return this; - } - public Builder clearWeek() { - result.hasWeek = false; - result.week_ = 0; - return this; - } - // required uint32 dayOfMonth = 4; public boolean hasDayOfMonth() { return result.hasDayOfMonth(); @@ -1119,21 +1148,21 @@ public final class LocalTimeProtocol { return this; } - // required uint32 dayOfWeek = 5; + // required .org.jboss.netty.example.localtime.DayOfWeek dayOfWeek = 5; public boolean hasDayOfWeek() { return result.hasDayOfWeek(); } - public int getDayOfWeek() { + public org.jboss.netty.example.localtime.LocalTimeProtocol.DayOfWeek getDayOfWeek() { return result.getDayOfWeek(); } - public Builder setDayOfWeek(int value) { + public Builder setDayOfWeek(org.jboss.netty.example.localtime.LocalTimeProtocol.DayOfWeek value) { result.hasDayOfWeek = true; result.dayOfWeek_ = value; return this; } public Builder clearDayOfWeek() { result.hasDayOfWeek = false; - result.dayOfWeek_ = 0; + result.dayOfWeek_ = org.jboss.netty.example.localtime.LocalTimeProtocol.DayOfWeek.SUNDAY; return this; } @@ -1527,17 +1556,20 @@ public final class LocalTimeProtocol { "inent\030\001 \002(\0162,.org.jboss.netty.example.lo" + "caltime.Continent\022\014\n\004city\030\002 \002(\t\"J\n\tLocat" + "ions\022=\n\010location\030\001 \003(\0132+.org.jboss.netty" + - ".example.localtime.Location\"\213\001\n\tLocalTim" + - "e\022\014\n\004year\030\001 \002(\r\022\r\n\005month\030\002 \002(\r\022\014\n\004week\030\003" + - " \002(\r\022\022\n\ndayOfMonth\030\004 \002(\r\022\021\n\tdayOfWeek\030\005 " + - "\002(\r\022\014\n\004hour\030\006 \002(\r\022\016\n\006minute\030\007 \002(\r\022\016\n\006sec" + - "ond\030\010 \002(\r\"M\n\nLocalTimes\022?\n\tlocalTime\030\001 \003" + - "(\0132,.org.jboss.netty.example.localtime.L" + - "ocalTime*\231\001\n\tContinent\022\n\n\006AFRICA\020\000\022\013\n\007AM" + - "ERICA\020\001\022\016\n\nANTARCTICA\020\002\022\n\n\006ARCTIC\020\003\022\010\n\004A" + - "SIA\020\004\022\014\n\010ATLANTIC\020\005\022\r\n\tAUSTRALIA\020\006\022\n\n\006EU" + - "ROPE\020\007\022\n\n\006INDIAN\020\010\022\013\n\007MIDEAST\020\t\022\013\n\007PACIF" + - "IC\020\nB\002H\001"; + ".example.localtime.Location\"\253\001\n\tLocalTim" + + "e\022\014\n\004year\030\001 \002(\r\022\r\n\005month\030\002 \002(\r\022\022\n\ndayOfM" + + "onth\030\004 \002(\r\022?\n\tdayOfWeek\030\005 \002(\0162,.org.jbos" + + "s.netty.example.localtime.DayOfWeek\022\014\n\004h" + + "our\030\006 \002(\r\022\016\n\006minute\030\007 \002(\r\022\016\n\006second\030\010 \002(" + + "\r\"M\n\nLocalTimes\022?\n\tlocalTime\030\001 \003(\0132,.org" + + ".jboss.netty.example.localtime.LocalTime" + + "*\231\001\n\tContinent\022\n\n\006AFRICA\020\000\022\013\n\007AMERICA\020\001\022" + + "\016\n\nANTARCTICA\020\002\022\n\n\006ARCTIC\020\003\022\010\n\004ASIA\020\004\022\014\n" + + "\010ATLANTIC\020\005\022\r\n\tAUSTRALIA\020\006\022\n\n\006EUROPE\020\007\022\n" + + "\n\006INDIAN\020\010\022\013\n\007MIDEAST\020\t\022\013\n\007PACIFIC\020\n*g\n\t" + + "DayOfWeek\022\n\n\006SUNDAY\020\001\022\n\n\006MONDAY\020\002\022\013\n\007TUE" + + "SDAY\020\003\022\r\n\tWEDNESDAY\020\004\022\014\n\010THURSDAY\020\005\022\n\n\006F" + + "RIDAY\020\006\022\014\n\010SATURDAY\020\007B\002H\001"; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { public com.google.protobuf.ExtensionRegistry assignDescriptors( @@ -1564,7 +1596,7 @@ public final class LocalTimeProtocol { internal_static_org_jboss_netty_example_localtime_LocalTime_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_org_jboss_netty_example_localtime_LocalTime_descriptor, - new java.lang.String[] { "Year", "Month", "Week", "DayOfMonth", "DayOfWeek", "Hour", "Minute", "Second", }, + new java.lang.String[] { "Year", "Month", "DayOfMonth", "DayOfWeek", "Hour", "Minute", "Second", }, org.jboss.netty.example.localtime.LocalTimeProtocol.LocalTime.class, org.jboss.netty.example.localtime.LocalTimeProtocol.LocalTime.Builder.class); internal_static_org_jboss_netty_example_localtime_LocalTimes_descriptor = diff --git a/src/main/java/org/jboss/netty/example/localtime/LocalTimeProtocol.proto b/src/main/java/org/jboss/netty/example/localtime/LocalTimeProtocol.proto index 9700515e07..f5fcee4346 100644 --- a/src/main/java/org/jboss/netty/example/localtime/LocalTimeProtocol.proto +++ b/src/main/java/org/jboss/netty/example/localtime/LocalTimeProtocol.proto @@ -47,12 +47,21 @@ message Locations { repeated Location location = 1; } +enum DayOfWeek { + SUNDAY = 1; + MONDAY = 2; + TUESDAY = 3; + WEDNESDAY = 4; + THURSDAY = 5; + FRIDAY = 6; + SATURDAY = 7; +} + message LocalTime { required uint32 year = 1; required uint32 month = 2; - required uint32 week = 3; required uint32 dayOfMonth = 4; - required uint32 dayOfWeek = 5; + required DayOfWeek dayOfWeek = 5; required uint32 hour = 6; required uint32 minute = 7; required uint32 second = 8; diff --git a/src/main/java/org/jboss/netty/example/localtime/LocalTimeServer.java b/src/main/java/org/jboss/netty/example/localtime/LocalTimeServer.java new file mode 100644 index 0000000000..7ff85155c7 --- /dev/null +++ b/src/main/java/org/jboss/netty/example/localtime/LocalTimeServer.java @@ -0,0 +1,59 @@ +/* + * JBoss, Home of Professional Open Source + * + * Copyright 2008, Red Hat Middleware LLC, and individual contributors + * by the @author tags. See the COPYRIGHT.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.localtime; + +import java.net.InetSocketAddress; +import java.util.concurrent.Executors; + +import org.jboss.netty.bootstrap.ServerBootstrap; +import org.jboss.netty.channel.ChannelFactory; +import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; + +/** + * Receives a list of continent/city pairs from a {@link LocalTimeClient} to + * get the local times of the specified cities. + * + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Trustin Lee (tlee@redhat.com) + * + * @version $Rev$, $Date$ + */ +public class LocalTimeServer { + + public static void main(String[] args) throws Exception { + // Configure the server. + ChannelFactory factory = + new NioServerSocketChannelFactory( + Executors.newCachedThreadPool(), + Executors.newCachedThreadPool()); + + ServerBootstrap bootstrap = new ServerBootstrap(factory); + + bootstrap.setPipelineFactory(new LocalTimeServerPipelineFactory()); + bootstrap.setOption("child.tcpNoDelay", true); + bootstrap.setOption("child.keepAlive", true); + + // Bind and start to accept incoming connections. + bootstrap.bind(new InetSocketAddress(8080)); + } +} diff --git a/src/main/java/org/jboss/netty/example/localtime/LocalTimeServerHandler.java b/src/main/java/org/jboss/netty/example/localtime/LocalTimeServerHandler.java new file mode 100644 index 0000000000..df0264f666 --- /dev/null +++ b/src/main/java/org/jboss/netty/example/localtime/LocalTimeServerHandler.java @@ -0,0 +1,107 @@ +/* + * JBoss, Home of Professional Open Source + * + * Copyright 2008, Red Hat Middleware LLC, and individual contributors + * by the @author tags. See the COPYRIGHT.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.localtime; + +import static java.util.Calendar.*; + +import java.util.Calendar; +import java.util.TimeZone; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.jboss.netty.channel.ChannelEvent; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.ChannelPipelineCoverage; +import org.jboss.netty.channel.ChannelStateEvent; +import org.jboss.netty.channel.ExceptionEvent; +import org.jboss.netty.channel.MessageEvent; +import org.jboss.netty.channel.SimpleChannelHandler; +import org.jboss.netty.example.localtime.LocalTimeProtocol.Continent; +import org.jboss.netty.example.localtime.LocalTimeProtocol.DayOfWeek; +import org.jboss.netty.example.localtime.LocalTimeProtocol.LocalTime; +import org.jboss.netty.example.localtime.LocalTimeProtocol.LocalTimes; +import org.jboss.netty.example.localtime.LocalTimeProtocol.Location; +import org.jboss.netty.example.localtime.LocalTimeProtocol.Locations; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Trustin Lee (tlee@redhat.com) + * + * @version $Rev$, $Date$ + */ +@ChannelPipelineCoverage("all") +public class LocalTimeServerHandler extends SimpleChannelHandler { + + private static final Logger logger = Logger.getLogger( + LocalTimeServerHandler.class.getName()); + + @Override + public void handleUpstream( + ChannelHandlerContext ctx, ChannelEvent e) throws Exception { + if (e instanceof ChannelStateEvent) { + logger.info(e.toString()); + } + super.handleUpstream(ctx, e); + } + + @Override + public void messageReceived( + ChannelHandlerContext ctx, MessageEvent e) { + + Locations locations = (Locations) e.getMessage(); + long currentTime = System.currentTimeMillis(); + + LocalTimes.Builder builder = LocalTimes.newBuilder(); + for (Location l: locations.getLocationList()) { + TimeZone tz = TimeZone.getTimeZone( + toString(l.getContinent()) + '/' + l.getCity()); + Calendar calendar = Calendar.getInstance(tz); + calendar.setTimeInMillis(currentTime); + + builder.addLocalTime(LocalTime.newBuilder(). + setYear(calendar.get(YEAR)). + setMonth(calendar.get(MONTH) + 1). + setDayOfMonth(calendar.get(DAY_OF_MONTH)). + setDayOfWeek(DayOfWeek.valueOf(calendar.get(DAY_OF_WEEK))). + setHour(calendar.get(HOUR)). + setMinute(calendar.get(MINUTE)). + setSecond(calendar.get(SECOND)).build()); + } + + e.getChannel().write(builder.build()); + } + + @Override + public void exceptionCaught( + ChannelHandlerContext ctx, ExceptionEvent e) { + logger.log( + Level.WARNING, + "Unexpected exception from downstream.", + e.getCause()); + e.getChannel().close(); + } + + private static String toString(Continent c) { + return "" + c.name().charAt(0) + c.name().toLowerCase().substring(1); + } +} diff --git a/src/main/java/org/jboss/netty/example/localtime/LocalTimeServerPipelineFactory.java b/src/main/java/org/jboss/netty/example/localtime/LocalTimeServerPipelineFactory.java new file mode 100644 index 0000000000..1920da5295 --- /dev/null +++ b/src/main/java/org/jboss/netty/example/localtime/LocalTimeServerPipelineFactory.java @@ -0,0 +1,52 @@ +/* + * JBoss, Home of Professional Open Source + * + * Copyright 2009, Red Hat Middleware LLC, and individual contributors + * by the @author tags. See the COPYRIGHT.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.netty.example.localtime; + +import static org.jboss.netty.channel.Channels.*; + +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.channel.ChannelPipelineFactory; +import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder; +import org.jboss.netty.handler.codec.frame.LengthFieldPrepender; +import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder; +import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder; + +/** + * @author The Netty Project (netty-dev@lists.jboss.org) + * @author Trustin Lee (tlee@redhat.com) + * @version $Rev$, $Date$ + */ +public class LocalTimeServerPipelineFactory implements ChannelPipelineFactory { + + public ChannelPipeline getPipeline() throws Exception { + ChannelPipeline p = pipeline(); + p.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4)); + p.addLast("protobufDecoder", new ProtobufDecoder(LocalTimeProtocol.Locations.getDefaultInstance())); + + p.addLast("frameEncoder", new LengthFieldPrepender(4)); + p.addLast("protobufEncoder", new ProtobufEncoder()); + + p.addLast("handler", new LocalTimeServerHandler()); + return p; + } +}