Source Code Cross Referenced for ServiceSearcher.java in  » 6.0-JDK-Modules » j2me » com » sun » kvem » jsr082 » bluetooth » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » com.sun.kvem.jsr082.bluetooth 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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.bluetooth.BluetoothStateException;
030:        import javax.bluetooth.DataElement;
031:        import javax.bluetooth.DiscoveryListener;
032:        import javax.bluetooth.RemoteDevice;
033:        import javax.bluetooth.UUID;
034:        import java.util.Hashtable;
035:
036:        /**
037:         * This class saves information about responses to SDP_ServiceSearchRequest
038:         * and SDP_ServiceAttributeRequest requests
039:         * and provides functionality of DiscoveryAgent.serviceSearch using
040:         * multiple requests via SDPClient (Service Discovery Protocol)
041:         *
042:         */
043:        class ServiceSearcher extends ServiceSearcherBase {
044:
045:            /** Set to false in RR version - then the javac skip the code. */
046:            private static final boolean DEBUG = false;
047:
048:            /** this class name for debug. */
049:            private static final String cn = "ServiceSearcher";
050:
051:            /** ID of transaction this listener works in. */
052:            private short transactionID;
053:
054:            /**
055:             * Listens for service discovery and is informed as a service is
056:             * discovered.
057:             */
058:            private DiscoveryListener discListener;
059:
060:            /** SDP client to send requests. */
061:            private SDPClient sdp;
062:
063:            /** Service records handles retrieved from a server response. */
064:            private int[] handles;
065:
066:            /** Number of service records handles processed. */
067:            private int processedHandle;
068:
069:            /** Indicates if this listener is inactive. */
070:            private boolean inactive = false;
071:
072:            /** Indicates if service search has been canceled. */
073:            private boolean canceled = false;
074:
075:            /** Indicates if listener notification has been called. */
076:            private boolean notified = false;
077:
078:            /** Current quantity of service discovering requests. */
079:            private static int requestCounter = 0;
080:
081:            /** Keeps the references of current service search requests. */
082:            private static Hashtable searchers = new Hashtable();
083:
084:            /**
085:             * Creates ServiceSearcher and save all required info in it.
086:             *
087:             * @param attrSet list of attributes whose values are requested.
088:             * @param uuidSet list of UUIDs that indicate services relevant to request.
089:             * @param btDev remote Bluetooth device to listen response from.
090:             * @param discListener discovery listener.
091:             *
092:             * @see SDPClient#serviceSearchRequest
093:             * @see SDPClient#serviceAttributeRequest
094:             */
095:            ServiceSearcher(int[] attrSet, UUID[] uuidSet, RemoteDevice btDev,
096:                    DiscoveryListener discListener) {
097:                super (attrSet, uuidSet, btDev);
098:
099:                if (discListener == null) {
100:                    throw new NullPointerException("DiscoveryListener is null");
101:                }
102:                this .discListener = discListener;
103:            }
104:
105:            /**
106:             * Starts SDP_ServiceSearchRequest.
107:             *
108:             * @see SDPClient#serviceSearchRequest
109:             *
110:             * @return ID of transaction that has been initiated by the request.
111:             */
112:            int start() throws BluetoothStateException {
113:                synchronized (ServiceSearcher.class) {
114:                    if (requestCounter == ServiceRecordImpl.TRANS_MAX) {
115:                        throw new BluetoothStateException(
116:                                "Too much concurrent requests");
117:                    }
118:                    requestCounter++;
119:                }
120:                transactionID = SDPClient.newTransactionID();
121:                searchers.put(new Integer(transactionID), this );
122:
123:                try {
124:                    sdp = new SDPClient(btDev.getBluetoothAddress());
125:                    sdp.serviceSearchRequest(uuidSet, transactionID, this );
126:                } catch (IOException ioe) {
127:                    if (DEBUG) {
128:                        ioe.printStackTrace();
129:                    }
130:
131:                    synchronized (this ) {
132:                        stop();
133:                        new NotifyListenerRunner(
134:                                DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE);
135:                    }
136:                }
137:
138:                return transactionID;
139:            }
140:
141:            /**
142:             * Receives SDP_ErrorResponse and completes the search request activity
143:             * by error reason.
144:             *
145:             * @param errorCode error code form SDP_ErrorResponse.
146:             * @param info error details firm SDP_ErrorResponse.
147:             * @param transactionID ID of transaction response got within.
148:             */
149:            public void errorResponse(int errorCode, String info,
150:                    int transactionID) {
151:                if (DEBUG) {
152:                    System.out.println(cn + ".errorResponse: called");
153:                }
154:
155:                stop();
156:
157:                if ((errorCode == SDP_INVALID_VERSION)
158:                        || (errorCode == SDP_INVALID_SYNTAX)
159:                        || (errorCode == SDP_INVALID_PDU_SIZE)
160:                        || (errorCode == SDP_INVALID_CONTINUATION_STATE)
161:                        || (errorCode == SDP_INSUFFICIENT_RESOURCES)) {
162:                    notifyListener(DiscoveryListener.SERVICE_SEARCH_ERROR);
163:                    System.err.println(info);
164:                } else if (errorCode == SDP_INVALID_SR_HANDLE) {
165:                    notifyListener(DiscoveryListener.SERVICE_SEARCH_NO_RECORDS);
166:                    System.err.println(info);
167:                } else if (errorCode == IO_ERROR) {
168:                    notifyListener(DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE);
169:                } else if (errorCode == TERMINATED) {
170:                    new NotifyListenerRunner(
171:                            DiscoveryListener.SERVICE_SEARCH_TERMINATED);
172:                }
173:            }
174:
175:            /**
176:             * Receives array of handles retrieved form SDP_serviceSearchResponse.
177:             *
178:             * @param handleList service record handles retrieved from
179:             *        SDP_srviceSearchResponse.
180:             * @param transactionID ID of transaction response has been received in.
181:             */
182:            public void serviceSearchResponse(int[] handleList,
183:                    int transactionID) {
184:                if (DEBUG) {
185:                    System.out.println(cn + ".serviceSearchResponse: called");
186:                }
187:
188:                // there is no reason to perform response processing if search
189:                //  is canceled
190:                if (isCanceled()) {
191:                    return;
192:                }
193:
194:                if (handleList == null || handleList.length == 0) {
195:                    stop();
196:                    notifyListener(DiscoveryListener.SERVICE_SEARCH_NO_RECORDS);
197:                    return;
198:                }
199:
200:                synchronized (this ) {
201:                    handles = handleList;
202:                    processedHandle = 0;
203:                }
204:
205:                try {
206:                    // there is no reason to request service attributes if service
207:                    // search is canceled
208:                    if (isCanceled()) {
209:                        return;
210:                    }
211:                    sdp.serviceAttributeRequest(handles[processedHandle],
212:                            attrSet, transactionID, this );
213:                } catch (IOException ioe) {
214:                    if (DEBUG) {
215:                        ioe.printStackTrace();
216:                    }
217:                    stop();
218:                    notifyListener(DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE);
219:                }
220:            }
221:
222:            /**
223:             * Receives arrays of service record attributes and their values retrieved
224:             * from server response.
225:             */
226:            public void serviceAttributeResponse(int[] attrIDs,
227:                    DataElement[] attributeValues, int transactionID) {
228:                if (DEBUG) {
229:                    System.out
230:                            .println(cn + ".serviceAttributeResponse: called");
231:                }
232:
233:                // there is no reason to process service attributes if service
234:                // search is canceled
235:                if (isCanceled()) {
236:                    return;
237:                }
238:
239:                synchronized (this ) {
240:                    processedHandle++;
241:                }
242:
243:                if (attributeValues != null) {
244:                    ServiceRecordImpl[] serviceRecordSet = new ServiceRecordImpl[1];
245:                    serviceRecordSet[0] = new ServiceRecordImpl(btDev, attrIDs,
246:                            attributeValues);
247:                    try {
248:                        // The spec for DiscoveryAgent.cancelServiceSearch() says:
249:                        // "After receiving SERVICE_SEARCH_TERMINATED event,
250:                        // no further servicesDiscovered() events will occur
251:                        // as a result of this search."
252:                        if (isCanceled()) {
253:                            return;
254:                        }
255:                        discListener.servicesDiscovered(this .transactionID,
256:                                serviceRecordSet);
257:                    } catch (Throwable e) {
258:                        e.printStackTrace();
259:                    }
260:                }
261:
262:                if (processedHandle == handles.length) {
263:                    stop();
264:                    notifyListener(DiscoveryListener.SERVICE_SEARCH_COMPLETED);
265:                    return;
266:                }
267:
268:                try {
269:                    // there is no reason to continue attributes discovery if search
270:                    //  is canceled
271:                    if (isCanceled()) {
272:                        return;
273:                    }
274:                    sdp.serviceAttributeRequest(handles[processedHandle],
275:                            attrSet, transactionID, this );
276:                } catch (IOException ioe) {
277:                    if (DEBUG) {
278:                        ioe.printStackTrace();
279:                    }
280:                    stop();
281:                    notifyListener(DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE);
282:                }
283:            }
284:
285:            /**
286:             * Base class method not relevant to this subclass, must never be called.
287:             */
288:            public void serviceSearchAttributeResponse(int[] attrIDs,
289:                    DataElement[] attributeValues, int transactionID) {
290:                if (DEBUG) {
291:                    System.out.println(cn
292:                            + ".serviceSearchAttributeResponse: called");
293:                }
294:                throw new RuntimeException("Unexpected call");
295:            }
296:
297:            /**
298:             * Finishes the service searcher activity.
299:             */
300:            void stop() {
301:                SDPClient sdp;
302:                SDPClient.freeTransactionID(transactionID);
303:                searchers.remove(new Integer(transactionID));
304:
305:                synchronized (this ) {
306:                    if (this .sdp == null) {
307:                        return;
308:                    }
309:                    inactive = true;
310:                    sdp = this .sdp;
311:                    this .sdp = null;
312:                }
313:
314:                synchronized (ServiceSearcher.class) {
315:                    requestCounter--;
316:                }
317:
318:                try {
319:                    sdp.close();
320:                } catch (IOException ioe) {
321:                    if (DEBUG) {
322:                        ioe.printStackTrace();
323:                    }
324:                    // ignore
325:                }
326:            }
327:
328:            /**
329:             * Cancels current transaction.
330:             *
331:             * @return false if there is no current transaction, cancels it and returns
332:             * true otherwise.
333:             */
334:            boolean cancel() {
335:                synchronized (this ) {
336:                    if (inactive) {
337:                        return false;
338:                    }
339:                    inactive = true;
340:
341:                    if (sdp == null) {
342:                        return false;
343:                    }
344:
345:                    if (canceled) {
346:                        return false;
347:                    }
348:                    canceled = true;
349:                }
350:
351:                // cancel running effective transaction if any.
352:                // if sdp.cancelServiceSearch returns false (there is no running
353:                // transactions) then call the notification directly.
354:                if (!sdp.cancelServiceSearch(transactionID)) {
355:                    new NotifyListenerRunner(
356:                            DiscoveryListener.SERVICE_SEARCH_TERMINATED);
357:                }
358:
359:                return true;
360:            }
361:
362:            /**
363:             * Determines whether  the service search has been canceled by
364:             * the application and did not complete.
365:             *
366:             * @return <code>true</code> indicates the service search has been
367:             *         canceled; <code>false</code> the application has not called
368:             *         cancel operation
369:             */
370:            private boolean isCanceled() {
371:                return canceled;
372:            }
373:
374:            /**
375:             * Cancels transaction with given ID.
376:             *
377:             * @param transactionID ID of transaction to be cancelled.
378:             *
379:             * @return false if there is no open transaction with ID given, true
380:             * otherwise.
381:             */
382:            static boolean cancel(int transactionID) {
383:                ServiceSearcher carrier = (ServiceSearcher) searchers
384:                        .get(new Integer(transactionID));
385:
386:                if (carrier == null) {
387:                    return false;
388:                } else {
389:                    return carrier.cancel();
390:                }
391:            }
392:
393:            /**
394:             * Notifies the listener that service search has
395:             * been completed with specified response code.
396:             *
397:             * @param respCode response code.
398:             */
399:            private void notifyListener(int respCode) {
400:                // guard against multiple notification calls
401:                synchronized (this ) {
402:                    if (!notified) {
403:                        notified = true;
404:                    } else {
405:                        return;
406:                    }
407:                }
408:
409:                if (DEBUG) {
410:                    String codeStr = "Undefined";
411:
412:                    switch (respCode) {
413:                    case DiscoveryListener.SERVICE_SEARCH_COMPLETED:
414:                        codeStr = "SERVICE_SEARCH_COMPLETED";
415:                        break;
416:
417:                    case DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE:
418:                        codeStr = "SERVICE_SEARCH_DEVICE_NOT_REACHABLE";
419:                        break;
420:
421:                    case DiscoveryListener.SERVICE_SEARCH_ERROR:
422:                        codeStr = "SERVICE_SEARCH_ERROR";
423:                        break;
424:
425:                    case DiscoveryListener.SERVICE_SEARCH_NO_RECORDS:
426:                        codeStr = "SERVICE_SEARCH_NO_RECORDS";
427:                        break;
428:
429:                    case DiscoveryListener.SERVICE_SEARCH_TERMINATED:
430:                        codeStr = "SERVICE_SEARCH_TERMINATED";
431:                        break;
432:                    default:
433:                    }
434:                    System.out.println("serviceSearchCompleted:");
435:                    System.out.println("\ttransID=" + transactionID);
436:                    System.out.println("\trespCode=" + codeStr);
437:                    System.out.println("\tinactive=" + inactive);
438:                }
439:
440:                try {
441:                    discListener
442:                            .serviceSearchCompleted(transactionID, respCode);
443:                } catch (Throwable e) {
444:                    e.printStackTrace();
445:                }
446:            }
447:
448:            /**
449:             * Runnable for launching <code>notifyListener()</code> in a separate
450:             * thread.
451:             *
452:             * @see #notifyListener(int)
453:             */
454:            class NotifyListenerRunner implements  Runnable {
455:                /** Response code to pass to a listener. */
456:                int respCode;
457:
458:                /**
459:                 * Constructs Runnable instance to pass single response code, starts
460:                 * a thread for that.
461:                 *
462:                 * @param respCode response code value
463:                 */
464:                NotifyListenerRunner(int respCode) {
465:                    this .respCode = respCode;
466:                    new Thread(this ).start();
467:                }
468:
469:                /**
470:                 * The <code>run()</code> method.
471:                 * @see java.lang.Runnable
472:                 */
473:                public void run() {
474:                    notifyListener(respCode);
475:                }
476:            }
477:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.