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 javax.microedition.io.Connection;
030: import javax.bluetooth.ServiceRecord;
031: import javax.bluetooth.ServiceRegistrationException;
032: import javax.bluetooth.DataElement;
033: import com.sun.midp.io.BluetoothUrl;
034: import java.util.Enumeration;
035:
036: /**
037: * Base class for all bluetooth notifiers.
038: */
039: public abstract class BluetoothNotifier implements Connection {
040:
041: /** Flag to identify if this notifier is closed. */
042: protected boolean isClosed = false;
043:
044: /** Bluetooth url this notifier created with. */
045: protected BluetoothUrl url;
046:
047: /** Service record that describes represented service. */
048: protected ServiceRecordImpl serviceRec = null;
049:
050: /** Keeps open mode. */
051: protected int mode;
052:
053: /**
054: * Class constructor.
055: *
056: * @param url server connection string this notifier was created with
057: * @param mode I/O access mode
058: */
059: protected BluetoothNotifier(BluetoothUrl url, int mode) {
060: // IMPL_NOTE: find proper place; the intent here is to start EmulationPolling
061: // and SDPServer prior to create a user's notifier
062: SDDB.getInstance();
063: this .url = url;
064: this .mode = mode;
065: }
066:
067: /**
068: * Retrieves service record for this notifier.
069: * It always returns the same object reference.
070: *
071: * @return service record associated with this notifier
072: * @throws IllegalArgumentException if the notifier is closed
073: */
074: ServiceRecord getServiceRecord() {
075: if (isClosed) {
076: throw new IllegalArgumentException("Notifier is closed.");
077: }
078: // IMPL_NOTE: copy should probably be returned instead of a reference,
079: // but the current implementation returns reference to make TCK pass
080: // return serviceRec.copy();
081: return serviceRec;
082: }
083:
084: /**
085: * Stores the service record for this notifier in the local SDDB.
086: * If there is no SDDB version of the service record, this method will
087: * do nothing.
088: *
089: * @param record new service record value
090: * @throws IllegalArgumentException if new record is invalid
091: *
092: * @throws ServiceRegistrationException if the record cannot be
093: * updated successfully in the SDDB
094: */
095: protected void updateServiceRecord(ServiceRecordImpl record)
096: throws ServiceRegistrationException {
097: // IMPL_NOTE: the current implementation assumes record and
098: // this.serviceRec reference the same object to make TCK pass
099: // ServiceRecordImpl oldRecord = serviceRec;
100: // serviceRec = record.copy();
101: try {
102: checkServiceRecord();
103: } catch (ServiceRegistrationException e) {
104: // serviceRec = oldRecord;
105: throw new IllegalArgumentException(e.getMessage());
106: }
107: if (SDDB.getInstance().contains(serviceRec)) {
108: SDDB.getInstance().updateServiceRecord(serviceRec);
109: }
110: }
111:
112: /**
113: * Ensures that the service record is valid.
114: *
115: * @throws ServiceRegistrationException if the structure of the
116: * <code>srvRecord</code> is missing any mandatory service
117: * attributes, or if an attempt has been made to change any of the
118: * values described as fixed
119: */
120: protected abstract void checkServiceRecord()
121: throws ServiceRegistrationException;
122:
123: /**
124: * Compares two DataElements.
125: *
126: * @param first first DataElement
127: * @param second second DataElement
128: * @return true if elements are equal, false otherwise
129: * @see javax.bluetooth.DataElement
130: */
131: protected boolean compareDataElements(DataElement first,
132: DataElement second) {
133: boolean ret = false;
134: int valueType = first.getDataType();
135: if (ret = (valueType == second.getDataType())) {
136: switch (valueType) {
137: case DataElement.BOOL:
138: ret = first.getBoolean() == second.getBoolean();
139: break;
140: case DataElement.U_INT_1:
141: case DataElement.U_INT_2:
142: case DataElement.U_INT_4:
143: case DataElement.INT_1:
144: case DataElement.INT_2:
145: case DataElement.INT_4:
146: case DataElement.INT_8:
147: ret = first.getLong() == second.getLong();
148: break;
149: default:
150: Object v1 = first.getValue();
151: Object v2 = second.getValue();
152: if (v1 instanceof Enumeration
153: && v2 instanceof Enumeration) {
154: Enumeration e1 = (Enumeration) v1;
155: Enumeration e2 = (Enumeration) v2;
156: ret = true;
157: while (e1.hasMoreElements() && e2.hasMoreElements()
158: && ret) {
159: ret &= e1.nextElement()
160: .equals(e2.nextElement());
161: }
162: ret = ret
163: && !(e1.hasMoreElements() || e2
164: .hasMoreElements());
165: } else if (v1 instanceof byte[] && v2 instanceof byte[]) {
166: byte[] a1 = (byte[]) v1;
167: byte[] a2 = (byte[]) v2;
168: ret = a1.length == a2.length;
169: for (int i = a1.length; --i >= 0 && ret;) {
170: ret &= (a1[i] == a2[i]);
171: }
172: } else {
173: ret = v1.equals(v2);
174: }
175: break;
176: }
177: }
178: return ret;
179: }
180:
181: /**
182: * Closes the connection. <code>Connection</code> interface implementation.
183: *
184: * @throws IOException if an I/O error occurs
185: */
186: public abstract void close() throws IOException;
187: }
|