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

Quick Search    Search Deep

Source code: net/jxta/ext/config/Configurator.java


1   /*
2    *  Copyright (c) 2001 Sun Microsystems, Inc.  All rights
3    *  reserved.
4    *
5    *  Redistribution and use in source and binary forms, with or without
6    *  modification, are permitted provided that the following conditions
7    *  are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright
10   *  notice, this list of conditions and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright
13   *  notice, this list of conditions and the following disclaimer in
14   *  the documentation and/or other materialsset provided with the
15   *  distribution.
16   *
17   *  3. The end-user documentation included with the redistribution,
18   *  if any, must include the following acknowledgment:
19   *  "This product includes software developed by the
20   *  Sun Microsystems, Inc. for Project JXTA."
21   *  Alternately, this acknowledgment may appear in the software itself,
22   *  if and wherever such third-party acknowledgments normally appear.
23   *
24   *  4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA"
25   *  must not be used to endorse or promote products derived from this
26   *  software without prior written permission. For written
27   *  permission, please contact Project JXTA at http://www.jxta.org.
28   *
29   *  5. Products derived from this software may not be called "JXTA",
30   *  nor may "JXTA" appear in their name, without prior written
31   *  permission of Sun.
32   *
33   *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
34   *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35   *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36   *  DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
37   *  ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38   *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39   *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
40   *  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41   *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42   *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43   *  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44   *  SUCH DAMAGE.
45   *  ====================================================================
46   *
47   *  This software consists of voluntary contributions made by many
48   *  individuals on behalf of Project JXTA.  For more
49   *  information on Project JXTA, please see
50   *  <http://www.jxta.org/>.
51   *
52   *  This license is based on the BSD license adopted by the Apache Foundation.
53   *
54   *  $Id: Configurator.java,v 1.188 2005/03/09 04:09:50 gonzo Exp $
55   */
56  package net.jxta.ext.config;
57  
58  import net.jxta.ext.config.optimizers.RelayOptimizer;
59  import net.jxta.ext.http.Dispatcher;
60  import net.jxta.ext.http.Message;
61  
62  import java.io.Externalizable;
63  import java.io.File;
64  import java.io.FileNotFoundException;
65  import java.io.FileInputStream;
66  import java.io.FileOutputStream;
67  import java.io.FileReader;
68  import java.io.InputStreamReader;
69  import java.io.Reader;
70  import java.io.IOException;
71  import java.io.ObjectInput;
72  import java.io.ObjectOutput;
73  import java.io.StreamTokenizer;
74  import java.io.StringReader;
75  import java.net.MalformedURLException;
76  import java.net.URI;
77  import java.net.URISyntaxException;
78  import java.net.URL;
79  import java.security.cert.Certificate;
80  import java.security.cert.X509Certificate;
81  import java.text.MessageFormat;
82  import java.util.Arrays;
83  import java.util.ArrayList;
84  import java.util.Collections;
85  import java.util.Enumeration;
86  import java.util.HashMap;
87  import java.util.Iterator;
88  import java.util.List;
89  import java.util.Map;
90  import java.util.Map.Entry;
91  import java.util.NoSuchElementException;
92  import net.jxta.document.AdvertisementFactory;
93  import net.jxta.document.Attributable;
94  import net.jxta.document.Attribute;
95  import net.jxta.document.Element;
96  import net.jxta.document.MimeMediaType;
97  import net.jxta.document.StructuredDocument;
98  import net.jxta.document.StructuredDocumentFactory;
99  import net.jxta.document.StructuredDocumentUtils;
100 import net.jxta.document.StructuredTextDocument;
101 import net.jxta.document.TextElement;
102 import net.jxta.document.XMLDocument;
103 import net.jxta.exception.ConfiguratorException;
104 import net.jxta.id.ID;
105 import net.jxta.id.IDFactory;
106 import net.jxta.impl.membership.pse.PSEUtils;
107 import net.jxta.impl.peergroup.PlatformConfigurator;
108 import net.jxta.impl.protocol.HTTPAdv;
109 import net.jxta.impl.protocol.PlatformConfig;
110 import net.jxta.impl.protocol.PSEConfigAdv;
111 import net.jxta.impl.protocol.RdvConfigAdv;
112 import net.jxta.impl.protocol.RelayConfigAdv;
113 import net.jxta.impl.protocol.TCPAdv;
114 import net.jxta.protocol.ConfigParams;
115 import net.jxta.peer.PeerID;
116 import net.jxta.peergroup.PeerGroupFactory;
117 import net.jxta.protocol.TransportAdvertisement;
118 import org.apache.log4j.Level;
119 import org.apache.log4j.Logger;
120 
121 /**
122  *  A JXTA configurator.<br>
123  *  <br>
124  *  <code>Configurator<code> serves primarily as a JXTA property sheet and
125  *  implements very little attribute association logic beyond that of what
126  *  is required to perform integrity validation and address expansion. To
127  *  the latter, All addresses are of the form URI. Addresses that do not
128  *  specify a scheme will default accordingly. Further, <code>RendezVous</code>
129  *  and <code>Relay</code> addresses that do not specify a host wil be replaced
130  *  with the corresponding boostrap results. If a scheme is specified only
131  *  bootstrap results with matching schemes will be maintained. All other
132  *  addresses that do not specify a host will, in turn, be replaced with the
133  *  local host. All fields have backing defaults enabling one to seed a
134  *  configuration with a partial yet valid resource file.<br>
135  *  <br>
136  *  Configurator will parse an existing {@link Env#PLATFORM PlatformConfig} if
137  *  one exists in the specified {@link Env#JXTA_HOME JXTA home} directory. If
138  *  this is not the case, a {@link Env#PROFILE Configuration} file will be
139  *  parsed it one such file exists. Lastly, if neither of the above are
140  *  resolvable the {@link ResourceConfiguration.Profile#Default Default profile}
141  *  will be used to seed the newly created instance.<br>
142  *  <br>
143  *  Resulting <code>PlatformConfig</code> instances can then be retrieved or
144  *  persisted upon passing the integrity validation checks.
145  *
146  * @author     james todd [gonzo at jxta dot org]
147  * @version    $Id: Configurator.java,v 1.188 2005/03/09 04:09:50 gonzo Exp $
148  * @created    November 13, 2003
149  */
150 
151 public class Configurator
152 implements Externalizable, PlatformConfigurator {
153     
154     private final static String COLON = ":";
155     private final static String EMPTY_STRING = "";
156     private final static int MILLISECONDS_PER_SECOND = 1000;
157     private final static char NULL_CHAR = '\0';
158     private final static long MAX_WAIT = 7 * 1000;
159     
160     private final static Logger LOG = Logger.getLogger(Configurator.class.getName());
161     
162     private static File HOME = Env.JXTA_HOME;
163     
164     private String descriptor = Default.PEER_DESCRIPTOR;
165     private String peerName = null;
166     private String peerDescription = null;
167     private Trace trace = Trace.DEFAULT;
168     private PeerID peerId = null;
169     private boolean isSecurity = Default.SECURITY_IS_ENABLED;
170     private String principal = null;
171     private String password = null;
172     private URI rootCertificateAddress = null;
173     private PSEConfigAdv pse = null;
174     private URI peerProxy = null;
175     private URI rendezVousBootstrap = Default.RENDEZVOUS_BOOTSTRAP_ADDRESS;
176     private URI relaysBootstrap = Default.RELAYS_BOOTSTRAP_ADDRESS;
177     private boolean isRelaysDiscovery = Default.RELAYS_DISCOVERY_IS_ENABLED;
178     private URI reflectionBootstrap = Default.REFLECTION_BOOTSTRAP_ADDRESS;
179     private List transports = null;
180 //    private List relays = null;
181 //    private boolean isRelayEnabled = Default.RELAY_SERVICE_IS_ENABLED;
182 //    private boolean isRelayIncomingEnabled = Default.RELAY_SERVICE_INCOMING_IS_ENABLED;
183 //    private int maximumRelayIncoming = Default.INCOMING_MAXIMUM;
184 //    private long incomingRelayLease = Default.INCOMING_LEASE;
185 //    private boolean isRelayOutgoingEnabled = Default.RELAY_SERVICE_OUTGOING_IS_ENABLED;
186 //    private int maximumRelayOutgoing = Default.OUTGOING_MAXIMUM;
187 //    private long relayOutgoingLease = Default.OUTGOING_LEASE;
188 //    private int relayQueueSize = Default.RELAY_SERVICE_QUEUE_SIZE;
189     private RelayConfigAdv relayConfig = null;
190     private int endpointQueueSize = Default.ENDPOINT_SERVICE_QUEUE_SIZE;
191     private boolean isProxyEnabled = Default.PROXY_SERVICE_IS_ENABLED;
192     private RdvConfigAdv rdvConfig = null;
193     private List optimizers = null;
194     
195     private Map customParams = null;
196     
197     {
198         customParams = new HashMap();
199         
200         process((PlatformConfig)
201         AdvertisementFactory.newAdvertisement(PlatformConfig.getAdvertisementType()));
202         process(Profile.SEED, true);
203         
204         setHome(Env.JXTA_HOME);
205     }
206     
207     /**
208      *  Gets base JXTA home.
209      *
210      * @return    The home value
211      */
212     public static File getHome() {
213         return HOME;
214     }
215     
216     /*
217      *  Sets base JXTA home.
218      */
219     /**
220      *  Sets the home attribute of the Configurator class
221      *
222      * @param  home  The new home value
223      */
224     public static void setHome(File home) {
225         if (home != null) {
226             HOME = home;
227         }
228     }
229     
230     public static void setConfigurator(Class configurator) {
231         IllegalArgumentException rc = null;
232         
233         if (configurator != null &&
234             PlatformConfigurator.class.isAssignableFrom(configurator)) {
235             try {
236                 PeerGroupFactory.setConfiguratorClass(configurator);
237             } catch (Exception e) {
238                 // xxx: needed for 1.4.x
239                 //rc = new IllegalArgumentException("invalid configurator", e);
240                 rc = new IllegalArgumentException("invalid configurator: " +
241                     e.getMessage());
242                 
243                 rc.initCause(e);
244             }
245         } else {
246             rc = new IllegalArgumentException("invalid configurator: " +
247                 (configurator != null ? configurator.getName() : null));
248         }
249         
250         if (rc != null) {
251             if (LOG.isEnabledFor(Level.ERROR)) {
252                 LOG.error("invalid configurator: ", rc);
253             }
254             
255             throw rc;
256         }
257     }
258 
259     /**
260      *  Method to transpose <code>URI</code> into one that represents all local
261      *  interfaces.
262      *
263      * @param  base  The provided address
264      * @return       Description of the Return Value
265      * @see          Env.ALL_ADDRESSES
266      */
267     public static URI toAllAddresses(URI base) {
268         URI u = null;
269         URI b = base;
270         String a = Env.ALL_ADDRESSES.getHostAddress();
271         
272         if (b != null) {
273             try {
274                 u = new URI(b.getScheme(), EMPTY_STRING, a, b.getPort(),
275                 b.getPath(), b.getPath(), b.getFragment());
276             } catch (URISyntaxException use) {
277                 if (LOG.isEnabledFor(Level.ERROR)) {
278                     LOG.error("invalid transformation", use);
279                 }
280             }
281         } else {
282             try {
283                 u = new URI(Default.ANY_TCP_ADDRESS.getScheme(), EMPTY_STRING,
284                 a, Default.TCP_PORT, EMPTY_STRING, EMPTY_STRING,
285                 EMPTY_STRING);
286             } catch (URISyntaxException use) {
287                 if (LOG.isEnabledFor(Level.ERROR)) {
288                     LOG.error("invalid transformation", use);
289                 }
290             }
291         }
292         
293         return u;
294     }
295     
296     /**
297      *  Constructor for the Configurator object.
298      *
299      * @deprecated It's recommended to use the four params constructor
300      *
301      */
302     public Configurator() {
303         this(null, null, null, null);
304     }
305     
306     /**
307      *  Constructor for the Configurator object.
308      *
309      * @param  name       peer name
310      * @param  password   peer password
311      */
312     public Configurator(String name, String password) {
313         this(name, null, name, password);
314     }
315     
316     /**
317      *  Constructor for the Configurator object.
318      *
319      * @deprecated It's recommended to use the four param constructor
320      *
321      * @param  name       peer name
322      * @param  principal  peer principal
323      * @param  password   peer password
324      */
325     public Configurator(String name, String principal, String password) {
326         this(name, null, principal, password);
327     }
328     
329     /**
330      *  Constructor for the Configurator object.<br>
331      *  <br>
332      *  If a {@link Env#PLATFORM_CONFIG Platform configuration file} is found
333      *  residing in the {@link Env#JXTA_HOME JXTA home} directory it is used to
334      *  seed this instance. If this fails and a {@link Env#PROFILEProfile} is
335      *  found residing in the {@link Env#JXTA_HOME JXTA home} directory, it is,
336      *  in turn, used to seed this instance. In the event neither of these
337      *  configuration files are found the {@link Default defaults} are
338      *  configured accordingly.
339      *
340      * @param  name         peer name
341      * @param  description  peer description
342      * @param  principal    peer principal
343      * @param  password     peer password
344      * @see                 net.jxta.impl.protocol.PlatformConfig
345      */
346     public Configurator(String name, String description, String principal,
347         String password) {
348         PlatformConfig pc = null;
349         
350         try {
351             pc = (PlatformConfig)load();
352         } catch (ConfiguratorException ce) {
353             LOG.error("bad existing configuration");
354         }
355         
356         File cf = new File(getHome(), Env.PROFILE);
357         Profile p = Profile.DEFAULT;
358         
359         if (pc == null &&
360             cf.exists()) {
361             try {
362                 p = new Profile(cf.toURL());
363             } catch (MalformedURLException mue) {
364                 if (LOG.isEnabledFor(Level.ERROR)) {
365                     LOG.error("invalid config", mue);
366                 }
367             }
368         }
369         
370         if (pc != null) {
371             process(pc);
372         } else if (p != null) {
373             process(p);
374         }
375         
376         description = (description != null &&
377         description.trim().length() > 0) ?
378             description.trim() : Default.PEER_DESCRIPTION;
379         
380         if (name != null &&
381             name.trim().length() > 0) {
382             setName(name);
383         }
384         
385         if (description.trim().length() > 0) {
386             setDescription(description);
387         }
388         
389         setSecurity(principal, password);
390         setTrace(getTrace());
391     }
392     
393     /**
394      *  Constructor for the Configurator object.<br>
395      *  <br>
396      *  If the provided <code>Profile</code> is null the {@link Profile#DDFAULT
397      *  default profile} will be used in it's place.
398      *
399      * @param  profile  profile
400      */
401     public Configurator(Profile profile) {
402         process(profile);
403     }
404     
405     /**
406      *  Constructor for the Configurator object.<br>
407      *  <br>
408      *  If the provided <code>PlatformConfig</code> is null a default
409      *  PlatformConfig will be used in it's place.
410      *
411      * @param  config  configuration
412      * @see            net.jxta.impl.protocol.PlatformConfig
413      */
414     public Configurator(PlatformConfig config) {
415         process(config);
416     }
417     
418     /**
419      *  {@inheritDoc}
420      **/
421     public ConfigParams load()
422     throws ConfiguratorException {
423         return load(new File(getHome(), Env.PLATFORM_CONFIG));
424     }
425     
426     /**
427      *  {@inheritDoc}
428      **/
429     public PlatformConfig load(File loadFile)
430     throws ConfiguratorException {
431         if (LOG.isEnabledFor(Level.DEBUG)) {
432             LOG.debug("Reading Platform Config from : " +
433             loadFile.getAbsolutePath());
434         }
435         
436         PlatformConfig pc = null;
437         FileInputStream advStream = null;
438         
439         try {
440             advStream = new FileInputStream(loadFile);
441             Reader advReader = new InputStreamReader(advStream, "UTF-8");
442             
443             pc = (PlatformConfig)AdvertisementFactory.newAdvertisement(MimeMediaType.XMLUTF8,
444                 advReader);
445             
446             if (LOG.isEnabledFor(Level.DEBUG)) {
447                 LOG.debug("Recovered Platform Config from : " +
448                     loadFile.getAbsolutePath());
449             }
450         } catch (FileNotFoundException e) {
451             if (LOG.isEnabledFor(Level.WARN)) {
452                 LOG.warn("Platform Config not found : " +
453                     loadFile.getAbsolutePath());
454             }
455         } catch (Exception e) {
456             if (LOG.isEnabledFor(Level.WARN)) {
457                 LOG.warn("Failed to Recover '" + loadFile.getAbsolutePath() +
458                     "' due to : ", e);
459             }
460             
461             try {
462                 // delete that bad file.
463                 loadFile.delete();
464             } catch (Exception ex1) {
465                 LOG.fatal("Could not remove bad Configuration file", ex1);
466                 
467                 throw new ConfiguratorException( "Could not remove '" +
468                     loadFile.getAbsolutePath() +
469                     "'. Remove it by hand before retrying", ex1);
470             }
471             
472             throw new ConfiguratorException("Failed to Recover PlatformConfig", e);
473         } finally {
474             try {
475                 if (advStream != null) {
476                     advStream.close();
477                 }
478                 
479                 advStream = null;
480             } catch (Exception ignored) {
481             }
482         }
483         
484         return pc;
485     }
486             
487     public URI getJXTAHome() {
488         return getHome().toURI();
489     }
490     
491     /**
492      *  Gets the descriptor.
493      *
494      * @return    The descriptor value
495      */
496     public String getDescriptor() {
497         return this.descriptor;
498     }
499     
500     /**
501      *  Sets the descriptor
502      *
503      * @param  descriptor  The new descriptor value
504      */
505     public void setDescriptor(String descriptor) {
506         this.descriptor = descriptor;
507     }
508     
509     /**
510      *  Gets the <code>Peer</code> name.
511      *
512      * @return    The peer name
513      */
514     public String getName() {
515         return this.peerName;
516     }
517     
518     
519     /**
520      *  Sets the <code>Peer</code> name.
521      *
522      * @param  name  the peer name
523      */
524     public void setName(String name) {
525         this.peerName = (name != null && name.trim().length() > 0 ?
526             name.trim() : null);
527     }
528     
529     /**
530      *  Gets the <code>Peer</code> description.
531      *
532      * @return    The peer description
533      */
534     public String getDescription() {
535         return this.peerDescription;
536     }
537     
538     /**
539      *  Sets the <code>Peer</code> description.
540      *
541      * @param  description  the peer description
542      */
543     public void setDescription(String description) {
544         this.peerDescription = (description != null &&
545             description.trim().length() > 0 ?
546                 description.trim() : null);
547     }
548     
549     /**
550      *  Gets the <code>Trace</code>.
551      *
552      * @return    The Trace
553      */
554     public Trace getTrace() {
555         return this.trace;
556     }
557     
558     /**
559      *  Sets the <code>Trace</code> level.
560      *
561      * @param  trace  the Trace
562      */
563     public void setTrace(Trace trace) {
564         if (trace != null) {
565             this.trace = trace;
566         }
567     }
568     
569     /**
570      *  Gets the <code>PeerID</code>.
571      *
572      * @return    The PeerID
573      */
574     public PeerID getPeerId() {
575         return this.peerId;
576     }
577     
578     /**
579      *  Sets the <code>PeerID</code>.<br>
580      *  <br>
581      *  Unspecified PeerIDs will be generated by the <code>Platform</code>.
582      *
583      * @param  peerId  The PeerID
584      */
585     public void setPeerId(PeerID peerId) {
586         this.peerId = peerId;
587     }
588     
589     /**
590      *  Gets the <code>RendezVous</code> enabler.
591      *
592      * @return    The RendezVous enabler
593      */
594     public boolean isRendezVous() {
595         return RdvConfigAdv.RendezVousConfiguration.RENDEZVOUS ==
596             rdvConfig.getConfiguration();
597     }
598     
599     /**
600      *  Sets the <code>RendezVous</code> enabler.
601      *
602      * @param  isEnabled  The RendezVous enabler
603      */
604     public void setRendezVous( boolean isEnabled) {
605         rdvConfig.setConfiguration(isEnabled ?
606             RdvConfigAdv.RendezVousConfiguration.RENDEZVOUS :
607             RdvConfigAdv.RendezVousConfiguration.EDGE);
608     }
609     
610     /**
611      *  Gets the <code>RendezVous</code> addresses.
612      *
613      * @return    The RendezVous addresses
614      */
615     public List getRendezVous() {
616         return new ArrayList(Arrays.asList(rdvConfig.getSeedRendezvous()));
617     }
618     
619     /**
620      *  Sets the <code>RendezVous</code> addresses.<br>
621      *  <br>
622      *  RendezVous addresses with unspecified host information will be, upon
623      *  <code>PlatformConfig</code> generation, be replaced with the associated
624      *  bootstrap results. Further, if the scheme is provided.then only matching
625      *  boostrap results will be retained.
626      *
627      * @param  rendezVous                 The RendezVous address
628      * @exception  ConfiguratorException  Description of the Exception
629      */
630     public void setRendezVous(URI rendezVous)
631     throws ConfiguratorException {
632         setRendezVous(Collections.singletonList(rendezVous));
633     }
634     
635     /**
636      *  Sets the <code>RendezVous</code> addresses.<br>
637      *  <br>
638      *  RendezVous addresses with unspecified host information will be, upon
639      *  <code>PlatformConfig</code> generation, be replaced with the associated
640      *  bootstrap results. Further, if the scheme is provided.then only matching
641      *  boostrap results will be retained.
642      *
643      * @param  rendezVous                 The RendezVous addresses
644      * @exception  ConfiguratorException  Description of the Exception
645      */
646     public void setRendezVous(List seed)
647     throws ConfiguratorException {
648         this.rdvConfig.clearSeedRendezvous();
649         addRendezVous(seed);
650     }
651     
652     /**
653      *  Adds a <code>RendezVous</code> address.<br>
654      *  <br>
655      *  RendezVous addresses with unspecified host information will be, upon
656      *  <code>PlatformConfig</code> generation, be replaced with the associated
657      *  bootstrap results. Further, if the scheme is provided.then only matching
658      *  boostrap results will be retained.
659      *
660      * @param  rendezVous                 The RendezVous address
661      * @exception  ConfiguratorException  Description of the Exception
662      */
663     public void addRendezVous(URI seed)
664     throws ConfiguratorException {
665         addRendezVous(Collections.singletonList(seed));
666     }
667     
668     /**
669      *  Adds <code>RendezVous</code> addresses.<br>
670      *  <br>
671      *  RendezVous addresses with unspecified host information will be, upon
672      *  <code>PlatformConfig</code> generation, be replaced with the associated
673      *  bootstrap results. Further, if the scheme is provided.then only matching
674      *  boostrap results will be retained.
675      *
676      * @param  rendezVous                 The RendezVous addressses
677      * @exception  ConfiguratorException  Description of the Exception
678      */
679     public void addRendezVous(List seed)
680     throws ConfiguratorException {
681         for (Iterator r = seed.iterator(); r.hasNext();) {
682             URI u = (URI)r.next();
683             
684             if (Util.validateAddress(u, false).trim().length() == 0) {
685                 rdvConfig.addSeedRendezvous(u);
686             } else {
687                 throw new ConfiguratorException("invalid address: " + u);
688             }
689         }
690     }
691     
692     /**
693      *  Remove the <code>RendezVous</code> address.
694      *
695      * @param  rendezVous  The RendezVous address
696      * @return             Description of the Return Value
697      */
698     public URI removeRendezVous(URI rendezVous) {
699         return rdvConfig.removeSeedRendezvous(rendezVous) ? rendezVous : null;
700     }
701     
702     /**
703      *  Remove all <code>RendezVous</code> addresses.
704      */
705     public void clearRendezVous() {
706         rdvConfig.clearSeedRendezvous();
707     }
708     
709     /**
710      *  Get <code>RendezVousService</code> AutoStart status.
711      *
712      * @return    The rendezVousAutoStart value
713      */
714     public boolean isRendezVousAutoStart() {
715         return (rdvConfig.getAutoRendezvousCheckInterval() != 0);
716     }
717     
718     /**
719      *  Set <code>RendezVousService</code> AutoStart status enabling the
720      *  resulting <code>Peer</code> to become a <code>RendezVous</code> if the
721      *  ascribed RendezVous are not accessible.
722      *
723      *  @deprecated controlled via setting autostart interval.
724      *
725      * @param  isAutoStart  The new rendezVousAutoStart value
726      */
727     public void setRendezVousAutoStart(boolean isAutoStart) {}
728     
729     /**
730      *  Gets the <code>RendezVous</code> AutoStart delay in milliseconds.
731      *
732      * @return    autoStart
733      */
734     public long getRendezVousAutoStart() {
735         return rdvConfig.getAutoRendezvousCheckInterval();
736     }
737     
738     /**
739      *  Sets the <code>RendezVous</code> AutoStart delay measured in
740      *  milliseconds.
741      *
742      * @param  autoStart  autoStart delay in milliseconds
743      */
744     public void setRendezVousAutoStart(long autoStart) {
745         rdvConfig.setAutoRendezvousCheckInterval(autoStart);
746     }
747     
748     /**
749      *  Gets the <code>Relay</code> enabler.
750      *
751      * @return    The Relay enabler.
752      */
753     public boolean isRelay() {
754         return this.relayConfig.isClientEnabled() || this.relayConfig.isServerEnabled();
755     }
756     
757     /**
758      *  Sets the <code>Relay</code> enabler.
759      *
760      * @param  isEnabled  The Relay enabler.
761      */
762     public void setRelay(boolean isEnabled) {
763 //         throw new UnsupportedOperationException( "this doesn't work" );
764     }
765     
766     /**
767      *  Gets the <code>Relay</code> addresses.
768      *
769      * @return    The relays value
770      */
771     public List getRelays() {
772         List allSeeds = Arrays.asList( this.relayConfig.getSeedRelays() );
773         List result = new ArrayList(allSeeds.size());
774         
775         Iterator eachSeed = allSeeds.iterator();
776         while( eachSeed.hasNext() ) {
777             try {
778             result.add( new URI( eachSeed.next().toString() ));
779             } catch( URISyntaxException ignored ) {
780                 ;
781             }
782         }
783         
784         return result;
785     }
786     
787     /**
788      *  Sets the <code>Relay</code> address.<br>
789      *  <br>
790      *  Relays addresses with unspecified host information will be, upon
791      *  <code>PlatformConfig</code> generation, be replaced with the
792      *  associated bootstrap results. Further if the scheme is provided.then
793      *  only matching boostrap results will be retained.
794      *
795      * @param  relay                      The Relay address
796      * @exception  ConfiguratorException  Description of the Exception
797      */
798     public void setRelay(URI relay)
799     throws ConfiguratorException {
800         this.relayConfig.clearSeedRelays();
801         this.relayConfig.addSeedRelay( relay.toString() );
802     }
803     
804     /**
805      *  Sets the <code>Relay</code> addresses.<br>
806      *  <br>
807      *  Relays addresses with unspecified host information will be, upon
808      *  <code>PlatformConfig</code> generation, be replaced with the
809      *  associated bootstrap results. Further, if the scheme is provided
810      *  then only matching boostrap results will be retained.
811      *
812      * @param  relays                     The Relay addresses
813      * @exception  ConfiguratorException  Description of the Exception
814      */
815     public void setRelays(List relays) throws ConfiguratorException {
816         this.relayConfig.clearSeedRelays();
817         
818         addRelays(relays);
819     }
820     
821     /**
822      *  Adds a <code>Relay</code> address.<br>
823      *  <br>
824      *  Relays addresses with unspecified host information will be, upon
825      *  <code>PlatformConfig</code> generation, be replaced with the
826      *  associated bootstrap results. Further if the scheme is provided
827      *  then only matching boostrap results will be retained.
828      *
829      * @param  relay                      The Relay address.
830      * @exception  ConfiguratorException  Description of the Exception
831      */
832     public void addRelay(URI relay) throws ConfiguratorException {
833         try {
834        this.relayConfig.addSeedRelay( relay.toString() );
835         } catch( Exception all ) {
836             throw new ConfiguratorException( "Bad relay", all );
837         }
838     }
839     
840     /**
841      *  Adds <code>Relay</code> addresses.<br>
842      *  <br>
843      *  Relays addresses with unspecified host information will be, upon
844      *  <code>PlatformConfig</code> generation, be replaced with the
845      *  associated bootstrap results. Further if the scheme is provided
846      *  then only matching boostrap results will be retained.
847      *
848      * @param  relays                     The Relay addresses
849      * @exception  ConfiguratorException  Description of the Exception
850      */
851     public void addRelays(List relays)
852     throws ConfiguratorException {
853         Iterator eachRelay = relays.iterator();
854         while( eachRelay.hasNext() ) {
855             addRelay( (URI) eachRelay.next() );
856         }
857     }
858     
859     /**
860      *  Remove the <code>Relay</code> address.
861      *
862      * @param  relay  The Relay address
863      * @return        Description of the Return Value
864      */
865     public URI removeRelay(URI relay) {
866         throw new UnsupportedOperationException( "this doesn't work" );
867     }
868     
869     /**
870      *  Remove all <code>Relay</code> addresses.
871      */
872     public void clearRelays() {
873         this.relayConfig.clearSeedRelays();
874     }
875     
876     /**
877      *  Gets the <code>Relay</code> incoming enabler.
878      *
879      * @return    The Relay enabler
880      */
881     public boolean isRelayIncoming() {
882         return this.relayConfig.isServerEnabled();
883     }
884     
885     /**
886      *  Sets the <code>Relay</code> enabler enabling inbound connections.
887      *
888      * @param  isEnabled  The Relay enabler
889      */
890     public void setRelayIncoming(boolean isEnabled) {
891         this.relayConfig.setServerEnabled( isEnabled );
892     }
893     
894     /**
895      *  Gets the <code>Relay</code> incoming maximum.
896      *
897      * @return    The Relay incoming maximum
898      */
899     public int getRelayIncomingMaximum() {
900         return this.relayConfig.getMaxClients( );
901     }
902     
903     /**
904      *  Sets the <code>Relay</code> incoming maximum.
905      *
906      * @param  maximumIncoming  The Relay incoming maximum
907      */
908     public void setRelayIncomingMaximum(int maximumIncoming) {
909         this.relayConfig.setMaxClients( maximumIncoming );
910     }
911     
912     /**
913      *  Gets the <code>Relay</code> incoming lease measured in milliseconds.
914      *
915      * @return    The Relay incoming lease
916      */
917     public long getRelayIncomingLease() {
918         return this.relayConfig.getServerLeaseDuration();
919     }
920     
921     /**
922      *  Sets the <code>Relay</code> incoming lease measured in milliseconds.
923      *
924      * @param  incomingLease  The Relay incoming lease
925      */
926     public void setRelayIncomingLease(long incomingLease) {
927         this.relayConfig.setServerLeaseDuration( incomingLease );
928     }
929     
930     /**
931      *  Gets the <code>Relay</code> outgoing enabler.
932      *
933      * @return    The Relay outgoing enabler
934      */
935     public boolean isRelayOutgoing() {
936         return this.relayConfig.isClientEnabled();
937     }
938     
939     /**
940      *  Sets the <code>Relay</code> outgoing enabler enabling outbound
941      *  connnections.
942      *
943      * @param  isEnabled  The Relay outgoing enabler
944      */
945     public void setRelayOutgoing(boolean isEnabled) {
946         this.relayConfig.setClientEnabled( isEnabled );
947     }
948     
949     /**
950      *  Gets the <code>Relay</code> outgoing maximum.
951      *
952      * @return    The Relay outgoing maximum
953      */
954     public int getRelayOutgoingMaximum() {
955         return this.relayConfig.getMaxRelays();
956     }
957     
958     /**
959      *  Sets the <code>Relay</code> outgoing maximum.
960      *
961      * @param  maximumOutgoing  The Relay outgoing maximum
962      */
963     public void setRelayOutgoingMaximum(int maximumOutgoing) {
964         this.relayConfig.setMaxRelays( maximumOutgoing );
965     }
966     
967     /**
968      *  Gets the <code>Relay</code> outgoing lease measured in milliseconds.
969      *
970      * @return    The Relay outgoing lease
971      */
972     public long getRelayOutgoingLease() {
973         return this.relayConfig.getClientLeaseDuration();
974     }
975     
976     /**
977      *  Sets the <code>Relay</code> outgoing lease measured in milliseconds.
978      *
979      * @param  outgoingLease  The Relay outgoing lease
980      */
981     public void setRelayOutgoingLease(long outgoingLease) {
982         this.relayConfig.setClientLeaseDuration( outgoingLease );
983     }
984     
985     /**
986      *  Gets the <code>Relay</code> queue size measured in messages.
987      *
988      * @return    The Relay queue size
989      */
990     public int getRelayQueueSize() {
991         return this.relayConfig.getClientMessageQueueSize();
992     } 
993     
994     /**
995      *  Sets the <code>Relay</code> queue size measured in messages.
996      *
997      * @param  queueSize  The Relay queue size
998      */
999     public void setRelayQueueSize(int queueSize) {
1000        this.relayConfig.setClientMessageQueueSize( queueSize );
1001    }
1002    
1003    /**
1004     *  Gets the transports attribute of the Configurator object
1005     *
1006     * @return    The transports value
1007     */
1008    public List getTransports() {
1009        return this.transports != null ?
1010            (List)((ArrayList)this.transports).clone() :
1011            Collections.EMPTY_LIST;
1012    }
1013    
1014    /**
1015     *  Sets the transport attribute of the Configurator object
1016     *
1017     * @param  transport  The new transport value
1018     */
1019    public void setTransport(Transport transport) {
1020        List t = new ArrayList();
1021        
1022        t.add(transport);
1023        
1024        setTransports(t);
1025    }
1026    
1027    /**
1028     *  Sets the transports attribute of the Configurator object
1029     *
1030     * @param  transports  The new transports value
1031     */
1032    public void setTransports(List transports) {
1033        if (this.transports != null) {
1034            this.transports.clear();
1035        }
1036        
1037        addTransports(transports);
1038    }
1039    
1040    /**
1041     *  Adds a feature to the Transport attribute of the Configurator object
1042     *
1043     * @param  transport  The feature to be added to the Transport attribute
1044     */
1045    public void addTransport(Transport transport) {
1046        List t = new ArrayList();
1047        
1048        t.add(transport);
1049        
1050        addTransports(t);
1051    }
1052    
1053    /**
1054     *  Adds a feature to the Transports attribute of the Configurator object
1055     *
1056     * @param  transports  The feature to be added to the Transports attribute
1057     */
1058    public void addTransports(List transports) {
1059        for (Iterator i = transports != null ?
1060            transports.iterator() : Collections.EMPTY_LIST.iterator();
1061            i.hasNext(); ) {
1062            Transport t = (Transport)i.next();
1063            
1064            if (t != null &&
1065                (this.transports == null ||
1066                ! this.transports.contains(t))) {
1067                if (this.transports == null) {
1068                    this.transports = new ArrayList();
1069                }
1070                
1071                this.transports.add(t);
1072            }
1073        }
1074    }
1075    
1076    /**
1077     *  Description of the Method
1078     *
1079     * @param  transport  Description of the Parameter
1080     * @return            Description of the Return Value
1081     */
1082    public Transport removeTransport(Transport transport) {
1083        Object o = null;
1084        
1085        if (this.transports != null) {
1086            int i = this.transports.indexOf(transport);
1087            
1088            if (i > -1) {
1089                o = this.transports.remove(i);
1090                
1091                if (this.transports.size() == 0) {
1092                    this.transports = null;
1093                }
1094            }
1095        }
1096        
1097        return (Transport)o;
1098    }
1099    
1100    /**
1101     *  Description of the Method
1102     */
1103    public void clearTransports() {
1104        if (this.transports != null) {
1105            this.transports.clear();
1106            
1107            this.transports = null;
1108        }
1109    }
1110    
1111    /**
1112     *  Gets the principal.
1113     *
1114     * @return    The principal
1115     */
1116    public String getPrincipal() {
1117        return this.principal;
1118    }
1119    
1120    /**
1121     *  Gets the security enabler.
1122     *
1123     * @return    security enabler
1124     */
1125    public boolean isSecurity() {
1126        return this.isSecurity;
1127    }
1128    
1129    /**
1130     *  Sets the security enabler.
1131     *
1132     * @param  isEnabled  The new security value
1133     */
1134    public void setSecurity(boolean isEnabled) {
1135        this.isSecurity = isEnabled;
1136    }
1137    
1138    /**
1139     *  Sets the principal and associated password.
1140     *
1141     * @param  principal  The principal
1142     * @param  password   The password
1143     */
1144    public void setSecurity(String principal, String password) {
1145        this.principal = (principal != null &&
1146            principal.trim().length() > 0 ? principal.trim() : null);
1147        this.password = (password != null &&
1148            password.trim().length() > 0 ? password.trim() : null);
1149    }
1150    
1151    /**
1152     *  Gets the Root Certificate address.
1153     *
1154     * @return    The root certificate address
1155     */
1156    public URI getRootCertificateAddress() {
1157        return this.rootCertificateAddress;
1158    }
1159    
1160    /**
1161     *  Sets the Root Certificate address.
1162     *
1163     * @param  rootCertificateAddress  the root certificate address
1164     */
1165    public void setRootCertificateAddress(URI rootCertificateAddress) {
1166        this.rootCertificateAddress = rootCertificateAddress;
1167    }
1168    
1169    /**
1170     *  Gets the root certificate.
1171     *
1172     * @return    The root certificate
1173     */
1174    public Certificate getRootCertificate() {
1175        return this.pse.getCertificate();
1176    }
1177    
1178    /**
1179     *  Gets the root certificate Base64 encoded.
1180     *
1181     * @return    The root certificate
1182     */
1183    public String getRootCertificateBase64() {
1184        String s = null;
1185        
1186        try {
1187            s = this.pse.getCert();
1188        } catch (Exception e) {
1189            if (LOG.isEnabledFor(Level.DEBUG)) {
1190                LOG.debug("can't get root cert");
1191            }
1192        }
1193        
1194        return s;
1195    }
1196    
1197    /**
1198     *  Sets the root certificate
1199     *
1200     * @param  rootCertificate  root certificate
1201     */
1202    public void setRootCertificate(Certificate rootCertificate) {
1203        this.pse.setCertificate((X509Certificate) rootCertificate);
1204    }
1205    
1206    /**
1207     *  Sets the root certificate
1208     *
1209     * @param  rootCertificate  Base64 encoded root certificate
1210     */
1211    public void setRootCertificateBase64(String rootCertificate) {
1212        if (rootCertificate != null) {
1213            this.pse.setCert(rootCertificate);
1214        }
1215    }
1216    
1217    /**
1218     *  Gets the proxy used for configuration.
1219     *
1220     * @return    The cofigurator proxy address value
1221     */
1222    public URI getPeerProxyAddress() {
1223        return this.peerProxy;
1224    }
1225    
1226    /**
1227     *  Sets the proxy used for configuration. If the address scheme is not
1228     *  specified the appropriate value will be assigned.
1229     *
1230     * @param  peerProxyAddress           The new peerProxyAddress value
1231     * @exception  ConfiguratorException  if the address scheme is not "http" or
1232     *      the port is invalid
1233     */
1234    public void setPeerProxyAddress(URI peerProxyAddress)
1235    throws ConfiguratorException {
1236        if (Util.validateAddress(peerProxyAddress, true).trim().length() == 0) {
1237            this.peerProxy = peerProxyAddress;
1238        } else {
1239            throw new ConfiguratorException("invalid proxy",
1240                new IllegalArgumentException("invalid proxy uri: " +
1241                    peerProxyAddress));
1242        }
1243    }
1244    
1245    /**
1246     *  Gets the Endpoint queue size measured in messages
1247     *
1248     * @return    The endpointOutgoingQueueSize value
1249     */
1250    public int getEndpointOutgoingQueueSize() {
1251        return this.endpointQueueSize;
1252    }
1253    
1254    /**
1255     *  Sets the Endpoint queue size measured in messages
1256     *
1257     * @param  size  The endpoint queue size
1258     */
1259    public void setEndpointOutgoingQueueSize(int size) {
1260        this.endpointQueueSize = size;
1261    }
1262    
1263    /**
1264     *  Gets the proxy service enabler.
1265     *
1266     * @return    The proxy service enabler
1267     */
1268    public boolean isProxy() {
1269        return this.isProxyEnabled;
1270    }
1271    
1272    /**
1273     *  Sets the proxy service enabler.
1274     *
1275     * @param  isEnabled  The proxy service enabler
1276     */
1277    public void setProxy(boolean isEnabled) {
1278        this.isProxyEnabled = isEnabled;
1279    }
1280    
1281    /**
1282     *  Gets the <code>RendezVous</code> bootstrap address.
1283     *
1284     * @return    The rendezVousBootstrap value
1285     */
1286    public URI getRendezVousBootstrapAddress() {
1287        //return this.rendezVousBootstrap;
1288        URI[] u = this.rdvConfig.getSeedingURIs();
1289        
1290        return (u.length > 0 ? u[0] : null);
1291    }
1292    
1293    /**
1294     *  Sets the <code>RendezVous</code> bootstrap address that will be used to
1295     *  resolve all addresses that do not specify a host.
1296     *
1297     * @param  rendezVousBootstrapAddress  The new rendezVousBootstrapAddress
1298     *      value
1299     * @exception  ConfiguratorException   Description of the Exception
1300     */
1301    public void setRendezVousBootstrapAddress(URI rendezVousBootstrapAddress)
1302    throws ConfiguratorException {
1303        if (rendezVousBootstrapAddress != null &&
1304            Util.validateAddress(rendezVousBootstrapAddress, -1).trim().length() > 0) {
1305            throw new ConfiguratorException("invalid address: " +
1306                rendezVousBootstrapAddress);
1307        }
1308        
1309        //this.rendezVousBootstrap = rendezVousBootstrapAddress;
1310        this.rdvConfig.addSeedingURI(rendezVousBootstrapAddress);
1311    }
1312    
1313    /**
1314     *  Gets the <code>RendezVous</code> discovery enabler.
1315     *
1316     * @return    The rendezVousDiscovery value
1317     */
1318    public boolean isRendezVousDiscovery() {
1319        return !rdvConfig.getUseOnlySeeds();
1320    }
1321    
1322    /**
1323     *  Sets the <code>RendezVous</code> discovery enabler.
1324     *
1325     * @param  isEnabled  The new rendezVousDiscovery value
1326     */
1327    public void setRendezVousDiscovery(boolean discover ) {
1328        rdvConfig.setUseOnlySeeds( !discover );
1329    }
1330    
1331    /**
1332     *  Gets the <code>Relay</code> bootstrap address.
1333     *
1334     * @return    The relaysBootstrap value
1335     */
1336    public URI getRelaysBootstrapAddress() {
1337        //return this.relaysBootstrap;
1338        URI[] u = this.relayConfig.getSeedingURIs();
1339        
1340        return (u.length > 0 ? u[0] : null);
1341    }
1342    
1343    /**
1344     *  Sets the <code>Relay</code> bootstrap address that will be used to
1345     *  resolve all addresses that do not specify a host.
1346     *
1347     * @param  relaysBootstrapAddress     The new relaysBootstrapAddress value
1348     * @exception  ConfiguratorException  Description of the Exception
1349     */
1350    public void setRelaysBootstrapAddress(URI relaysBootstrapAddress)
1351    throws ConfiguratorException {
1352        if (relaysBootstrapAddress != null &&
1353            Util.validateAddress(relaysBootstrapAddress, -1).trim().length() > 0) {
1354            throw new ConfiguratorException("invalid address: " +
1355                relaysBootstrapAddress);
1356        }
1357        
1358        //this.relaysBootstrap = relaysBootstrapAddress;
1359        this.relayConfig.addSeedingURI(relaysBootstrapAddress);
1360    }
1361    
1362    /**
1363     *  Gets the <code>Relay</code> discovery enabler.
1364     *
1365     * @return    The relayDiscovery value
1366     */
1367    public boolean isRelaysDiscovery() {
1368        return this.isRelaysDiscovery;
1369    }
1370    
1371    /**
1372     *  Sets the <code>Relay</code> discovery enabler.
1373     *
1374     * @param  isEnabled  The new relayDiscovery value
1375     */
1376    public void setRelayDiscovery(boolean isEnabled) {
1377        this.isRelaysDiscovery = isEnabled;
1378    }
1379    
1380    /**
1381     *  Gets the <code>Relay</code> discovery enabler.
1382     *
1383     * @return    The relaysDiscovery value
1384     */
1385    public boolean getRelaysDiscovery() {
1386        return this.isRelaysDiscovery;
1387    }
1388    
1389    /**
1390     *  Sets the <code>Relays</code> discovery enabler.
1391     *
1392     * @param  isEnabled  The new relaysDiscovery value
1393     */
1394    public void setRelaysDiscovery(boolean isEnabled) {
1395        this.isRelaysDiscovery = isEnabled;
1396    }
1397    
1398    /**
1399     *  Gets the <code>Reflection</code> bootstrap address.
1400     *
1401     * @return    The reflectionBootstrap value
1402     * @deprecated moved to {@link net.jxta.ext.config.optimizers.RelayOptimizer RelayOptimizer} property
1403     */
1404    public URI getReflectionBootstrapAddress() {
1405        return this.reflectionBootstrap;
1406    }
1407    
1408    /**
1409     *  Sets the <code>Reflection</code> bootstrap address that is used during
1410     * the optimization process.
1411     *
1412     * @param  reflectionBootstrapAddress     The new reflectionBootstrapAddress value
1413     * @exception  ConfiguratorException  Description of the Exception
1414     * @deprecated moved to {@link net.jxta.ext.config.optimizers.RelayOptimizer RelayOptimizer} property
1415     */
1416    public void setReflectionBootstrapAddress(URI reflectionBootstrapAddress)
1417    throws ConfiguratorException {
1418        if (reflectionBootstrapAddress != null &&
1419            Util.validateAddress(reflectionBootstrapAddress, -1).trim().length() > 0) {
1420            throw new ConfiguratorException("invalid address: " +
1421                reflectionBootstrapAddress);
1422        }
1423        
1424        this.reflectionBootstrap = reflectionBootstrapAddress;
1425    }
1426    
1427    /**
1428     *  Gets the <code>PlatformConfig</code> that is comprised of the
1429     *  constituent properties. Contingencies include the following integrity
1430     *  validation checks:<br>
1431     *  <br>
1432     *
1433     *  <ul>
1434     *    <li> specified Peer name</li>
1435     *    <li> valid principal and password</li>
1436     *    <li> at least one transport is enabled</li>
1437     *    <li> transport host and port is specified</li>
1438     *    <li> valid multicast port and size</li>
1439     *    <li> for Relays at least one transport is specified</li>
1440     *    <li> valid Http proxy, if requiired</li>
1441     *  </ul>
1442     *
1443     *
1444     * @return                            The PlatformConfig
1445     * @exception  ConfiguratorException  if invalid configuration
1446     */
1447    public PlatformConfig getPlatformConfig()
1448