]> sjero.net Git - linphone/blob - p2pproxy/dependencies-src/jxse-src-2.5/api/src/net/jxta/endpoint/AbstractMessenger.java
d81cba5eb72a62361df0d5e54d7fb840f082c85f
[linphone] / p2pproxy / dependencies-src / jxse-src-2.5 / api / src / net / jxta / endpoint / AbstractMessenger.java
1 /*
2  * Copyright (c) 2004-2007 Sun Microsystems, Inc.  All rights reserved.
3  *  
4  *  The Sun Project JXTA(TM) Software License
5  *  
6  *  Redistribution and use in source and binary forms, with or without 
7  *  modification, are permitted provided that the following conditions are met:
8  *  
9  *  1. Redistributions of source code must retain the above copyright notice,
10  *     this list of conditions and the following disclaimer.
11  *  
12  *  2. Redistributions in binary form must reproduce the above copyright notice, 
13  *     this list of conditions and the following disclaimer in the documentation 
14  *     and/or other materials provided with the distribution.
15  *  
16  *  3. The end-user documentation included with the redistribution, if any, must 
17  *     include the following acknowledgment: "This product includes software 
18  *     developed by Sun Microsystems, Inc. for JXTA(TM) technology." 
19  *     Alternately, this acknowledgment may appear in the software itself, if 
20  *     and wherever such third-party acknowledgments normally appear.
21  *  
22  *  4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must 
23  *     not be used to endorse or promote products derived from this software 
24  *     without prior written permission. For written permission, please contact 
25  *     Project JXTA at http://www.jxta.org.
26  *  
27  *  5. Products derived from this software may not be called "JXTA", nor may 
28  *     "JXTA" appear in their name, without prior written permission of Sun.
29  *  
30  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
31  *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
32  *  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SUN 
33  *  MICROSYSTEMS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
34  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
35  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
36  *  OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
37  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
38  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
39  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  *  
41  *  JXTA is a registered trademark of Sun Microsystems, Inc. in the United 
42  *  States and other countries.
43  *  
44  *  Please see the license information page at :
45  *  <http://www.jxta.org/project/www/license.html> for instructions on use of 
46  *  the license in source files.
47  *  
48  *  ====================================================================
49  *  
50  *  This software consists of voluntary contributions made by many individuals 
51  *  on behalf of Project JXTA. For more information on Project JXTA, please see 
52  *  http://www.jxta.org.
53  *  
54  *  This license is based on the BSD license adopted by the Apache Foundation. 
55  */
56
57 package net.jxta.endpoint;
58
59
60 import net.jxta.util.AbstractSimpleSelectable;
61 import net.jxta.util.SimpleSelectable;
62
63 import java.io.IOException;
64 import java.io.InterruptedIOException;
65
66
67 /**
68  * An AbstractMessenger is used to implement messengers (for example, by transport modules).
69  * It supplies the convenience, bw compatible, obvious, or otherwise rarely changed methods.
70  * Many method cannot be overloaded in order to ensure standard behaviour.
71  * The rest is left to implementations.
72  *
73  * @see net.jxta.endpoint.EndpointService
74  * @see net.jxta.endpoint.EndpointAddress
75  * @see net.jxta.endpoint.Message
76  */
77 public abstract class AbstractMessenger extends AbstractSimpleSelectable implements Messenger {
78
79     /**
80      * The default Maximum Transmission Unit.
81      */
82     protected static final long DEFAULT_MTU = Long.parseLong(System.getProperty("net.jxta.MTU", "65536"));
83
84     /**
85      * The destination address of messages sent on this messenger.
86      */
87     protected final EndpointAddress dstAddress;
88
89     /**
90      * The stateLock that we share with the implementation.
91      * This permits to implement waitState in a totally generic way: waitState depends only on the lock
92      * (provided at construction), and on getState(), supplied by the implementation.
93      */
94     private Object stateLock;
95
96     /**
97      * Create a new abstract messenger.
98      * <p/>
99      * Warning: This class needs to know the object on which to waitState must synchronize. It is generally impossible
100      * to pass it at construction because it is not yet constructed. Instead implementations MUST call {@link #setStateLock}
101      * from their constructor.
102      *
103      * @param dest who messages should be addressed to
104      */
105     public AbstractMessenger(EndpointAddress dest) {
106         dstAddress = dest;
107     }
108
109     /**
110      * {@inheritDoc}
111      * <p/>
112      * A simple implementation for debugging. Do not depend upon the format.
113      */
114     @Override
115     public String toString() {
116         return super.toString() + " {" + dstAddress + "}";
117     }
118
119     /**
120      * Specifies the object on which waitState must synchronize.
121      *
122      * @param stateLock The object on which waitState must synchronize. This has to be the object that gets notified when the
123      *                  implementation changes its state. Changing state is defined as "any operation that causes the result of the
124      *                  <code>getState</code> method to change". Implementations that use the MessengerState state machine should typically use the
125      *                  MessengerState object as their state lock, but it is not assumed.
126      */
127     protected void setStateLock(Object stateLock) {
128         this.stateLock = stateLock;
129     }
130
131     /*
132      * Messenger methods implementations.
133      */
134
135     /**
136      * {@inheritDoc}
137      * <p/>
138      * This is here for backward compatibility reasons.  The notion of long term unemployment still exists, but is no-longer part
139      * of the API.  Self closing for unemployment is now a built-in feature of messengers.
140      */
141     @Deprecated
142     public final boolean isIdle() {
143         return false;
144     }
145
146     /**
147      * {@inheritDoc}
148      */
149     @Deprecated
150     public final boolean isSynchronous() {
151         return false;
152     }
153
154     /**
155      * {@inheritDoc}
156      */
157     public final EndpointAddress getDestinationAddress() {
158         return dstAddress;
159     }
160
161     /**
162      * {@inheritDoc}
163      */
164     @Deprecated
165     public final EndpointAddress getDestinationAddressObject() {
166         return dstAddress;
167     }
168
169     /**
170      * {@inheritDoc}
171      * <p/>It is not always enforced. At least this much can always be sent. 
172      */
173     public long getMTU() {
174         return DEFAULT_MTU;
175     }
176
177     /**
178      * {@inheritDoc}
179      * <p/>
180      * This is a minimal implementation. It may not detect closure
181      * initiated by the other side unless the messenger was actually used
182      * since. A more accurate (but not mandatory implementation) would
183      * actually go and check the underlying connection, if relevant...unless
184      * breakage initiated by the other side is actually reported asynchronously
185      * when it happens. Breakage detection from the other side need not
186      * be reported atomically with its occurrence. This not very important
187      * since we canonicalize transport messengers and so do not need to
188      * aggressively collect closed ones. When not used, messengers die by themselves.
189      */
190     public boolean isClosed() {
191         return (getState() & USABLE) == 0;
192     }
193
194     /**
195      * {@inheritDoc}
196      */
197     public final void flush() throws IOException {
198         int currentState = 0;
199
200         try {
201             currentState = waitState(IDLE, 0);
202         } catch (InterruptedException ie) {
203             InterruptedIOException iio = new InterruptedIOException("flush() interrupted");
204
205             iio.initCause(ie);
206             throw iio;
207         }
208         
209         if ((currentState & (CLOSED | USABLE)) != 0) {
210             return;
211         }
212         
213         throw new IOException("Messenger was unexpectedly closed.");
214     }
215
216     /**
217      * {@inheritDoc}
218      */
219     public final boolean sendMessage(Message msg) throws IOException {
220         return sendMessage(msg, null, null);
221     }
222
223     /**
224      * {@inheritDoc}
225      *
226      */
227     public void sendMessage(Message msg, String service, String serviceParam, OutgoingMessageEventListener listener) {
228         throw new UnsupportedOperationException("This legacy method is not supported by this messenger.");
229     }
230
231     /**
232      * {@inheritDoc}
233      */
234     public final boolean sendMessage(Message msg, String rService, String rServiceParam) throws IOException {
235
236         // We have to retrieve the failure from the message and throw it if its an IOException, this is what the API
237         // says that this method does.
238
239         if (sendMessageN(msg, rService, rServiceParam)) {
240             return true;
241         }
242
243         Object failed = msg.getMessageProperty(Messenger.class);
244
245         if ((failed == null) || !(failed instanceof OutgoingMessageEvent)) {
246             // huh ?
247             return false;
248         }
249
250         Throwable t = ((OutgoingMessageEvent) failed).getFailure();
251
252         if (t == null) {
253             // Must be saturation, then. (No throw for that).
254             return false;
255         }
256
257         // Now see how we can manage to throw it.
258         if (t instanceof IOException) {
259             throw (IOException) t;
260         } else if (t instanceof RuntimeException) {
261             throw (RuntimeException) t;
262         } else if (t instanceof Error) {
263             throw (Error) t;
264         }
265
266         IOException failure = new IOException("Failure sending message");
267
268         failure.initCause(t);
269
270         throw failure;
271     }
272
273     /**
274      * {@inheritDoc}
275      * <p/>
276      * This method synchronizes on the lock object supplied at construction.
277      */
278     public final int waitState(int wantedStates, long timeout) throws InterruptedException {
279         synchronized (stateLock) {
280             if (timeout == 0) {
281                 while ((wantedStates & getState()) == 0) {
282                     stateLock.wait();
283                 }
284                 return getState();
285             }
286
287             if (timeout < 0) {
288                 stateLock.wait(timeout); // let it throw the appropriate error.
289             }
290
291             long start = System.currentTimeMillis();
292             long end = start + timeout;
293
294             if (end < start) {
295                 end = Long.MAX_VALUE;
296             }
297             long left = end - start;
298
299             while ((left > 0) && (wantedStates & getState()) == 0) {
300
301                 stateLock.wait(left);
302
303                 left = end - System.currentTimeMillis();
304             }
305             
306             return getState();
307         }
308     }
309
310     /*
311      * SimpleSelectable implementation.
312      */
313
314     /**
315      * Implements a default for all AbstractMessengers: mirror the event to our selectors. This is what is needed by all the
316      * known AbstractMessengers that register themselves somewhere. (That is ChannelMessengers).
317      * FIXME - jice@jxta.org 20040413: Not sure that this is the best default.
318      *
319      * @param changedObject Ignored.
320      */
321     public void itemChanged(SimpleSelectable changedObject) {
322         notifyChange();
323     }
324 }