/* * * * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ package com.sun.jsr082.bluetooth; import javax.bluetooth.RemoteDevice; import javax.bluetooth.UUID; import javax.bluetooth.DataElement; import com.sun.jsr082.bluetooth.SDPClient; import java.util.Enumeration; import java.util.Hashtable; /* * This class saves information about every service descovery request * to provide functionality of DiscoveryAgent using multiple requests * via SDPClient (Service Descovery Protocol) by ServiceSelector * and ServiceSearcher classes. */ abstract public class ServiceSearcherBase implements SDPResponseListener { /* * maximum number of allowed UUIDS in search uuids sequence */ private static final int MAX_ALLOWED_UUIDS = 12; private static final Object FAKE_VALUE = new Object(); /* Mask to determine an attribute ID out of range. */ private static final int MASK_OVERFLOW = 0xffff0000; /* RemoteDevice whose response to be listened. */ RemoteDevice btDev; /* * The UUIDs from SDP_ServiceSearchRequest or * SDP_ServiceSearchAttrbuteRequest. * * @see SDPClient#serviceSearchRequest * @see SDPClient#serviceSearchAttributeRequest */ UUID[] uuidSet; /* * Attributes list from SDP_ServiceSearchAttrbuteRequest. * * @see SDPClient#serviceSearchAttributeRequest */ int[] attrSet; /* * Creates ServiceSearcherBase and save all required info in it. */ ServiceSearcherBase() { super(); } /* * Creates an instance of ServiceSearcherBase * * @param attrSet list of attributes whose values are requested. * @param uuidSet list of UUIDs that indicate services relevant to request. * @param btDev remote Bluetooth device to listen response from. * @param discListener discovery listener. */ ServiceSearcherBase(int[] attrSet, UUID[] uuidSet, RemoteDevice btDev) { super(); initialize(attrSet, uuidSet, btDev); } /* * Initializes an instance of ServiceSearcherBase * * @param attrSet list of attributes whose values are requested. * @param uuidSet list of UUIDs that indicate services relevant to request. * @param btDev remote Bluetooth device to listen response from. * @param discListener discovery listener. */ protected void initialize(int[] attrSet, UUID[] uuidSet, RemoteDevice btDev) throws IllegalArgumentException, NullPointerException { this.btDev = btDev; this.attrSet = ServiceSearcherBase.extendByStandardAttrs(attrSet); this.uuidSet = ServiceSearcherBase.removeDuplicatedUuids(uuidSet); } /* * Informs this listener about errors during Service Discovering process. * * @param errorCode error code recieved from server or generated locally * due to transaction terminating. * * @param info detail information about the error * * @param transactionID ID of transaction response recieved within. */ abstract public void errorResponse(int errorCode, String info, int transactionID); /* * Informs this listener about found services records. * * @param handleList service records handles returned by server within * SDP_ServiceSearchResponse. * * @param transactionID ID of transaction response recieved within. */ abstract public void serviceSearchResponse(int[] handleList, int transactionID); /* * Informs this listener about found attributes of specified service record. * * @param attrIDs list of attributes whose values requested from server * within SDP_ServiceAttributesRequest. * * @param attributeValues values returned by server within * SDP_ServiceAttributesResponse. * * @param transactionID ID of transaction response recieved within. */ abstract public void serviceAttributeResponse(int[] attrIDs, DataElement[] attributeValues, int transactionID); /* * Informs this listener about attributes of fisrt found service record. */ abstract public void serviceSearchAttributeResponse(int[] attrIDs, DataElement[] attributeValues, int transactionID); public static int[] extendByStandardAttrs( int[] attrSet ) throws IllegalArgumentException { /* Extend attributes IDs with standard values from the spec except duplicates */ Hashtable uniquies = new Hashtable(); /* appending by user required attributes */ if (attrSet != null) { if (attrSet.length <= 0 || attrSet.length > ServiceRecordImpl.RETRIEVABLE_MAX) { throw new IllegalArgumentException("Invalid attribute set length"); } for (int i=0; i<attrSet.length; i++) { if (uniquies.put(new Integer(attrSet[i]), FAKE_VALUE) != null ) { throw new IllegalArgumentException( "Duplicate attribute Ox" + Integer.toHexString(attrSet[i]) ); } if ((attrSet[i] & MASK_OVERFLOW) != 0) { throw new IllegalArgumentException("Illegal attribute ID"); } } } /* Adding standard attributes */ for (int i=0; i<5; i++) { uniquies.put(new Integer(i), FAKE_VALUE); } int [] extendedAttributes = new int[uniquies.size()]; Enumeration attrs = uniquies.keys(); for( int i=0; attrs.hasMoreElements(); i++ ) { extendedAttributes[i] = ((Integer) attrs.nextElement()).intValue(); } attrSort(extendedAttributes); return extendedAttributes; } /* * Sorts an integer array in ascending order. */ private static void attrSort(int[] data) { for (int k = 0; k < data.length - 1; k++) { boolean isSorted = true; for (int i = 1; i < data.length - k; i++) { if (data[i] < data[i - 1]) { int tmp = data[i]; data[i] = data[i - 1]; data[i - 1] = tmp; isSorted = false; } } if (isSorted) break; } } public static UUID[] removeDuplicatedUuids( UUID[] uuidSet ) throws IllegalArgumentException, NullPointerException { Hashtable uniquies = new Hashtable(); UUID[] uuids; if ((uuidSet != null) && (uuidSet.length > 0)) { /* uuid checking */ for (int i = 0; i < uuidSet.length; i++) { if (uuidSet[i] == null) { throw new NullPointerException("Invalid UUID. Null"); } /* check UUID duplication */ if (uniquies.put(uuidSet[i], FAKE_VALUE) != null) { throw new IllegalArgumentException("Duplicated UUID: " + uuidSet[i]); } } uuids = new UUID[uniquies.size()]; Enumeration keys = uniquies.keys(); for (int i = 0; keys.hasMoreElements(); i++) { uuids[i] = (UUID) keys.nextElement(); } } else { uuids = new UUID[0]; } return uuids; } }