]> sjero.net Git - linphone/blob - p2pproxy/dependencies-src/jxse-src-2.5/impl/src/net/jxta/impl/peergroup/StdPeerGroupParamAdv.java
c35b9ce4111e917b58ab028abc5e163733c09221
[linphone] / p2pproxy / dependencies-src / jxse-src-2.5 / impl / src / net / jxta / impl / peergroup / StdPeerGroupParamAdv.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.impl.peergroup;
58
59
60 import net.jxta.document.Advertisement;
61 import net.jxta.document.AdvertisementFactory;
62 import net.jxta.document.Document;
63 import net.jxta.document.Element;
64 import net.jxta.document.MimeMediaType;
65 import net.jxta.document.StructuredDocument;
66 import net.jxta.document.StructuredDocumentFactory;
67 import net.jxta.document.StructuredDocumentUtils;
68 import net.jxta.document.XMLElement;
69 import net.jxta.id.IDFactory;
70 import net.jxta.logging.Logging;
71 import net.jxta.peergroup.PeerGroup;
72 import net.jxta.platform.ModuleClassID;
73 import net.jxta.platform.ModuleSpecID;
74 import net.jxta.protocol.ModuleImplAdvertisement;
75
76 import java.net.URI;
77 import java.util.Enumeration;
78 import java.util.HashMap;
79 import java.util.Map;
80 import java.util.logging.Level;
81 import java.util.logging.Logger;
82
83
84 /**
85  * Not actually an advertisement, but often acts as part of one.
86  *
87  * @deprecated This internal class will eventually be removed. It has several
88  * problems which make it difficult to support. (The most obvious that it 
89  * provides poor abstraction and provides references to its' own internal data
90  * structures). This class is expected to be replaced by a public API class
91  * performing a similar function though such an alternative is not yet available.
92  * You are encouraged to copy this code into your own application or service if
93  * if you depend upon it.
94  */
95 @Deprecated
96 public class StdPeerGroupParamAdv {
97
98     /**
99      * Logger
100      */
101     private static final Logger LOG = Logger.getLogger(StdPeerGroupParamAdv.class.getName());
102
103     private static final String PARAM_TAG = "Parm";
104     private static final String PROTO_TAG = "Proto";
105     private static final String APP_TAG = "App";
106     private static final String SVC_TAG = "Svc";
107     private static final String MCID_TAG = "MCID";
108     private static final String MSID_TAG = "MSID";
109     private static final String MIA_TAG = ModuleImplAdvertisement.getAdvertisementType();
110
111     // In the future we should be able to manipulate all modules regardless of 
112     // their kind, but right now it helps to keep them categorized as follows.
113     
114     /**
115      * The services which will be loaded for this peer group.
116      * <p/>
117      * <ul>
118      *     <li>Keys are {@link net.jxta.platform.ModuleClassID}.</li>
119      *     <li>Values are {@link net.jxta.platform.ModuleSpecID} or
120      *     {@link net.jxta.protocol.ModuleImplAdvertisement}.</li>
121      * </ul>
122      */    
123     private final Map<ModuleClassID, Object> services = new HashMap<ModuleClassID, Object>();
124     
125     /**
126      * The protocols (message transports) which will be loaded for this peer
127      * group.
128      * <p/>
129      * <ul>
130      *     <li>Keys are {@link net.jxta.platform.ModuleClassID}.</li>
131      *     <li>Values are {@link net.jxta.platform.ModuleSpecID} or
132      *     {@link net.jxta.protocol.ModuleImplAdvertisement}.</li>
133      * </ul>
134      */    
135     private final Map<ModuleClassID, Object> transports = new HashMap<ModuleClassID, Object>();
136     
137     /**
138      * The applications which will be loaded for this peer group.
139      * <p/>
140      * <ul>
141      *     <li>Keys are {@link net.jxta.platform.ModuleClassID}.</li>
142      *     <li>Values are {@link net.jxta.platform.ModuleSpecID} or
143      *     {@link net.jxta.protocol.ModuleImplAdvertisement}.</li>
144      * </ul>
145      */    
146     private final Map<ModuleClassID, Object> apps = new HashMap<ModuleClassID, Object>();
147
148     /**
149      * Private constructor for new instances.
150      */
151     public StdPeerGroupParamAdv() {
152     }
153
154     /**
155      * Private constructor for serialized instances.
156      *
157      * @param root the root element
158      */
159     public StdPeerGroupParamAdv(Element root) {
160         if (!(root instanceof XMLElement)) {
161             throw new IllegalArgumentException(getClass().getName() + " only supports XMLElement");
162         }
163         initialize((XMLElement) root);
164     }
165
166     /**
167      * Private constructor for xml serialized instances.
168      *
169      * @param doc The XML serialization of the advertisement.
170      */
171     public StdPeerGroupParamAdv(XMLElement doc) {
172         initialize(doc);
173     }
174
175     /**
176      * Add a service to the set of services entries described in this
177      * Advertisement.
178      *
179      * @param mcid   The module class id of the module being added.
180      * @param module The module being added.
181      */
182     public void addService(ModuleClassID mcid, Object module) {
183         if(null == mcid) {
184             throw new IllegalArgumentException("Illegal ModuleClassID");
185         }
186         
187         if(null == module) {
188             throw new IllegalArgumentException("Illegal module");
189         }
190         
191         services.put(mcid, module);
192     }
193
194     /**
195      * Return the services entries described in this Advertisement.
196      * <p/>
197      * The result (very unwisely) is the internal map of this
198      * Advertisement. Modifying it results in changes to this Advertisement.
199      * For safety the Map should be copied before being modified.
200      *
201      * @return the services entries described in this Advertisement.
202      */
203     public Map<ModuleClassID, Object> getServices() {
204         return services;
205     }
206
207     /**
208      * Add a protocol (message transport) to the set of protocol entries
209      * described in this Advertisement.
210      *
211      * @param mcid   The module class id of the module being added.
212      * @param module The module being added.
213      */
214     public void addProto(ModuleClassID mcid, Object module) {
215         if(null == mcid) {
216             throw new IllegalArgumentException("Illegal ModuleClassID");
217         }
218         
219         if(null == module) {
220             throw new IllegalArgumentException("Illegal module");
221         }
222         
223         transports.put(mcid, module);
224     }
225
226     /**
227      * Return the protocols (message transports) entries described in this Advertisement.
228      * <p/>
229      * The result (very unwisely) is the internal map of this Advertisement.
230      * Modifying it results in changes to this Advertisement.
231      * For safety the Map should be copied before being modified.
232      *
233      * @return the protocols (message transports) entries described in this Advertisement.
234      */
235     public Map<ModuleClassID, Object> getProtos() {
236         return transports;
237     }
238
239     /**
240      * Add an application to the set of application entries described in this
241      * Advertisement.
242      *
243      * @param mcid   The module class id of the module being added.
244      * @param module The module being added.
245      */
246     public void addApp(ModuleClassID mcid, Object module) {
247         if(null == mcid) {
248             throw new IllegalArgumentException("Illegal ModuleClassID");
249         }
250         
251         if(null == module) {
252             throw new IllegalArgumentException("Illegal module");
253         }
254         
255         apps.put(mcid, module);
256     }
257
258     /**
259      * Return the application entries described in this Advertisement.
260      * <p/>
261      * The result (very unwisely) is the internal map of this Advertisement. 
262      * Modifying it results in changes to this Advertisement.
263      * For safety the Map should be copied before being modified.
264      *
265      * @return the application entries described in this Advertisement.
266      */
267     public Map<ModuleClassID, Object> getApps() {
268         return apps;
269     }
270
271     /**
272      * Replaces the table of services described by this Advertisement. All
273      * existing entries are lost.
274      *
275      * @param servicesTable the services table
276      */
277     public void setServices(Map<ModuleClassID, Object> servicesTable) {
278         if(servicesTable.containsKey(null)) {
279             throw new IllegalArgumentException("null key in servicesTable");
280         }
281         
282         if(servicesTable.containsValue(null)) {
283             throw new IllegalArgumentException("null value in servicesTable");
284         }        
285         
286         if (servicesTable == this.services) {
287             return;
288         }
289
290         this.services.clear();
291
292         if (null != servicesTable) {
293             this.services.putAll(servicesTable);
294         }
295     }
296
297     /**
298      * Replaces the table of protocols described by this Advertisement. All
299      * existing entries are lost.
300      *
301      * @param protosTable The message transport descriptors for the group.
302      */
303     public void setProtos(Map<ModuleClassID, Object> protosTable) {
304         if(protosTable.containsKey(null)) {
305             throw new IllegalArgumentException("null key in protosTable");
306         }
307         
308         if(protosTable.containsValue(null)) {
309             throw new IllegalArgumentException("null value in protosTable");
310         }        
311         
312         if (protosTable == this.transports) {
313             return;
314         }
315
316         this.transports.clear();
317
318         if (null != protosTable) {
319             this.transports.putAll(protosTable);
320         }
321     }
322
323     /**
324      * Replaces the table of applications described by this Advertisement. All
325      * existing entries are lost.
326      *
327      * @param appsTable The application descriptors for the group.
328      */
329     public void setApps(Map<ModuleClassID, Object> appsTable) {
330         if(appsTable.containsKey(null)) {
331             throw new IllegalArgumentException("null key in appsTable");
332         }
333         
334         if(appsTable.containsValue(null)) {
335             throw new IllegalArgumentException("null value in appsTable");
336         }        
337         
338         if (appsTable == this.apps) {
339             return;
340         }
341
342         this.apps.clear();
343
344         if (null != appsTable) {
345             this.apps.putAll(appsTable);
346         }
347     }
348
349     private void initialize(XMLElement doc) {
350         if (!doc.getName().equals(PARAM_TAG)) {
351             throw new IllegalArgumentException("Can not construct " + getClass().getName() + "from doc containing a " + doc.getName());
352         }
353
354         // set defaults
355         int appCount = 0;
356         Enumeration<XMLElement> modules = doc.getChildren();
357
358         while (modules.hasMoreElements()) {
359             XMLElement module = modules.nextElement();
360             String tagName = module.getName();
361
362             Map<ModuleClassID, Object> theTable;
363
364             if (SVC_TAG.equals(tagName)) {
365                 theTable = services;
366             } else if (APP_TAG.equals(tagName)) {
367                 theTable = apps;
368             } else if (PROTO_TAG.equals(tagName)) {
369                 theTable = transports;
370             } else {
371                 if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
372                     LOG.log(Level.WARNING, "Unhandled top-level tag : " + tagName);
373                 }
374                 continue;
375             }
376
377             ModuleSpecID specID = null;
378             ModuleClassID classID = null;
379             ModuleImplAdvertisement inLineAdv = null;
380
381             try {
382                 if (module.getTextValue() != null) {
383                     specID = (ModuleSpecID) IDFactory.fromURI(new URI(module.getTextValue()));
384                 }
385
386                 // Check for children anyway.
387                 Enumeration<XMLElement> fields = module.getChildren();
388
389                 while (fields.hasMoreElements()) {
390                     XMLElement field = fields.nextElement();
391
392                     String fieldName = field.getName();
393
394                     if (MCID_TAG.equals(fieldName)) {
395                         classID = (ModuleClassID) IDFactory.fromURI(new URI(field.getTextValue()));
396                     } else if (MSID_TAG.equals(field.getName())) {
397                         specID = (ModuleSpecID) IDFactory.fromURI(new URI(field.getTextValue()));
398                     } else if (MIA_TAG.equals(field.getName())) {
399                         inLineAdv = (ModuleImplAdvertisement) AdvertisementFactory.newAdvertisement(field);
400                     } else {
401                         if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
402                             LOG.log(Level.WARNING, "Unhandled field : " + fieldName);
403                         }
404                     }
405                 }
406             } catch (Exception any) {
407                 if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
408                     LOG.log(Level.WARNING, "Broken entry; skipping", any);
409                 }
410                 continue;
411             }
412
413             if (inLineAdv == null && specID == null) {
414                 if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
415                     LOG.warning("Insufficent entry; skipping");
416                 }
417                 continue;
418             }
419
420             Object theValue;
421
422             if (inLineAdv != null) {
423                 specID = inLineAdv.getModuleSpecID();
424                 theValue = inLineAdv;
425             } else {
426                 theValue = specID;
427             }
428
429             if (classID == null) {
430                 classID = specID.getBaseClass();
431             }
432
433             // For applications, the role does not matter. We just create a 
434             // unique role ID on the fly.
435             // When outputing the adv we get rid of it to save space.
436
437             if (theTable == apps) {
438                 // Only the first (or only) one may use the base class.
439                 if (classID == PeerGroup.applicationClassID) {
440                     if (appCount++ != 0) {
441                         classID = IDFactory.newModuleClassID(classID);
442                     }
443                 }
444             }
445             theTable.put(classID, theValue);
446         }
447     }
448
449     /**
450      * {@inheritDoc}
451      */
452     public Document getDocument(MimeMediaType encodeAs) {
453         StructuredDocument doc = StructuredDocumentFactory.newStructuredDocument(encodeAs, PARAM_TAG);
454
455         outputModules(doc, services, SVC_TAG);
456         outputModules(doc, transports, PROTO_TAG);
457         outputModules(doc, apps, APP_TAG);
458
459         return doc;
460     }
461
462     private void outputModules(StructuredDocument doc, Map<ModuleClassID, Object> modulesTable, String mainTag) {
463
464         for (Map.Entry<ModuleClassID, Object> entry : modulesTable.entrySet()) {
465             ModuleClassID mcid = entry.getKey();
466             Object val = entry.getValue();
467             Element m;
468
469             if(null == mcid) {
470                 throw new IllegalStateException("null ModuleClassID in " + mainTag );
471             }
472             
473             // For applications, we ignore the role ID. It is not meaningfull,
474             // and a new one is assigned on the fly when loading this adv.
475
476             if (val instanceof Advertisement) {
477                 m = doc.createElement(mainTag);
478                 doc.appendChild(m);
479
480                 if (modulesTable != apps && !mcid.equals(mcid.getBaseClass())) {
481                     // It is not an app and there is a role ID. Output it.
482                     Element i = doc.createElement(MCID_TAG, mcid.toString());
483
484                     m.appendChild(i);
485                 }
486
487                 StructuredDocument advdoc = (StructuredDocument) ((Advertisement) val).getDocument(doc.getMimeType());
488
489                 StructuredDocumentUtils.copyElements(doc, m, advdoc);
490             } else if (val instanceof ModuleSpecID) {
491                 if (modulesTable == apps || mcid.equals(mcid.getBaseClass())) {
492                     // Either it is an app or there is no role ID.
493                     // So the specId is good enough.
494                     m = doc.createElement(mainTag, val.toString());
495                     doc.appendChild(m);
496                 } else {
497                     // The role ID matters, so the classId must be separate.
498                     m = doc.createElement(mainTag);
499                     doc.appendChild(m);
500
501                     Element i;
502
503                     i = doc.createElement(MCID_TAG, mcid.toString());
504                     m.appendChild(i);
505
506                     i = doc.createElement(MSID_TAG, val.toString());
507                     m.appendChild(i);
508                 }
509             } else {
510                 if (Logging.SHOW_SEVERE && LOG.isLoggable(Level.SEVERE)) {
511                     LOG.severe("unsupported descriptor for " + mcid + " in " + mainTag +" module table : " + val);
512                 }
513                 throw new IllegalStateException("unsupported descriptor for " + mcid + " in " + mainTag +" module table : " + val);
514             }
515         }
516     }
517 }