Source Code Cross Referenced for ObexPacketStream.java in  » 6.0-JDK-Modules » j2me » com » sun » kvem » jsr082 » obex » 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.obex 
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.obex;
027:
028:        import java.io.IOException;
029:        import java.io.InterruptedIOException;
030:        import java.util.Calendar;
031:        import java.util.Date;
032:        import java.util.TimeZone;
033:        import java.util.Vector;
034:        import java.util.Stack;
035:        import javax.microedition.io.Connection;
036:        import javax.obex.ResponseCodes;
037:        import javax.obex.Authenticator;
038:        import com.sun.midp.log.Logging;
039:
040:        /**
041:         * Obex core protocol.
042:         */
043:        public abstract class ObexPacketStream implements  Connection {
044:
045:            /** Debug information, should be false for RR. */
046:            private static final boolean DEBUG = false;
047:            private static final boolean DEBUG2 = false;
048:
049:            // OBEX operations opcodes
050:            static final int OPCODE_CONNECT = 0x80;
051:            static final int OPCODE_DISCONNECT = 0x81;
052:            static final int OPCODE_PUT = 0x02;
053:            static final int OPCODE_GET = 0x03;
054:            static final int OPCODE_SETPATH = 0x85;
055:            static final int OPCODE_CONTINUE = 0x90;
056:            static final int OPCODE_ABORT = 0xFF;
057:            static final int OPCODE_FINAL = 0x80;
058:            static final int OPCODE_GET_FINAL = OPCODE_GET | OPCODE_FINAL;
059:
060:            static final byte[] PACKET_ABORT = { (byte) OPCODE_ABORT, 0, 0 };
061:            static final byte[] PACKET_CONTINUE = { (byte) OPCODE_CONTINUE, 0,
062:                    0 };
063:            static final byte[] PACKET_DISCONNECT = { (byte) OPCODE_DISCONNECT,
064:                    0, 0 };
065:            static final byte[] PACKET_SUCCESS = {
066:                    (byte) ResponseCodes.OBEX_HTTP_OK, 0, 0 };
067:
068:            static final byte[] PACKET_BAD_REQUEST = {
069:                    (byte) ResponseCodes.OBEX_HTTP_BAD_REQUEST, 0, 0 };
070:
071:            static final byte[] PACKET_NOT_IMPLEMENTED = {
072:                    (byte) ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED, 0, 0 };
073:
074:            private static final int HEADER_BODY = 0x48;
075:            private static final int HEADER_EOFBODY = 0x49;
076:            private static final int HEADER_CONNECTION_ID = 0xCB;
077:            static final int HEADER_AUTH_CHALLENGE = 0x4D;
078:            static final int HEADER_AUTH_RESPONSE = 0x4E;
079:
080:            static TimeZone utcTimeZone = TimeZone.getTimeZone("UTC");
081:
082:            private static final int TRANSPORT_READ_INTERVAL = 10;
083:
084:            private ObexTransport transport;
085:
086:            Authenticator authenticator;
087:
088:            /**
089:             * Generated authentication responses. They will be send in sendPacket().
090:             * Stored in <CODE>byte[]</CODE> format.
091:             */
092:            Vector authResponses = new Vector();
093:
094:            /**
095:             * Sent authentication challenges.
096:             * They will be used for check authentication responses.
097:             */
098:            Vector authChallenges = new Vector();
099:
100:            /**
101:             * True when buffer contains packet for sending and some headers can
102:             * be added.
103:             */
104:            boolean moreHeaders = false;
105:
106:            /**
107:             * Outgoing packet contains authentication challenges, so it should be
108:             * sent immediatly.
109:             */
110:            boolean challengesToSend = false;
111:
112:            /**
113:             * True if one of sending headers cannot feet in empty packet.
114:             */
115:            boolean headerOverflow = false;
116:
117:            /**
118:             * True if sending packet contains target header.
119:             */
120:            boolean containsTargetHeader = false;
121:
122:            /**
123:             * Queue of outgoing headers, not feet in packet.
124:             */
125:            Vector queuedHeaders;
126:            QueuedHeader newHeader;
127:            Stack emptyHeadersPool;
128:
129:            /**
130:             * Set when sending auth challenge,
131:             * reset when received valid auth response in next
132:             * packet.
133:             */
134:            boolean authFailed = false;
135:
136:            /**
137:             * True if this is ClientSession, false in ServerConnectionImpl.
138:             */
139:            boolean isClient;
140:
141:            /**
142:             * Client is connected flag. Ignored by ServerConnectionImpl.
143:             */
144:            boolean isConnected;
145:
146:            int OBEX_MAXIMUM_PACKET_LENGTH;
147:
148:            byte[] buffer, cache;
149:            int packetLength;
150:            int packetOffset;
151:            int packetType;
152:
153:            int maxSendLength;
154:
155:            boolean dataOpened, dataClosed;
156:            boolean isEof;
157:            int dataOffset;
158:
159:            /**
160:             * Connection id used in <code>setConnectionID</code>,
161:             * <code>getConnectioID</code>.
162:             */
163:
164:            ObexPacketStream(ObexTransport transport) {
165:                this .transport = transport;
166:                OBEX_MAXIMUM_PACKET_LENGTH = transport.getMaximumPacketSize();
167:                buffer = new byte[OBEX_MAXIMUM_PACKET_LENGTH];
168:                cache = new byte[OBEX_MAXIMUM_PACKET_LENGTH];
169:                maxSendLength = OBEX_MAXIMUM_PACKET_LENGTH;
170:                newHeader = new QueuedHeader(this );
171:                queuedHeaders = new Vector();
172:                emptyHeadersPool = new Stack();
173:            }
174:
175:            // interface visible function
176:            public void close() {
177:                try {
178:                    if (transport != null) {
179:                        transport.close();
180:                    }
181:                } catch (IOException e) {
182:                    // nothing
183:                }
184:                transport = null;
185:            }
186:
187:            public void setAuthenticator(Authenticator authenticator) {
188:                if (authenticator == null) {
189:                    throw new NullPointerException("null authenticator");
190:                }
191:                this .authenticator = authenticator;
192:            }
193:
194:            public Connection getTransport() throws IOException {
195:                if (transport == null) {
196:                    throw new IOException("connection error");
197:                }
198:                return transport.getUnderlyingConnection();
199:            }
200:
201:            /**
202:             * Sets link broken flag.
203:             */
204:            void brokenLink() {
205:                close();
206:            }
207:
208:            boolean isClosed() {
209:                return transport == null;
210:            }
211:
212:            void packetBegin(byte[] head) {
213:                if (DEBUG) {
214:                    System.out.println("packetBegin()");
215:                }
216:
217:                containsTargetHeader = false;
218:                moreHeaders = true;
219:                challengesToSend = false;
220:                System.arraycopy(head, 0, buffer, 0, head.length);
221:                packetLength = head.length;
222:                authChallenges.removeAllElements();
223:                dataOpened = false;
224:                dataClosed = false;
225:                dataOffset = -3; // generate aoobe when accessed
226:            }
227:
228:            int packetAddData(byte[] data, int offset, int length) {
229:                if (DEBUG) {
230:                    System.out.println("packetAddData()");
231:                }
232:                // preventing writing several data blocks, just in case
233:                if (dataClosed)
234:                    return 0;
235:
236:                if (!dataOpened) {
237:                    // let it be at least 3 bytes workload to create new Body header
238:                    if (packetLength + 6 > maxSendLength) {
239:                        return 0;
240:                    }
241:                    buffer[packetLength] = HEADER_BODY;
242:                    dataOffset = packetLength;
243:                    packetLength += 3;
244:                    dataOpened = true;
245:                }
246:
247:                int len;
248:                if (packetLength + length > maxSendLength) {
249:                    len = maxSendLength - packetLength;
250:                } else {
251:                    len = length;
252:                }
253:                System.arraycopy(data, offset, buffer, packetLength, len);
254:                packetLength += len;
255:                return len;
256:            }
257:
258:            int getPacketLength() {
259:                return packetLength;
260:            }
261:
262:            void restorePacketLength(int len) {
263:                packetLength = len;
264:            }
265:
266:            boolean packetEOFBody() {
267:                if (DEBUG) {
268:                    System.out.println("packetEOFBody()");
269:                }
270:                if (dataClosed) {
271:                    return false;
272:                }
273:                if (dataOpened) {
274:                    buffer[dataOffset + 0] = HEADER_EOFBODY;
275:                    return true;
276:                } else {
277:                    if (packetLength + 3 > maxSendLength) {
278:                        return false;
279:                    }
280:                    buffer[packetLength++] = HEADER_EOFBODY;
281:                    buffer[packetLength++] = 0; // length
282:                    buffer[packetLength++] = 3;
283:                    return true;
284:                }
285:            }
286:
287:            void packetMarkFinal() {
288:                if (DEBUG) {
289:                    System.out.println("packetMarkFinal()");
290:                }
291:                buffer[0] |= 0x80;
292:            }
293:
294:            void setPacketType(int type) {
295:                if (DEBUG) {
296:                    System.out.println("setPacketType()");
297:                }
298:                buffer[0] = (byte) type;
299:            }
300:
301:            /**
302:             * Finish packet and send it. Remove Connection ID header if packet also
303:             * contains TARGET header.
304:             */
305:            void packetEndStripConnID() throws IOException {
306:
307:                // first header id is in 3 byte on all packet except CONNECT
308:                // and this function is known not to be called for connect() operation.
309:                if ((buffer[3] & 0xFF) == HeaderSetImpl.TARGET) {
310:                    packetLength -= 5;
311:
312:                    // length of Connection ID packet is 5 bytes:
313:                    //  1 byte header + 4 byte int value
314:                    for (int i = 3; i < packetLength; i++) {
315:                        buffer[i] = buffer[i + 5];
316:                    }
317:                }
318:                packetEnd();
319:            }
320:
321:            void packetEnd() throws IOException {
322:                if (DEBUG) {
323:                    System.out.println("packetEnd()");
324:                }
325:                moreHeaders = false;
326:
327:                if (transport == null) {
328:                    throw new IOException("connection error");
329:                }
330:
331:                if (dataOpened) {
332:                    // closing Body header
333:                    int len = packetLength - dataOffset;
334:                    buffer[dataOffset + 1] = (byte) (len >> 8);
335:                    buffer[dataOffset + 2] = (byte) len;
336:                    dataOpened = false;
337:                    dataClosed = true;
338:                }
339:                // update packet length field
340:                buffer[1] = (byte) (packetLength / 0x100);
341:                buffer[2] = (byte) (packetLength % 0x100);
342:
343:                if (DEBUG) {
344:                    int len = packetLength;
345:                    if (!DEBUG2 && len > 20) {
346:                        len = 20;
347:                    }
348:                    System.out.println("send:");
349:                    for (int i = 0; i < len; i++) {
350:                        System.out.print(" 0x"
351:                                + Integer.toHexString(buffer[i] & 0xFF));
352:                        int chr = buffer[i] & 0xFF;
353:                        if (chr >= 32 && chr < 128) {
354:                            System.out.print("(" + (char) (buffer[i] & 0xFF)
355:                                    + ")");
356:                        }
357:                    }
358:                    if (packetLength != len) {
359:                        System.out.print("...");
360:                    }
361:                    System.out.println("");
362:                }
363:                try {
364:                    transport.write(buffer, packetLength);
365:                } catch (IOException e) {
366:                    brokenLink();
367:                    throw e;
368:                }
369:            }
370:
371:            /**
372:             * Connection Identifier:
373:             *     * must be first header in packet
374:             *     * 0xFFFFFFFF considered invalid - it is up to application
375:             *     * can't be sent on connect() request
376:             *     * can't be used with Target header in one packet
377:             */
378:            final void packetAddConnectionID(long id, HeaderSetImpl headers) {
379:                // SPEC: Illegal to send a Connection Id and a Target header
380:                // in the same operation.
381:                if (headers != null
382:                        && headers.getHeader(HeaderSetImpl.TARGET) != null) {
383:                    return;
384:                }
385:                if (id < 0L || id > 0xFFFFFFFFL) {
386:                    return;
387:                }
388:                buffer[packetLength++] = (byte) HEADER_CONNECTION_ID;
389:                encodeInt(id);
390:            }
391:
392:            /**
393:             * This method is called to handle a situation than header is too large.
394:             * @throws IOException
395:             */
396:            abstract void headerTooLarge() throws IOException;
397:
398:            /**
399:             * Adds the specified headers to the packet.
400:             */
401:            final void packetAddHeaders(HeaderSetImpl headers)
402:                    throws IOException {
403:                if (DEBUG) {
404:                    System.out.println("packetAddHeaders()");
405:                }
406:                headerOverflow = false;
407:                newHeader.sendAllQueued();
408:
409:                if (headers == null) {
410:                    return;
411:                }
412:
413:                int[] idList = headers.getHeaderList();
414:
415:                if (!headers.challenges.isEmpty()) {
416:                    newHeader.sendOrQueue(HEADER_AUTH_CHALLENGE,
417:                            headers.challenges);
418:                }
419:
420:                if (idList == null) {
421:                    return;
422:                }
423:
424:                for (int i = 0; i < idList.length; i++) {
425:                    int id = idList[i];
426:                    Object value = headers.getHeader(id);
427:                    newHeader.sendOrQueue(id, value);
428:                }
429:            }
430:
431:            void packetAddAuthResponses() throws IOException {
432:                try {
433:                    for (int i = 0; i < authResponses.size(); i++) {
434:                        if (DEBUG) {
435:                            System.out
436:                                    .println("packetAddAuthResponses(): added response");
437:                        }
438:                        ObexAuth response = (ObexAuth) authResponses
439:                                .elementAt(i);
440:                        int len = response.replyAuthChallenge(buffer,
441:                                packetLength, authenticator);
442:                        packetLength += len;
443:                    }
444:                } catch (ArrayIndexOutOfBoundsException e) {
445:                    throw new IOException("auth response request too large");
446:                }
447:                if (packetLength > maxSendLength) {
448:                    throw new IOException("auth response request too large");
449:                }
450:            }
451:
452:            final void sendPacket(byte[] head, long connectionId,
453:                    HeaderSetImpl headers, boolean allHeaders)
454:                    throws IOException {
455:                packetBegin(head);
456:                packetAddConnectionID(connectionId, headers);
457:                packetAddAuthResponses();
458:                packetAddHeaders(headers);
459:                if (allHeaders && !queuedHeaders.isEmpty()) {
460:                    queuedHeaders.removeAllElements();
461:                    throw new IOException("packet too large for peer");
462:                }
463:                packetEnd();
464:            }
465:
466:            private final void encodeInt(long val) {
467:                buffer[packetLength++] = (byte) (val >> 24);
468:                buffer[packetLength++] = (byte) (val >> 16);
469:                buffer[packetLength++] = (byte) (val >> 8);
470:                buffer[packetLength++] = (byte) val;
471:            }
472:
473:            /**
474:             * Reads at least <code>length</code> bytes starting from the given offset
475:             * into the internal buffer. More than <code>length</code> bytes may be
476:             * actually read. The calling function must ensure the buffer is large
477:             * enough to store the entire packet.
478:             *
479:             * @param offset starting offset in the destination buffer
480:             * @param length minimum number of bytes to read
481:             * @return number of bytes actually read
482:             * @throws IOException if an I/O error occurs
483:             */
484:            private int readLeast(int offset, int length) throws IOException {
485:                if (transport == null) {
486:                    throw new IOException("connection error");
487:                }
488:                int read = 0;
489:                while (read < length) {
490:                    int count = transport.read(cache);
491:                    System.arraycopy(cache, 0, buffer, offset + read, count);
492:                    read += count;
493:                    if (read < length) {
494:                        try {
495:                            Thread.sleep(TRANSPORT_READ_INTERVAL);
496:                        } catch (InterruptedException e) {
497:                            throw new InterruptedIOException(e.getMessage());
498:                        }
499:                    }
500:                }
501:                return read;
502:            }
503:
504:            final void recvPacket() throws IOException {
505:                authResponses.removeAllElements();
506:                if (transport == null) {
507:                    throw new IOException("connection error");
508:                }
509:                try {
510:                    int read = readLeast(0, 3);
511:                    packetType = buffer[0] & 0xff;
512:                    packetLength = ((buffer[1] & 0xff) << 8)
513:                            + (buffer[2] & 0xff);
514:                    if (DEBUG) {
515:                        Logging.report(Logging.INFORMATION, 0, "Expecting "
516:                                + packetLength + " bytes to arrive...");
517:                    }
518:                    if (read < packetLength) {
519:                        readLeast(read, packetLength - read);
520:                    }
521:
522:                    // dump packet:
523:                    if (DEBUG) {
524:                        int len = packetLength;
525:                        if (!DEBUG2 && len > 20) {
526:                            len = 20;
527:                        }
528:
529:                        System.out.println("recv: ");
530:                        for (int i = 0; i < len; i++) {
531:                            System.out.print(" 0x"
532:                                    + Integer.toHexString(buffer[i] & 0xFF)
533:                                            .toUpperCase());
534:                        }
535:                        if (len != packetLength)
536:                            System.out.print("...");
537:                        System.out.println("");
538:                    }
539:                } catch (IOException e) {
540:                    brokenLink();
541:                    throw e;
542:                }
543:            }
544:
545:            private final void parseHeader(HeaderSetImpl headers)
546:                    throws IOException {
547:                if (DEBUG) {
548:                    System.out.println("parseHeader()");
549:                }
550:                try {
551:                    int headerId = buffer[packetOffset++] & 0xff;
552:                    int inputType = headerId >> 6;
553:                    int outputType = HeaderSetImpl.internalType(headerId);
554:                    if (outputType != HeaderSetImpl.TYPE_UNSUPPORTED) {
555:                        inputType = outputType;
556:                    }
557:
558:                    Object result = null;
559:
560:                    switch (inputType) {
561:                    // ids which require special handling
562:                    case HeaderSetImpl.TYPE_SPECIAL_TIME_ISO:
563:                        try {
564:                            result = decodeTime8601();
565:                        } catch (IOException e) {
566:                            // IMPL_NOTE: Got invalid time header,
567:                            // should probably just ignore it.
568:                        }
569:                        break;
570:
571:                    case HeaderSetImpl.TYPE_SPECIAL_TIME_4:
572:                        long date = decodeInt();
573:                        Calendar cal = Calendar.getInstance(utcTimeZone);
574:                        cal.setTime(new Date(date * 1000L));
575:                        result = cal;
576:                        packetOffset += 4;
577:                        break;
578:
579:                    case HeaderSetImpl.TYPE_SPECIAL_TYPE:
580:                        int len = decodeLength16(packetOffset) - 3;
581:                        packetOffset += 2;
582:                        if (buffer[packetOffset + len - 1] != 0) {
583:                            throw new IOException("protocol error, "
584:                                    + "type field not null terminated");
585:                        }
586:                        result = new String(buffer, packetOffset, len - 1,
587:                                "ISO-8859-1");
588:                        packetOffset += len;
589:                        break;
590:
591:                    // normal ids
592:                    case HeaderSetImpl.TYPE_LONG:
593:                        result = new Long(decodeInt());
594:                        packetOffset += 4;
595:                        break;
596:
597:                    case HeaderSetImpl.TYPE_UNICODE:
598:                        len = decodeLength16(packetOffset) - 3;
599:                        packetOffset += 2;
600:                        if (len < 2 || buffer[packetOffset + len - 1] != 0
601:                                || buffer[packetOffset + len - 2] != 0) {
602:                            throw new IOException("protocol error, "
603:                                    + "unicode string is not null terminated");
604:                        }
605:                        result = new String(buffer, packetOffset, len - 2,
606:                                "UTF-16BE");
607:                        // result = new String(buffer, packetOffset, len,
608:                        //        "ISO-8859-1");
609:                        packetOffset += len;
610:                        break;
611:
612:                    case HeaderSetImpl.TYPE_BYTEARRAY:
613:                        len = decodeLength16(packetOffset) - 3;
614:                        packetOffset += 2;
615:                        result = new byte[len];
616:                        System.arraycopy(buffer, packetOffset, result, 0, len);
617:                        packetOffset += len;
618:                        break;
619:
620:                    case HeaderSetImpl.TYPE_BYTE:
621:                        result = new Byte(buffer[packetOffset++]);
622:                        break;
623:
624:                    case HeaderSetImpl.TYPE_AUTH_CHALLENGE:
625:                        len = decodeLength16(packetOffset);
626:                        ObexAuth response = ObexAuth.parseAuthChallenge(buffer,
627:                                packetOffset - 1, len);
628:                        if (response != null)
629:                            authResponses.addElement(response);
630:                        packetOffset += len - 1;
631:                        return;
632:
633:                    case HeaderSetImpl.TYPE_AUTH_RESPONSE:
634:                        len = decodeLength16(packetOffset);
635:                        boolean good = ObexAuth.checkAuthResponse(buffer,
636:                                packetOffset - 1, len, this , authChallenges);
637:                        if (good)
638:                            authFailed = false;
639:                        packetOffset += len - 1;
640:                        if (DEBUG) {
641:                            System.out.println("checkAuthResponse() = " + good);
642:                        }
643:                        return;
644:                    }
645:
646:                    if (packetOffset > packetLength) {
647:                        throw new IOException("protocol error");
648:                    }
649:
650:                    if (outputType != HeaderSetImpl.TYPE_UNSUPPORTED) {
651:                        headers.setHeader(headerId, result);
652:                    } else if (DEBUG) {
653:                        System.out.println("unsupported header id = 0x"
654:                                + Integer.toHexString(headerId).toUpperCase());
655:                    }
656:                } catch (ArrayIndexOutOfBoundsException e) {
657:                    throw new IOException("protocol error");
658:                }
659:            }
660:
661:            /**
662:             * Called when requested authentication failed.
663:             * Implemented on server to call handler.
664:             */
665:            abstract void onAuthenticationFailure(byte[] username)
666:                    throws IOException;
667:
668:            void onMissingAuthResponse() throws IOException {
669:            }
670:
671:            boolean shouldSendAuthResponse() {
672:                return (packetType == ResponseCodes.OBEX_HTTP_UNAUTHORIZED)
673:                        && (authResponses.size() != 0);
674:            }
675:
676:            /**
677:             * Parser all packet headers, BODY headers should not apear
678:             * and silently ignored.
679:             */
680:            final void parsePacketHeaders(HeaderSetImpl headers, int offset)
681:                    throws IOException {
682:                if (DEBUG) {
683:                    System.out.println("parsePacketHeaders()");
684:                }
685:
686:                packetOffset = offset;
687:                headers.packetType = buffer[0] & 0xFF;
688:
689:                parseConnectionID();
690:
691:                while (packetOffset != packetLength) {
692:                    parseHeader(headers);
693:                }
694:                parseEnd();
695:            }
696:
697:            private final void parseConnectionID() {
698:
699:                int headerId = buffer[packetOffset] & 0xFF;
700:                // parse connection ID
701:                if (packetOffset + 5 > packetLength
702:                        || headerId != HEADER_CONNECTION_ID) {
703:                    return;
704:                }
705:                packetOffset++;
706:                long id = decodeInt();
707:                packetOffset += 4;
708:                setConnectionID(id);
709:            }
710:
711:            public abstract void setConnectionID(long id);
712:
713:            public abstract long getConnectionID();
714:
715:            /**
716:             * Begin parsing packet headers in packet possibly containing BODY
717:             * (data fields).
718:             */
719:            final void parsePacketDataBegin(HeaderSetImpl headers, int offset) {
720:                if (DEBUG) {
721:                    System.out.println("parsePacketDataBegin()");
722:                }
723:                packetOffset = offset;
724:                headers.packetType = buffer[0] & 0xFF;
725:
726:                parseConnectionID();
727:                dataOffset = packetOffset;
728:            }
729:
730:            /**
731:             * Parse packet headers, put BODY field content (data) in specified output
732:             * array. If output is null, search for a BODY block and return 1 if it is
733:             * found.
734:             * @return number of bytes put in output.
735:             */
736:            final int parsePacketData(HeaderSetImpl headers, byte[] output,
737:                    int outputOffset, int outputLength) throws IOException {
738:                if (DEBUG2) {
739:                    System.out.println("parsePacketData()");
740:                }
741:                int result = 0;
742:                while (true) {
743:                    int len = packetOffset - dataOffset;
744:                    if (DEBUG2) {
745:                        System.out.print("packetOffset = " + packetOffset
746:                                + " dataOffset = " + dataOffset);
747:                        System.out.println(" len = " + len);
748:                    }
749:                    if (len > 0) {
750:                        if (output == null) {
751:                            // special case for serching first data block
752:                            // without actual read
753:                            return 1;
754:                        }
755:                        if (len > outputLength)
756:                            len = outputLength;
757:                        System.arraycopy(buffer, dataOffset, output,
758:                                outputOffset, len);
759:                        outputOffset += len;
760:                        outputLength -= len;
761:                        dataOffset += len;
762:                        result += len;
763:                        if (outputLength == 0)
764:                            return result;
765:                        continue;
766:                    }
767:
768:                    if (DEBUG) {
769:                        System.out.println("packetOffset = " + packetOffset
770:                                + " packetLength = " + packetLength);
771:                    }
772:                    if (packetOffset == packetLength) {
773:                        return result;
774:                    }
775:                    int headerId = buffer[packetOffset] & 0xff;
776:
777:                    if (headerId == HEADER_BODY || headerId == HEADER_EOFBODY) {
778:                        isEof = (headerId == HEADER_EOFBODY);
779:                        dataOffset = packetOffset + 3;
780:                        int length = decodeLength16(packetOffset + 1);
781:                        if (packetOffset + length > packetLength) {
782:                            throw new IOException("protocol error");
783:                        }
784:                        packetOffset += length;
785:                        continue;
786:                    }
787:
788:                    parseHeader(headers);
789:                    dataOffset = packetOffset;
790:                }
791:            }
792:
793:            final void parseEnd() throws IOException {
794:                if (DEBUG) {
795:                    System.out.println("parseEnd()");
796:                }
797:                if (authFailed) {
798:                    authFailed = false;
799:                    onMissingAuthResponse();
800:                }
801:            }
802:
803:            final int decodeLength16(int off) {
804:                return ((((int) buffer[off]) & 0xFF) << 8)
805:                        + (((int) buffer[off + 1]) & 0xFF);
806:            }
807:
808:            private final long decodeInt() {
809:                return ((buffer[packetOffset + 0] & 0xffl) << 24)
810:                        + ((buffer[packetOffset + 1] & 0xffl) << 16)
811:                        + ((buffer[packetOffset + 2] & 0xffl) << 8)
812:                        + (buffer[packetOffset + 3] & 0xffl);
813:            }
814:
815:            private final Calendar decodeTime8601() throws IOException {
816:                int year, month, date, hour, minute, second;
817:
818:                int len = decodeLength16(packetOffset) - 3;
819:                packetOffset += 2;
820:
821:                if (len < 15 || len > 16 || buffer[packetOffset + 8] != 0x54 // 'T'
822:                        || (len == 16 && buffer[packetOffset + 15] != 0x5A)) { // 'Z'
823:                    packetOffset += len;
824:                    throw new IOException("corrupted time header");
825:                }
826:                for (int i = 0; i < 14; i++) {
827:                    if (i == 8)
828:                        continue;
829:                    int chr = buffer[packetOffset + i] - 0x30; // '0'
830:                    if (chr < 0 || chr > 9) {
831:                        packetOffset += len;
832:                        throw new IOException("corrupted time header");
833:                    }
834:                }
835:
836:                year = (buffer[packetOffset + 0] - 0x30) * 1000
837:                        + (buffer[packetOffset + 1] - 0x30) * 100
838:                        + (buffer[packetOffset + 2] - 0x30) * 10
839:                        + (buffer[packetOffset + 3] - 0x30);
840:                month = (buffer[packetOffset + 4] - 0x30) * 10
841:                        + (buffer[packetOffset + 5] - 0x30);
842:                date = (buffer[packetOffset + 6] - 0x30) * 10
843:                        + (buffer[packetOffset + 7] - 0x30);
844:
845:                hour = (buffer[packetOffset + 9] - 0x30) * 10
846:                        + (buffer[packetOffset + 10] - 0x30);
847:                minute = (buffer[packetOffset + 11] - 0x30) * 10
848:                        + (buffer[packetOffset + 12] - 0x30);
849:                second = (buffer[packetOffset + 13] - 0x30) * 10
850:                        + (buffer[packetOffset + 14] - 0x30);
851:
852:                // is check validness of time fields required?
853:
854:                Calendar cal;
855:                // 'len' value 15 means local time,
856:                // 16 means UTC (in this case time string has 'Z' suffix)
857:                if (len == 16) {
858:                    cal = Calendar.getInstance(utcTimeZone);
859:                } else {
860:                    cal = Calendar.getInstance();
861:                }
862:                cal.set(Calendar.YEAR, year);
863:                cal.set(Calendar.MONTH, month - 1); // Calendar.JANUARY = 0
864:                cal.set(Calendar.DATE, date);
865:
866:                // ISO 8601 standard uses the 24-hour clock
867:                // Therefore you use HOUR_OF_DAY not HOUR
868:                cal.set(Calendar.HOUR_OF_DAY, hour);
869:
870:                cal.set(Calendar.MINUTE, minute);
871:                cal.set(Calendar.SECOND, second);
872:
873:                // set milliseconds to zero since
874:                // ISO 8601 uses only second precision
875:                cal.set(Calendar.MILLISECOND, 0);
876:
877:                packetOffset += len;
878:                return cal;
879:            }
880:
881:            static int validateStatus(int status) {
882:                switch (status) {
883:                case ResponseCodes.OBEX_DATABASE_FULL:
884:                case ResponseCodes.OBEX_DATABASE_LOCKED:
885:                case ResponseCodes.OBEX_HTTP_ACCEPTED:
886:                case ResponseCodes.OBEX_HTTP_BAD_GATEWAY:
887:                case ResponseCodes.OBEX_HTTP_BAD_METHOD:
888:                case ResponseCodes.OBEX_HTTP_BAD_REQUEST:
889:                case ResponseCodes.OBEX_HTTP_CONFLICT:
890:                case ResponseCodes.OBEX_HTTP_CREATED:
891:                case ResponseCodes.OBEX_HTTP_ENTITY_TOO_LARGE:
892:                case ResponseCodes.OBEX_HTTP_FORBIDDEN:
893:                case ResponseCodes.OBEX_HTTP_GATEWAY_TIMEOUT:
894:                case ResponseCodes.OBEX_HTTP_GONE:
895:                case ResponseCodes.OBEX_HTTP_INTERNAL_ERROR:
896:                case ResponseCodes.OBEX_HTTP_LENGTH_REQUIRED:
897:                case ResponseCodes.OBEX_HTTP_MOVED_PERM:
898:                case ResponseCodes.OBEX_HTTP_MOVED_TEMP:
899:                case ResponseCodes.OBEX_HTTP_MULT_CHOICE:
900:                case ResponseCodes.OBEX_HTTP_NO_CONTENT:
901:                case ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE:
902:                case ResponseCodes.OBEX_HTTP_NOT_AUTHORITATIVE:
903:                case ResponseCodes.OBEX_HTTP_NOT_FOUND:
904:                case ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED:
905:                case ResponseCodes.OBEX_HTTP_NOT_MODIFIED:
906:                case ResponseCodes.OBEX_HTTP_OK:
907:                case ResponseCodes.OBEX_HTTP_PARTIAL:
908:                case ResponseCodes.OBEX_HTTP_PAYMENT_REQUIRED:
909:                case ResponseCodes.OBEX_HTTP_PRECON_FAILED:
910:                case ResponseCodes.OBEX_HTTP_PROXY_AUTH:
911:                case ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE:
912:                case ResponseCodes.OBEX_HTTP_RESET:
913:                case ResponseCodes.OBEX_HTTP_SEE_OTHER:
914:                case ResponseCodes.OBEX_HTTP_TIMEOUT:
915:                case ResponseCodes.OBEX_HTTP_UNAUTHORIZED:
916:                case ResponseCodes.OBEX_HTTP_UNAVAILABLE:
917:                case ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE:
918:                case ResponseCodes.OBEX_HTTP_USE_PROXY:
919:                case ResponseCodes.OBEX_HTTP_VERSION:
920:                    return status;
921:                default:
922:                    return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
923:                }
924:            }
925:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.