001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package javax.microedition.io;
028:
029: import java.io.*;
030: import com.sun.cldc.io.*;
031:
032: /**
033: * This class is factory for creating new Connection objects.
034: * <p>
035: * The creation of Connections is performed dynamically by looking
036: * up a protocol implementation class whose name is formed from the
037: * platform name (read from a system property) and the protocol name
038: * of the requested connection (extracted from the parameter string
039: * supplied by the application programmer.)
040: *
041: * The parameter string that describes the target should conform
042: * to the URL format as described in RFC 2396.
043: * This takes the general form:
044: * <p>
045: * <code>{scheme}:[{target}][{params}]</code>
046: * <p>
047: * where <code>{scheme}</code> is the name of a protocol such as
048: * <i>http</i>}.
049: * <p>
050: * The <code>{target}</code> is normally some kind of network
051: * address.
052: * <p>
053: * Any <code>{params}</code> are formed as a series of equates
054: * of the form ";x=y". Example: ";type=a".
055: * <p>
056: * An optional second parameter may be specified to the open
057: * function. This is a mode flag that indicates to the protocol
058: * handler the intentions of the calling code. The options here
059: * specify if the connection is going to be read (READ), written
060: * (WRITE), or both (READ_WRITE). The validity of these flag
061: * settings is protocol dependent. For instance, a connection
062: * for a printer would not allow read access, and would throw
063: * an IllegalArgumentException. If the mode parameter is not
064: * specified, READ_WRITE is used by default.
065: * <p>
066: * An optional third parameter is a boolean flag that indicates
067: * if the calling code can handle timeout exceptions. If this
068: * flag is set, the protocol implementation may throw an
069: * InterruptedIOException when it detects a timeout condition.
070: * This flag is only a hint to the protocol handler, and it
071: * does not guarantee that such exceptions will actually be thrown.
072: * If this parameter is not set, no timeout exceptions will be
073: * thrown.
074: * <p>
075: * Because connections are frequently opened just to gain access
076: * to a specific input or output stream, four convenience
077: * functions are provided for this purpose.
078: *
079: * See also: {@link DatagramConnection DatagramConnection}
080: * for information relating to datagram addressing
081: *
082: * @version 12/17/01 (CLDC 1.1)
083: * @since CLDC 1.0
084: */
085:
086: public class Connector {
087:
088: /*
089: * Implementation notes: The open parameter is used for
090: * dynamically constructing a class name in the form:
091: * <p>
092: * <code>com.sun.cldc.io.{platform}.{protocol}.Protocol</code>
093: * <p>
094: * The platform name is derived from the system by looking for
095: * the system property "microedition.platform". If this property
096: * key is not found or the associated class is not present, then
097: * "j2me" is used by default.
098: * <p>
099: * The protocol name is derived from the parameter string
100: * describing the target of the connection. This takes the from:
101: * <p>
102: * <code> {protocol}:[{target}][ {params}] </code>
103: * <p>
104: * The protocol name is used for dynamically finding the
105: * appropriate protocol implementation class. This information
106: * is stripped from the target name that is given as a parameter
107: * to the open() method. In order to avoid problems with illegal
108: * class file names, all the '-' characters in the protocol name
109: * are automatically converted into '_' characters.
110: */
111:
112: /**
113: * Access mode READ.
114: */
115: public final static int READ = 1;
116:
117: /**
118: * Access mode WRITE.
119: */
120: public final static int WRITE = 2;
121:
122: /**
123: * Access mode READ_WRITE.
124: */
125: public final static int READ_WRITE = (READ | WRITE);
126:
127: /**
128: * The platform name.
129: */
130: private static String platform;
131:
132: /**
133: * The root of the classes.
134: */
135: private static String classRoot;
136:
137: /**
138: * Class initializer.
139: */
140: static {
141: /* Set up the platform name */
142: platform = System.getProperty("microedition.platform");
143: if ((platform == null) || (platform.equals("generic"))) {
144: platform = "j2me";
145: }
146:
147: /* Set up the library class root path */
148: /* This may vary from one CLDC implementation to another */
149: classRoot = System
150: .getProperty("javax.microedition.io.Connector.protocolpath");
151: if (classRoot == null) {
152: classRoot = "com.sun.cldc.io";
153: }
154: }
155:
156: /**
157: * Prevent instantiation of this class.
158: */
159: private Connector() {
160: }
161:
162: /**
163: * Create and open a Connection.
164: *
165: * @param name The URL for the connection.
166: * @return A new Connection object.
167: *
168: * @exception IllegalArgumentException If a parameter is invalid.
169: * @exception ConnectionNotFoundException If the target of the
170: * name cannot be found, or if the requested protocol type
171: * is not supported.
172: * @exception IOException If some other kind of I/O error occurs.
173: * @exception SecurityException May be thrown if access to the
174: * protocol handler is prohibited.
175: */
176: public static Connection open(String name) throws IOException {
177: return open(name, READ_WRITE);
178: }
179:
180: /**
181: * Create and open a Connection.
182: *
183: * @param name The URL for the connection.
184: * @param mode The access mode.
185: * @return A new Connection object.
186: *
187: * @exception IllegalArgumentException If a parameter is invalid.
188: * @exception ConnectionNotFoundException If the target of the
189: * name cannot be found, or if the requested protocol type
190: * is not supported.
191: * @exception IOException If some other kind of I/O error occurs.
192: * @exception SecurityException May be thrown if access to the
193: * protocol handler is prohibited.
194: */
195: public static Connection open(String name, int mode)
196: throws IOException {
197: return open(name, mode, false);
198: }
199:
200: /**
201: * Create and open a Connection.
202: *
203: * @param name The URL for the connection
204: * @param mode The access mode
205: * @param timeouts A flag to indicate that the caller
206: * wants timeout exceptions
207: * @return A new Connection object
208: *
209: * @exception IllegalArgumentException If a parameter is invalid.
210: * @exception ConnectionNotFoundException If the target of the
211: * name cannot be found, or if the requested protocol type
212: * is not supported.
213: * @exception IOException If some other kind of I/O error occurs.
214: * @exception SecurityException May be thrown if access to the
215: * protocol handler is prohibited.
216: */
217: public static Connection open(String name, int mode,
218: boolean timeouts) throws IOException {
219: try {
220: return openPrim(name, mode, timeouts);
221: } catch (ClassNotFoundException x) {
222: }
223:
224: throw new ConnectionNotFoundException(
225: /* #ifdef VERBOSE_EXCEPTIONS */
226: /// skipped "The requested protocol does not exist "+name
227: /* #endif */
228: );
229: }
230:
231: /**
232: * Create and open a Connection.
233: *
234: * @param string The URL for the connection
235: * @param mode The access mode
236: * @param timeouts A flag to indicate that the caller
237: * wants timeout exceptions
238: * @return A new Connection object
239: *
240: * @exception ClassNotFoundException If the protocol cannot be found.
241: * @exception IllegalArgumentException If a parameter is invalid.
242: * @exception ConnectionNotFoundException If the target of the
243: * name cannot be found, or if the requested protocol type
244: * is not supported.
245: * @exception IOException If some other kind of I/O error occurs.
246: * @exception IllegalArgumentException If a parameter is invalid.
247: */
248: private static Connection openPrim(String name, int mode,
249: boolean timeouts) throws IOException,
250: ClassNotFoundException {
251:
252: /* Test for null argument */
253: if (name == null) {
254: throw new IllegalArgumentException(
255: /* #ifdef VERBOSE_EXCEPTIONS */
256: /// skipped "Null URL"
257: /* #endif */
258: );
259: }
260:
261: /* Look for : as in "http:", "file:", or whatever */
262: int colon = name.indexOf(':');
263:
264: /* Test for null argument */
265: if (colon < 1) {
266: throw new IllegalArgumentException(
267: /* #ifdef VERBOSE_EXCEPTIONS */
268: /// skipped "no ':' in URL"
269: /* #endif */
270: );
271: }
272:
273: try {
274: String protocol;
275:
276: /* Strip off the protocol name */
277: protocol = name.substring(0, colon);
278:
279: /* sanity check the protocol name */
280: char[] chars = protocol.toCharArray();
281: for (int i = 0; i < chars.length; ++i) {
282: char c = chars[i];
283: /* only allow characters that are valid in RFC 2396
284: alpha *( alpha | digit | "+" | "-" | "." )
285: */
286: if (('A' <= c && c <= 'Z')
287: || ('a' <= c && c <= 'z')
288: || ((i > 0) && (('0' <= c && c <= '9')
289: || c == '+' || c == '-' || c == '.'))) {
290: continue;
291: }
292: throw new IllegalArgumentException(
293: "Invalid protocol name");
294: }
295:
296: /* Strip off the rest of the string */
297: name = name.substring(colon + 1);
298:
299: /* Convert all the '-' characters in the protocol */
300: /* name to '_' characters (dashes are not allowed */
301: /* in class names). This operation creates garbage */
302: /* only if the protocol name actually contains dashes */
303: protocol = protocol.replace('-', '_');
304:
305: /* Use the platform and protocol names to look up */
306: /* a class to implement the connection */
307: Class clazz = Class.forName(classRoot + "." + platform
308: + "." + protocol + ".Protocol");
309:
310: /* Construct a new instance of the protocol */
311: ConnectionBaseInterface uc = (ConnectionBaseInterface) clazz
312: .newInstance();
313:
314: /* Open the connection, and return it */
315: return uc.openPrim(name, mode, timeouts);
316:
317: } catch (InstantiationException x) {
318: throw new IOException(
319: /* #ifdef VERBOSE_EXCEPTIONS */
320: /// skipped x.toString()
321: /* #endif */
322: );
323: } catch (IllegalAccessException x) {
324: throw new IOException(
325: /* #ifdef VERBOSE_EXCEPTIONS */
326: /// skipped x.toString()
327: /* #endif */
328: );
329: } catch (ClassCastException x) {
330: throw new IOException(
331: /* #ifdef VERBOSE_EXCEPTIONS */
332: /// skipped x.toString()
333: /* #endif */
334: );
335: }
336: }
337:
338: /**
339: * Create and open a connection input stream.
340: *
341: * @param name The URL for the connection.
342: * @return A DataInputStream.
343: *
344: * @exception IllegalArgumentException If a parameter is invalid.
345: * @exception ConnectionNotFoundException If the target of the
346: * name cannot be found, or if the requested protocol type
347: * is not supported.
348: * @exception IOException If some other kind of I/O error occurs.
349: * @exception SecurityException May be thrown if access to the
350: * protocol handler is prohibited.
351: */
352: public static DataInputStream openDataInputStream(String name)
353: throws IOException {
354:
355: InputConnection con = null;
356: try {
357: con = (InputConnection) Connector
358: .open(name, Connector.READ);
359: } catch (ClassCastException e) {
360: throw new IOException(
361: /* #ifdef VERBOSE_EXCEPTIONS */
362: /// skipped e.toString()
363: /* #endif */
364: );
365: }
366:
367: try {
368: return con.openDataInputStream();
369: } finally {
370: con.close();
371: }
372: }
373:
374: /**
375: * Create and open a connection output stream.
376: *
377: * @param name The URL for the connection.
378: * @return A DataOutputStream.
379: *
380: * @exception IllegalArgumentException If a parameter is invalid.
381: * @exception ConnectionNotFoundException If the target of the
382: * name cannot be found, or if the requested protocol type
383: * is not supported.
384: * @exception IOException If some other kind of I/O error occurs.
385: * @exception SecurityException May be thrown if access to the
386: * protocol handler is prohibited.
387: */
388: public static DataOutputStream openDataOutputStream(String name)
389: throws IOException {
390:
391: OutputConnection con = null;
392: try {
393: con = (OutputConnection) Connector.open(name,
394: Connector.WRITE);
395: } catch (ClassCastException e) {
396: throw new IOException(
397: /* #ifdef VERBOSE_EXCEPTIONS */
398: /// skipped e.toString()
399: /* #endif */
400: );
401: }
402:
403: try {
404: return con.openDataOutputStream();
405: } finally {
406: con.close();
407: }
408: }
409:
410: /**
411: * Create and open a connection input stream.
412: *
413: * @param name The URL for the connection.
414: * @return An InputStream.
415: *
416: * @exception IllegalArgumentException If a parameter is invalid.
417: * @exception ConnectionNotFoundException If the target of the
418: * name cannot be found, or if the requested protocol type
419: * is not supported.
420: * @exception IOException If some other kind of I/O error occurs.
421: * @exception SecurityException May be thrown if access to the
422: * protocol handler is prohibited.
423: */
424: public static InputStream openInputStream(String name)
425: throws IOException {
426:
427: return openDataInputStream(name);
428: }
429:
430: /**
431: * Create and open a connection output stream.
432: *
433: * @param name The URL for the connection.
434: * @return An OutputStream.
435: *
436: * @exception IllegalArgumentException If a parameter is invalid.
437: * @exception ConnectionNotFoundException If the target of the
438: * name cannot be found, or if the requested protocol type
439: * is not supported.
440: * @exception IOException If some other kind of I/O error occurs.
441: * @exception SecurityException May be thrown if access to the
442: * protocol handler is prohibited.
443: */
444: public static OutputStream openOutputStream(String name)
445: throws IOException {
446:
447: return openDataOutputStream(name);
448: }
449:
450: }
|