View Javadoc

1   /**
2    *  BlueCove - Java library for Bluetooth
3    *  Copyright (C) 2004 Intel Corporation
4    *  Copyright (C) 2006-2008 Vlad Skarzhevskyy
5    *
6    *  Licensed to the Apache Software Foundation (ASF) under one
7    *  or more contributor license agreements.  See the NOTICE file
8    *  distributed with this work for additional information
9    *  regarding copyright ownership.  The ASF licenses this file
10   *  to you under the Apache License, Version 2.0 (the
11   *  "License"); you may not use this file except in compliance
12   *  with the License.  You may obtain a copy of the License at
13   *
14   *    http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing,
17   *  software distributed under the License is distributed on an
18   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19   *  KIND, either express or implied.  See the License for the
20   *  specific language governing permissions and limitations
21   *  under the License.
22   *
23   *  @version $Id: MicroeditionConnector.java 2523 2008-12-09 01:09:17Z skarzhevskyy $
24   */
25  package com.intel.bluetooth;
26  
27  import java.io.DataInputStream;
28  import java.io.DataOutputStream;
29  import java.io.IOException;
30  import java.io.InputStream;
31  import java.io.OutputStream;
32  import java.util.Enumeration;
33  import java.util.Hashtable;
34  
35  import javax.bluetooth.BluetoothConnectionException;
36  import javax.bluetooth.L2CAPConnection;
37  import javax.bluetooth.UUID;
38  import javax.microedition.io.Connection;
39  import javax.microedition.io.ConnectionNotFoundException;
40  import javax.microedition.io.Connector;
41  import javax.microedition.io.InputConnection;
42  import javax.microedition.io.OutputConnection;
43  
44  import com.intel.bluetooth.gcf.socket.ServerSocketConnection;
45  import com.intel.bluetooth.gcf.socket.SocketConnection;
46  import com.intel.bluetooth.obex.OBEXClientSessionImpl;
47  import com.intel.bluetooth.obex.OBEXConnectionParams;
48  import com.intel.bluetooth.obex.OBEXSessionNotifierImpl;
49  
50  /**
51   * 
52   * Implementation of javax.microedition.io.Connector
53   * <p>
54   * <b><u>Your application should not use this class directly.</u></b>
55   * <p>
56   * BlueCove specific JSR-82 extension <tt>bluecovepsm</tt> enables the use of specific PSM channel in L2CAP service.
57   * <tt>btl2cap://localhost;name=...;bluecovepsm=1007</tt>
58   */
59  public abstract class MicroeditionConnector {
60  	/*
61  	 * Access mode READ. The value 1 is assigned to READ.
62  	 */
63  
64  	public static final int READ = Connector.READ;
65  
66  	/*
67  	 * Access mode WRITE. The value 2 is assigned to WRITE.
68  	 */
69  
70  	public static final int WRITE = Connector.WRITE;
71  
72  	/*
73  	 * Access mode READ_WRITE. The value 3 is assigned to READ_WRITE.
74  	 */
75  
76  	public static final int READ_WRITE = Connector.READ_WRITE;
77  
78  	private static Hashtable/* <String, String> */suportScheme = new Hashtable();
79  
80  	private static Hashtable/* <String, String> */srvParams = new Hashtable();
81  
82  	private static Hashtable/* <String, String> */cliParams = new Hashtable();
83  
84  	private static Hashtable/* <String, String> */cliParamsL2CAP = new Hashtable();
85  
86  	private static Hashtable/* <String, String> */srvParamsL2CAP = new Hashtable();
87  
88  	private static final String AUTHENTICATE = "authenticate";
89  
90  	private static final String AUTHORIZE = "authorize";
91  
92  	private static final String ENCRYPT = "encrypt";
93  
94  	private static final String MASTER = "master";
95  
96  	private static final String NAME = "name";
97  
98  	private static final String RECEIVE_MTU = "receivemtu";
99  
100 	private static final String TRANSMIT_MTU = "transmitmtu";
101 
102 	private static final String EXT_BLUECOVE_L2CAP_PSM = "bluecovepsm";
103 
104 	static {
105 		// cliParams ::== master | encrypt | authenticate
106 		cliParams.put(AUTHENTICATE, AUTHENTICATE);
107 		cliParams.put(ENCRYPT, ENCRYPT);
108 		cliParams.put(MASTER, MASTER);
109 
110 		// srvParams ::== name | master | encrypt | authorize | authenticate
111 		copyAll(srvParams, cliParams);
112 		srvParams.put(AUTHORIZE, AUTHORIZE);
113 		srvParams.put(NAME, NAME);
114 
115 		copyAll(cliParamsL2CAP, cliParams);
116 
117 		cliParamsL2CAP.put(RECEIVE_MTU, RECEIVE_MTU);
118 		cliParamsL2CAP.put(TRANSMIT_MTU, TRANSMIT_MTU);
119 
120 		copyAll(srvParamsL2CAP, cliParamsL2CAP);
121 		srvParamsL2CAP.put(AUTHORIZE, AUTHORIZE);
122 		srvParamsL2CAP.put(NAME, NAME);
123 		srvParamsL2CAP.put(EXT_BLUECOVE_L2CAP_PSM, EXT_BLUECOVE_L2CAP_PSM);
124 
125 		// "socket://" host ":" port
126 		// no validation for socket, since this is internal connector
127 
128 		suportScheme.put(BluetoothConsts.PROTOCOL_SCHEME_RFCOMM, Boolean.TRUE);
129 		suportScheme.put(BluetoothConsts.PROTOCOL_SCHEME_BT_OBEX, Boolean.TRUE);
130 		suportScheme.put(BluetoothConsts.PROTOCOL_SCHEME_TCP_OBEX, Boolean.TRUE);
131 		suportScheme.put(BluetoothConsts.PROTOCOL_SCHEME_L2CAP, Boolean.TRUE);
132 		suportScheme.put("socket", Boolean.TRUE);
133 	}
134 
135 	private MicroeditionConnector() {
136 
137 	}
138 
139 	static void copyAll(Hashtable dest, Hashtable src) {
140 		for (Enumeration en = src.keys(); en.hasMoreElements();) {
141 			Object key = en.nextElement();
142 			dest.put(key, src.get(key));
143 		}
144 	}
145 
146 	static String validParamName(Hashtable map, String paramName) {
147 		String validName = (String) map.get(paramName.toLowerCase());
148 		if (validName != null) {
149 			return validName;
150 		}
151 		return null;
152 	}
153 
154 	/*
155 	 * Create and open a Connection. Parameters: name - The URL for the connection. Returns: A new Connection object.
156 	 * Throws: IllegalArgumentException - If a parameter is invalid. ConnectionNotFoundException - If the requested
157 	 * connection cannot be made, or the protocol type does not exist. java.io.IOException - If some other kind of I/O
158 	 * error occurs. SecurityException - If a requested protocol handler is not permitted.
159 	 */
160 
161 	public static Connection open(String name) throws IOException {
162 		return openImpl(name, READ_WRITE, false, true);
163 	}
164 
165 	private static Connection openImpl(String name, int mode, boolean timeouts, boolean allowServer) throws IOException {
166 
167 		DebugLog.debug("connecting", name);
168 
169 		/*
170 		 * parse URL
171 		 */
172 
173 		String host = null;
174 		String portORuuid = null;
175 
176 		Hashtable values = new Hashtable();
177 
178 		// scheme : // host : port [;param=val]
179 		int schemeEnd = name.indexOf("://");
180 		if (schemeEnd == -1) {
181 			throw new ConnectionNotFoundException(name);
182 		}
183 		String scheme = name.substring(0, schemeEnd);
184 		if (!suportScheme.containsKey(scheme)) {
185 			throw new ConnectionNotFoundException(scheme);
186 		}
187 		boolean schemeBluetooth = (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_RFCOMM))
188 				|| (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_BT_OBEX) || (scheme
189 						.equals(BluetoothConsts.PROTOCOL_SCHEME_L2CAP)));
190 		boolean isL2CAP = scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_L2CAP);
191 		boolean isTCPOBEX = scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_TCP_OBEX);
192 
193 		BluetoothStack bluetoothStack = null;
194 
195 		if (schemeBluetooth) {
196 			bluetoothStack = BlueCoveImpl.instance().getBluetoothStack();
197 		}
198 
199 		boolean isServer;
200 
201 		int hostEnd = name.indexOf(':', scheme.length() + 3);
202 
203 		if (hostEnd > -1) {
204 			host = name.substring(scheme.length() + 3, hostEnd);
205 			isServer = host.equals("localhost");
206 
207 			Hashtable params;
208 			if (isTCPOBEX) {
209 				params = new Hashtable();
210 				isServer = (host.length() == 0);
211 			} else if (isL2CAP) {
212 				if (isServer) {
213 					params = srvParamsL2CAP;
214 				} else {
215 					params = cliParamsL2CAP;
216 				}
217 			} else {
218 				if (isServer) {
219 					params = srvParams;
220 				} else {
221 					params = cliParams;
222 				}
223 			}
224 
225 			String paramsStr = name.substring(hostEnd + 1);
226 			UtilsStringTokenizer tok = new UtilsStringTokenizer(paramsStr, ";");
227 			if (tok.hasMoreTokens()) {
228 				portORuuid = tok.nextToken();
229 			} else {
230 				portORuuid = paramsStr;
231 			}
232 			while (tok.hasMoreTokens()) {
233 				String t = tok.nextToken();
234 				int equals = t.indexOf('=');
235 				if (equals > -1) {
236 					String param = t.substring(0, equals);
237 					String value = t.substring(equals + 1);
238 					String validName = validParamName(params, param);
239 					if (validName != null) {
240 						String hasValue = (String) values.get(validName);
241 						if ((hasValue != null) && (!hasValue.equals(value))) {
242 							throw new IllegalArgumentException("duplicate param [" + param + "] value [" + value + "]");
243 						}
244 						values.put(validName, value);
245 					} else {
246 						throw new IllegalArgumentException("invalid param [" + param + "] value [" + value + "]");
247 					}
248 				} else {
249 					throw new IllegalArgumentException("invalid param [" + t + "]");
250 				}
251 			}
252 		} else if (isTCPOBEX) {
253 			host = name.substring(scheme.length() + 3);
254 			isServer = (host.length() == 0);
255 		} else {
256 			throw new IllegalArgumentException(name.substring(scheme.length() + 3));
257 		}
258 
259 		if (isTCPOBEX) {
260 			if ((portORuuid == null) || (portORuuid.length() == 0)) {
261 				portORuuid = String.valueOf(BluetoothConsts.TCP_OBEX_DEFAULT_PORT);
262 			}
263 			// else {
264 			// try {
265 			// int port = Integer.parseInt(portORuuid);
266 			// if ((port < 1023) && (port !=
267 			// BluetoothConsts.TCP_OBEX_DEFAULT_PORT)) {
268 			// throw new IllegalArgumentException("Port " + portORuuid + " can't
269 			// be used; the 0-1023 range is reserved");
270 			// }
271 			// } catch (NumberFormatException e) {
272 			// throw new IllegalArgumentException("port " + portORuuid);
273 			// }
274 			// }
275 		}
276 
277 		if (host == null || portORuuid == null) {
278 			throw new IllegalArgumentException();
279 		}
280 
281 		BluetoothConnectionNotifierParams notifierParams = null;
282 
283 		BluetoothConnectionParams connectionParams = null;
284 
285 		int channel = 0;
286 		if (isServer) {
287 			if (!allowServer) {
288 				throw new IllegalArgumentException("Can't use server connection URL");
289 			}
290 			if (values.get(NAME) == null) {
291 				values.put(NAME, "BlueCove");
292 			} else if (schemeBluetooth) {
293 				validateBluetoothServiceName((String) values.get(NAME));
294 			}
295 			if (schemeBluetooth) {
296 				notifierParams = new BluetoothConnectionNotifierParams(new UUID(portORuuid, false), paramBoolean(
297 						values, AUTHENTICATE), paramBoolean(values, ENCRYPT), paramBoolean(values, AUTHORIZE),
298 						(String) values.get(NAME), paramBoolean(values, MASTER));
299 				notifierParams.timeouts = timeouts;
300 				if (notifierParams.encrypt && (!notifierParams.authenticate)) {
301 					if (values.get(AUTHENTICATE) == null) {
302 						notifierParams.authenticate = true;
303 					} else {
304 						throw new BluetoothConnectionException(BluetoothConnectionException.UNACCEPTABLE_PARAMS,
305 								"encryption requires authentication");
306 					}
307 				}
308 				if (notifierParams.authorize && (!notifierParams.authenticate)) {
309 					if (values.get(AUTHENTICATE) == null) {
310 						notifierParams.authenticate = true;
311 					} else {
312 						throw new BluetoothConnectionException(BluetoothConnectionException.UNACCEPTABLE_PARAMS,
313 								"authorization requires authentication");
314 					}
315 				}
316 				if (isL2CAP) {
317 					String bluecove_ext_psm = (String) values.get(EXT_BLUECOVE_L2CAP_PSM);
318 					if (bluecove_ext_psm != null) {
319 						int psm = Integer.parseInt(bluecove_ext_psm, 16);
320 						validateL2CAPPSM(psm, bluecove_ext_psm);
321 						notifierParams.bluecove_ext_psm = psm;
322 					}
323 				}
324 			}
325 		} else { // (!isServer)
326 			try {
327 				channel = Integer.parseInt(portORuuid, isL2CAP ? 16 : 10);
328 			} catch (NumberFormatException e) {
329 				throw new IllegalArgumentException("channel " + portORuuid);
330 			}
331 			if (channel < 0) {
332 				throw new IllegalArgumentException("channel " + portORuuid);
333 			}
334 			if (schemeBluetooth) {
335 				if (isL2CAP) {
336 					validateL2CAPPSM(channel, portORuuid);
337 				} else {
338 					if ((channel < BluetoothConsts.RFCOMM_CHANNEL_MIN)
339 							|| (channel > BluetoothConsts.RFCOMM_CHANNEL_MAX)) {
340 						throw new IllegalArgumentException("RFCOMM channel " + portORuuid);
341 					}
342 				}
343 
344 				connectionParams = new BluetoothConnectionParams(RemoteDeviceHelper.getAddress(host), channel,
345 						paramBoolean(values, AUTHENTICATE), paramBoolean(values, ENCRYPT));
346 				connectionParams.timeouts = timeouts;
347 				if (connectionParams.encrypt && (!connectionParams.authenticate)) {
348 					if (values.get(AUTHENTICATE) == null) {
349 						connectionParams.authenticate = true;
350 					} else {
351 						throw new BluetoothConnectionException(BluetoothConnectionException.UNACCEPTABLE_PARAMS,
352 								"encryption requires authentication");
353 					}
354 				}
355 				connectionParams.timeout = BlueCoveImpl.getConfigProperty(
356 						BlueCoveConfigProperties.PROPERTY_CONNECT_TIMEOUT,
357 						BluetoothConnectionParams.DEFAULT_CONNECT_TIMEOUT);
358 			}
359 		}
360 		OBEXConnectionParams obexConnectionParams = null;
361 
362 		if (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_TCP_OBEX)
363 				|| scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_BT_OBEX)) {
364 			obexConnectionParams = new OBEXConnectionParams();
365 			obexConnectionParams.timeouts = timeouts;
366 			obexConnectionParams.timeout = BlueCoveImpl.getConfigProperty(
367 					BlueCoveConfigProperties.PROPERTY_OBEX_TIMEOUT, OBEXConnectionParams.DEFAULT_TIMEOUT);
368 			obexConnectionParams.mtu = BlueCoveImpl.getConfigProperty(BlueCoveConfigProperties.PROPERTY_OBEX_MTU,
369 					OBEXConnectionParams.OBEX_DEFAULT_MTU);
370 		}
371 
372 		/*
373 		 * create connection
374 		 */
375 		if (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_RFCOMM)) {
376 			if (isServer) {
377 				return new BluetoothRFCommConnectionNotifier(bluetoothStack, notifierParams);
378 			} else {
379 				return new BluetoothRFCommClientConnection(bluetoothStack, connectionParams);
380 			}
381 		} else if (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_BT_OBEX)) {
382 			if (isServer) {
383 				notifierParams.obex = true;
384 				return new OBEXSessionNotifierImpl(
385 						new BluetoothRFCommConnectionNotifier(bluetoothStack, notifierParams), obexConnectionParams);
386 			} else {
387 				return new OBEXClientSessionImpl(new BluetoothRFCommClientConnection(bluetoothStack, connectionParams),
388 						obexConnectionParams);
389 			}
390 		} else if (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_L2CAP)) {
391 			if (isServer) {
392 				return new BluetoothL2CAPConnectionNotifier(bluetoothStack, notifierParams, paramL2CAPMTU(values,
393 						RECEIVE_MTU), paramL2CAPMTU(values, TRANSMIT_MTU));
394 			} else {
395 				return new BluetoothL2CAPClientConnection(bluetoothStack, connectionParams, paramL2CAPMTU(values,
396 						RECEIVE_MTU), paramL2CAPMTU(values, TRANSMIT_MTU));
397 			}
398 		} else if (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_TCP_OBEX)) {
399 			if (isServer) {
400 				try {
401 					channel = Integer.parseInt(portORuuid);
402 				} catch (NumberFormatException e) {
403 					throw new IllegalArgumentException("port " + portORuuid);
404 				}
405 				return new OBEXSessionNotifierImpl(new ServerSocketConnection(channel), obexConnectionParams);
406 			} else {
407 				return new OBEXClientSessionImpl(new SocketConnection(host, channel), obexConnectionParams);
408 			}
409 		} else if (scheme.equals("socket")) {
410 			if (isServer) {
411 				try {
412 					channel = Integer.parseInt(portORuuid);
413 				} catch (NumberFormatException e) {
414 					throw new IllegalArgumentException("port " + portORuuid);
415 				}
416 				return new ServerSocketConnection(channel);
417 			} else {
418 				return new SocketConnection(host, channel);
419 			}
420 		} else {
421 			throw new ConnectionNotFoundException("scheme [" + scheme + "]");
422 		}
423 	}
424 
425 	private static void validateL2CAPPSM(int channel, String channelAsString) throws IllegalArgumentException {
426 		// Valid PSM range: 0x0001-0x0019 (0x1001-0xFFFF dynamically
427 		// assigned, 0x0019-0x0100 reserved for future use).
428 		if ((channel < BluetoothConsts.L2CAP_PSM_MIN) || (channel > BluetoothConsts.L2CAP_PSM_MAX)) {
429 			// PSM 1 discovery, 3 RFCOMM
430 			throw new IllegalArgumentException("PCM " + channelAsString);
431 		}
432 		if ((channel < BluetoothConsts.L2CAP_PSM_MIN_JSR_82)
433 				&& (!BlueCoveImpl.getConfigProperty(BlueCoveConfigProperties.PROPERTY_JSR_82_PSM_MINIMUM_OFF, false))) {
434 			throw new IllegalArgumentException("PCM values restricted by JAR82 to minimum "
435 					+ BluetoothConsts.L2CAP_PSM_MIN_JSR_82);
436 		}
437 
438 		// has the 9th bit (0x100) set to zero
439 		if ((channel & 0x100) != 0) {
440 			throw new IllegalArgumentException("9th bit set in PCM " + channelAsString);
441 		}
442 		// The least significant byte must be odd
443 		byte lsByte = (byte) (0xFF & channel);
444 		if ((lsByte % 2) == 0) {
445 			throw new IllegalArgumentException("PSM value " + channelAsString + " least significant byte must be odd");
446 		}
447 		byte msByte = (byte) ((0xFF00 & channel) >> 8);
448 		if ((msByte % 2) == 1) {
449 			throw new IllegalArgumentException("PSM value " + channelAsString + " most significant byte must be even");
450 		}
451 	}
452 
453 	private static void validateBluetoothServiceName(String serviceName) {
454 		if (serviceName.length() == 0) {
455 			throw new IllegalArgumentException("zero length service name");
456 		}
457 		final String allowNameCharactes = " -_";
458 		for (int i = 0; i < serviceName.length(); i++) {
459 			char c = serviceName.charAt(i);
460 			if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')
461 					|| allowNameCharactes.indexOf(c) != -1) {
462 				continue;
463 			}
464 			throw new IllegalArgumentException("Illegal character '" + c + "' in service name");
465 		}
466 	}
467 
468 	private static boolean paramBoolean(Hashtable values, String name) {
469 		String v = (String) values.get(name);
470 		if (v == null) {
471 			return false;
472 		} else if ("true".equals(v)) {
473 			return true;
474 		} else if ("false".equals(v)) {
475 			return false;
476 		} else {
477 			throw new IllegalArgumentException("invalid param value " + name + "=" + v);
478 		}
479 	}
480 
481 	private static int paramL2CAPMTU(Hashtable values, String name) {
482 		String v = (String) values.get(name);
483 		if (v == null) {
484 			if (name.equals(TRANSMIT_MTU)) {
485 				// This will select RemoteMtu
486 				return -1;
487 			} else {
488 				return L2CAPConnection.DEFAULT_MTU;
489 			}
490 		}
491 		try {
492 			int mtu = Integer.parseInt(v);
493 			if (mtu >= L2CAPConnection.MINIMUM_MTU) {
494 				return mtu;
495 			}
496 			if ((mtu > 0) && (mtu < L2CAPConnection.MINIMUM_MTU) && (name.equals(TRANSMIT_MTU))) {
497 				return L2CAPConnection.MINIMUM_MTU;
498 			}
499 		} catch (NumberFormatException e) {
500 			throw new IllegalArgumentException("invalid MTU value " + v);
501 		}
502 		throw new IllegalArgumentException("invalid MTU param value " + name + "=" + v);
503 	}
504 
505 	/*
506 	 * Create and open a Connection. Parameters: name - The URL for the connection. mode - The access mode. Returns: A
507 	 * new Connection object. Throws: IllegalArgumentException - If a parameter is invalid. ConnectionNotFoundException
508 	 * - If the requested connection cannot be made, or the protocol type does not exist. java.io.IOException - If some
509 	 * other kind of I/O error occurs. SecurityException - If a requested protocol handler is not permitted.
510 	 */
511 
512 	public static Connection open(String name, int mode) throws IOException {
513 		return openImpl(name, mode, false, true);
514 	}
515 
516 	/*
517 	 * Create and open a Connection. Parameters: name - The URL for the connection mode - The access mode timeouts - A
518 	 * flag to indicate that the caller wants timeout exceptions Returns: A new Connection object Throws:
519 	 * IllegalArgumentException - If a parameter is invalid. ConnectionNotFoundException - if the requested connection
520 	 * cannot be made, or the protocol type does not exist. java.io.IOException - If some other kind of I/O error
521 	 * occurs. SecurityException - If a requested protocol handler is not permitted.
522 	 */
523 
524 	public static Connection open(String name, int mode, boolean timeouts) throws IOException {
525 		return openImpl(name, mode, timeouts, true);
526 	}
527 
528 	/*
529 	 * Create and open a connection input stream. Parameters: name - The URL for the connection. Returns: A
530 	 * DataInputStream. Throws: IllegalArgumentException - If a parameter is invalid. ConnectionNotFoundException - If
531 	 * the connection cannot be found. java.io.IOException - If some other kind of I/O error occurs. SecurityException -
532 	 * If access to the requested stream is not permitted.
533 	 */
534 
535 	public static DataInputStream openDataInputStream(String name) throws IOException {
536 		return new DataInputStream(openInputStream(name));
537 	}
538 
539 	/*
540 	 * Create and open a connection output stream. Parameters: name - The URL for the connection. Returns: A
541 	 * DataOutputStream. Throws: IllegalArgumentException - If a parameter is invalid. ConnectionNotFoundException - If
542 	 * the connection cannot be found. java.io.IOException - If some other kind of I/O error occurs. SecurityException -
543 	 * If access to the requested stream is not permitted.
544 	 */
545 
546 	public static DataOutputStream openDataOutputStream(String name) throws IOException {
547 		return new DataOutputStream(openOutputStream(name));
548 	}
549 
550 	/*
551 	 * Create and open a connection input stream. Parameters: name - The URL for the connection. Returns: An
552 	 * InputStream. Throws: IllegalArgumentException - If a parameter is invalid. ConnectionNotFoundException - If the
553 	 * connection cannot be found. java.io.IOException - If some other kind of I/O error occurs. SecurityException - If
554 	 * access to the requested stream is not permitted.
555 	 */
556 
557 	public static InputStream openInputStream(String name) throws IOException {
558 		InputConnection con = ((InputConnection) openImpl(name, READ, false, false));
559 		try {
560 			return con.openInputStream();
561 		} finally {
562 			con.close();
563 		}
564 	}
565 
566 	/*
567 	 * Create and open a connection output stream. Parameters: name - The URL for the connection. Returns: An
568 	 * OutputStream. Throws: IllegalArgumentException - If a parameter is invalid. ConnectionNotFoundException - If the
569 	 * connection cannot be found. java.io.IOException - If some other kind of I/O error occurs. SecurityException - If
570 	 * access to the requested stream is not permitted.
571 	 */
572 
573 	public static OutputStream openOutputStream(String name) throws IOException {
574 		OutputConnection con = ((OutputConnection) openImpl(name, WRITE, false, false));
575 		try {
576 			return con.openOutputStream();
577 		} finally {
578 			con.close();
579 		}
580 	}
581 
582 }