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.irdaobex;
027:
028: import javax.microedition.io.Connection;
029: import javax.microedition.io.StreamConnection;
030: import javax.microedition.io.StreamConnectionNotifier;
031: import java.io.IOException;
032: import java.io.InterruptedIOException;
033:
034: /**
035: * Provides the implementation of a stream connection notifier for the IrDA
036: * protocol.
037: */
038: public class IrNativeNotifier implements StreamConnectionNotifier {
039:
040: /** Hint bits to be set by the server. */
041: private int hints;
042:
043: /** IAS services to be advertised by the server. */
044: private String[] ias;
045:
046: /**
047: * Handle to peer connection. This handle is mainained until it is passed
048: * to IrNativeConnection to prevent resource leaks in case of VM
049: * termination. Only accessed from native code.
050: */
051: private int peerHandle = getInvalidPeerHandle();
052:
053: /**
054: * Handle to native array containing connection handles,
055: * except for <code>peer</code>. Only accessed from native code.
056: */
057: private int dataHandle = getInvalidDataHandle();
058:
059: /** Flag forcing acceptAndOpen() method to exit. */
060: private boolean closeRq = false;
061:
062: /** Period in milliseconds between connection attempts. */
063: private final int ACCEPT_RETRY_PERIOD = 50;
064:
065: /** Static initializer. */
066: static {
067: initialize();
068: }
069:
070: /**
071: * Native class initializer.
072: */
073: private static native void initialize();
074:
075: /**
076: * Class constructor.
077: *
078: * @param hints hint bits
079: * @param ias IAS string
080: */
081: public IrNativeNotifier(int hints, String[] ias) {
082: this .hints = hints;
083: this .ias = ias;
084: }
085:
086: /**
087: * Native finalizer. Releases all native resources used by this notifier.
088: */
089: private native void finalize();
090:
091: /**
092: * Returns a StreamConnection object that represents a server side
093: * connection.
094: *
095: * @return a StreamConnection to communicate with a client
096: * @throws IOException if an I/O error occurs
097: */
098: public StreamConnection acceptAndOpen() throws IOException {
099: try {
100: closeRq = false;
101: for (int i = 0; i < ias.length; i++) {
102: listen(i, hints, ias[i]);
103: }
104: int i = 0;
105: while (!accept(i) && !closeRq) {
106: i = (i + 1) % ias.length;
107: try {
108: Thread.sleep(ACCEPT_RETRY_PERIOD);
109: } catch (InterruptedException e) {
110: throw new InterruptedIOException(
111: "Operation was interrupted.");
112: }
113: }
114: if (closeRq) {
115: throw new IOException("Connection was closed.");
116: }
117: IrNativeConnection conn = new IrNativeConnection();
118: passPeer(conn);
119: return conn;
120: } finally {
121: release();
122: }
123: }
124:
125: /**
126: * Interrupts acceptAndOpen() operation.
127: *
128: * @throws IOException if an I/O error occurs
129: */
130: public void close() throws IOException {
131: closeRq = true;
132: }
133:
134: /**
135: * Allocates native connection resource for listening with specified
136: * hint bits and IAS set.
137: *
138: * @param index connection number starting from 0
139: * @param hints hint bits to be set
140: * @param ias IAS to be advertised
141: * @throws IOException if an I/O error occurs
142: */
143: private native void listen(int index, int hints, String ias)
144: throws IOException;
145:
146: /**
147: * Accepts a pending client connection.
148: *
149: * @param index connection number starting from 0
150: * @return true if the connection was established, false otherwise
151: * @throws IOException if an I/O error occurs
152: */
153: private native boolean accept(int index) throws IOException;
154:
155: /**
156: * Releases native resources.
157: */
158: private native void release();
159:
160: /**
161: * Passes ownership of the native peer handle to the IrNativeConnection
162: * object. <code>peer</code> is set to <code>-1</code> after calling this
163: * method.
164: *
165: * @param conn IrNativeConnection object to pass native peer handle to.
166: */
167: private native void passPeer(IrNativeConnection conn);
168:
169: /**
170: * Returns an invalid connection handle value to be used during
171: * initialization of instances of this class.
172: *
173: * @return a native connection handle value considered to be invalid
174: */
175: private static native int getInvalidPeerHandle();
176:
177: /**
178: * Returns an invalid memory handle value to be used during
179: * initialization of instances of this class.
180: *
181: * @return a native memory handle value considered to be invalid
182: */
183: private static native int getInvalidDataHandle();
184:
185: }
|