2 * Copyright(c) 2001-2007 Sun Microsystems, Inc. All rights reserved.
4 * The Sun Project JXTA(TM) Software License
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
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.
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.
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.
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.
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.
41 * JXTA is a registered trademark of Sun Microsystems, Inc. in the United
42 * States and other countries.
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.
48 * ====================================================================
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.
54 * This license is based on the BSD license adopted by the Apache Foundation.
57 package net.jxta.protocol;
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;
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;
81 * This class defines the DiscoveryService message "Response". <p/>
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
87 *@see net.jxta.discovery.DiscoveryService
88 *@see net.jxta.protocol.DiscoveryQueryMsg
90 public abstract class DiscoveryResponseMsg {
95 private final static transient Logger LOG = Logger.getLogger(DiscoveryResponseMsg.class.getName());
98 * attribute used by the query
100 protected String attr = null;
103 * Responding peer's advertisement
105 protected PeerAdvertisement peerAdvertisement = null;
108 * The advertisement responses serialized into strings.
110 protected final List<String> responses = new ArrayList<String>(0);
113 * The advertisement responses deserialized.
115 protected final List<Advertisement> advertisements = new ArrayList<Advertisement>(0);
120 protected final List<Long> expirations = new ArrayList<Long>(0);
123 * Advertisement type used by the query
125 * <p/>FIXME 20040514 bondolo@jxta.org not a great default...
127 protected int type = DiscoveryService.PEER;
130 * Value used by the query
132 protected String value = null;
135 * All messages have a type(in xml this is !doctype) which identifies the
138 * @return String "jxta:ResolverResponse"
140 public static String getAdvertisementType() {
141 return "jxta:DiscoveryResponse";
145 * Get the response type
147 * @return int type of discovery message PEER, GROUP or ADV discovery type
150 public int getDiscoveryType() {
155 * set the Response type whether it's peer, or group discovery
157 * @param type int representing the type
159 public void setDiscoveryType(int type) {
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.
170 * @param asMimeType mime-type requested
171 * @return Document document that represents the advertisement
174 public abstract Document getDocument(MimeMediaType asMimeType);
177 * returns the responding peer's advertisement
179 * @return the Peer's advertisement
181 public PeerAdvertisement getPeerAdvertisement() {
182 return peerAdvertisement;
186 * Sets the responding peer's advertisement
188 * @param newAdv the responding Peer's advertisement
190 public void setPeerAdvertisement(PeerAdvertisement newAdv) {
191 peerAdvertisement = newAdv;
195 * returns the attributes used by the query
197 * @return String attribute of the query
199 public String getQueryAttr() {
204 * returns the value used by the query
206 *@return String value used by the query
208 public String getQueryValue() {
213 * Get the response count
217 public int getResponseCount() {
218 if (expirations.isEmpty() && (peerAdvertisement != null) && (type == DiscoveryService.PEER)) {
221 return responses.size();
226 * Gets the expirations attribute of the DiscoveryResponseMsg object
228 * @return The expirations value
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);
236 return Collections.enumeration(expirations);
240 * set the expirations for this query
242 * @param expirations the expirations for this query
244 public void setExpirations(List<Long> expirations) {
245 this.expirations.clear();
246 this.expirations.addAll(expirations);
250 * returns the response(s)
252 * @return Enumeration of String responses
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());
260 return Collections.enumeration(responses);
264 * Set the responses to the query. The responses may be either
265 * {@code Advertisement}, {@code String} or {@code InputStream}.
267 * @param responses List of responses
269 public void setResponses(List responses) {
270 this.responses.clear();
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);
280 if (null != result) {
281 this.responses.add(result);
284 throw new IllegalArgumentException("Non-String or InputStream response recevied.");
290 * Reads in a stream into a string
292 * @param is inputstream
293 * @return string representation of a stream
295 private String streamToString(InputStream is) {
296 Reader reader = null;
299 reader = new InputStreamReader(is, "UTF-8");
300 } catch (UnsupportedEncodingException impossible) {
301 throw new Error("UTF-8 encoding not supported?!?");
304 StringBuilder stw = new StringBuilder();
305 char[] buf = new char[512];
309 int c = reader.read(buf);
314 stw.append(buf, 0, c);
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);
324 } catch (IOException ignored) {}
327 return stw.toString();
331 * Set the attribute used by the query
333 * @param attr query attribute
335 public void setQueryAttr(String attr) {
340 * Set the value used by the query
342 * @param value Query value
344 public void setQueryValue(String value) {
349 * Get the responses to the query as advertisements.
351 * @return The response advertisements.
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));
359 if (advertisements.isEmpty() && !responses.isEmpty()) {
360 // Convert the responses.
361 for (String aResponse : responses) {
363 XMLDocument anXMLDoc = (XMLDocument) StructuredDocumentFactory.newStructuredDocument(MimeMediaType.XMLUTF8
365 new StringReader(aResponse));
366 Advertisement anAdv = AdvertisementFactory.newAdvertisement(anXMLDoc);
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);
377 return Collections.enumeration(advertisements);