View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
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  
30  import org.apache.mina.common.AbstractIoAcceptor;
31  import org.apache.mina.common.IoFuture;
32  import org.apache.mina.common.IoHandler;
33  import org.apache.mina.common.IoSession;
34  import org.apache.mina.common.TransportMetadata;
35  
36  /**
37   * Binds the specified {@link IoHandler} to the specified
38   * {@link VmPipeAddress}.
39   *
40   * @author The Apache MINA Project (dev@mina.apache.org)
41   * @version $Rev: 605069 $, $Date: 2007-12-17 19:47:03 -0700 (Mon, 17 Dec 2007) $
42   */
43  public final class VmPipeAcceptor extends AbstractIoAcceptor {
44      static final Map<VmPipeAddress, VmPipe> boundHandlers = new HashMap<VmPipeAddress, VmPipe>();
45  
46      /**
47       * Creates a new instance.
48       */
49      public VmPipeAcceptor() {
50          super(new DefaultVmPipeSessionConfig());
51      }
52  
53      public TransportMetadata getTransportMetadata() {
54          return VmPipeSessionImpl.METADATA;
55      }
56  
57      @Override
58      public VmPipeSessionConfig getSessionConfig() {
59          return (VmPipeSessionConfig) super.getSessionConfig();
60      }
61  
62      @Override
63      public VmPipeAddress getLocalAddress() {
64          return (VmPipeAddress) super.getLocalAddress();
65      }
66  
67      @Override
68      public VmPipeAddress getDefaultLocalAddress() {
69          return (VmPipeAddress) super.getDefaultLocalAddress();
70      }
71  
72      // This method is overriden to work around a problem with
73      // bean property access mechanism.
74  
75      public void setDefaultLocalAddress(VmPipeAddress localAddress) {
76          super.setDefaultLocalAddress(localAddress);
77      }
78  
79      @Override
80      protected IoFuture dispose0() throws Exception {
81          unbind();
82          return null;
83      }
84  
85      @Override
86      protected Set<SocketAddress> bind0(List<? extends SocketAddress> localAddresses) throws IOException {
87          Set<SocketAddress> newLocalAddresses = new HashSet<SocketAddress>();
88  
89          synchronized (boundHandlers) {
90              for (SocketAddress a: localAddresses) {
91                  VmPipeAddress localAddress = (VmPipeAddress) a;
92                  if (localAddress == null || localAddress.getPort() == 0) {
93                      localAddress = null;
94                      for (int i = 10000; i < Integer.MAX_VALUE; i++) {
95                          VmPipeAddress newLocalAddress = new VmPipeAddress(i);
96                          if (!boundHandlers.containsKey(newLocalAddress) &&
97                              !newLocalAddresses.contains(newLocalAddress)) {
98                              localAddress = newLocalAddress;
99                              break;
100                         }
101                     }
102     
103                     if (localAddress == null) {
104                         throw new IOException("No port available.");
105                     }
106                 } else if (localAddress.getPort() < 0) {
107                     throw new IOException("Bind port number must be 0 or above.");
108                 } else if (boundHandlers.containsKey(localAddress)) {
109                     throw new IOException("Address already bound: " + localAddress);
110                 }
111                 
112                 newLocalAddresses.add(localAddress);
113             }
114 
115             for (SocketAddress a: newLocalAddresses) {
116                 VmPipeAddress localAddress = (VmPipeAddress) a;
117                 if (!boundHandlers.containsKey(localAddress)) {
118                     boundHandlers.put(localAddress, new VmPipe(this, localAddress,
119                             getHandler(), getListeners()));
120                 } else {
121                     for (SocketAddress a2: newLocalAddresses) {
122                         boundHandlers.remove(a2);
123                     }
124                     throw new IOException("Duplicate local address: " + a);
125                 }
126             }
127         }
128 
129         return newLocalAddresses;
130     }
131 
132     @Override
133     protected void unbind0(List<? extends SocketAddress> localAddresses) {
134         synchronized (boundHandlers) {
135             for (SocketAddress a: localAddresses) {
136                 boundHandlers.remove(a);
137             }
138         }
139     }
140 
141     public IoSession newSession(SocketAddress remoteAddress, SocketAddress localAddress) {
142         throw new UnsupportedOperationException();
143     }
144 
145     void doFinishSessionInitialization(IoSession session, IoFuture future) {
146         finishSessionInitialization(session, future, null);
147     }
148 }