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: package com.sun.kvem.jsr082.bluetooth;
027:
028: import java.io.IOException;
029: import com.sun.midp.io.BluetoothUrl;
030: import com.sun.kvem.jsr082.obex.ObexPacketStream;
031: import com.sun.kvem.jsr082.obex.ObexTransport;
032:
033: import javax.bluetooth.RemoteDevice;
034: import javax.bluetooth.BluetoothConnectionException;
035: import javax.microedition.io.Connection;
036: import javax.microedition.io.Connector;
037:
038: /**
039: * Base class for all bluetooth connections.
040: */
041: abstract public class BluetoothConnection {
042:
043: /** Keeps requested connection details. */
044: protected BluetoothUrl url;
045:
046: /** Keeps open mode. */
047: protected int mode;
048:
049: /** true if this connection was authorized, false otherwise. */
050: private boolean authorized;
051:
052: /** true if this connection has requested encryption and is encrypted. */
053: private boolean encrypted;
054:
055: /** Remote device for this connection. */
056: private RemoteDevice remoteDevice;
057:
058: /**
059: * Retrieves <code>BluetoothConnection</code> from given one.
060: * Connection given is supposed to be either Bluetooth connection
061: * or a connection that uses Bluetooth as transport. All involved
062: * connections supposed to be open.
063: *
064: * @param conn the connection to extract Bluetooth connection from
065: * @return proper <code>BluetoothConnection</code> instance
066: * @throws IllegalArgumentException if connection is neither an instance
067: * of BluetoothConnection, nor uses one as transport.
068: * @throws IOException if connection given or transport is closed or
069: * transport is invalid.
070: */
071: public static BluetoothConnection getConnection(Connection conn)
072: throws IOException {
073: if (conn == null) {
074: throw new NullPointerException("Null connection specified.");
075: }
076:
077: if (conn instanceof ObexPacketStream) {
078: conn = ((ObexPacketStream) conn).getTransport();
079: }
080:
081: if (!(conn instanceof BluetoothConnection)) {
082: throw new IllegalArgumentException(
083: "The specified connection "
084: + "is not a Bluetooth connection.");
085: }
086:
087: BluetoothConnection btConn = (BluetoothConnection) conn;
088: btConn.checkOpen();
089: return btConn;
090: }
091:
092: /**
093: * Creates a new instance of this class.
094: *
095: * @param url connection url
096: * @param mode I/O access mode server side otherwise it's false
097: */
098: protected BluetoothConnection(BluetoothUrl url, int mode) {
099: // IMPL_NOTE: find proper place; the intent here is to start EmulationPolling
100: // and SDPServer prior to create a user's notifier
101: SDDB.getInstance();
102:
103: this .url = url;
104: this .mode = mode;
105: }
106:
107: /**
108: * Returns remote device for this connection.
109: *
110: * @return <code>RemoteDevice</code> object for this connection
111: * @throws IOException if this connection is closed
112: */
113: public RemoteDevice getRemoteDevice() throws IOException {
114: checkOpen();
115: return remoteDevice;
116: }
117:
118: /**
119: * Returns Bluetooth address of the remote device for this connection.
120: *
121: * @return Bluetooth address of the remote device
122: */
123: public abstract String getRemoteDeviceAddress();
124:
125: /**
126: * Retrieves reference to the remote device for this connection.
127: */
128: protected void setRemoteDevice() {
129: remoteDevice = DiscoveryAgentImpl.getInstance()
130: .getRemoteDevice(getRemoteDeviceAddress());
131: BCC.getInstance().addConnection(getRemoteDeviceAddress());
132: }
133:
134: /**
135: * Removes reference to the remote device.
136: */
137: protected void resetRemoteDevice() {
138: if (encrypted) {
139: encrypt(false);
140: }
141: remoteDevice = null;
142: BCC.getInstance().removeConnection(getRemoteDeviceAddress());
143: }
144:
145: /**
146: * Determines if this connection is closed.
147: *
148: * @return true if this connection is closed, false otherwise
149: */
150: public boolean isClosed() {
151: return remoteDevice == null;
152: }
153:
154: /**
155: * Determines whether this connection represents the server side,
156: * i.e. this connection was created by a notifier in acceptAndOpen().
157: *
158: * @return true if this connection is a server-side connection,
159: * false otherwise
160: */
161: public boolean isServerSide() {
162: return url.isServer;
163: }
164:
165: /**
166: * Returns the authorization state of this connection.
167: *
168: * @return true if this connection has been authorized, false otherwise
169: */
170: public boolean isAuthorized() {
171: return authorized;
172: }
173:
174: /**
175: * Authorizes this connection. It is assumed that the remote device has
176: * previously been authenticated. This connection must represent the server
177: * side, i.e. isServer() should return true.
178: *
179: * @return true if the operation succeeded, false otherwise
180: */
181: public boolean authorize() {
182: authorized = BCC.getInstance().authorize(
183: remoteDevice.getBluetoothAddress(),
184: getServiceRecordHandle());
185: return authorized;
186: }
187:
188: /**
189: * Changes encryption for this connection.
190: *
191: * @param enable specifies whether encription should be turned on or off
192: * @return true if encryption has been set as required, false otherwise
193: */
194: public boolean encrypt(boolean enable) {
195: if (enable == encrypted) {
196: return true;
197: }
198: BCC.getInstance().encrypt(remoteDevice.getBluetoothAddress(),
199: enable);
200: if (remoteDevice.isEncrypted()) {
201: if (enable) {
202: encrypted = true;
203: return true;
204: }
205: encrypted = false;
206: return false;
207: } else {
208: if (enable) {
209: return false;
210: }
211: encrypted = false;
212: return true;
213: }
214: }
215:
216: /**
217: * Returns handle for the service record of the service this connection
218: * is attached to. Valid for server-side (incoming) connections only.
219: *
220: * @return service record handle, or 0 if the handle is not available
221: */
222: protected int getServiceRecordHandle() {
223: return 0;
224: }
225:
226: /**
227: * Checks if this connection is open.
228: *
229: * @throws IOException if this connection is closed
230: */
231: protected void checkOpen() throws IOException {
232: if (isClosed()) {
233: throw new IOException("Connection is closed.");
234: }
235: }
236:
237: /**
238: * Performs security checks, such as authentication, authorization, and
239: * encryption setup.
240: *
241: * @throws BluetoothConnectionException when failed
242: */
243: protected void checkSecurity() throws BluetoothConnectionException,
244: IOException {
245: if (url.authenticate) {
246: if (!remoteDevice.authenticate()) {
247: throw new BluetoothConnectionException(
248: BluetoothConnectionException.SECURITY_BLOCK,
249: "Authentication failed.");
250: }
251: }
252: if (url.authorize) {
253: if (!remoteDevice.authorize((Connection) this )) {
254: throw new BluetoothConnectionException(
255: BluetoothConnectionException.SECURITY_BLOCK,
256: "Authorization failed.");
257: }
258: }
259: if (url.encrypt) {
260: if (!remoteDevice.encrypt((Connection) this , true)) {
261: throw new BluetoothConnectionException(
262: BluetoothConnectionException.SECURITY_BLOCK,
263: "Encryption failed.");
264: }
265: }
266: }
267:
268: /**
269: * Checks read access.
270: *
271: * @throws IOException if open mode does not permit read access
272: */
273: protected void checkReadMode() throws IOException {
274: if ((mode & Connector.READ) == 0) {
275: throw new IOException("Invalid mode: " + mode);
276: }
277: }
278:
279: /**
280: * Checks write access.
281: *
282: * @throws IOException if open mode does not permit write access
283: */
284: protected void checkWriteMode() throws IOException {
285: if ((mode & Connector.WRITE) == 0) {
286: throw new IOException("Invalid mode: " + mode);
287: }
288: }
289:
290: }
|