1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.transport.vmpipe;
21
22 import java.io.IOException;
23 import java.net.SocketAddress;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.concurrent.Executor;
30
31 import org.apache.mina.core.future.IoFuture;
32 import org.apache.mina.core.service.AbstractIoAcceptor;
33 import org.apache.mina.core.service.IoHandler;
34 import org.apache.mina.core.service.TransportMetadata;
35 import org.apache.mina.core.session.IdleStatusChecker;
36 import org.apache.mina.core.session.IoSession;
37
38
39
40
41
42
43
44 public final class VmPipeAcceptor extends AbstractIoAcceptor {
45
46
47 private IdleStatusChecker idleChecker;
48
49 static final Map<VmPipeAddress, VmPipe> boundHandlers = new HashMap<VmPipeAddress, VmPipe>();
50
51
52
53
54 public VmPipeAcceptor() {
55 this(null);
56 }
57
58
59
60
61 public VmPipeAcceptor(Executor executor) {
62 super(new DefaultVmPipeSessionConfig(), executor);
63 idleChecker = new IdleStatusChecker();
64
65
66 executeWorker(idleChecker.getNotifyingTask(), "idleStatusChecker");
67 }
68
69 public TransportMetadata getTransportMetadata() {
70 return VmPipeSession.METADATA;
71 }
72
73 @Override
74 public VmPipeSessionConfig getSessionConfig() {
75 return (VmPipeSessionConfig) super.getSessionConfig();
76 }
77
78 @Override
79 public VmPipeAddress getLocalAddress() {
80 return (VmPipeAddress) super.getLocalAddress();
81 }
82
83 @Override
84 public VmPipeAddress getDefaultLocalAddress() {
85 return (VmPipeAddress) super.getDefaultLocalAddress();
86 }
87
88
89
90
91 public void setDefaultLocalAddress(VmPipeAddress localAddress) {
92 super.setDefaultLocalAddress(localAddress);
93 }
94
95 @Override
96 protected IoFuture dispose0() throws Exception {
97
98 idleChecker.getNotifyingTask().cancel();
99 unbind();
100 return null;
101 }
102
103 @Override
104 protected Set<SocketAddress> bindInternal(List<? extends SocketAddress> localAddresses) throws IOException {
105 Set<SocketAddress> newLocalAddresses = new HashSet<SocketAddress>();
106
107 synchronized (boundHandlers) {
108 for (SocketAddress a: localAddresses) {
109 VmPipeAddress localAddress = (VmPipeAddress) a;
110 if (localAddress == null || localAddress.getPort() == 0) {
111 localAddress = null;
112 for (int i = 10000; i < Integer.MAX_VALUE; i++) {
113 VmPipeAddress newLocalAddress = new VmPipeAddress(i);
114 if (!boundHandlers.containsKey(newLocalAddress) &&
115 !newLocalAddresses.contains(newLocalAddress)) {
116 localAddress = newLocalAddress;
117 break;
118 }
119 }
120
121 if (localAddress == null) {
122 throw new IOException("No port available.");
123 }
124 } else if (localAddress.getPort() < 0) {
125 throw new IOException("Bind port number must be 0 or above.");
126 } else if (boundHandlers.containsKey(localAddress)) {
127 throw new IOException("Address already bound: " + localAddress);
128 }
129
130 newLocalAddresses.add(localAddress);
131 }
132
133 for (SocketAddress a: newLocalAddresses) {
134 VmPipeAddress localAddress = (VmPipeAddress) a;
135 if (!boundHandlers.containsKey(localAddress)) {
136 boundHandlers.put(localAddress, new VmPipe(this, localAddress,
137 getHandler(), getListeners()));
138 } else {
139 for (SocketAddress a2: newLocalAddresses) {
140 boundHandlers.remove(a2);
141 }
142 throw new IOException("Duplicate local address: " + a);
143 }
144 }
145 }
146
147 return newLocalAddresses;
148 }
149
150 @Override
151 protected void unbind0(List<? extends SocketAddress> localAddresses) {
152 synchronized (boundHandlers) {
153 for (SocketAddress a: localAddresses) {
154 boundHandlers.remove(a);
155 }
156 }
157 }
158
159 public IoSession newSession(SocketAddress remoteAddress, SocketAddress localAddress) {
160 throw new UnsupportedOperationException();
161 }
162
163 void doFinishSessionInitialization(IoSession session, IoFuture future) {
164 initSession(session, future, null);
165 }
166 }