getChannel();
15 |
16 | /**
17 | * @return the event type.
18 | */
19 | ChannelEventType getType();
20 |
21 | /**
22 | * Fire the event.
23 | */
24 | void fire();
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/ChannelEventType.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | /**
4 | * An enumeration that represents the type of {@link ChannelEvent}.
5 | *
6 | * @author mindwind
7 | * @version 1.0, Feb 21, 2013
8 | */
9 | public enum ChannelEventType {
10 |
11 | /** When channel has been opened, fire this event */
12 | CHANNEL_OPENED,
13 |
14 | /** When channel has been closed, fire this event */
15 | CHANNEL_CLOSED,
16 |
17 | /** When channel has read some data, fire this event */
18 | CHANNEL_READ,
19 |
20 | /** When channel would flush out data in it, fire this event */
21 | CHANNEL_FLUSH,
22 |
23 | /** When channel has written some data, fire this event */
24 | CHANNEL_WRITTEN,
25 |
26 | /** When channel has no data transmit for a while, fire this event */
27 | CHANNEL_IDLE,
28 |
29 | /** When channel operation throw exception, fire this event */
30 | CHANNEL_THROWN
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/ChannelState.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | /**
4 | * The state of a {@link Channel}.
5 | *
6 | * @author mindwind
7 | * @version 1.0, Feb 21, 2013
8 | */
9 | public enum ChannelState {
10 |
11 | /** Channel in OPEN state once a channel is created. */
12 | OPEN,
13 |
14 | /** Channel in CLOSING state for async close operation, means in closing process. */
15 | CLOSING,
16 |
17 | /** Channel in ClOSED state, means channel can not be used. */
18 | CLOSED,
19 |
20 | /** Channel in PAUSED state, means pause accept new data transmit request, but data already in the buffer of channel can be transmitted. */
21 | PAUSED
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IllegalChannelStateException.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | /**
4 | * Unchecked exception thrown when an attempt is made to write data to channel that is not available.
5 | *
6 | * @author mindwind
7 | * @version 1.0, Aug 22, 2014
8 | */
9 | public class IllegalChannelStateException extends IllegalStateException {
10 |
11 |
12 | private static final long serialVersionUID = 668172854459635294L;
13 |
14 |
15 | public IllegalChannelStateException() {}
16 |
17 | public IllegalChannelStateException(String message, Throwable cause) {
18 | super(message, cause);
19 | }
20 |
21 | public IllegalChannelStateException(String s) {
22 | super(s);
23 | }
24 |
25 | public IllegalChannelStateException(Throwable cause) {
26 | super(cause);
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoAcceptor.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | import java.io.IOException;
4 | import java.net.SocketAddress;
5 | import java.util.Set;
6 |
7 | /**
8 | * Accepts I/O incoming request base on specific implementation.
9 | *
10 | * @author mindwind
11 | * @version 1.0, Mar 12, 2013
12 | */
13 | public interface IoAcceptor extends IoReactor, IoAcceptorMBean {
14 |
15 | /**
16 | * Binds to specified local port with any local address and start to accept incoming request.
17 | *
18 | * @param port
19 | * @throws IOException
20 | */
21 | void bind(int port) throws IOException;
22 |
23 | /**
24 | * Binds to the specified local addresses and start to accept incoming request.
25 | * If any address binding failed then rollback the already bound addresses.
26 | * Bind operation is fail fast, if encounter the first bind exception then throw it immediately.
27 | *
28 | * @param firstLocalAddress
29 | * @param otherLocalAddresses
30 | * @throws throw if bind failed.
31 | */
32 | void bind(SocketAddress firstLocalAddress, SocketAddress... otherLocalAddresses) throws IOException;
33 |
34 | /**
35 | * Unbinds specified local addresses that is already bound to and stops to accept incoming connections at the port.
36 | *
37 | * @param port
38 | * @throws IOException throw if unbind failed
39 | */
40 | void unbind(int port) throws IOException;
41 |
42 | /**
43 | * Unbinds specified local addresses that is already bound to and stops to accept incoming connections at the specified addresses.
44 | * All connections with these addresses will be closed.
45 | *
46 | * NOTE: This method returns silently if no local address is bound yet.
47 | *
48 | * @param firstLocalAddress
49 | * @param otherLocalAddresses
50 | * @throws IOException throw if unbind failed
51 | */
52 | void unbind(SocketAddress firstLocalAddress, SocketAddress... otherLocalAddresses) throws IOException;
53 |
54 |
55 | /**
56 | * Get currently bound addresses
57 | *
58 | * @return bound addresses
59 | */
60 | Set getBoundAddresses();
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoAcceptorMBean.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | /**
4 | * MBean for {@link IoAcceptor}
5 | *
6 | * @author mindwind
7 | * @version 1.0, Dec 24, 2013
8 | */
9 | public interface IoAcceptorMBean {
10 |
11 |
12 | /**
13 | * @return x-ray of {@link IoAcceptor}
14 | */
15 | IoAcceptorX x();
16 |
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoAcceptorX.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | import java.net.SocketAddress;
4 | import java.util.Set;
5 |
6 |
7 | /**
8 | * The x-ray of {@link IoAcceptor}
9 | *
10 | * @author mindwind
11 | * @version 1.0, Oct 15, 2014
12 | */
13 | public interface IoAcceptorX extends IoReactorX {
14 |
15 | /**
16 | * @return wait to bind address set.
17 | */
18 | Set waitBindAddresses();
19 |
20 | /**
21 | * @return wait to unbind address set.
22 | */
23 | Set waitUnbindAddresses();
24 |
25 | /**
26 | * @return already bound address set.
27 | */
28 | Set boundAddresses();
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoConfig.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 | import lombok.ToString;
6 |
7 | /**
8 | * I/O common configuration object
9 | *
10 | * @author mindwind
11 | * @version 1.0, Feb 22, 2013
12 | */
13 | @ToString(of = { "minReadBufferSize", "defaultReadBufferSize", "maxReadBufferSize", "ioTimeoutInMillis" })
14 | public abstract class IoConfig {
15 |
16 |
17 | public static final int MIN_READ_BUFFER_SIZE = 64 ;
18 | public static final int DEFAULT_READ_BUFFER_SIZE = 2048 ;
19 | public static final int MAX_READ_BUFFER_SIZE = 65536;
20 |
21 |
22 | @Getter @Setter protected int minReadBufferSize = MIN_READ_BUFFER_SIZE ;
23 | @Getter @Setter protected int defaultReadBufferSize = DEFAULT_READ_BUFFER_SIZE;
24 | @Getter @Setter protected int maxReadBufferSize = MAX_READ_BUFFER_SIZE ;
25 | @Getter @Setter protected int ioTimeoutInMillis = 120 * 1000 ;
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoConnector.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | import java.io.IOException;
4 | import java.net.SocketAddress;
5 | import java.util.concurrent.Future;
6 |
7 | /**
8 | * Connects to server based on specific implementation.
9 | *
10 | * @author mindwind
11 | * @version 1.0, Mar 12, 2013
12 | */
13 | public interface IoConnector extends IoReactor, IoConnectorMBean {
14 |
15 | /**
16 | * Connects to the specified ip and port.
17 | *
18 | * @param ip
19 | * @param port
20 | * @return Future
instance which is completed when the channel initiated by this call succeeds or fails.
21 | * @throws IOException If some other I/O error occurs
22 | */
23 | Future> connect(String ip, int port) throws IOException;
24 |
25 | /**
26 | * Connects to the specified remote address.
27 | *
28 | * @param remoteAddress
29 | * @return Future
instance which is completed when the channel initiated by this call succeeds or fails.
30 | * @throws IOException If some other I/O error occurs
31 | */
32 | Future> connect(SocketAddress remoteAddress) throws IOException;
33 |
34 |
35 | /**
36 | * Connects to the specified remote address and binds to the specified local address.
37 | *
38 | * @param remoteAddress
39 | * @param localAddress
40 | * @return Future
instance which is completed when the channel initiated by this call succeeds or fails.
41 | * @throws IOException If some other I/O error occurs
42 | */
43 | Future> connect(SocketAddress remoteAddress, SocketAddress localAddress) throws IOException;
44 | }
45 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoConnectorMBean.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | /**
4 | * MBean for {@link IoConnector}
5 | *
6 | * @author mindwind
7 | * @version 1.0, Dec 25, 2013
8 | */
9 | public interface IoConnectorMBean {
10 |
11 | /**
12 | * @return x-ray of {@link IoConnector}
13 | */
14 | IoConnectorX x();
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoConnectorX.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | /**
4 | * The x-ray of {@link IoConnector}
5 | *
6 | * @author mindwind
7 | * @version 1.0, Oct 15, 2014
8 | */
9 | public interface IoConnectorX extends IoReactorX {
10 |
11 |
12 | /**
13 | * @return current connecting channel count.
14 | */
15 | int connectingChannelCount();
16 |
17 | /**
18 | * @return current disconnecting channel count.
19 | */
20 | int disconnectingChannelCount();
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoHandler.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | import java.io.IOException;
4 |
5 | /**
6 | * Handles I/O events fired by craft-atom-io series component.
7 | *
8 | * @author mindwind
9 | * @version 1.0, Feb 20, 2013
10 | */
11 | public interface IoHandler {
12 |
13 | /**
14 | * Invoked when channel opened.
15 | *
16 | * @param channel
17 | */
18 | void channelOpened(Channel channel);
19 |
20 | /**
21 | * Invoked when channel closed.
22 | *
23 | * @param channel
24 | */
25 | void channelClosed(Channel channel);
26 |
27 |
28 | /**
29 | * Invoked when channel is idle, idle means there is no data transmission (read or write).
30 | *
31 | * @param channel
32 | */
33 | void channelIdle(Channel channel);
34 |
35 | /**
36 | * Invoked when channel has read some bytes.
37 | *
38 | * @param channel
39 | * @param bytes
40 | */
41 | void channelRead(Channel channel, byte[] bytes);
42 |
43 | /**
44 | * Invoked when channel would flush out some bytes.
45 | *
46 | * @param channel
47 | * @param bytes
48 | */
49 | void channelFlush(Channel channel, byte[] bytes);
50 |
51 | /**
52 | * Invoked when channel has written some bytes.
53 | *
54 | * @param channel
55 | * @param bytes
56 | */
57 | void channelWritten(Channel channel, byte[] bytes);
58 |
59 | /**
60 | * Invoked when any exception is thrown.
61 | * If cause
is an instance of {@link IOException} channel should be closed.
62 | *
63 | * @param channel
64 | * @param cause
65 | */
66 | void channelThrown(Channel channel, Exception cause);
67 | }
68 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoProcessor.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | /**
4 | * Process I/O read and write, it is a mark interface, any class implements it indicate it is a I/O processor.
5 | *
6 | * @author mindwind
7 | * @version 1.0, Feb 8, 2014
8 | */
9 | public interface IoProcessor extends IoReactor, IoProcessorMBean {
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoProcessorMBean.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | /**
4 | * MBean for {@link IoProcessor}
5 | *
6 | * @author mindwind
7 | * @version 1.0, Feb 8, 2014
8 | */
9 | public interface IoProcessorMBean {
10 |
11 |
12 | /**
13 | * @return x-ray of {@link IoProcessor}
14 | */
15 | IoProcessorX x();
16 |
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoProcessorX.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 |
4 | /**
5 | * The x-ray of {@link IoProcessor}
6 | *
7 | * @author mindwind
8 | * @version 1.0, Oct 15, 2014
9 | */
10 | public interface IoProcessorX extends IoReactorX {
11 |
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoProtocol.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | /**
4 | * I/O protocol enumeration
5 | *
6 | * @author mindwind
7 | * @version 1.0, Feb 24, 2013
8 | */
9 | public enum IoProtocol {
10 | TCP, UDP
11 | }
12 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoReactor.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 |
4 | /**
5 | * Abstracts reactor model, base api interface.
6 | *
7 | * @author mindwind
8 | * @version 1.0, Mar 12, 2013
9 | * @see IoAcceptor
10 | * @see IoConnector
11 | * @see IoProcessor
12 | */
13 | public interface IoReactor {
14 |
15 |
16 | /**
17 | * Releases any resources allocated by this reactor.
18 | */
19 | void shutdown();
20 |
21 | /**
22 | * Returns the io handler associates with the reactor
23 | */
24 | IoHandler getHandler();
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/craft-atom-io/src/main/java/io/craft/atom/io/IoReactorX.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.io;
2 |
3 | /**
4 | * The x-ray of {@link IoReactor}
5 | *
6 | * @author mindwind
7 | * @version 1.0, Oct 15, 2014
8 | */
9 | public interface IoReactorX {
10 |
11 |
12 | /**
13 | * @return current alive channel count.
14 | */
15 | int aliveChannelCount();
16 |
17 | /**
18 | * @return current new channel to be processed count.
19 | */
20 | int newChannelCount();
21 |
22 | /**
23 | * @return current flushing channel count.
24 | */
25 | int flushingChannelCount();
26 |
27 | /**
28 | * @return current closing channel count.
29 | */
30 | int closingChannelCount();
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/craft-atom-lock/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | io.craftcode
5 | craft-atom
6 | 3.1.3-SNAPSHOT
7 |
8 | ${project.artifactId}
9 | craft-atom-lock
10 |
11 |
12 |
13 | ${project.groupId}
14 | craft-atom-redis
15 | ${project.version}
16 |
17 |
18 | ${project.groupId}
19 | craft-atom-test
20 | ${project.version}
21 | test
22 |
23 |
24 | org.slf4j
25 | slf4j-api
26 |
27 |
28 |
--------------------------------------------------------------------------------
/craft-atom-lock/src/main/java/io/craft/atom/lock/api/DLock.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.lock.api;
2 |
3 | import java.util.concurrent.TimeUnit;
4 |
5 | /**
6 | * {@code DLock} is the abbreviation of distributed lock.
7 | *
8 | * A distributed lock is a tool for controlling access to a shared resource by multiple threads or processes.
9 | * Commonly, a distributed lock provides exclusive access to a shared resource: only one thread at a time can acquire the lock and all access to the shared resource requires that the lock be acquired first.
10 | *
11 | * @author mindwind
12 | * @version 1.0, Nov 19, 2012
13 | */
14 | public interface DLock {
15 |
16 | /**
17 | * Acquires the lock with specified lock key if it is free within the given TTL time.
18 | *
19 | * If the lock is available this method returns immediately with the value true
, otherwise false
20 | *
21 | * @param lockKey lock key resource, which associated with a shared resource
22 | * @param ttl lock time to live
23 | * @param unit time unit for ttl
24 | * @return true
if the lock was acquired and false
if lock acquired failed.
25 | */
26 | boolean tryLock(String lockKey, int ttl, TimeUnit unit);
27 |
28 | /**
29 | * Releases the lock with specified lock key.
30 | *
31 | * Tip: make sure you hold the lock, you release lock by invoking {@link #unlock(String)}
32 | *
33 | * @param lockKey
34 | * @return true
if the lock was released and false
if lock released failed.
35 | */
36 | boolean unlock(String lockKey);
37 | }
38 |
--------------------------------------------------------------------------------
/craft-atom-lock/src/main/java/io/craft/atom/lock/api/DLockFactory.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.lock.api;
2 |
3 | import io.craft.atom.lock.Redis24DLock;
4 | import io.craft.atom.lock.Redis26DLock;
5 | import io.craft.atom.lock.ShardedRedis24DLock;
6 | import io.craft.atom.lock.ShardedRedis26DLock;
7 | import io.craft.atom.redis.api.RedisCommand;
8 | import io.craft.atom.redis.api.ShardedRedisCommand;
9 |
10 |
11 | /**
12 | * Distributed lock factory
13 | *
14 | * @author mindwind
15 | * @version 1.0, Jul 16, 2013
16 | */
17 | public class DLockFactory {
18 |
19 | /**
20 | * @param redis
21 | * @return new distributed lock base on singleton redis version 2.4.x
22 | */
23 | public static DLock newRedis24DLock(RedisCommand redis) {
24 | return new Redis24DLock(redis);
25 | }
26 |
27 | /**
28 | * @param redis
29 | * @return new distributed lock base on sharded redis version 2.4.x
30 | */
31 | public static DLock newRedis24DLock(ShardedRedisCommand redis) {
32 | return new ShardedRedis24DLock(redis);
33 | }
34 |
35 | /**
36 | * @param redis
37 | * @return new distributed lock base on singleton redis version 2.6.12+
38 | */
39 | public static DLock newRedis26DLock(RedisCommand redis) {
40 | return new Redis26DLock(redis);
41 | }
42 |
43 | /**
44 | * @param redis
45 | * @return new distributed lock base on sharded redis version 2.6.x
46 | */
47 | public static DLock newRedis26DLock(ShardedRedisCommand redis) {
48 | return new ShardedRedis26DLock(redis);
49 | }
50 |
51 | /**
52 | * @deprecated replace by {@link #newRedis24DLock(ShardedRedisCommand)}
53 | * @param redis
54 | * @return new distributed lock base on sharded redis version 2.4.x
55 | */
56 | public static DLock newShardedRedis24DLock(ShardedRedisCommand redis) {
57 | return new ShardedRedis24DLock(redis);
58 | }
59 |
60 | /**
61 | * @deprecated replace by {@link #newRedis26DLock(ShardedRedisCommand)}
62 | * @param redis
63 | * @return new distributed lock base on sharded redis version 2.6.12+
64 | */
65 | public static DLock newShardedRedis26DLock(ShardedRedisCommand redis) {
66 | return new ShardedRedis26DLock(redis);
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/craft-atom-lock/src/test/java/io/craft/atom/lock/AbstractDLockTests.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.lock;
2 |
3 | import io.craft.atom.lock.api.DLock;
4 | import io.craft.atom.lock.api.DLockFactory;
5 | import io.craft.atom.redis.api.Redis;
6 | import io.craft.atom.redis.api.RedisFactory;
7 | import io.craft.atom.redis.api.ShardedRedis;
8 |
9 | import org.junit.Assert;
10 |
11 | /**
12 | * @author mindwind
13 | * @version 1.0, Dec 22, 2013
14 | */
15 | public abstract class AbstractDLockTests {
16 |
17 | protected Redis redis1 ;
18 | protected Redis redis2 ;
19 | protected DLock dLock ;
20 | protected ShardedRedis shardedRedis;
21 | protected DLock shardedDLock;
22 |
23 |
24 | public AbstractDLockTests() {
25 | init();
26 | selfcheck();
27 | }
28 |
29 | private void init() {
30 | redis1 = RedisFactory.newRedis("localhost", 6379) ;
31 | redis2 = RedisFactory.newRedis("localhost", 6380) ;
32 | shardedRedis = RedisFactory.newShardedRedis(redis1, redis2);
33 | dLock = DLockFactory.newRedis24DLock(redis1) ;
34 | shardedDLock = DLockFactory.newRedis24DLock(shardedRedis) ;
35 | }
36 |
37 | private void selfcheck() {
38 | try {
39 | redis1.ping();
40 | } catch (Exception e) {
41 | e.printStackTrace();
42 | System.err.println("[CRAFT-ATOM-LOCK] Self check for redis1 fail");
43 | Assert.fail();
44 | }
45 |
46 | try {
47 | redis2.ping();
48 | } catch (Exception e) {
49 | e.printStackTrace();
50 | System.err.println("[CRAFT-ATOM-LOCK] Self check for redis2 fail");
51 | Assert.fail();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/craft-atom-lock/src/test/java/io/craft/atom/lock/TestRedis24DLock.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.lock;
2 |
3 | import io.craft.atom.test.CaseCounter;
4 |
5 | import java.util.concurrent.TimeUnit;
6 |
7 | import junit.framework.Assert;
8 |
9 | import org.junit.Before;
10 | import org.junit.Test;
11 |
12 |
13 | /**
14 | * @author mindwind
15 | * @version 1.0, Dec 22, 2013
16 | */
17 | public class TestRedis24DLock extends AbstractDLockTests {
18 |
19 |
20 | private String lockKey = "redis24.dlock";
21 |
22 |
23 | // ~ -------------------------------------------------------------------------------------------------------------
24 |
25 |
26 | public TestRedis24DLock() {
27 | super();
28 | }
29 |
30 | @Before
31 | public void before() {
32 | redis1.flushall();
33 | }
34 |
35 |
36 | // ~ -------------------------------------------------------------------------------------------------------------
37 |
38 |
39 | @Test
40 | public void testTryLockFalse() {
41 | // WATCH: lock=true GET: lock=true -> LOCK: false
42 | // WATCH: lock=true GET: lock=false -> LOCK: false
43 | // WATCH: lock=false GET: lock=true -> LOCK: false
44 | redis1.set(lockKey, "1");
45 | boolean b = dLock.tryLock(lockKey, 30, TimeUnit.SECONDS);
46 | Assert.assertFalse(b);
47 | System.out.println(String.format("[CRAFT-ATOM-REDIS] (^_^) <%s> Case -> test try lock false. ", CaseCounter.incr(1)));
48 | }
49 |
50 | @Test
51 | public void testTryLockTrue() {
52 | // WATCH: lock=false GET: lock=false -> LOCK: true
53 | redis1.del(lockKey);
54 | boolean b = dLock.tryLock(lockKey, 30, TimeUnit.SECONDS);
55 | Assert.assertTrue(b);
56 | System.out.println(String.format("[CRAFT-ATOM-REDIS] (^_^) <%s> Case -> test try lock true. ", CaseCounter.incr(1)));
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/craft-atom-lock/src/test/java/io/craft/atom/lock/TestShardedRedis24DLock.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.lock;
2 |
3 | import io.craft.atom.test.CaseCounter;
4 |
5 | import java.util.concurrent.TimeUnit;
6 |
7 | import junit.framework.Assert;
8 |
9 | import org.junit.Before;
10 | import org.junit.Test;
11 |
12 |
13 | /**
14 | * @author mindwind
15 | * @version 1.0, Dec 22, 2013
16 | */
17 | public class TestShardedRedis24DLock extends AbstractDLockTests {
18 |
19 |
20 | private String lockKey = "sharded.redis24.dlock";
21 |
22 |
23 | // ~ -------------------------------------------------------------------------------------------------------------
24 |
25 |
26 | public TestShardedRedis24DLock() {
27 | super();
28 | }
29 |
30 | @Before
31 | public void before() {
32 | redis1.flushall();
33 | }
34 |
35 |
36 | // ~ -------------------------------------------------------------------------------------------------------------
37 |
38 |
39 | @Test
40 | public void testTryLockFalse() {
41 | // WATCH: lock=true GET: lock=true -> LOCK: false
42 | // WATCH: lock=true GET: lock=false -> LOCK: false
43 | // WATCH: lock=false GET: lock=true -> LOCK: false
44 | shardedRedis.set(lockKey, lockKey, "1");
45 | boolean b = shardedDLock.tryLock(lockKey, 30, TimeUnit.SECONDS);
46 | Assert.assertFalse(b);
47 | System.out.println(String.format("[CRAFT-ATOM-REDIS] (^_^) <%s> Case -> test try lock false. ", CaseCounter.incr(1)));
48 | }
49 |
50 | @Test
51 | public void testTryLockTrue() {
52 | // WATCH: lock=false GET: lock=false -> LOCK: true
53 | shardedRedis.del(lockKey, lockKey);
54 | boolean b = shardedDLock.tryLock(lockKey, 30, TimeUnit.SECONDS);
55 | Assert.assertTrue(b);
56 | System.out.println(String.format("[CRAFT-ATOM-REDIS] (^_^) <%s> Case -> test try lock true. ", CaseCounter.incr(1)));
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/craft-atom-nio/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 |
5 | io.craftcode
6 | craft-atom
7 | 3.1.3-SNAPSHOT
8 |
9 |
10 | craft-atom-nio
11 | ${project.artifactId}
12 |
13 |
14 |
15 | ${project.groupId}
16 | craft-atom-test
17 | ${project.version}
18 | test
19 |
20 |
21 | ${project.groupId}
22 | craft-atom-io
23 | ${project.version}
24 |
25 |
26 | ${project.groupId}
27 | craft-atom-util
28 | ${project.version}
29 |
30 |
31 | org.slf4j
32 | slf4j-api
33 |
34 |
35 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/AbstractNioByteChannelEvent.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.AbstractChannelEvent;
4 | import io.craft.atom.io.Channel;
5 | import io.craft.atom.io.ChannelEvent;
6 | import io.craft.atom.io.ChannelEventType;
7 | import lombok.ToString;
8 |
9 |
10 | /**
11 | * @author mindwind
12 | * @version 1.0, Feb 26, 2013
13 | */
14 | @ToString(callSuper = true, of = "channel")
15 | abstract public class AbstractNioByteChannelEvent extends AbstractChannelEvent implements ChannelEvent {
16 |
17 |
18 | protected final NioByteChannel channel;
19 |
20 |
21 | // ~ --------------------------------------------------------------------------------------------------------------
22 |
23 |
24 | AbstractNioByteChannelEvent(ChannelEventType type, NioByteChannel channel) {
25 | super(type);
26 | if (channel == null) {
27 | throw new IllegalArgumentException("channel == null");
28 | }
29 | this.channel = channel;
30 | }
31 |
32 |
33 | // ~ --------------------------------------------------------------------------------------------------------------
34 |
35 |
36 | @Override
37 | public Channel getChannel() {
38 | return channel;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/NioAcceptorX.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.IoAcceptorX;
4 |
5 | import java.net.SocketAddress;
6 | import java.util.Set;
7 |
8 | import lombok.Getter;
9 | import lombok.Setter;
10 | import lombok.ToString;
11 |
12 |
13 | /**
14 | * @author mindwind
15 | * @version 1.0, Oct 15, 2014
16 | */
17 | @ToString
18 | public class NioAcceptorX extends NioReactorX implements IoAcceptorX {
19 |
20 |
21 | @Getter @Setter private Set waitBindAddresses ;
22 | @Getter @Setter private Set waitUnbindAddresses;
23 | @Getter @Setter private Set boundAddresses ;
24 |
25 |
26 | @Override
27 | public Set waitBindAddresses() {
28 | return waitBindAddresses;
29 | }
30 |
31 | @Override
32 | public Set waitUnbindAddresses() {
33 | return waitUnbindAddresses;
34 | }
35 |
36 | @Override
37 | public Set boundAddresses() {
38 | return boundAddresses;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/NioAdaptiveBufferSizePredictorFactory.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.nio.spi.NioBufferSizePredictor;
4 | import io.craft.atom.nio.spi.NioBufferSizePredictorFactory;
5 |
6 | /**
7 | * @author mindwind
8 | * @version 1.0, Feb 24, 2013
9 | */
10 | public class NioAdaptiveBufferSizePredictorFactory implements NioBufferSizePredictorFactory {
11 |
12 | @Override
13 | public NioBufferSizePredictor newPredictor(int minimum, int initial, int maximum) {
14 | return new NioAdaptiveBufferSizePredictor(minimum, initial, maximum);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/NioConfig.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.IoConfig;
4 | import lombok.Getter;
5 | import lombok.Setter;
6 | import lombok.ToString;
7 |
8 |
9 | /**
10 | * Nio component common configuration object.
11 | *
12 | * @author mindwind
13 | * @version 1.0, Feb 21, 2013
14 | */
15 | @ToString(callSuper = true, of = { "processorPoolSize", "executorSize", "readWritefair", "channelEventSize", "totalEventSize" })
16 | abstract public class NioConfig extends IoConfig {
17 |
18 |
19 | @Getter protected int processorPoolSize = Runtime.getRuntime().availableProcessors();
20 | @Getter @Setter protected int executorSize = processorPoolSize << 3 ;
21 | @Getter @Setter protected boolean readWritefair = true ;
22 | @Getter protected int channelEventSize = Integer.MAX_VALUE ;
23 | @Getter protected int totalEventSize = Integer.MAX_VALUE ;
24 |
25 |
26 | // ~ -------------------------------------------------------------------------------------------------------------
27 |
28 |
29 | public void setProcessorPoolSize(int processorPoolSize) {
30 | if (processorPoolSize <= 0) {
31 | throw new IllegalArgumentException("processor pool size must > 0");
32 | }
33 |
34 | this.processorPoolSize = processorPoolSize;
35 | }
36 |
37 | public void setChannelEventSize(int channelEventSize) {
38 | if (channelEventSize <= 0) {
39 | channelEventSize = Integer.MAX_VALUE;
40 | }
41 |
42 | this.channelEventSize = channelEventSize;
43 | }
44 |
45 | public void setTotalEventSize(int totalEventSize) {
46 | if (totalEventSize <= 0) {
47 | totalEventSize = Integer.MAX_VALUE;
48 | }
49 |
50 | this.totalEventSize = totalEventSize;
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/NioConnectorX.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.IoConnectorX;
4 | import lombok.Getter;
5 | import lombok.Setter;
6 | import lombok.ToString;
7 |
8 |
9 | /**
10 | * @author mindwind
11 | * @version 1.0, Oct 15, 2014
12 | */
13 | @ToString
14 | public class NioConnectorX extends NioReactorX implements IoConnectorX {
15 |
16 |
17 | @Getter @Setter private int connectingChannelCount ;
18 | @Getter @Setter private int disconnectingChannelCount;
19 |
20 |
21 | @Override
22 | public int connectingChannelCount() {
23 | return connectingChannelCount;
24 | }
25 |
26 | @Override
27 | public int disconnectingChannelCount() {
28 | return disconnectingChannelCount;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/NioOrderedDirectChannelEventDispatcher.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.ChannelEvent;
4 | import io.craft.atom.nio.spi.AbstractNioChannelEventDispatcher;
5 | import io.craft.atom.nio.spi.NioChannelEventDispatcher;
6 | import lombok.ToString;
7 |
8 |
9 | /**
10 | * An {@link NioChannelEventDispatcher} that maintains order of {@link NioByteChannelEvent} in the same channel.
11 | * It use io process thread pool to dispatch event.
12 | *
13 | * @author mindwind
14 | * @version 1.0, Feb 22, 2013
15 | */
16 | @ToString(callSuper = true)
17 | public class NioOrderedDirectChannelEventDispatcher extends AbstractNioChannelEventDispatcher {
18 |
19 |
20 | public NioOrderedDirectChannelEventDispatcher() {
21 | super();
22 | }
23 |
24 | public NioOrderedDirectChannelEventDispatcher(int totalEventSize) {
25 | super(totalEventSize);
26 | }
27 |
28 |
29 | // ~ ------------------------------------------------------------------------------------------------------------
30 |
31 |
32 | @Override
33 | public void dispatch(ChannelEvent event) {
34 | NioByteChannel channel = (NioByteChannel) event.getChannel();
35 | beforeDispatch(channel);
36 | try {
37 | event.fire();
38 | } finally {
39 | afterDispatch(channel);
40 | }
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/NioProcessorX.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.IoProcessorX;
4 |
5 | /**
6 | * @author mindwind
7 | * @version 1.0, Oct 15, 2014
8 | */
9 | public class NioProcessorX extends NioReactorX implements IoProcessorX {
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/NioReactor.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.IoHandler;
4 | import io.craft.atom.io.IoProcessorX;
5 | import io.craft.atom.io.IoReactor;
6 | import io.craft.atom.io.IoReactorX;
7 | import io.craft.atom.nio.spi.NioBufferSizePredictorFactory;
8 | import io.craft.atom.nio.spi.NioChannelEventDispatcher;
9 | import lombok.ToString;
10 |
11 |
12 | /**
13 | * Nio component provide a reactor pattern implementation. {@link NioReactor }
14 | * Represents a base reactor object.
15 | *
16 | * @author mindwind
17 | * @version 1.0, Feb 21, 2013
18 | * @see NioAcceptor
19 | * @see NioProcessor
20 | * @see NioConnector
21 | */
22 | @ToString(of = { "handler", "dispatcher", "predictorFactory" })
23 | abstract public class NioReactor implements IoReactor {
24 |
25 |
26 | protected IoHandler handler ;
27 | protected NioChannelEventDispatcher dispatcher ;
28 | protected NioBufferSizePredictorFactory predictorFactory;
29 | protected NioProcessorPool pool ;
30 |
31 |
32 | // ~ ----------------------------------------------------------------------------------------------------------
33 |
34 |
35 | @Override
36 | public void shutdown() {
37 | dispatcher.shutdown();
38 | pool.shutdown();
39 | }
40 |
41 | @Override
42 | public IoHandler getHandler() {
43 | return handler;
44 | }
45 |
46 | public NioChannelEventDispatcher getDispatcher() {
47 | return dispatcher;
48 | }
49 |
50 | public NioBufferSizePredictorFactory getPredictorFactory() {
51 | return predictorFactory;
52 | }
53 |
54 | protected IoReactorX x() {
55 | NioReactorX x = new NioReactorX();
56 | NioProcessor[] nps = pool.getPool();
57 | int nc = 0;
58 | int fc = 0;
59 | int cc = 0;
60 | for (NioProcessor np : nps) {
61 | IoProcessorX px = np.x();
62 | nc += px.newChannelCount();
63 | fc += px.flushingChannelCount();
64 | cc += px.closingChannelCount();
65 | }
66 | x.setNewChannelCount(nc);
67 | x.setFlushingChannelCount(fc);
68 | x.setClosingChannelCount(cc);
69 | x.setAliveChannelCount(pool.getIdleTimer().aliveChannels().size());
70 | return x;
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/NioReactorX.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.IoReactorX;
4 | import lombok.Getter;
5 | import lombok.Setter;
6 | import lombok.ToString;
7 |
8 |
9 | /**
10 | * @author mindwind
11 | * @version 1.0, Oct 15, 2014
12 | */
13 | @ToString
14 | public class NioReactorX implements IoReactorX {
15 |
16 |
17 | @Getter @Setter private int aliveChannelCount ;
18 | @Getter @Setter private int newChannelCount ;
19 | @Getter @Setter private int flushingChannelCount;
20 | @Getter @Setter private int closingChannelCount ;
21 |
22 |
23 | @Override
24 | public int aliveChannelCount() {
25 | return aliveChannelCount;
26 | }
27 |
28 | @Override
29 | public int newChannelCount() {
30 | return newChannelCount;
31 | }
32 |
33 | @Override
34 | public int flushingChannelCount() {
35 | return flushingChannelCount;
36 | }
37 |
38 | @Override
39 | public int closingChannelCount() {
40 | return closingChannelCount;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/NioUdpByteChannel.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.nio.spi.NioBufferSizePredictor;
4 | import io.craft.atom.nio.spi.NioChannelEventDispatcher;
5 |
6 | import java.io.IOException;
7 | import java.net.SocketAddress;
8 | import java.nio.ByteBuffer;
9 | import java.nio.channels.DatagramChannel;
10 | import java.nio.channels.SelectableChannel;
11 |
12 | import lombok.ToString;
13 |
14 |
15 | /**
16 | * A nio channel for datagram-oriented sockets.
17 | *
18 | * @author mindwind
19 | * @version 1.0, Feb 22, 2013
20 | */
21 | @ToString(callSuper = true)
22 | public class NioUdpByteChannel extends NioByteChannel {
23 |
24 |
25 | private DatagramChannel datagramChannel;
26 |
27 |
28 | public NioUdpByteChannel(DatagramChannel datagramChannel, NioConfig config, NioBufferSizePredictor predictor, NioChannelEventDispatcher dispatcher) {
29 | super(config, predictor, dispatcher);
30 |
31 | if (datagramChannel == null) {
32 | throw new IllegalArgumentException("DatagramChannel can not be null.");
33 | }
34 |
35 | this.datagramChannel = datagramChannel;
36 | this.localAddress = datagramChannel.socket().getLocalSocketAddress();
37 | }
38 |
39 | @Override
40 | protected SocketAddress readUdp(ByteBuffer buf) throws IOException {
41 | return datagramChannel.receive(buf);
42 | }
43 |
44 | @Override
45 | protected int writeUdp(ByteBuffer buf, SocketAddress target) throws IOException {
46 | return datagramChannel.send(buf, target);
47 | }
48 |
49 | @Override
50 | protected SelectableChannel innerChannel() {
51 | return datagramChannel;
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/api/NioAcceptorConfig.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio.api;
2 |
3 | import io.craft.atom.nio.NioConfig;
4 | import io.craft.atom.nio.NioTcpAcceptor;
5 | import lombok.Getter;
6 | import lombok.Setter;
7 | import lombok.ToString;
8 |
9 |
10 | /**
11 | * Configuration object for {@link NioTcpAcceptor}
12 | *
13 | * @author mindwind
14 | * @version 1.0, Feb 22, 2013
15 | */
16 | @ToString(callSuper = true, of = { "reuseAddress", "backlog" })
17 | public class NioAcceptorConfig extends NioConfig {
18 |
19 |
20 | @Getter @Setter private boolean reuseAddress = true ;
21 | @Getter @Setter private int channelSize = Integer.MAX_VALUE;
22 | @Getter private int backlog = 50 ;
23 |
24 |
25 | // ~ ---------------------------------------------------------------------------------------------------------------
26 |
27 |
28 | public void setBacklog(int backlog) {
29 | this.backlog = (backlog <= 0 ? 50 : backlog);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/api/NioConnectorConfig.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio.api;
2 |
3 | import io.craft.atom.nio.NioConfig;
4 | import io.craft.atom.nio.NioConnector;
5 | import lombok.Getter;
6 | import lombok.Setter;
7 | import lombok.ToString;
8 |
9 |
10 | /**
11 | * Configuration object for {@link NioConnector}
12 | *
13 | * @author mindwind
14 | * @version 1.0, Feb 24, 2013
15 | */
16 | @ToString(callSuper = true, of = "connectTimeoutInMillis")
17 | public class NioConnectorConfig extends NioConfig {
18 |
19 | /** 2 seconds as default connect timeout */
20 | @Getter @Setter private int connectTimeoutInMillis = 2000;
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/api/NioTcpAcceptorBuilder.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio.api;
2 |
3 | import io.craft.atom.io.IoAcceptor;
4 | import io.craft.atom.io.IoHandler;
5 | import io.craft.atom.nio.NioTcpAcceptor;
6 |
7 |
8 | /**
9 | * Builder for {@link NioTcpAcceptor}
10 | *
11 | * @author mindwind
12 | * @version 1.0, Mar 7, 2014
13 | */
14 | public class NioTcpAcceptorBuilder extends NioBuilder {
15 |
16 |
17 | private int backlog = 50 ;
18 | private int channelSize = Integer.MAX_VALUE;
19 | private boolean reuseAddress = true ;
20 |
21 |
22 | public NioTcpAcceptorBuilder(IoHandler handler) {
23 | super(handler);
24 | }
25 |
26 |
27 | public NioTcpAcceptorBuilder backlog (int backlog) { this.backlog = backlog ; return this; }
28 | public NioTcpAcceptorBuilder channelSize (int channelSize) { this.channelSize = channelSize ; return this; }
29 | public NioTcpAcceptorBuilder reuseAddress(boolean reuseAddress) { this.reuseAddress = reuseAddress; return this; }
30 |
31 |
32 | public IoAcceptor build() {
33 | NioAcceptorConfig config = new NioAcceptorConfig();
34 | config.setBacklog(backlog);
35 | config.setChannelSize(channelSize);
36 | config.setReuseAddress(reuseAddress);
37 | set(config);
38 | return new NioTcpAcceptor(handler, config, dispatcher, predictorFactory);
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/api/NioTcpConnectorBuilder.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio.api;
2 |
3 | import io.craft.atom.io.IoConnector;
4 | import io.craft.atom.io.IoHandler;
5 | import io.craft.atom.nio.NioTcpConnector;
6 |
7 |
8 | /**
9 | * Builder for {@link NioTcpConnector}
10 | *
11 | * @author mindwind
12 | * @version 1.0, Mar 7, 2014
13 | */
14 | public class NioTcpConnectorBuilder extends NioBuilder {
15 |
16 |
17 | private int connectTimeoutInMillis = 2000;
18 |
19 |
20 | public NioTcpConnectorBuilder(IoHandler handler) {
21 | super(handler);
22 | }
23 |
24 |
25 | public NioTcpConnectorBuilder connectTimeoutInMillis(int timeout) { this.connectTimeoutInMillis = timeout; return this; }
26 |
27 |
28 | public IoConnector build() {
29 | NioConnectorConfig config = new NioConnectorConfig();
30 | config.setConnectTimeoutInMillis(connectTimeoutInMillis);
31 | set(config);
32 | return new NioTcpConnector(handler, config, dispatcher, predictorFactory);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/spi/AbstractNioChannelEventDispatcher.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio.spi;
2 |
3 | import io.craft.atom.nio.NioByteChannel;
4 |
5 | import java.util.concurrent.Semaphore;
6 |
7 | import lombok.ToString;
8 |
9 | import org.slf4j.Logger;
10 | import org.slf4j.LoggerFactory;
11 |
12 |
13 | /**
14 | * Base implementation of {@link NioChannelEventDispatcher}
15 | *
16 | * @author mindwind
17 | * @version 1.0, Feb 27, 2013
18 | */
19 | @ToString(of = { "semaphore" })
20 | abstract public class AbstractNioChannelEventDispatcher implements NioChannelEventDispatcher {
21 |
22 |
23 | private static final Logger LOG = LoggerFactory.getLogger(AbstractNioChannelEventDispatcher.class);
24 |
25 |
26 | protected final Semaphore semaphore;
27 |
28 |
29 | // ~ ------------------------------------------------------------------------------------------------------------
30 |
31 |
32 | public AbstractNioChannelEventDispatcher() {
33 | this(Integer.MAX_VALUE);
34 | }
35 |
36 | public AbstractNioChannelEventDispatcher(int totalEventSize) {
37 | if (totalEventSize <= 0) {
38 | totalEventSize = Integer.MAX_VALUE;
39 | }
40 | this.semaphore = new Semaphore(totalEventSize, false);
41 | }
42 |
43 |
44 | // ~ ------------------------------------------------------------------------------------------------------------
45 |
46 |
47 | protected void beforeDispatch(NioByteChannel channel) {
48 | boolean b = channel.tryAcquire();
49 | if (!b) {
50 | channel.pause();
51 | LOG.warn("[CRAFT-ATOM-NIO]] Pause |channel={}, availablePermits={}|", channel, channel.availablePermits());
52 | }
53 |
54 | try {
55 | semaphore.acquire();
56 | } catch (InterruptedException e) {
57 | LOG.warn("[CRAFT-ATOM-NIO] Semaphore acquire interrupt", e);
58 | }
59 | }
60 |
61 | protected void afterDispatch(NioByteChannel channel) {
62 | channel.release();
63 | if (channel.isPaused()) {
64 | channel.resume();
65 | LOG.warn("[CRAFT-ATOM-NIO]] Resume |channel={} availablePermits={}|", channel, channel.availablePermits());
66 | }
67 |
68 | semaphore.release();
69 | }
70 |
71 | @Override
72 | public void shutdown() {}
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/spi/NioBufferSizePredictor.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio.spi;
2 |
3 | /**
4 | * Predicts the nio buffer size.
5 | *
6 | * Predict buffer size allocation, More accurate the prediction is, more effective the memory utilization will be.
7 | *
8 | * @author mindwind
9 | * @version 1.0, Jan 25, 2013
10 | */
11 | public interface NioBufferSizePredictor {
12 |
13 | /**
14 | * Predicts the size of next operaion.
15 | *
16 | * @return the expected size at this time for next operation
17 | */
18 | int next();
19 |
20 | /**
21 | * Updates predictor by specifying the actual size in the previous operation.
22 | *
23 | * @param previousSize the actual size in the previous read operation
24 | */
25 | void previous(int previousSize);
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/spi/NioBufferSizePredictorFactory.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio.spi;
2 |
3 | /**
4 | * Factory of {@link NioBufferSizePredictor}
5 | *
6 | * @author mindwind
7 | * @version 1.0, Feb 24, 2013
8 | */
9 | public interface NioBufferSizePredictorFactory {
10 |
11 | /**
12 | * Return a nio buffer size predictor
13 | *
14 | * @param minimum the inclusive lower bound of the expected buffer size
15 | * @param initial the initial buffer size when no feed back was received
16 | * @param maximum the inclusive upper bound of the expected buffer size
17 | * @return a nio buffer size predictor
18 | */
19 | NioBufferSizePredictor newPredictor(int minimum, int initial, int maximum);
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/main/java/io/craft/atom/nio/spi/NioChannelEventDispatcher.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio.spi;
2 |
3 | import io.craft.atom.io.ChannelEvent;
4 | import io.craft.atom.io.IoHandler;
5 | import io.craft.atom.nio.NioOrderedDirectChannelEventDispatcher;
6 | import io.craft.atom.nio.NioOrderedThreadPoolChannelEventDispatcher;
7 |
8 |
9 | /**
10 | * Nio channel event dispatcher, dispatch all channel I/O events to {@link IoHandler}
11 | *
12 | * @author mindwind
13 | * @version 1.0, Feb 22, 2013
14 | * @see NioOrderedThreadPoolChannelEventDispatcher
15 | * @see NioOrderedDirectChannelEventDispatcher
16 | */
17 | public interface NioChannelEventDispatcher {
18 |
19 | /**
20 | * Dispatch event to handle.
21 | *
22 | * @param event
23 | */
24 | void dispatch(ChannelEvent event);
25 |
26 | /**
27 | * Shutdown the dispatcher and dispose holden resources.
28 | */
29 | void shutdown();
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/test/java/io/craft/atom/nio/NioAcceptorHandler.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.AbstractIoHandler;
4 | import io.craft.atom.io.Channel;
5 |
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | /**
10 | * @author mindwind
11 | * @version 1.0, 2011-12-19
12 | */
13 | public class NioAcceptorHandler extends AbstractIoHandler {
14 |
15 | private static final Logger LOG = LoggerFactory.getLogger(NioAcceptorHandler.class);
16 | private static final byte LF = 10 ;
17 |
18 |
19 | private StringBuilder buf = new StringBuilder();
20 |
21 |
22 | @Override
23 | public void channelRead(Channel channel, byte[] bytes) {
24 | LOG.debug("[CRAFT-ATOM-NIO] Channel read bytes size={}", bytes.length);
25 |
26 | for (byte b : bytes) {
27 | buf.append((char) b);
28 | }
29 |
30 | if (bytes[bytes.length - 1] == LF) {
31 | byte[] echoBytes = buf.toString().getBytes();
32 | LOG.debug("[CRAFT-ATOM-NIO] Echo bytes size={} \n", echoBytes.length);
33 | channel.write(echoBytes);
34 | buf = new StringBuilder();
35 | }
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/test/java/io/craft/atom/nio/NioAcceptorNapHandler.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.AbstractIoHandler;
4 | import io.craft.atom.io.Channel;
5 |
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | /**
10 | * @author mindwind
11 | * @version 1.0, 2011-12-19
12 | */
13 | public class NioAcceptorNapHandler extends AbstractIoHandler {
14 |
15 |
16 | private static final Logger LOG = LoggerFactory.getLogger(NioAcceptorNapHandler.class);
17 | private static final byte LF = 10 ;
18 |
19 |
20 | private StringBuilder buf = new StringBuilder();
21 |
22 |
23 | @Override
24 | public void channelRead(Channel channel, byte[] bytes) {
25 | LOG.debug("[CRAFT-ATOM-NIO] Channel read bytes size={}, is paused={}", bytes.length, channel.isPaused());
26 |
27 | for (byte b : bytes) {
28 | buf.append((char) b);
29 | }
30 |
31 | nap();
32 |
33 | if (bytes[bytes.length - 1] == LF) {
34 | byte[] echoBytes = buf.toString().getBytes();
35 | LOG.debug("[CRAFT-ATOM-NIO] Echo bytes size={}, take a nap \n", echoBytes.length);
36 | channel.write(echoBytes);
37 | buf = new StringBuilder();
38 | }
39 | }
40 |
41 | private void nap() {
42 | try {
43 | Thread.sleep(200);
44 | } catch (InterruptedException e) {
45 | e.printStackTrace();
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/test/java/io/craft/atom/nio/NioConnectorHandler.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.AbstractIoHandler;
4 | import io.craft.atom.io.Channel;
5 | import lombok.Getter;
6 |
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | /**
11 | * @author mindwind
12 | * @version 1.0, 2011-12-19
13 | */
14 | public class NioConnectorHandler extends AbstractIoHandler {
15 |
16 |
17 | private static final Logger LOG = LoggerFactory.getLogger(NioConnectorHandler.class);
18 | private static final byte LF = 10 ;
19 |
20 |
21 | @Getter private StringBuilder buf = new StringBuilder();
22 | @Getter private String rcv = null ;
23 |
24 |
25 | @Override
26 | public void channelRead(Channel channel, byte[] bytes) {
27 | LOG.debug("[CRAFT-ATOM-NIO] Channel read bytes size={}", bytes.length);
28 |
29 | for (byte b : bytes) {
30 | buf.append((char) b);
31 | }
32 |
33 | if (bytes[bytes.length - 1] == LF) {
34 | rcv = buf.toString();
35 | byte[] echoBytes = buf.toString().getBytes();
36 | LOG.debug("[CRAFT-ATOM-NIO] Echo received bytes size={} \n", echoBytes.length);
37 | buf = new StringBuilder();
38 | synchronized(channel) {
39 | channel.notifyAll();
40 | }
41 | }
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/test/java/io/craft/atom/nio/NioEchoClient.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.IoConnector;
4 | import io.craft.atom.nio.api.NioFactory;
5 |
6 | import java.io.IOException;
7 |
8 |
9 | /**
10 | * @author mindwind
11 | * @version 1.0, Mar 18, 2014
12 | */
13 | public class NioEchoClient {
14 |
15 | private String ip ;
16 | private int port;
17 |
18 | public NioEchoClient(String ip, int port) {
19 | this.ip = ip;
20 | this.port = port;
21 | }
22 |
23 | public void start() throws IOException {
24 | IoConnector connector = NioFactory.newTcpConnectorBuilder(new NioEchoClientHandler()).connectTimeoutInMillis(3000).build();
25 | connector.connect(ip, port);
26 | }
27 |
28 | public static void main(String[] args) throws IOException {
29 | new NioEchoClient("127.0.0.1", 1314).start();
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/test/java/io/craft/atom/nio/NioEchoClientHandler.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.AbstractIoHandler;
4 | import io.craft.atom.io.Channel;
5 |
6 | import java.util.concurrent.atomic.AtomicInteger;
7 |
8 |
9 | /**
10 | * @author mindwind
11 | * @version 1.0, Mar 15, 2014
12 | */
13 | public class NioEchoClientHandler extends AbstractIoHandler {
14 |
15 | private AtomicInteger counter = new AtomicInteger();
16 |
17 | @Override
18 | public void channelOpened(Channel channel) {
19 | send(channel);
20 | }
21 |
22 | @Override
23 | public void channelRead(Channel channel, byte[] bytes) {
24 | System.out.println("ECHO-RECV: " + new String(bytes));
25 | try { Thread.sleep(1000); } catch (InterruptedException e) {}
26 | send(channel);
27 | }
28 |
29 | private void send(Channel channel) {
30 | String toSend = Integer.toString(counter.incrementAndGet());
31 | channel.write(toSend.getBytes());
32 | System.out.println("ECHO-SENT: " + toSend);
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/test/java/io/craft/atom/nio/NioEchoServer.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.IoAcceptor;
4 | import io.craft.atom.nio.api.NioFactory;
5 |
6 | import java.io.IOException;
7 |
8 |
9 | /**
10 | * @author mindwind
11 | * @version 1.0, Mar 15, 2014
12 | */
13 | public class NioEchoServer {
14 |
15 | private int port;
16 |
17 | public NioEchoServer(int port) {
18 | this.port = port;
19 | }
20 |
21 | public void start() throws IOException {
22 | IoAcceptor acceptor = NioFactory.newTcpAcceptorBuilder(new NioEchoServerHandler()).build();
23 | acceptor.bind(port);
24 | }
25 |
26 | public static void main(String[] args) throws IOException {
27 | new NioEchoServer(1314).start();
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/test/java/io/craft/atom/nio/NioEchoServerHandler.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.AbstractIoHandler;
4 | import io.craft.atom.io.Channel;
5 |
6 | /**
7 | * @author mindwind
8 | * @version 1.0, Mar 15, 2014
9 | */
10 | public class NioEchoServerHandler extends AbstractIoHandler {
11 |
12 | @Override
13 | public void channelRead(Channel channel, byte[] bytes) {
14 | channel.write(bytes);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/test/java/io/craft/atom/nio/TestNioBuilder.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.Channel;
4 | import io.craft.atom.io.IoAcceptor;
5 | import io.craft.atom.io.IoConnector;
6 | import io.craft.atom.nio.api.NioFactory;
7 | import io.craft.atom.test.AvailablePortFinder;
8 | import io.craft.atom.test.CaseCounter;
9 |
10 | import java.io.IOException;
11 | import java.util.concurrent.ExecutionException;
12 | import java.util.concurrent.Future;
13 | import java.util.concurrent.TimeUnit;
14 | import java.util.concurrent.TimeoutException;
15 |
16 | import org.junit.Assert;
17 | import org.junit.Test;
18 |
19 | /**
20 | * @author mindwind
21 | * @version 1.0, Mar 9, 2014
22 | */
23 | public class TestNioBuilder {
24 |
25 |
26 | @Test
27 | public void testNioAcceptorBuilder() throws IOException {
28 | IoAcceptor acceptor = NioFactory.newTcpAcceptorBuilder(new NioAcceptorHandler()).reuseAddress(true).backlog(100).totalEventSize(50000).ioTimeoutInMillis(30000).build();
29 | int port = AvailablePortFinder.getNextAvailable(22222);
30 | acceptor.bind(port);
31 |
32 | try {
33 | acceptor.bind(port);
34 | Assert.fail();
35 | } catch(IOException e) {
36 |
37 | }
38 |
39 | System.out.println(String.format("[CRAFT-ATOM-NIO] (^_^) <%s> Case -> test nio tcp acceptor builder. ", CaseCounter.incr(1)));
40 | }
41 |
42 | @Test
43 | public void testNioConnectorBuilder() throws IOException {
44 | IoConnector connector = NioFactory.newTcpConnectorBuilder(new NioConnectorHandler()).connectTimeoutInMillis(1000).ioTimeoutInMillis(60000).executorSize(32).build();
45 | Future> future = connector.connect("127.0.0.1", AvailablePortFinder.getNextAvailable());
46 |
47 | try {
48 | future.get(1, TimeUnit.SECONDS);
49 | } catch (InterruptedException e) {
50 |
51 | } catch (ExecutionException e) {
52 |
53 | } catch (TimeoutException e) {
54 | Assert.assertTrue(true);
55 | }
56 | System.out.println(String.format("[CRAFT-ATOM-NIO] (^_^) <%s> Case -> test nio tcp connector builder. ", CaseCounter.incr(1)));
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/test/java/io/craft/atom/nio/TestNioTcpAcceptorChannelSizeLimit.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.Channel;
4 | import io.craft.atom.io.IoAcceptor;
5 | import io.craft.atom.io.IoConnector;
6 | import io.craft.atom.nio.api.NioFactory;
7 | import io.craft.atom.test.AvailablePortFinder;
8 | import io.craft.atom.test.CaseCounter;
9 |
10 | import java.io.IOException;
11 | import java.util.concurrent.Future;
12 | import java.util.concurrent.TimeUnit;
13 |
14 | import org.junit.Assert;
15 | import org.junit.Before;
16 | import org.junit.Test;
17 |
18 | /**
19 | * @author mindwind
20 | * @version 1.0, Sep 23, 2014
21 | */
22 | public class TestNioTcpAcceptorChannelSizeLimit {
23 |
24 |
25 | private static final int PORT = AvailablePortFinder.getNextAvailable(33333);
26 |
27 |
28 | private IoConnector connector ;
29 | private IoAcceptor acceptor ;
30 | private int channelSize;
31 |
32 |
33 | @Before
34 | public void before() throws IOException {
35 | channelSize = 2;
36 | acceptor = NioFactory.newTcpAcceptorBuilder(new NioAcceptorHandler()).channelSize(channelSize).build();
37 | acceptor.bind(PORT);
38 | connector = NioFactory.newTcpConnector(new NioConnectorHandler());
39 | }
40 |
41 | @Test
42 | public void testChannelSizeLimit() throws IOException {
43 | for (int i = 0; i < channelSize; i++) {
44 | connector.connect("127.0.0.1", PORT);
45 | }
46 |
47 | try {
48 | Thread.sleep(100);
49 | Future> future = connector.connect("127.0.0.1", PORT);
50 | Channel channel = future.get(200, TimeUnit.MILLISECONDS);
51 | Thread.sleep(200);
52 | Assert.assertFalse(channel.isOpen());
53 | } catch (Exception e) {
54 | Assert.fail();
55 | }
56 | System.out.println(String.format("[CRAFT-ATOM-NIO] (^_^) <%s> Case -> test nio acceptor channel size limit ", CaseCounter.incr(1)));
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/test/java/io/craft/atom/nio/TestNioTcpConnector.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.Channel;
4 | import io.craft.atom.io.IoConnector;
5 | import io.craft.atom.nio.NioTcpConnector;
6 | import io.craft.atom.nio.api.NioFactory;
7 | import io.craft.atom.test.AvailablePortFinder;
8 | import io.craft.atom.test.CaseCounter;
9 |
10 | import java.io.IOException;
11 | import java.util.concurrent.ExecutionException;
12 | import java.util.concurrent.Future;
13 | import java.util.concurrent.TimeUnit;
14 | import java.util.concurrent.TimeoutException;
15 |
16 | import org.junit.Assert;
17 | import org.junit.Test;
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 |
21 | /**
22 | * Tests for {@link NioTcpConnector}
23 | *
24 | * @author mindwind
25 | * @version 1.0, 2011-12-20
26 | */
27 | public class TestNioTcpConnector {
28 |
29 |
30 | private static final Logger LOG = LoggerFactory.getLogger(TestNioTcpConnector.class);
31 |
32 |
33 | @Test
34 | public void testTimeout() throws IOException {
35 | IoConnector connector = NioFactory.newTcpConnector(new NioConnectorHandler());
36 | Future> future = connector.connect("127.0.0.1", AvailablePortFinder.getNextAvailable());
37 |
38 | try {
39 | future.get(200, TimeUnit.MILLISECONDS);
40 | Assert.fail();
41 | } catch (InterruptedException e) {
42 |
43 | } catch (ExecutionException e) {
44 |
45 | } catch (TimeoutException e) {
46 | LOG.debug("[CRAFT-ATOM-NIO] Test catch timeout exception");
47 | Assert.assertTrue(true);
48 | }
49 | System.out.println(String.format("[CRAFT-ATOM-NIO] (^_^) <%s> Case -> test nio tcp connector timeout. ", CaseCounter.incr(1)));
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/test/java/io/craft/atom/nio/TestNioTimeout.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.nio;
2 |
3 | import io.craft.atom.io.AbstractIoHandler;
4 | import io.craft.atom.io.Channel;
5 | import io.craft.atom.io.IoAcceptor;
6 | import io.craft.atom.io.IoHandler;
7 | import io.craft.atom.nio.api.NioFactory;
8 | import io.craft.atom.nio.api.NioTcpAcceptorBuilder;
9 | import io.craft.atom.test.AvailablePortFinder;
10 | import io.craft.atom.test.CaseCounter;
11 | import junit.framework.Assert;
12 |
13 | import org.junit.Test;
14 |
15 | /**
16 | * Test for nio timeout config
17 | *
18 | * @author mindwind
19 | * @version 1.0, Sep 5, 2014
20 | */
21 | public class TestNioTimeout {
22 |
23 |
24 | @Test
25 | public void testMaxIntegerTimeout() {
26 | try {
27 | int port = AvailablePortFinder.getNextAvailable();
28 | NioTcpAcceptorBuilder builder = NioFactory.newTcpAcceptorBuilder(new NioAcceptorHandler());
29 | IoAcceptor acceptor = builder.ioTimeoutInMillis(Integer.MAX_VALUE).build();
30 | acceptor.bind(port);
31 | } catch (Throwable t) {
32 | Assert.fail();
33 | }
34 |
35 | Assert.assertTrue(true);
36 | System.out.println(String.format("[CRAFT-ATOM-NIO] (^_^) <%s> Case -> test max integer timeout. ", CaseCounter.incr(1)));
37 | }
38 |
39 | @Test
40 | public void testLessOneHundredMillisecondsTimeout() {
41 | try {
42 | int port = AvailablePortFinder.getNextAvailable();
43 | IoHandler handler = new AbstractIoHandler() {
44 | @Override
45 | public void channelIdle(Channel channel) {
46 | super.channelIdle(channel);
47 | channel.close();
48 | }
49 | };
50 | NioTcpAcceptorBuilder builder = NioFactory.newTcpAcceptorBuilder(handler);
51 | IoAcceptor acceptor = builder.ioTimeoutInMillis(50).build();
52 | acceptor.bind(port);
53 | } catch (Throwable t) {
54 | t.printStackTrace();
55 | Assert.fail();
56 | }
57 |
58 | Assert.assertTrue(true);
59 | System.out.println(String.format("[CRAFT-ATOM-NIO] (^_^) <%s> Case -> test less one hundred milliseconds timeout. ", CaseCounter.incr(1)));
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/craft-atom-nio/src/test/resources/log4j.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/craft-atom-protocol-http/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | io.craftcode
5 | craft-atom
6 | 3.1.3-SNAPSHOT
7 |
8 | craft-atom-protocol-http
9 | ${project.artifactId}
10 |
11 |
12 |
13 | ${project.groupId}
14 | craft-atom-protocol
15 | ${project.version}
16 |
17 |
18 | ${project.groupId}
19 | craft-atom-test
20 | ${project.version}
21 | test
22 |
23 |
24 | org.slf4j
25 | slf4j-api
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/craft-atom-protocol-http/src/main/java/io/craft/atom/protocol/http/HttpCookieEncoder.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.protocol.http;
2 |
3 | import io.craft.atom.protocol.AbstractProtocolCodec;
4 | import io.craft.atom.protocol.ProtocolEncoder;
5 | import io.craft.atom.protocol.ProtocolException;
6 | import io.craft.atom.protocol.http.model.HttpCookie;
7 |
8 | import java.nio.charset.Charset;
9 |
10 | import lombok.ToString;
11 |
12 |
13 | /**
14 | * A {@link ProtocolEncoder} which encodes a {@code Cookie} object into bytes follow the HTTP specification, default charset is utf-8.
15 | *
16 | * Thread safe.
17 | *
18 | * @author mindwind
19 | * @version 1.0, Mar 25, 2013
20 | */
21 | @ToString(callSuper = true)
22 | public class HttpCookieEncoder extends AbstractProtocolCodec implements ProtocolEncoder {
23 |
24 |
25 | public HttpCookieEncoder() {}
26 |
27 | public HttpCookieEncoder(Charset charset) {
28 | this.charset = charset;
29 | }
30 |
31 | @Override
32 | public byte[] encode(HttpCookie cookie) throws ProtocolException {
33 | if (cookie == null) return null;
34 | String httpString = cookie.toHttpString();
35 | return httpString.getBytes(charset);
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/craft-atom-protocol-http/src/main/java/io/craft/atom/protocol/http/HttpDates.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.protocol.http;
2 |
3 | import java.text.DateFormat;
4 | import java.text.ParseException;
5 | import java.text.SimpleDateFormat;
6 | import java.util.Date;
7 | import java.util.Locale;
8 | import java.util.TimeZone;
9 |
10 | /**
11 | * Generates date in the format required by the HTTP protocol.
12 | *
13 | * @author mindwind
14 | * @version 1.0, Mar 22, 2013
15 | */
16 | public class HttpDates {
17 |
18 |
19 | /** The date format pattern used to generate the header in RFC 1123 format. */
20 | private static final String DATE_FORMAT_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
21 | private static final TimeZone GMT = TimeZone.getTimeZone("GMT") ;
22 | private static final ThreadLocal threadLocal = new ThreadLocal() ;
23 | private static long dateAsLong = 0L ;
24 | private static String dateAsText = null ;
25 |
26 |
27 | // ~ -----------------------------------------------------------------------------------------------------------
28 |
29 |
30 | private static DateFormat getDateFormat() {
31 | DateFormat df = threadLocal.get();
32 | if (df == null) {
33 | df = new SimpleDateFormat(DATE_FORMAT_RFC1123, Locale.US);
34 | df.setTimeZone(GMT);
35 | threadLocal.set(df);
36 | }
37 | return df;
38 | }
39 |
40 | public static String formatCurrentDate() {
41 | long now = System.currentTimeMillis();
42 | if (now - dateAsLong > 1000) {
43 | dateAsText = format(new Date(now));
44 | dateAsLong = now;
45 | }
46 | return dateAsText;
47 | }
48 |
49 | public static String format(Date date) {
50 | DateFormat df = getDateFormat();
51 | return df.format(date);
52 | }
53 |
54 | public static Date parse(String dateString) {
55 | DateFormat df = getDateFormat();
56 | try {
57 | return df.parse(dateString);
58 | } catch (ParseException e) {
59 | throw new IllegalArgumentException("Invalid date string format=" + dateString, e);
60 | }
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/craft-atom-protocol-http/src/main/java/io/craft/atom/protocol/http/HttpEncoder.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.protocol.http;
2 |
3 | import io.craft.atom.protocol.AbstractProtocolEncoder;
4 | import lombok.ToString;
5 |
6 |
7 | /**
8 | * @author mindwind
9 | * @version 1.0, Feb 3, 2013
10 | * @see HttpRequestEncoder
11 | * @see HttpResponseEncoder
12 | */
13 | @ToString(callSuper = true)
14 | abstract public class HttpEncoder extends AbstractProtocolEncoder {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/craft-atom-protocol-http/src/main/java/io/craft/atom/protocol/http/HttpParameterEncoder.java:
--------------------------------------------------------------------------------
1 | package io.craft.atom.protocol.http;
2 |
3 | import static io.craft.atom.protocol.http.HttpConstants.S_AMPERSAND;
4 | import static io.craft.atom.protocol.http.HttpConstants.S_EQUAL_SIGN;
5 |
6 | import io.craft.atom.protocol.AbstractProtocolCodec;
7 | import io.craft.atom.protocol.ProtocolEncoder;
8 | import io.craft.atom.protocol.ProtocolException;
9 |
10 | import java.io.UnsupportedEncodingException;
11 | import java.net.URLEncoder;
12 | import java.nio.charset.Charset;
13 | import java.util.List;
14 | import java.util.Map;
15 | import java.util.Map.Entry;
16 | import java.util.Set;
17 |
18 | import lombok.ToString;
19 |
20 |
21 | /**
22 | * A {@link ProtocolEncoder} which encodes a {@code Map>} object into bytes
23 | * with the application/x-www-form-urlencoded
MIME format follow the HTTP specification, default charset is utf-8.
24 | *
25 | * Thread safe.
26 | *
27 | * @author mindwind
28 | * @version 1.0, Mar 25, 2013
29 | */
30 | @ToString(callSuper = true)
31 | public class HttpParameterEncoder extends AbstractProtocolCodec implements ProtocolEncoder