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
45 public final class VmPipeAcceptor extends AbstractIoAcceptor {
46
47
48 private IdleStatusChecker idleChecker;
49
50 static final Map<VmPipeAddress, VmPipe> boundHandlers = new HashMap<VmPipeAddress, VmPipe>();
51
52
53
54
55 public VmPipeAcceptor() {
56 this(null);
57 }
58
59
60
61
62 public VmPipeAcceptor(Executor executor) {
63 super(new DefaultVmPipeSessionConfig(), executor);
64 idleChecker = new IdleStatusChecker();
65
66
67 executeWorker(idleChecker.getNotifyingTask(), "idleStatusChecker");
68 }
69
70 public TransportMetadata getTransportMetadata() {
71 return VmPipeSession.METADATA;
72 }
73
74 @Override
75 public VmPipeSessionConfig getSessionConfig() {
76 return (VmPipeSessionConfig) super.getSessionConfig();
77 }
78
79 @Override
80 public VmPipeAddress getLocalAddress() {
81 return (VmPipeAddress) super.getLocalAddress();
82 }
83
84 @Override
85 public VmPipeAddress getDefaultLocalAddress() {
86 return (VmPipeAddress) super.getDefaultLocalAddress();
87 }
88
89
90
91
92 public void setDefaultLocalAddress(VmPipeAddress localAddress) {
93 super.setDefaultLocalAddress(localAddress);
94 }
95
96 @Override
97 protected IoFuture dispose0() throws Exception {
98
99 idleChecker.getNotifyingTask().cancel();
100 unbind();
101 return null;
102 }
103
104 @Override
105 protected Set<SocketAddress> bind0(List<? extends SocketAddress> localAddresses) throws IOException {
106 Set<SocketAddress> newLocalAddresses = new HashSet<SocketAddress>();
107
108 synchronized (boundHandlers) {
109 for (SocketAddress a: localAddresses) {
110 VmPipeAddress localAddress = (VmPipeAddress) a;
111 if (localAddress == null || localAddress.getPort() == 0) {
112 localAddress = null;
113 for (int i = 10000; i < Integer.MAX_VALUE; i++) {
114 VmPipeAddress newLocalAddress = new VmPipeAddress(i);
115 if (!boundHandlers.containsKey(newLocalAddress) &&
116 !newLocalAddresses.contains(newLocalAddress)) {
117 localAddress = newLocalAddress;
118 break;
119 }
120 }
121
122 if (localAddress == null) {
123 throw new IOException("No port available.");
124 }
125 } else if (localAddress.getPort() < 0) {
126 throw new IOException("Bind port number must be 0 or above.");
127 } else if (boundHandlers.containsKey(localAddress)) {
128 throw new IOException("Address already bound: " + localAddress);
129 }
130
131 newLocalAddresses.add(localAddress);
132 }
133
134 for (SocketAddress a: newLocalAddresses) {
135 VmPipeAddress localAddress = (VmPipeAddress) a;
136 if (!boundHandlers.containsKey(localAddress)) {
137 boundHandlers.put(localAddress, new VmPipe(this, localAddress,
138 getHandler(), getListeners()));
139 } else {
140 for (SocketAddress a2: newLocalAddresses) {
141 boundHandlers.remove(a2);
142 }
143 throw new IOException("Duplicate local address: " + a);
144 }
145 }
146 }
147
148 return newLocalAddresses;
149 }
150
151 @Override
152 protected void unbind0(List<? extends SocketAddress> localAddresses) {
153 synchronized (boundHandlers) {
154 for (SocketAddress a: localAddresses) {
155 boundHandlers.remove(a);
156 }
157 }
158 }
159
160 public IoSession newSession(SocketAddress remoteAddress, SocketAddress localAddress) {
161 throw new UnsupportedOperationException();
162 }
163
164 void doFinishSessionInitialization(IoSession session, IoFuture future) {
165 finishSessionInitialization(session, future, null);
166 }
167 }