]> sjero.net Git - linphone/blob - p2pproxy/dependencies-src/jxse-src-2.5/impl/src/net/jxta/impl/peergroup/AutomaticConfigurator.java
9f6dee07f404fa754daca60ff23a8aa3e43e0896
[linphone] / p2pproxy / dependencies-src / jxse-src-2.5 / impl / src / net / jxta / impl / peergroup / AutomaticConfigurator.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 java.net.InetAddress;
61 import java.net.URI;
62 import java.util.Enumeration;
63 import java.util.Iterator;
64
65 import java.util.logging.Level;
66 import net.jxta.logging.Logging;
67 import java.util.logging.Logger;
68
69 import net.jxta.document.AdvertisementFactory;
70 import net.jxta.document.MimeMediaType;
71 import net.jxta.document.StructuredDocumentFactory;
72 import net.jxta.document.StructuredDocumentUtils;
73 import net.jxta.document.XMLDocument;
74 import net.jxta.document.XMLElement;
75 import net.jxta.peergroup.PeerGroup;
76 import net.jxta.protocol.TransportAdvertisement;
77
78 import net.jxta.exception.ConfiguratorException;
79
80 import net.jxta.impl.endpoint.IPUtils;
81 import net.jxta.impl.protocol.HTTPAdv;
82 import net.jxta.impl.protocol.PlatformConfig;
83 import net.jxta.impl.protocol.PSEConfigAdv;
84 import net.jxta.impl.protocol.RdvConfigAdv;
85 import net.jxta.impl.protocol.RelayConfigAdv;
86 import net.jxta.impl.protocol.TCPAdv;
87
88
89 /**
90  * A simple platform configurator. This implementation provides reasonable
91  * automatic configuration for edge peers on the JXTA public network.
92  * <p/>
93  * This implementation will read default values from several Java system
94  * properties as appropriate:
95  * <p/>
96  * jxta.peer.name    --  The peer name to use.
97  * jxta.http.port    --  The http port to use.
98  * jxta.tcp.port     --  The tcp port to use.
99  *
100  * @see net.jxta.peergroup.Configurator
101  */
102 public class AutomaticConfigurator extends NullConfigurator {
103
104     /**
105      * Log4J logger
106      */
107     private final static transient Logger LOG = Logger.getLogger(AutomaticConfigurator.class.getName());
108
109     /**
110      * Configures the platform using the specified directory.
111      * @param jxtaHome store home URI
112      * @throws net.jxta.exception.ConfiguratorException if a configuration error occurs
113      */
114     public AutomaticConfigurator(URI jxtaHome) throws ConfiguratorException {
115         super(jxtaHome);
116     }
117
118     /**
119      * {@inheritDoc}
120      */
121     @Override
122     public PlatformConfig getPlatformConfig() throws ConfiguratorException {
123         super.getPlatformConfig();
124
125         boolean reconf;
126
127         try {
128             reconf = buildPlatformConfig();
129         } catch (RuntimeException serious) {
130             if (Logging.SHOW_SEVERE && LOG.isLoggable(Level.SEVERE)) {
131                 LOG.log(Level.SEVERE, "Trouble while fixing PlatformConfig. Hope for the best.", serious);
132             }
133
134             reconf = true;
135         }
136
137         // See if we need a reconf
138         if (reconf) {
139             throw new IncompleteConfigurationException("Damaged platform configuration.");
140         }
141
142         // Save the updated config.
143         save();
144
145         return advertisement;
146     }
147
148     /**
149      * Makes sure a PlatformConfig is present and if not, creates one.
150      * <p/>
151      * Performs some checking of PlatformConfig values and will fix some
152      * minor configuration problems automatically.
153      *
154      * @return If <tt>true</tt> then manual reconfiguration (of some form) is required.
155      */
156     private boolean buildPlatformConfig() {
157
158         boolean reconf = false;
159
160         if (advertisement == null) {
161             if (Logging.SHOW_CONFIG && LOG.isLoggable(Level.CONFIG)) {
162                 LOG.config("New PlatformConfig Advertisement");
163             }
164             advertisement = (PlatformConfig) AdvertisementFactory.newAdvertisement(PlatformConfig.getAdvertisementType());
165             advertisement.setDescription("Platform Config Advertisement created by : " + AutomaticConfigurator.class.getName());
166         }
167
168         // Set the peer name
169         String peerName = advertisement.getName();
170
171         if ((null == peerName) || (0 == peerName.trim().length())) {
172             String jpn = System.getProperty("jxta.peer.name", "");
173
174             if (0 != jpn.trim().length()) {
175                 advertisement.setName(jpn);
176             }
177         }
178
179         // Check the HTTP Message Transport parameters.
180         XMLDocument http = (XMLDocument) advertisement.getServiceParam(PeerGroup.httpProtoClassID);
181         HTTPAdv httpAdv = null;
182         boolean httpEnabled = true;
183
184         if (http != null) {
185             try {
186                 httpEnabled = advertisement.isSvcEnabled(PeerGroup.httpProtoClassID);
187
188                 XMLElement param = null;
189
190                 Enumeration httpChilds = http.getChildren(TransportAdvertisement.getAdvertisementType());
191
192                 // get the HTTPAdv from TransportAdv
193                 if (httpChilds.hasMoreElements()) {
194                     param = (XMLElement) httpChilds.nextElement();
195                 }
196
197                 if (null != param) {
198                     httpAdv = (HTTPAdv) AdvertisementFactory.newAdvertisement(param);
199
200                     if (httpEnabled) {
201                         // check if the interface address is still valid.
202                         String intf = httpAdv.getInterfaceAddress();
203
204                         if ((null != intf) && !isValidInetAddress(intf)) {
205                             reconf = true;
206
207                             if (Logging.SHOW_CONFIG && LOG.isLoggable(Level.CONFIG)) {
208                                 LOG.config("Reconfig requested - invalid interface address");
209                             }
210                         }
211                     }
212                 }
213             } catch (RuntimeException advTrouble) {
214                 if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
215                     LOG.log(Level.WARNING, "HTTP advertisement corrupted", advTrouble);
216                 }
217
218                 httpAdv = null;
219             }
220         }
221
222         if (httpAdv == null) {
223             if (Logging.SHOW_CONFIG && LOG.isLoggable(Level.CONFIG)) {
224                 LOG.config("HTTP advertisement missing, making a new one.");
225             }
226
227             int port = 0;
228             // get the port from a property
229             String httpPort = System.getProperty("jxta.http.port");
230
231             if (httpPort != null) {
232                 try {
233                     int propertyPort = Integer.parseInt(httpPort);
234
235                     if ((propertyPort < 65536) && (propertyPort >= 0)) {
236                         port = propertyPort;
237                     } else {
238                         if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
239                             LOG.warning("Property \'jxta.http.port\' is not a valid port number : " + propertyPort);
240                         }
241                     }
242                 } catch (NumberFormatException ignored) {
243                     if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
244                         LOG.warning("Property \'jxta.http.port\' was not an integer : " + http);
245                     }
246                 }
247             }
248
249             httpAdv = (HTTPAdv) AdvertisementFactory.newAdvertisement(HTTPAdv.getAdvertisementType());
250             httpAdv.setProtocol("http");
251             httpAdv.setPort(port);
252             httpAdv.setServerEnabled(false);
253         }
254
255         // Create new param docs that contain the updated adv
256         http = (XMLDocument) StructuredDocumentFactory.newStructuredDocument(MimeMediaType.XMLUTF8, "Parm");
257         XMLDocument httAdvDoc = (XMLDocument) httpAdv.getDocument(MimeMediaType.XMLUTF8);
258
259         StructuredDocumentUtils.copyElements(http, http, httAdvDoc);
260         if (!httpEnabled) {
261             http.appendChild(http.createElement("isOff"));
262         }
263         advertisement.putServiceParam(PeerGroup.httpProtoClassID, http);
264
265         // Check the TCP Message Transport parameters.
266         XMLDocument tcp = (XMLDocument) advertisement.getServiceParam(PeerGroup.tcpProtoClassID);
267         TCPAdv tcpAdv = null;
268         boolean tcpEnabled = true;
269
270         if (tcp != null) {
271             try {
272                 tcpEnabled = advertisement.isSvcEnabled(PeerGroup.tcpProtoClassID);
273
274                 XMLElement param = null;
275
276                 Enumeration tcpChilds = tcp.getChildren(TransportAdvertisement.getAdvertisementType());
277
278                 // get the TransportAdv
279                 if (tcpChilds.hasMoreElements()) {
280                     param = (XMLElement) tcpChilds.nextElement();
281                 }
282
283                 if (null != param) {
284                     tcpAdv = (TCPAdv) AdvertisementFactory.newAdvertisement(param);
285
286                     if (tcpEnabled) {
287                         String intf = tcpAdv.getInterfaceAddress();
288
289                         if ((null != intf) && !isValidInetAddress(intf)) {
290                             reconf = true;
291
292                             if (Logging.SHOW_CONFIG && LOG.isLoggable(Level.CONFIG)) {
293                                 LOG.config("Reconfig requested - invalid interface address");
294                             }
295                         }
296                     }
297                 }
298             } catch (RuntimeException advTrouble) {
299                 if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
300                     LOG.log(Level.WARNING, "TCP advertisement corrupted", advTrouble);
301                 }
302
303                 tcpAdv = null;
304             }
305         }
306
307         if (tcpAdv == null) {
308             if (Logging.SHOW_CONFIG && LOG.isLoggable(Level.CONFIG)) {
309                 LOG.config("TCP advertisement missing, making a new one.");
310             }
311
312             int port = 0;
313             // get the port from a property
314             String tcpPort = System.getProperty("jxta.tcp.port");
315
316             if (tcpPort != null) {
317                 try {
318                     int propertyPort = Integer.parseInt(tcpPort);
319
320                     if ((propertyPort < 65536) && (propertyPort >= 0)) {
321                         port = propertyPort;
322                     } else {
323                         if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
324                             LOG.warning("Property \'jxta.tcp.port\' is not a valid port number : " + propertyPort);
325                         }
326                     }
327                 } catch (NumberFormatException ignored) {
328                     if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
329                         LOG.warning("Property \'jxta.tcp.port\' was not an integer : " + tcpPort);
330                     }
331                 }
332             }
333
334             tcpAdv = (TCPAdv) AdvertisementFactory.newAdvertisement(TCPAdv.getAdvertisementType());
335
336             tcpAdv.setProtocol("tcp");
337             tcpAdv.setPort(port);
338             tcpAdv.setMulticastAddr("224.0.1.85");
339             tcpAdv.setMulticastPort(1234);
340             tcpAdv.setMulticastSize(16384);
341             tcpAdv.setMulticastState(true);
342         }
343
344         tcp = (XMLDocument) StructuredDocumentFactory.newStructuredDocument(MimeMediaType.XMLUTF8, "Parm");
345
346         StructuredDocumentUtils.copyElements(tcp, tcp, (XMLDocument) tcpAdv.getDocument(MimeMediaType.XMLUTF8));
347         if (!tcpEnabled) {
348             tcp.appendChild(tcp.createElement("isOff"));
349         }
350         advertisement.putServiceParam(PeerGroup.tcpProtoClassID, tcp);
351
352         // Check the relay config
353         RelayConfigAdv relayConfig = null;
354
355         try {
356             XMLElement param = (XMLElement) advertisement.getServiceParam(PeerGroup.relayProtoClassID);
357
358             if (param != null) {
359                 // XXX 20041027 backwards compatibility
360                 param.addAttribute("type", RelayConfigAdv.getAdvertisementType());
361
362                 relayConfig = (RelayConfigAdv) AdvertisementFactory.newAdvertisement(param);
363             }
364         } catch (Exception failure) {
365             if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
366                 LOG.log(Level.WARNING, "Problem reading relay configuration", failure);
367             }
368         }
369
370         if (null == relayConfig) {
371             if (Logging.SHOW_CONFIG && LOG.isLoggable(Level.CONFIG)) {
372                 LOG.config("Relay Config advertisement missing, making a new one.");
373             }
374
375             // restore default values.
376             relayConfig = (RelayConfigAdv) AdvertisementFactory.newAdvertisement(RelayConfigAdv.getAdvertisementType());
377
378             // Enable relay if any transport doesn't support incoming.
379             if (!tcpAdv.isServerEnabled() || !httpAdv.isServerEnabled()) {
380                 relayConfig.setClientEnabled(true);
381             }
382         }
383
384         /*
385          if( (0 == relayConfig.getSeedingURIs().length) && (0 == relayConfig.getSeedRelays().length) && !relayConfig.isServerEnabled() ) {
386          // add the default relay seeding peer.
387          relayConfig.addSeedingURI( "http://rdv.jxtahosts.net/cgi-bin/relays.cgi?3" );
388          }
389          */
390
391         XMLDocument relayDoc = (XMLDocument) relayConfig.getDocument(MimeMediaType.XMLUTF8);
392
393         advertisement.putServiceParam(PeerGroup.relayProtoClassID, relayDoc);
394
395         // Check Rendezvous Configuration
396         RdvConfigAdv rdvAdv = null;
397
398         try {
399             XMLElement param = (XMLElement) advertisement.getServiceParam(PeerGroup.rendezvousClassID);
400
401             if (param != null) {
402                 // XXX 20041027 backwards compatibility
403                 param.addAttribute("type", RdvConfigAdv.getAdvertisementType());
404
405                 rdvAdv = (RdvConfigAdv) AdvertisementFactory.newAdvertisement(param);
406             }
407         } catch (Exception failure) {
408             if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
409                 LOG.log(Level.WARNING, "Problem reading rendezvous configuration", failure);
410             }
411         }
412
413         if (null == rdvAdv) {
414             if (Logging.SHOW_CONFIG && LOG.isLoggable(Level.CONFIG)) {
415                 LOG.config("Rdv Config advertisement missing, making a new one.");
416             }
417
418             // restore default values.
419             rdvAdv = (RdvConfigAdv) AdvertisementFactory.newAdvertisement(RdvConfigAdv.getAdvertisementType());
420         }
421
422         /*
423          if( (0 == rdvAdv.getSeedingURIs().length) &&
424          (0 == rdvAdv.getSeedRendezvous().length) &&
425          (RdvConfigAdv.RendezVousConfiguration.RENDEZVOUS != rdvAdv.getConfiguration()) &&
426          (RdvConfigAdv.RendezVousConfiguration.AD_HOC != rdvAdv.getConfiguration()) &&
427          !relayConfig.isClientEnabled() ) {
428          // add the default rendezvous seeding peer if we don't know of any rendezvous, aren't a rendezvous ourselves, aren't in ad-hoc mode or using a relay.
429          rdvAdv.addSeedingURI( "http://rdv.jxtahosts.net/cgi-bin/rendezvous.cgi?3" );
430          }
431          */
432         XMLDocument rdvDoc = (XMLDocument) rdvAdv.getDocument(MimeMediaType.XMLUTF8);
433
434         advertisement.putServiceParam(PeerGroup.rendezvousClassID, rdvDoc);
435
436         // if no proxy param section, disable it.
437         XMLDocument proxy = (XMLDocument) advertisement.getServiceParam(PeerGroup.proxyClassID);
438
439         if (null == proxy) {
440             if (Logging.SHOW_CONFIG && LOG.isLoggable(Level.CONFIG)) {
441                 LOG.config("Proxy config advertisement missing, making a new one.");
442             }
443
444             proxy = (XMLDocument) StructuredDocumentFactory.newStructuredDocument(MimeMediaType.XMLUTF8, "Parm");
445             proxy.appendChild(proxy.createElement("isOff"));
446             advertisement.putServiceParam(PeerGroup.proxyClassID, proxy);
447         }
448
449         // Check the PSE Configuration
450         PSEConfigAdv pseConfig = null;
451
452         try {
453             XMLElement param = (XMLElement) advertisement.getServiceParam(PeerGroup.membershipClassID);
454
455             if (param != null) {
456                 // XXX 20041027 backwards compatibility
457                 param.addAttribute("type", PSEConfigAdv.getAdvertisementType());
458
459                 pseConfig = (PSEConfigAdv) AdvertisementFactory.newAdvertisement(param);
460             }
461         } catch (Exception failure) {
462             if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) {
463                 LOG.log(Level.WARNING, "Problem reading pse configuration", failure);
464             }
465         }
466
467         if (null == pseConfig) {
468             if (Logging.SHOW_CONFIG && LOG.isLoggable(Level.CONFIG)) {
469                 LOG.config("PSE Config advertisement missing, making a new one.");
470             }
471
472             // restore default values.
473             pseConfig = (PSEConfigAdv) AdvertisementFactory.newAdvertisement(PSEConfigAdv.getAdvertisementType());
474             XMLDocument pseDoc = (XMLDocument) pseConfig.getDocument(MimeMediaType.XMLUTF8);
475
476             advertisement.putServiceParam(PeerGroup.membershipClassID, pseDoc);
477         }
478
479         // If we did not modify anything of importance or see anything wrong,
480         // leave the adv alone.
481
482         return reconf;
483     }
484
485     private boolean isValidInetAddress(String address) {
486         boolean found = false;
487         boolean loopback;
488
489         InetAddress[] ias;
490
491         try {
492             ias = InetAddress.getAllByName(address);
493         } catch (java.net.UnknownHostException notfound) {
494             return false;
495         }
496
497         for (Iterator la = IPUtils.getAllLocalAddresses(); la.hasNext() && !found;) {
498             for (InetAddress ia1 : ias) {
499                 found |= ia1.equals(la.next());
500             }
501         }
502
503         loopback = true;
504
505         for (InetAddress ia1 : ias) {
506             loopback &= ia1.isLoopbackAddress();
507         }
508
509         return found || loopback;
510     }
511 }