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  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.IoSession;
36  
37  /**
38   * Binds the specified {@link IoHandler} to the specified
39   * {@link VmPipeAddress}.
40   *
41   * @author The Apache MINA Project (dev@mina.apache.org)
42   * @version $Rev: 671827 $, $Date: 2008-06-26 10:49:48 +0200 (jeu, 26 jun 2008) $
43   */
44  public final class VmPipeAcceptor extends AbstractIoAcceptor {
45      static final Map<VmPipeAddress, VmPipe> boundHandlers = new HashMap<VmPipeAddress, VmPipe>();
46  
47      /**
48       * Creates a new instance.
49       */
50      public VmPipeAcceptor() {
51          this(null);
52      }
53      
54      /**
55       * Creates a new instance.
56       */
57      public VmPipeAcceptor(Executor executor) {
58          super(new DefaultVmPipeSessionConfig(), executor);
59      }
60  
61      public TransportMetadata getTransportMetadata() {
62          return VmPipeSession.METADATA;
63      }
64  
65      @Override
66      public VmPipeSessionConfig getSessionConfig() {
67          return (VmPipeSessionConfig) super.getSessionConfig();
68      }
69  
70      @Override
71      public VmPipeAddress getLocalAddress() {
72          return (VmPipeAddress) super.getLocalAddress();
73      }
74  
75      @Override
76      public VmPipeAddress getDefaultLocalAddress() {
77          return (VmPipeAddress) super.getDefaultLocalAddress();
78      }
79  
80      // This method is overriden to work around a problem with
81      // bean property access mechanism.
82  
83      public void setDefaultLocalAddress(VmPipeAddress localAddress) {
84          super.setDefaultLocalAddress(localAddress);
85      }
86  
87      @Override
88      protected IoFuture dispose0() throws Exception {
89          unbind();
90          return null;
91      }
92  
93      @Override
94      protected Set<SocketAddress> bind0(List<? extends SocketAddress> localAddresses) throws IOException {
95          Set<SocketAddress> newLocalAddresses = new HashSet<SocketAddress>();
96  
97          synchronized (boundHandlers) {
98              for (SocketAddress a: localAddresses) {
99                  VmPipeAddress localAddress = (VmPipeAddress) a;
100                 if (localAddress == null || localAddress.getPort() == 0) {
101                     localAddress = null;
102                     for (int i = 10000; i < Integer.MAX_VALUE; i++) {
103                         VmPipeAddress newLocalAddress = new VmPipeAddress(i);
104                         if (!boundHandlers.containsKey(newLocalAddress) &&
105                             !newLocalAddresses.contains(newLocalAddress)) {
106                             localAddress = newLocalAddress;
107                             break;
108                         }
109                     }
110     
111                     if (localAddress == null) {
112                         throw new IOException("No port available.");
113                     }
114                 } else if (localAddress.getPort() < 0) {
115                     throw new IOException("Bind port number must be 0 or above.");
116                 } else if (boundHandlers.containsKey(localAddress)) {
117                     throw new IOException("Address already bound: " + localAddress);
118                 }
119                 
120                 newLocalAddresses.add(localAddress);
121             }
122 
123             for (SocketAddress a: newLocalAddresses) {
124                 VmPipeAddress localAddress = (VmPipeAddress) a;
125                 if (!boundHandlers.containsKey(localAddress)) {
126                     boundHandlers.put(localAddress, new VmPipe(this, localAddress,
127                             getHandler(), getListeners()));
128                 } else {
129                     for (SocketAddress a2: newLocalAddresses) {
130                         boundHandlers.remove(a2);
131                     }
132                     throw new IOException("Duplicate local address: " + a);
133                 }
134             }
135         }
136 
137         return newLocalAddresses;
138     }
139 
140     @Override
141     protected void unbind0(List<? extends SocketAddress> localAddresses) {
142         synchronized (boundHandlers) {
143             for (SocketAddress a: localAddresses) {
144                 boundHandlers.remove(a);
145             }
146         }
147     }
148 
149     public IoSession newSession(SocketAddress remoteAddress, SocketAddress localAddress) {
150         throw new UnsupportedOperationException();
151     }
152 
153     void doFinishSessionInitialization(IoSession session, IoFuture future) {
154         finishSessionInitialization(session, future, null);
155     }
156 }