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.midp.io.j2me.btgoep;
027:
028: import com.sun.kvem.jsr082.obex.ObexTransport;
029: import javax.microedition.io.StreamConnection;
030: import javax.microedition.io.Connection;
031: import java.io.InputStream;
032: import java.io.OutputStream;
033: import java.io.IOException;
034: import com.sun.midp.main.Configuration;
035:
036: /**
037: * Provides underlying stream connection used as transport by shared obex
038: * implementation.
039: */
040: public class BTGOEPConnection implements ObexTransport {
041:
042: private StreamConnection sock;
043: private InputStream is;
044: private OutputStream os;
045:
046: /*
047: * Create BTGOEPConnection
048: * @param sock Stream connection for the transport layer
049: */
050: protected BTGOEPConnection(StreamConnection sock)
051: throws IOException {
052: this .sock = sock;
053: is = sock.openInputStream();
054: os = sock.openOutputStream();
055: }
056:
057: /**
058: * Closes connection as well as the input stream and
059: * the output stream openning for this connection.
060: * @throws IOException if I/O error.
061: */
062: public void close() throws IOException {
063: IOException ioe = null;
064:
065: try {
066: is.close();
067: } catch (IOException e) {
068: ioe = e;
069: }
070:
071: try {
072: os.close();
073: } catch (IOException e) {
074: ioe = e;
075: }
076:
077: try {
078: sock.close();
079: } catch (IOException e) {
080: ioe = e;
081: }
082:
083: // catch IOException if any of the above call has thrown one
084: if (ioe != null) {
085: throw ioe;
086: }
087: }
088:
089: /**
090: * Reads the packet data into specified buffer.
091: * <p>
092: * If the specified buffer length is 0, then 0 data
093: * will be read into this buffer, and the rest of packet
094: * data is lost.
095: * <p>
096: *
097: * @param inData the data array to fill with received bytes.
098: * @exception IOException if a local or remote connection
099: * is closed or I/O error has happen.
100: *
101: * @exception NullPointerException if the specified buffer is null.
102: */
103: public int read(byte[] inData) throws IOException {
104: readFully(inData, 0, 3); // read header
105: int packetLength = decodeLength16(inData, 1);
106: if (packetLength < 3 || packetLength > inData.length) {
107: throw new IOException("protocol error");
108: }
109:
110: readFully(inData, 3, packetLength - 3);
111: return packetLength;
112: }
113:
114: /**
115: *
116: * @param outData the buffer with the data to be sent.
117: * @param len the number of bytes to be sent.
118: * @exception IOException if a local or remote connection
119: * is closed or I/O error has happen.
120: *
121: * @exception NullPointerException if the specified buffer is null.
122: */
123: public void write(byte[] outData, int len) throws IOException {
124: os.write(outData, 0, len);
125: os.flush();
126: }
127:
128: /**
129: * Determines the amount of data (maximum packet size) that can
130: * be successfully sent in a single write operation. If the size
131: * of data is greater than the maximum packet size, then then only
132: * the first maximum packet size bytes of the packet are sent,
133: * and the rest will be discarded.
134: * <p>
135: *
136: * @return the maximum number of bytes that can be sent/received
137: * in a single call to read()/ write() without losing any data.
138: */
139: public int getMaximumPacketSize() {
140: return Configuration.getIntProperty("obex.packetLength.max",
141: 4096);
142: }
143:
144: /**
145: * Reads up to <code>len</code> bytes of data from the input stream into
146: * an array of bytes.
147: * @param array the buffer into which the data is read.
148: * @param offset the start offset in array <code>b</code>
149: * at which the data is written.
150: * @param size the maximum number of bytes to read.
151: * @exception IOException if an I/O error occurs.
152: */
153: private final void readFully(byte[] array, int offset, int size)
154: throws IOException {
155: while (size != 0) {
156: int count = is.read(array, offset, size);
157: if (count == -1) {
158: throw new IOException("read error");
159: }
160: offset += count;
161: size -= count;
162: }
163: }
164:
165: private final int decodeLength16(byte[] buffer, int off) {
166: return ((((int) buffer[off]) & 0xFF) << 8)
167: + (((int) buffer[off + 1]) & 0xFF);
168: }
169:
170: /**
171: * Get underlying connection.
172: */
173: public Connection getUnderlyingConnection() {
174: return sock;
175: }
176: }
|