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.common;
21
22 import java.io.InvalidObjectException;
23 import java.io.ObjectStreamException;
24 import java.io.Serializable;
25 import java.util.HashMap;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.TreeSet;
29
30 /**
31 * Represents network transport types.
32 * MINA provides three transport types by default:
33 * <ul>
34 * <li>{@link #SOCKET} - TCP/IP</li>
35 * <li>{@link #DATAGRAM} - UDP/IP</li>
36 * <li>{@link #VM_PIPE} - in-VM pipe support (only available in protocol
37 * layer</li>
38 * </ul>
39 * <p>
40 * You can also create your own transport type. Please refer to
41 * {@link #TransportType(String[], boolean)}.
42 *
43 * @author The Apache Directory Project (mina-dev@directory.apache.org)
44 * @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (Fri, 13 Jul 2007) $
45 */
46 public final class TransportType implements Serializable {
47 private static final long serialVersionUID = 3258132470497883447L;
48
49 private static final Map<String, TransportType> name2type = new HashMap<String, TransportType>();
50
51 private static void register(String[] names, TransportType type) {
52 synchronized (name2type) {
53 for (int i = names.length - 1; i >= 0; i--) {
54 if (name2type.containsKey(names[i])) {
55 throw new IllegalArgumentException("Transport type name '"
56 + names[i] + "' is already taken.");
57 }
58 }
59
60 for (int i = names.length - 1; i >= 0; i--) {
61 name2type.put(names[i].toUpperCase(), type);
62 }
63 }
64 }
65
66 /**
67 * Transport type: TCP/IP (Registry name: <tt>"SOCKET"</tt> or <tt>"TCP"</tt>)
68 */
69 public static final TransportType SOCKET = new TransportType(new String[] {
70 "SOCKET", "TCP" }, false);
71
72 /**
73 * Transport type: UDP/IP (Registry name: <tt>"DATAGRAM"</tt> or <tt>"UDP"</tt>)
74 */
75 public static final TransportType DATAGRAM = new TransportType(
76 new String[] { "DATAGRAM", "UDP" }, true);
77
78 /**
79 * Transport type: in-VM pipe (Registry name: <tt>"VM_PIPE"</tt>)
80 * Please refer to
81 * <a href="../protocol/vmpipe/package-summary.htm"><tt>org.apache.mina.protocol.vmpipe</tt></a>
82 * package.
83 */
84 public static final TransportType VM_PIPE = new TransportType(
85 new String[] { "VM_PIPE" }, Object.class, false);
86
87 /**
88 * Returns the transport type of the specified name.
89 * All names are case-insensitive.
90 *
91 * @param name the name of the transport type
92 * @return the transport type
93 * @throws IllegalArgumentException if the specified name is not available.
94 */
95 public static TransportType getInstance(String name) {
96 TransportType type = name2type.get(name.toUpperCase());
97 if (type != null) {
98 return type;
99 }
100
101 throw new IllegalArgumentException("Unknown transport type name: "
102 + name);
103 }
104
105 private final String[] names;
106
107 private final transient boolean connectionless;
108
109 private final transient Class<? extends Object> envelopeType;
110
111 /**
112 * Creates a new instance. New transport type is automatically registered
113 * to internal registry so that you can look it up using {@link #getInstance(String)}.
114 *
115 * @param names the name or aliases of this transport type
116 * @param connectionless <tt>true</tt> if and only if this transport type is connectionless
117 *
118 * @throws IllegalArgumentException if <tt>names</tt> are already registered or empty
119 */
120 public TransportType(String[] names, boolean connectionless) {
121 this(names, ByteBuffer.class, connectionless);
122 }
123
124 /**
125 * Creates a new instance. New transport type is automatically registered
126 * to internal registry so that you can look it up using {@link #getInstance(String)}.
127 *
128 * @param names the name or aliases of this transport type
129 * @param connectionless <tt>true</tt> if and only if this transport type is connectionless
130 *
131 * @throws IllegalArgumentException if <tt>names</tt> are already registered or empty
132 */
133 public TransportType(String[] names, Class<? extends Object> envelopeType,
134 boolean connectionless) {
135 if (names == null) {
136 throw new NullPointerException("names");
137 }
138 if (names.length == 0) {
139 throw new IllegalArgumentException("names is empty");
140 }
141 if (envelopeType == null) {
142 throw new NullPointerException("envelopeType");
143 }
144
145 for (int i = 0; i < names.length; i++) {
146 if (names[i] == null) {
147 throw new NullPointerException("strVals[" + i + "]");
148 }
149
150 names[i] = names[i].toUpperCase();
151 }
152
153 register(names, this);
154 this.names = names;
155 this.connectionless = connectionless;
156 this.envelopeType = envelopeType;
157 }
158
159 /**
160 * Returns <code>true</code> if the session of this transport type is
161 * connectionless.
162 */
163 public boolean isConnectionless() {
164 return connectionless;
165 }
166
167 public Class<? extends Object> getEnvelopeType() {
168 return envelopeType;
169 }
170
171 /**
172 * Returns the known names of this transport type.
173 */
174 public Set<String> getNames() {
175 Set<String> result = new TreeSet<String>();
176 for (int i = names.length - 1; i >= 0; i--) {
177 result.add(names[i]);
178 }
179
180 return result;
181 }
182
183 @Override
184 public String toString() {
185 return names[0];
186 }
187
188 private Object readResolve() throws ObjectStreamException {
189 for (int i = names.length - 1; i >= 0; i--) {
190 try {
191 return getInstance(names[i]);
192 } catch (IllegalArgumentException e) {
193 // ignore
194 }
195 }
196
197 throw new InvalidObjectException("Unknown transport type.");
198 }
199 }