Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: net/jxta/impl/protocol/PipeResolverMsg.java


1   /*
2    * Copyright (c) 2002 Sun Microsystems, Inc.  All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted provided that the following conditions
6    * are met:
7    *
8    * 1. Redistributions of source code must retain the above copyright
9    *    notice, this list of conditions and the following disclaimer.
10   *
11   * 2. Redistributions in binary form must reproduce the above copyright
12   *    notice, this list of conditions and the following disclaimer in
13   *    the documentation and/or other materials provided with the
14   *    distribution.
15   *
16   * 3. The end-user documentation included with the redistribution,
17   *    if any, must include the following acknowledgment:
18   *       "This product includes software developed by the
19   *       Sun Microsystems, Inc. for Project JXTA."
20   *    Alternately, this acknowledgment may appear in the software itself,
21   *    if and wherever such third-party acknowledgments normally appear.
22   *
23   * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must
24   *    not be used to endorse or promote products derived from this
25   *    software without prior written permission. For written
26   *    permission, please contact Project JXTA at http://www.jxta.org.
27   *
28   * 5. Products derived from this software may not be called "JXTA",
29   *    nor may "JXTA" appear in their name, without prior written
30   *    permission of Sun.
31   *
32   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
33   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
34   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35   * DISCLAIMED.  IN NO EVENT SHALL SUN MICROSYSTEMS OR
36   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43   * SUCH DAMAGE.
44   * ====================================================================
45   *
46   * This software consists of voluntary contributions made by many
47   * individuals on behalf of Project JXTA.  For more
48   * information on Project JXTA, please see
49   * <http://www.jxta.org/>.
50   *
51   * This license is based on the BSD license adopted by the Apache Foundation.
52   *
53   * $Id: PipeResolverMsg.java,v 1.11 2004/10/09 23:35:38 bondolo Exp $
54   */
55  
56  package net.jxta.impl.protocol;
57  
58  import java.io.InputStream;
59  import java.io.StringWriter;
60  import java.io.StringReader;
61  import java.io.Writer;
62  import java.net.URI;
63  import java.util.Enumeration;
64  import java.util.Hashtable;
65  import java.util.Iterator;
66  import java.util.Set;
67  
68  import java.io.IOException;
69  import java.net.URISyntaxException;
70  
71  import org.apache.log4j.Logger;
72  import org.apache.log4j.Level;
73  
74  import net.jxta.document.AdvertisementFactory;
75  import net.jxta.document.Attribute;
76  import net.jxta.document.Attributable;
77  import net.jxta.document.Element;
78  import net.jxta.document.TextElement;
79  import net.jxta.document.MimeMediaType;
80  import net.jxta.document.Document;
81  import net.jxta.document.StructuredTextDocument;
82  import net.jxta.document.StructuredDocumentFactory;
83  import net.jxta.document.StructuredDocumentUtils;
84  import net.jxta.id.ID;
85  import net.jxta.id.IDFactory;
86  import net.jxta.peer.PeerID;
87  import net.jxta.pipe.PipeID;
88  import net.jxta.protocol.PeerAdvertisement;
89  import net.jxta.protocol.PipeResolverMessage;
90  
91  /**
92   * This class implements {@link net.jxta.protocol.PipeResolverMessage} by
93   * providing {@link #initialize(Element)} and {@link #getDocument(MimeMediaType)}
94   * implementations.
95   *
96   * <p/>It implements the PipeResolver message for the standard Pipe
97     Binding Protocol (PBP) with the following schema:
98   *
99   * <pre><code>
100  * &lt;xs:element name="jxta:PipeResolver" type="jxta:PipeResolver"/>
101  *
102  * &lt;xs:simpleType name="PipeResolverMsgType">
103  *   &lt;xs:restriction base="xs:string">
104  *     &lt;!-- QUERY -->
105  *     &lt;xs:enumeration value="Query"/>
106  *     &lt;!-- ANSWER -->
107  *     &lt;xs:enumeration value="Answer"/>
108  *   &lt;/xs:restriction>
109  * &lt;/xs:simpleType>
110  *
111  * &lt;xs:complexType name="PipeResolver">
112  *   &lt;xs:sequence>
113  *     &lt;xs:element name="MsgType" type="jxta:PipeResolverMsgType"/>
114  *     &lt;xs:element name="PipeId" type="jxta:JXTAID"/>
115  * &lt;xs:element name="Type" type="xs:string"/>
116  *
117  *     &lt;!-- used in the query -->
118  * &lt;xs:element name="Cached" type="xs:boolean" default="true" minOccurs="0"/>
119  *     &lt;xs:element name="Peer" type="jxta:JXTAID" minOccurs="0"/>
120  *
121  *     &lt;!-- used in the answer -->
122  *     &lt;xs:element name="Found" type="xs:boolean"/>
123  * &lt;!-- This should refer to a peer adv, but is instead a whole doc -->
124  * &lt;xs:element name="PeerAdv" type="xs:string" minOccurs="0"/>
125  *   &lt;/xs:sequence>
126  * &lt;/xs:complexType>
127  * </code></pre>
128  *
129  * @see net.jxta.pipe.PipeService
130  * @see net.jxta.impl.pipe.PipeServiceImpl
131  * @see <a href="http://spec.jxta.org/nonav/v1.0/docbook/JXTAProtocols.html#proto-pbp" target="_blank">JXTA Protocols Specification : Pipe Binding Protocol</a>
132  **/
133 public class PipeResolverMsg extends PipeResolverMessage {
134     
135     /**
136      *  Log4J Logger
137      **/
138     private final static transient Logger LOG = Logger.getLogger( PipeResolverMsg.class.getName());
139     
140     private final static String MsgTypeTag       = "MsgType";
141     private final static String PipeIdTag        = "PipeId";
142     private final static String PipeTypeTag      = "Type";
143     private final static String PeerIdTag        = "Peer";
144     private final static String PeerAdvTag       = "PeerAdv";
145     private final static String FoundTag         = "Found";
146     
147     private final static String QueryMsgType     = "Query";
148     private final static String AnswerMsgType    = "Answer";
149     
150     public PipeResolverMsg() {
151         super();
152     }
153     
154     public PipeResolverMsg(Element root) {
155         this();
156         initialize( root );
157     }
158     
159     /**
160      *  Initializes the message from a document.
161      **/
162     protected void initialize(Element root) {
163         if( !TextElement.class.isInstance( root ) )
164             throw new IllegalArgumentException( getClass().getName() + " only supports TextElement" );
165         
166         TextElement doc = (TextElement) root;
167         
168         String docName = doc.getName();
169         
170         if( !docName.equals(getMessageType()) )
171             throw new IllegalArgumentException( "Could not construct : "
172             + getClass().getName()
173             + "from doc containing a "
174             + docName );
175         
176         Enumeration each = doc.getChildren();
177         
178         while (each.hasMoreElements()) {
179             TextElement elem = (TextElement) each.nextElement();
180             
181             if (elem.getName().equals(MsgTypeTag)) {
182                 String msgtype = elem.getTextValue();
183                 if( msgtype.equals( QueryMsgType ) )
184                     setMsgType( PipeResolverMessage.MessageType.QUERY );
185                 else if ( msgtype.equals( AnswerMsgType ) )
186                     setMsgType( PipeResolverMessage.MessageType.ANSWER );
187                 else
188                     throw new IllegalArgumentException( "Unexpected Message Type in parsing." );
189                 continue;
190             }
191             
192             if (elem.getName().equals(PipeIdTag)) {
193                 try {
194                     URI pipeID =  new URI( elem.getTextValue() );
195                     setPipeID( IDFactory.fromURI( pipeID ) );
196                 } catch ( URISyntaxException badID ) {
197                     throw new IllegalArgumentException( "Bad pipe ID in message" );
198                 }
199                 continue;
200             }
201             
202             if (elem.getName().equals(PipeTypeTag)) {
203                 setPipeType( elem.getTextValue() );
204                 continue;
205             }
206             
207             if (elem.getName().equals(PeerIdTag)) {
208                 try {
209                     URI peerID =  new URI( elem.getTextValue() );
210                     addPeerID( IDFactory.fromURI( peerID ) );
211                 } catch ( URISyntaxException badID ) {
212                     throw new IllegalArgumentException( "Bad peer ID in message" );
213                 }
214                 continue;
215             }
216             
217             if (elem.getName().equals(FoundTag)) {
218                 setFound( Boolean.valueOf(elem.getTextValue()).booleanValue() );
219                 continue;
220             }
221             
222             // let's check whether the responder sent us a adv
223             if (elem.getName().equals(PeerAdvTag)) {
224                 String peerAdv = elem.getTextValue();
225                 try {
226                     setInputPeerAdv( (PeerAdvertisement) AdvertisementFactory.newAdvertisement(
227                     MimeMediaType.XMLUTF8,
228                     new StringReader(peerAdv)) );
229                 } catch ( IOException caught ) {
230                     if (LOG.isEnabledFor(Level.DEBUG))
231                         LOG.debug( "Malformed peer adv in message", caught );
232                     throw new IllegalArgumentException( "Malformed peer adv in message : " + caught.getMessage() );
233                 }
234                 continue;
235             }
236 
237         }
238         
239         // Begin checking sanity!
240         PipeResolverMessage.MessageType msgType = getMsgType();
241         if ( null == msgType )
242             throw new IllegalArgumentException( "Message type was never set!" );
243         
244         ID pipeID = getPipeID();
245         if( (null == pipeID) || ID.nullID.equals(pipeID) || !(pipeID instanceof PipeID) )
246             throw new IllegalArgumentException( "Input Pipe ID not set or invalid" );
247         
248         if ( null == getPipeType() )
249             throw new IllegalArgumentException( "Pipe type was never set!" );
250         
251         //Query extra checks
252         
253         //Response extra checks
254         if (  PipeResolverMessage.MessageType.ANSWER.equals( msgType ) ) {
255             if( getPeerIDs().isEmpty() ) {
256                 throw new IllegalArgumentException( "An answer without responses is invalid" );
257             }
258         }
259     }
260     
261     /**
262      *  Creates a document out of the message.
263      *
264      *  @param  encodeAs  The document representation format requested.
265      *  @return the message as a document.
266      **/
267     public Document getDocument(MimeMediaType encodeAs) {
268         StructuredTextDocument doc = (StructuredTextDocument)
269         StructuredDocumentFactory.newStructuredDocument(encodeAs, getMessageType() );
270         
271         if( doc instanceof Attributable ) {
272             ((Attributable)doc).addAttribute( "xmlns:jxta", "http://jxta.org" );
273         }
274         
275         PipeResolverMessage.MessageType msgType = getMsgType();
276         if ( null == msgType ) {
277             throw new IllegalStateException( "Message type was never set!" );
278         }
279         
280         ID pipeID = getPipeID();
281         if( (null == pipeID) || ID.nullID.equals(pipeID) || !(pipeID instanceof PipeID) ) {
282             throw new IllegalStateException( "Pipe ID not set or invalid." );
283         }
284         
285         String pipeType = getPipeType();
286         if ( (null == pipeType) || (0 == pipeType.trim().length()) ) {
287             throw new IllegalStateException( "Pipe type was never set or is invalid." );
288         }
289         
290         Element e = null;
291         if(  PipeResolverMessage.MessageType.QUERY.equals( msgType ) ) {
292             e = doc.createElement(MsgTypeTag, QueryMsgType);
293         } else if (  PipeResolverMessage.MessageType.ANSWER.equals( msgType ) ) {
294             e = doc.createElement(MsgTypeTag, AnswerMsgType);
295         } else {
296             throw new IllegalStateException( "Unknown message type :" + msgType.toString() );
297         }
298         doc.appendChild(e);
299         
300         e = doc.createElement(PipeIdTag, pipeID.toString() );
301         doc.appendChild(e);
302         
303         if( (null != pipeType) && (0 != pipeType.length()) ) {
304             e = doc.createElement( PipeTypeTag, pipeType );
305             doc.appendChild(e);
306         }
307         
308         // Write the peer ids.
309         Set peers = getPeerIDs();
310         
311         if ( PipeResolverMessage.MessageType.ANSWER.equals( msgType ) && peers.isEmpty() ) {
312             throw new IllegalStateException( "An ANSWER message must contain at least one peer as part of the response." );
313         }
314         
315         Iterator eachPeer = peers.iterator();
316         
317         while( eachPeer.hasNext() ) {
318             ID aPeer = (ID) eachPeer.next();
319             
320                 e = doc.createElement(PeerIdTag, aPeer.toString() );
321                 doc.appendChild(e);
322         }
323         
324         if(  PipeResolverMessage.MessageType.QUERY.equals( msgType ) ) {
325             // nothing for now...
326         } else if (  PipeResolverMessage.MessageType.ANSWER.equals( msgType ) ) {
327             e = doc.createElement(FoundTag, (isFound() ? Boolean.TRUE : Boolean.FALSE).toString() );
328             doc.appendChild(e);
329             
330             PeerAdvertisement peerAdv = getInputPeerAdv();
331 
332             if (peerAdv != null) {
333                 if( !peers.contains( peerAdv.getPeerID() ) ) {
334                     throw new IllegalStateException( "Provided Peer Advertisement does not refer to one of the peers in the response list." );
335                 }
336                 
337         StructuredTextDocument asDoc = (StructuredTextDocument)
338       peerAdv.getDocument( MimeMediaType.XMLUTF8 );
339                 
340                 e = doc.createElement( PeerAdvTag, asDoc.toString() );
341         doc.appendChild(e);
342       }
343         } else {
344             throw new IllegalStateException( "Unknown message type :" + msgType.toString() );
345         }
346         
347         return doc;
348     }
349 }
350