]> sjero.net Git - linphone/blob - p2pproxy/dependencies-src/jxse-src-2.5/api/src/net/jxta/protocol/DiscoveryResponseMsg.java
7e49fdc0fa4b3ac1011590d09ed467e0a38a8088
[linphone] / p2pproxy / dependencies-src / jxse-src-2.5 / api / src / net / jxta / protocol / DiscoveryResponseMsg.java
1 /*
2  * Copyright(c) 2001-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.protocol;
58
59
60 import java.io.IOException;
61 import java.io.InputStream;
62 import java.io.InputStreamReader;
63 import java.io.Reader;
64 import java.io.StringReader;
65 import java.io.UnsupportedEncodingException;
66 import java.util.*;
67
68 import net.jxta.discovery.DiscoveryService;
69 import net.jxta.document.Document;
70 import net.jxta.document.MimeMediaType;
71 import net.jxta.document.Advertisement;
72 import net.jxta.document.AdvertisementFactory;
73 import net.jxta.document.StructuredDocumentFactory;
74 import net.jxta.document.XMLDocument;
75 import java.util.logging.Level;
76 import net.jxta.logging.Logging;
77 import java.util.logging.Logger;
78
79
80 /**
81  *  This class defines the DiscoveryService message "Response". <p/>
82  *
83  *  The default behavior of this abstract class is simply a place holder for the
84  *  generic resolver query fields. This message is the response to the
85  *  DiscoveryQueryMsg.
86  *
87  *@see    net.jxta.discovery.DiscoveryService
88  *@see    net.jxta.protocol.DiscoveryQueryMsg
89  */
90 public abstract class DiscoveryResponseMsg {
91     
92     /**
93      *  Logger
94      */
95     private final static transient Logger LOG = Logger.getLogger(DiscoveryResponseMsg.class.getName());
96     
97     /**
98      *  attribute used by the query
99      */
100     protected String attr = null;
101     
102     /**
103      *  Responding peer's advertisement
104      */
105     protected PeerAdvertisement peerAdvertisement = null;
106     
107     /**
108      * The advertisement responses serialized into strings.
109      */
110     protected final List<String> responses = new ArrayList<String>(0);
111     
112     /**
113      *  The advertisement responses deserialized.
114      */
115     protected final List<Advertisement> advertisements = new ArrayList<Advertisement>(0);
116     
117     /**
118      *  Expirations
119      */
120     protected final List<Long> expirations = new ArrayList<Long>(0);
121     
122     /**
123      *  Advertisement type used by the query
124      *
125      *  <p/>FIXME 20040514 bondolo@jxta.org not a great default...
126      */
127     protected int type = DiscoveryService.PEER;
128     
129     /**
130      *  Value used by the query
131      */
132     protected String value = null;
133     
134     /**
135      *  All messages have a type(in xml this is !doctype) which identifies the
136      *  message
137      *
138      * @return    String "jxta:ResolverResponse"
139      */
140     public static String getAdvertisementType() {
141         return "jxta:DiscoveryResponse";
142     }
143     
144     /**
145      *  Get the response type
146      *
147      * @return int type of discovery message PEER, GROUP or ADV discovery type
148      *      response
149      */
150     public int getDiscoveryType() {
151         return type;
152     }
153     
154     /**
155      *  set the Response type whether it's peer, or group discovery
156      *
157      * @param  type  int representing the type
158      */
159     public void setDiscoveryType(int type) {
160         this.type = type;
161     }
162     
163     /**
164      *  Write advertisement into a document. asMimeType is a mime media-type
165      *  specification and provides the form of the document which is being
166      *  requested. Two standard document forms are defined. "text/text" encodes
167      *  the document in a form nice for printing out and "text/xml" which
168      *  provides an XML format.
169      *
170      * @param  asMimeType  mime-type requested
171      * @return             Document document that represents the advertisement
172      */
173     
174     public abstract Document getDocument(MimeMediaType asMimeType);
175     
176     /**
177      *  returns the responding peer's advertisement
178      *
179      * @return the Peer's advertisement
180      */
181     public PeerAdvertisement getPeerAdvertisement() {
182         return peerAdvertisement;
183     }
184     
185     /**
186      *  Sets the responding peer's advertisement
187      *
188      * @param newAdv the responding Peer's advertisement
189      */
190     public void setPeerAdvertisement(PeerAdvertisement newAdv) {
191         peerAdvertisement = newAdv;
192     }
193     
194     /**
195      * returns the attributes used by the query
196      *
197      * @return    String attribute of the query
198      */
199     public String getQueryAttr() {
200         return attr;
201     }
202     
203     /**
204      *  returns the value used by the query
205      *
206      *@return    String value used by the query
207      */
208     public String getQueryValue() {
209         return value;
210     }
211     
212     /**
213      *  Get the response count
214      *
215      * @return    int count
216      */
217     public int getResponseCount() {
218         if (expirations.isEmpty() && (peerAdvertisement != null) && (type == DiscoveryService.PEER)) {
219             return 1;
220         } else {
221             return responses.size();
222         }
223     }
224     
225     /**
226      *  Gets the expirations attribute of the DiscoveryResponseMsg object
227      *
228      * @return    The expirations value
229      */
230     public Enumeration<Long> getExpirations() {
231         if (expirations.isEmpty() && (peerAdvertisement != null) && (type == DiscoveryService.PEER)) {
232             // this takes care of the case where the only response is the peerAdv
233             expirations.add(DiscoveryService.DEFAULT_EXPIRATION);
234         }
235         
236         return Collections.enumeration(expirations);
237     }
238     
239     /**
240      * set the expirations for this query
241      *
242      * @param  expirations  the expirations for this query
243      */
244     public void setExpirations(List<Long> expirations) {
245         this.expirations.clear();
246         this.expirations.addAll(expirations);
247     }
248     
249     /**
250      * returns the response(s)
251      *
252      * @return    Enumeration of String responses
253      */
254     public Enumeration<String> getResponses() {
255         if (responses.isEmpty() && (peerAdvertisement != null) && (type == DiscoveryService.PEER)) {
256             // this takes care of the case where the only response is the peerAdv
257             responses.add(peerAdvertisement.toString());
258         }
259         
260         return Collections.enumeration(responses);
261     }
262     
263     /**
264      *  Set the responses to the query. The responses may be either
265      *  {@code Advertisement}, {@code String} or {@code InputStream}.
266      *
267      *  @param  responses List of responses
268      */
269     public void setResponses(List responses) {
270         this.responses.clear();
271         
272         for (Object response : responses) {
273             if (response instanceof Advertisement) {
274                 this.responses.add(((Advertisement) response).getDocument(MimeMediaType.XMLUTF8).toString());
275             } else if (response instanceof String) {
276                 this.responses.add((String) response);
277             } else if (response instanceof InputStream) {
278                 String result = streamToString((InputStream) response);
279                 
280                 if (null != result) {
281                     this.responses.add(result);
282                 }
283             } else {
284                 throw new IllegalArgumentException("Non-String or InputStream response recevied.");
285             }
286         }
287     }
288
289     /**
290      *  Reads in a stream into a string
291      *
292      *  @param  is  inputstream
293      *  @return     string representation of a stream
294      */
295     private String streamToString(InputStream is) {
296         Reader reader = null;
297         
298         try {
299             reader = new InputStreamReader(is, "UTF-8");
300         } catch (UnsupportedEncodingException impossible) {
301             throw new Error("UTF-8 encoding not supported?!?");
302         }
303         
304         StringBuilder stw = new StringBuilder();
305         char[] buf = new char[512];
306
307         try {
308             do {
309                 int c = reader.read(buf);
310
311                 if (c == -1) {
312                     break;
313                 }
314                 stw.append(buf, 0, c);
315             } while (true);
316         } catch (IOException ie) {
317             if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
318                 LOG.log(Level.WARNING, "Got an Exception during stream conversion", ie);
319             }
320             return null;
321         } finally {
322             try {
323                 is.close();
324             } catch (IOException ignored) {}
325         }
326
327         return stw.toString();
328     }
329     
330     /**
331      *  Set the attribute used by the query
332      *
333      *  @param  attr query attribute
334      */
335     public void setQueryAttr(String attr) {
336         this.attr = attr;
337     }
338     
339     /**
340      *  Set the value used by the query
341      *
342      *  @param  value Query value
343      */
344     public void setQueryValue(String value) {
345         this.value = value;
346     }
347     
348     /**
349      * Get the responses to the query as advertisements.
350      *
351      * @return The response advertisements.
352      */
353     public Enumeration<Advertisement> getAdvertisements() {
354         if (responses.isEmpty() && (peerAdvertisement != null) && (type == DiscoveryService.PEER)) {
355             // this takes care of the case where the only response is the peerAdv
356             return Collections.enumeration(Collections.singletonList((Advertisement) peerAdvertisement));
357         }
358         
359         if (advertisements.isEmpty() && !responses.isEmpty()) {
360             // Convert the responses.
361             for (String aResponse : responses) {
362                 try {
363                     XMLDocument anXMLDoc = (XMLDocument) StructuredDocumentFactory.newStructuredDocument(MimeMediaType.XMLUTF8
364                             ,
365                             new StringReader(aResponse));
366                     Advertisement anAdv = AdvertisementFactory.newAdvertisement(anXMLDoc);
367                     
368                     advertisements.add(anAdv);
369                 } catch (IOException badAdvertisement) {
370                     if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
371                         LOG.log(Level.WARNING, "Invalid response in message : ", badAdvertisement);
372                     }
373                 }
374             }
375         }
376         
377         return Collections.enumeration(advertisements);
378     }
379 }