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 com.sun.midp.jsr082.bluetooth;
028:
029: import java.io.IOException;
030: import javax.bluetooth.DiscoveryAgent;
031: import com.sun.midp.io.BluetoothUrl;
032: import com.sun.midp.io.j2me.btl2cap.L2CAPNotifierImpl;
033: import com.sun.midp.io.j2me.btspp.BTSPPNotifierImpl;
034: import com.sun.kvem.jsr082.bluetooth.*;
035:
036: /**
037: * Bluetooth connect-anytime services support class.
038: */
039: public class BluetoothPush {
040:
041: /** 'authenticated' AllowedSender parameter. */
042: private static final String AUTHENTICATED = ";AUTHENTICATED";
043:
044: /** 'authorized' AllowedSender parameter. */
045: private static final String AUTHORIZED = ";AUTHORIZED";
046:
047: /** 'blacklist' AllowedSender parameter. */
048: private static final String BLACKLIST = ";BLACKLIST=";
049:
050: /** Service record serializer instance. */
051: private static ServiceRecordSerializer srs = new ServiceRecordSerializer();
052:
053: /**
054: * Checks if the specified URL is valid.
055: *
056: * @param url URL to verify
057: * @throws IllegalArgumentException if the URL is malformed
058: */
059: public static void verifyUrl(String url) {
060: BluetoothUrl btUrl = new BluetoothUrl(url);
061: if ((btUrl.encrypt || btUrl.authorize) && !btUrl.authenticate) {
062: throw new IllegalArgumentException(
063: "'authenticate=true' parameter is required.");
064: }
065: }
066:
067: /**
068: * Checks if the specified AllowedSender field is valid.
069: *
070: * @param filter filter to verify
071: * @throws IllegalArgumentException if the filter is malformed
072: */
073: public static void verifyFilter(String filter) {
074: if (filter.length() == 0) {
075: throw new IllegalArgumentException();
076: }
077: filter = filter.toUpperCase();
078: int i = 0;
079: while (i < filter.length() && i < 12) {
080: char c = filter.charAt(i++);
081: if (c == '*' || c == '?') {
082: continue;
083: }
084: if (c == ';') {
085: i--;
086: if (i == 0) {
087: throw new IllegalArgumentException(
088: "Invalid Bluetooth address.");
089: }
090: break;
091: }
092: if ((c < '0' || c > '9') && (c < 'A' || c > 'F')) {
093: throw new IllegalArgumentException(
094: "Invalid Bluetooth address.");
095: }
096: }
097: filter = filter.substring(i);
098: if (filter.length() == 0) {
099: return;
100: }
101: if (filter.startsWith(AUTHENTICATED)) {
102: filter = filter.substring(AUTHENTICATED.length());
103: } else if (filter.startsWith(AUTHORIZED)) {
104: filter = filter.substring(AUTHORIZED.length());
105: }
106: if (filter.length() == 0) {
107: return;
108: }
109: if (!filter.startsWith(BLACKLIST)) {
110: throw new IllegalArgumentException("Invalid parameter.");
111: }
112: filter = filter.substring(BLACKLIST.length());
113: if (filter.length() == 0) {
114: throw new IllegalArgumentException("Invalid blacklist.");
115: }
116: int count = 0;
117: while (true) {
118: if (++count > 1024) {
119: throw new IllegalArgumentException(
120: "Blacklist too long.");
121: }
122: i = 0;
123: while (i < filter.length() && i < 12) {
124: char c = filter.charAt(i++);
125: if (c == '*' || c == '?') {
126: continue;
127: }
128: if (c == ';') {
129: i--;
130: break;
131: }
132: if ((c < '0' || c > '9') && (c < 'A' || c > 'F')) {
133: throw new IllegalArgumentException(
134: "Invalid blacklist address.");
135: }
136: }
137: filter = filter.substring(i);
138: if (filter.length() == 0) {
139: return;
140: }
141: if (filter.charAt(0) != ';' || filter.length() == 1) {
142: throw new IllegalArgumentException("Invalid blacklist.");
143: }
144: filter = filter.substring(1);
145: }
146: }
147:
148: /**
149: * Registers URL within Bluetooth push subsytem.
150: *
151: * @param url URL to register
152: * @throws IOException if an I/O error occurs
153: */
154: public static void registerUrl(String url) throws IOException {
155: ServiceRecordImpl record = null;
156: String protocol = url.substring(0, url.indexOf(':'))
157: .toUpperCase();
158: if (protocol.equals("BTL2CAP")) {
159: record = L2CAPNotifierImpl.createServiceRecord(url);
160: } else if (protocol.equals("BTSPP")) {
161: record = BTSPPNotifierImpl.createServiceRecord(url);
162: } else if (protocol.equals("BTGOEP")) {
163: record = BTSPPNotifierImpl.createServiceRecord(url);
164: } else {
165: throw new RuntimeException(
166: "Unsupported Bluetooth protocol.");
167: }
168: if (!BCC.getInstance().isBluetoothEnabled()
169: && !BCC.getInstance().enableBluetooth()) {
170: throw new IOException("Bluetooth radio is not enabled.");
171: }
172: if (!registerUrl(url, srs.serialize(record))) {
173: throw new IOException("Error registering Bluetooth URL.");
174: }
175: if (BCC.getInstance().getAccessCode() != DiscoveryAgent.GIAC) {
176: BCC.getInstance().setAccessCode(DiscoveryAgent.GIAC);
177: }
178: // get the emulation services up and running
179: SDDB.getInstance();
180: }
181:
182: /**
183: * Retrieves service record associated with a service maintained by
184: * Bluetooth push subsytem.
185: *
186: * @param notifier Bluetooth notifier to be used with the service record
187: * @param url URL used during push entry registration
188: * @return service record instance
189: */
190: public static ServiceRecordImpl getServiceRecord(
191: BluetoothNotifier notifier, String url) {
192: return SDDB.getInstance().getServiceRecord(
193: getRecordHandle(url), notifier);
194: }
195:
196: /**
197: * Registers URL within Bluetooth push subsystem.
198: *
199: * @param url URL to register
200: * @param data serialized service record created from the URL
201: * @return true on success, false on failure
202: */
203: private native static boolean registerUrl(String url, byte[] data);
204:
205: /**
206: * Retrieves service record handle for a service maintained by
207: * Bluetooth push subsytem.
208: *
209: * @param url URL used during push entry registration
210: * @return service record handle
211: */
212: private native static int getRecordHandle(String url);
213:
214: }
|