2 * Copyright (c) 2001-2007 Sun Microsystems, Inc. All rights reserved.
4 * The Sun Project JXTA(TM) Software License
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * 3. The end-user documentation included with the redistribution, if any, must
17 * include the following acknowledgment: "This product includes software
18 * developed by Sun Microsystems, Inc. for JXTA(TM) technology."
19 * Alternately, this acknowledgment may appear in the software itself, if
20 * and wherever such third-party acknowledgments normally appear.
22 * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must
23 * not be used to endorse or promote products derived from this software
24 * without prior written permission. For written permission, please contact
25 * Project JXTA at http://www.jxta.org.
27 * 5. Products derived from this software may not be called "JXTA", nor may
28 * "JXTA" appear in their name, without prior written permission of Sun.
30 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
32 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SUN
33 * MICROSYSTEMS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
36 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
37 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
39 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 * JXTA is a registered trademark of Sun Microsystems, Inc. in the United
42 * States and other countries.
44 * Please see the license information page at :
45 * <http://www.jxta.org/project/www/license.html> for instructions on use of
46 * the license in source files.
48 * ====================================================================
50 * This software consists of voluntary contributions made by many individuals
51 * on behalf of Project JXTA. For more information on Project JXTA, please see
52 * http://www.jxta.org.
54 * This license is based on the BSD license adopted by the Apache Foundation.
57 package net.jxta.peergroup;
60 import net.jxta.document.MimeMediaType;
61 import net.jxta.document.StructuredDocumentFactory;
62 import net.jxta.document.XMLElement;
63 import net.jxta.exception.PeerGroupException;
64 import net.jxta.id.ID;
65 import net.jxta.id.IDFactory;
66 import net.jxta.logging.Logging;
67 import net.jxta.protocol.ConfigParams;
68 import net.jxta.protocol.ModuleImplAdvertisement;
70 import net.jxta.impl.protocol.PeerGroupConfigAdv;
71 import net.jxta.impl.peergroup.GenericPeerGroup;
74 import java.io.FileInputStream;
75 import java.io.IOException;
77 import java.util.MissingResourceException;
78 import java.util.PropertyResourceBundle;
79 import java.util.ResourceBundle;
80 import java.util.logging.Level;
81 import java.util.logging.Logger;
85 * A factory for instantiating a Network Peer Group instances. The Network Peer
86 * Group is the base peer group for applications and services within the JXTA
87 * network. Most applications and services will instantiate their own peer
88 * groups using the Network Peer Group as a base.
90 * A non-default configuration of <em>The Network Peer Group</em> may be
91 * set-up by the administrator in charge of the network domain inside which the
92 * peer is starting. <em>The Network Peer Group</em> may be discovered via the
93 * JXTA Discovery protocol. Many such groups may be configured by an
98 * @see net.jxta.peergroup.PeerGroup
99 * @see net.jxta.peergroup.WorldPeerGroupFactory
101 public final class NetPeerGroupFactory {
106 private final static transient Logger LOG = Logger.getLogger(NetPeerGroupFactory.class.getName());
109 * Our strong reference to the net peer group.
111 private final PeerGroup net;
114 * Instantiates the Net Peer Group using the ConfigParams found in the
115 * directory specified by the {@code JXTA_HOME} system property or the
116 * "{@code .jxta/}" directory if {@code JXTA_HOME} is not defined.
118 * This constructor is provided primarily for backwards compatibility.
119 * Though not deprecated this method should be considered as sample code
120 * only and the other constructors should be used whenever possible.
122 * @throws PeerGroupException Thrown for problems constructing the Net Peer
125 public NetPeerGroupFactory() throws PeerGroupException {
126 WorldPeerGroupFactory world = new WorldPeerGroupFactory();
127 PeerGroup worldGroup = world.getInterface();
128 NetGroupTunables tunables;
131 ConfigParams cp = worldGroup.getConfigAdvertisement();
132 PeerGroupConfigAdv netGroupConfig = (PeerGroupConfigAdv) cp.getSvcConfigAdvertisement(PeerGroup.peerGroupClassID);
134 if (null == netGroupConfig) {
135 tunables = new NetGroupTunables(ResourceBundle.getBundle("net.jxta.impl.config"), new NetGroupTunables());
136 // load overides from "${JXTA_HOME}config.properties".
137 URI storeHome = worldGroup.getStoreHome();
139 if (null != storeHome) {
141 File configProperties = new File(new File(storeHome), "config.properties");
142 ResourceBundle rsrcs = new PropertyResourceBundle(new FileInputStream(configProperties));
144 tunables = new NetGroupTunables(rsrcs, tunables);
145 if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) {
146 LOG.fine("Loaded defaults from " + rsrcs);
148 } catch (MissingResourceException ignored) {
150 } catch (IOException ignored) {
155 tunables = new NetGroupTunables(netGroupConfig.getPeerGroupID(), netGroupConfig.getName(), netGroupConfig.getDesc());
158 net = newNetPeerGroup(worldGroup, null, tunables.id, tunables.name, tunables.desc, null);
165 * Constructs a Net Peer Group using the specified parent peer group. This
166 * is the preferred constructor for constructing a Net Peer Group using the
167 * default configuration. The resulting Net Peer Group instance will use
168 * the default ID, Name and Description.
170 * @param parentGroup The Peer Group which will be the parent of the newly
171 * created net peer group. This should normally be the World Peer Group.
172 * @throws PeerGroupException Thrown for problems constructing the Net Peer
175 public NetPeerGroupFactory(PeerGroup parentGroup) throws PeerGroupException {
176 ConfigParams cp = parentGroup.getConfigAdvertisement();
177 PeerGroupConfigAdv netGroupConfig = (PeerGroupConfigAdv) cp.getSvcConfigAdvertisement(PeerGroup.peerGroupClassID);
178 NetGroupTunables tunables;
180 if (null == netGroupConfig) {
181 tunables = new NetGroupTunables(ResourceBundle.getBundle("net.jxta.impl.config"), new NetGroupTunables());
183 tunables = new NetGroupTunables(netGroupConfig.getPeerGroupID(), netGroupConfig.getName(), netGroupConfig.getDesc());
186 net = newNetPeerGroup(parentGroup, null, tunables.id, tunables.name, tunables.desc, null);
190 * Constructs a Net Peer Group and the World Peer Group using the
191 * configuration specified by the provided ConfigParams and using the
192 * specified storeHome location for persistence. The resulting Net Peer
193 * Group instance will use the default ID, Name and Description.
195 * @param config The configuration to use for the newly created World Peer
196 * Group and Net Peer Groups.
197 * @param storeHome The optional location that the World Peer Group, the
198 * Net Peer Group and its' services should use for storing persistent and
199 * transient information. May be {@code null} if the World Peer Group is
200 * not provided a persistent store (though this not currently supported).
201 * @throws PeerGroupException Thrown for problems constructing the Net Peer
204 public NetPeerGroupFactory(ConfigParams config, URI storeHome) throws PeerGroupException {
205 WorldPeerGroupFactory world = new WorldPeerGroupFactory(config, storeHome);
206 PeerGroup worldGroup = world.getInterface();
209 PeerGroupConfigAdv netGroupConfig = (PeerGroupConfigAdv) config.getSvcConfigAdvertisement(PeerGroup.peerGroupClassID);
210 NetGroupTunables tunables;
212 if (null == netGroupConfig) {
213 tunables = new NetGroupTunables(ResourceBundle.getBundle("net.jxta.impl.config"), new NetGroupTunables());
215 tunables = new NetGroupTunables(netGroupConfig.getPeerGroupID(), netGroupConfig.getName(), netGroupConfig.getDesc());
218 net = newNetPeerGroup(worldGroup, config, tunables.id, tunables.name, tunables.desc, null);
225 * Constructs a Net Peer Group and the World Peer Group using the
226 * configuration specified by the provided ConfigParams and using the
227 * specified storeHome location for persistence. The resulting Net Peer
228 * Group instance will use the group information provided in the
230 * This constructor is provided in anticipation of other improvements
231 * to the peer group instantiation process. Currently it has some
232 * unreasonable limitations which keep it from being very useful. In a
233 * future release it will be improved.
235 * @param config The configuration to use for the newly created World Peer
236 * Group and Net Peer Groups.
237 * @param storeHome The optional location that the World Peer Group, the
238 * Net Peer Group and its' services should use for storing persistent and
239 * transient information. May be {@code null} if the World Peer Group is
240 * not provided a persistent store (though this not currently supported).
241 * @throws PeerGroupException Thrown for problems constructing the Net Peer
243 * @param parentGroup the parent peer group
245 public NetPeerGroupFactory(PeerGroup parentGroup, ConfigParams config, URI storeHome) throws PeerGroupException {
247 if (config != parentGroup.getConfigAdvertisement()) {
248 throw new IllegalArgumentException("This constructor cannot currently accept group parameters different than the parent group");
251 if (null == storeHome) {
252 if (null != parentGroup.getStoreHome()) {
253 throw new IllegalArgumentException("This constructor cannot currently accept a different store location than the parent group");
256 if (!storeHome.equals(parentGroup.getStoreHome())) {
257 throw new IllegalArgumentException("This constructor cannot currently accept a different store location than the parent group");
261 ConfigParams cp = parentGroup.getConfigAdvertisement();
262 PeerGroupConfigAdv netGroupConfig = (PeerGroupConfigAdv) cp.getSvcConfigAdvertisement(PeerGroup.peerGroupClassID);
263 NetGroupTunables tunables;
265 if (null == netGroupConfig) {
266 tunables = new NetGroupTunables(ResourceBundle.getBundle("net.jxta.impl.config"), new NetGroupTunables());
268 tunables = new NetGroupTunables(netGroupConfig.getPeerGroupID(), netGroupConfig.getName(), netGroupConfig.getDesc());
271 net = newNetPeerGroup(parentGroup, config, tunables.id, tunables.name, tunables.desc, null);
275 * Constructs a Net Peer Group and the World Peer Group using the
276 * configuration specified by the provided ConfigParams and using the
277 * specified storeHome location for persistence.
279 * @deprecated With the addition of support for {@code PeerGroupConfigAdv}
280 * this constructor is being deprecated as the precedence of settings is
283 * @param config The configuration to use for the newly created World Peer
284 * Group and Net Peer Groups.
285 * @param storeHome The optional location that the World Peer Group, the
286 * Net Peer Group and its' services should use for storing persistent and
287 * transient information. May be {@code null} if the World Peer Group is
288 * not provided a persistent store (though this not currently supported).
289 * @param id The PeerGroupID which will be used for the new Net Peer Group
291 * @param name The name which will be used for the new Net Peer Group
293 * @param desc The description which will be used for the new Net Peer Group
294 * instance. You can construct an {@code XMLDocument} from a {@code String}
297 * XMLDocument asDoc = StructuredDocumentFactory.newStructuredDocument( MimeMediaType.XMLUTF8, "desc", asString );
299 * @throws PeerGroupException Thrown for problems constructing the Net Peer
303 public NetPeerGroupFactory(ConfigParams config, URI storeHome, ID id, String name, XMLElement desc) throws PeerGroupException {
304 WorldPeerGroupFactory world = new WorldPeerGroupFactory(config, storeHome);
305 PeerGroup worldGroup = world.getInterface();
308 net = newNetPeerGroup(worldGroup, config, id, name, desc, null);
315 * Constructs a Net Peer Group instance using the specified parent peer
316 * group (normally the World Peer Group). This is the preferred constructor
317 * for constructing a private Net Peer Group.
319 * @deprecated With the addition of support for {@code PeerGroupConfigAdv}
320 * this constructor is being deprecated as the precedence of settings is
323 * @param parentGroup The Peer Group which will be the parent of the
324 * newly created net peer group. This should normally be the World Peer
326 * @param id The PeerGroupID which will be used for the new Net Peer Group
328 * @param name The name which will be used for the new Net Peer Group
330 * @param desc The description which will be used for the new Net Peer Group
331 * instance. You can construct an {@code XMLDocument} from a {@code String}
334 * XMLDocument asDoc = StructuredDocumentFactory.newStructuredDocument( MimeMediaType.XMLUTF8, "desc", asString );
336 * @throws PeerGroupException Thrown for problems constructing the Net Peer
340 public NetPeerGroupFactory(PeerGroup parentGroup, ID id, String name, XMLElement desc) throws PeerGroupException {
341 net = newNetPeerGroup(parentGroup, null, id, name, desc, null);
345 * Constructs a Net Peer Group instance using the specified parent peer
346 * group (normally the World Peer Group). This is the preferred constructor
347 * for constructing a private Net Peer Group with a specific implementation.
349 * @deprecated With the addition of support for {@code PeerGroupConfigAdv}
350 * this constructor is being deprecated as the precedence of settings is
353 * @param parentGroup The Peer Group which will be the parent of the newly
354 * created net peer group. This should normally be the World Peer
356 * @param id The PeerGroupID which will be used for the new Net Peer Group
358 * @param name The name which will be used for the new Net Peer Group
360 * @param desc The description which will be used for the new Net Peer Group
361 * instance. You can construct an {@code XMLDocument} from a {@code String}
364 * XMLDocument asDoc = StructuredDocumentFactory.newStructuredDocument( MimeMediaType.XMLUTF8, "desc", asString );
366 * @param moduleImplAdv The Module Impl Advertisement for the new Net Peer
368 * @throws PeerGroupException Thrown for problems constructing the Net Peer
372 public NetPeerGroupFactory(PeerGroup parentGroup, ID id, String name, XMLElement desc, ModuleImplAdvertisement moduleImplAdv) throws PeerGroupException {
373 net = newNetPeerGroup(parentGroup, null, id, name, desc, moduleImplAdv);
377 * Constructs a Net Peer Group instance using the specified parent peer
378 * group (normally the World Peer Group). This is the preferred constructor
379 * for constructing a Net Peer Group with a specific implementation.
381 * @param parentGroup The Peer Group which will be the parent of the
382 * newly created net peer group. This should normally be the World Peer
384 * @param config The configuration parameters for the newly created Net Peer
386 * @param moduleImplAdv The Module Impl Advertisement for the new Net Peer
388 * @throws PeerGroupException Thrown for problems constructing the Net Peer
391 public NetPeerGroupFactory(PeerGroup parentGroup, ConfigParams config, ModuleImplAdvertisement moduleImplAdv) throws PeerGroupException {
392 PeerGroupConfigAdv netGroupConfig = (PeerGroupConfigAdv) config.getSvcConfigAdvertisement(PeerGroup.peerGroupClassID);
393 NetGroupTunables tunables;
395 if (null == netGroupConfig) {
396 tunables = new NetGroupTunables(ResourceBundle.getBundle("net.jxta.impl.config"), new NetGroupTunables());
398 tunables = new NetGroupTunables(netGroupConfig.getPeerGroupID(), netGroupConfig.getName(), netGroupConfig.getDesc());
401 net = newNetPeerGroup(parentGroup, config, tunables.id, tunables.name, tunables.desc, moduleImplAdv);
405 * Returns a strong (reference counted) interface object for the Net Peer
406 * Group instance. This reference should be explicitly unreferenced when it
407 * is no longer needed.
409 * @return A strong (reference counted) interface object for the Net Peer Group.
410 * @see PeerGroup#unref()
412 public PeerGroup getInterface() {
413 return (PeerGroup) net.getInterface();
417 * Returns a weak (non-reference counted) interface object for the Net Peer Group.
419 * @return A weak (non-reference counted) interface object for the Net Peer Group.
420 * @see PeerGroup#getWeakInterface()
422 public PeerGroup getWeakInterface() {
423 return net.getWeakInterface();
427 * Construct the new Net Peer Group instance.
429 * @param parentGroup The parent group of the newly created net peer group.
430 * @param config Configuration parameters for the newly created net peer group.
431 * @param id The name to use for the newly created Net Peer Group.
432 * @param name The name to use for the newly created Net Peer Group.
433 * @param desc The description to use for the newly created Net Peer Group.
434 * @param implAdv The Module Impl Advertisement for the new Net Peer Group
435 * instance or {@code null} to use the advertisement returned by
436 * {@ link PeerGroup.getAllPurposePeerGroupImplAdvertisement()}.
437 * @return the PeerGroup
438 * @throws PeerGroupException Thrown for errors instantiating the new Net
439 * Peer Group instance.
441 private PeerGroup newNetPeerGroup(PeerGroup parentGroup, ConfigParams config, ID id, String name, XMLElement desc, ModuleImplAdvertisement implAdv) throws PeerGroupException {
442 synchronized (PeerGroup.globalRegistry) {
443 PeerGroup result = PeerGroup.globalRegistry.lookupInstance((PeerGroupID) id);
445 if (null != result) {
447 throw new PeerGroupException("Only a single instance of a Peer Group may be instantiated at a single time.");
450 if (Logging.SHOW_INFO && LOG.isLoggable(Level.INFO)) {
451 LOG.info( "Instantiating net peer group : " + id +
452 "\n\tParent : " + parentGroup +
454 "\n\tName : " + name +
455 "\n\timpl : " + implAdv);
459 if (null == implAdv) {
460 // Use the default Peer Group Impl Advertisement
461 implAdv = parentGroup.getAllPurposePeerGroupImplAdvertisement();
465 GenericPeerGroup.setGroupConfigAdvertisement(id,config);
467 result = (PeerGroup) parentGroup.loadModule(id, implAdv);
469 // Set the name and description
470 // FIXME 20060217 bondolo How sad, we can't use our XML description.
472 result.publishGroup(name, desc.getTextValue());
474 result.publishGroup(name, null);
478 } catch (PeerGroupException failed) {
479 if (Logging.SHOW_SEVERE && LOG.isLoggable(Level.SEVERE)) {
480 LOG.log(Level.SEVERE, "newNetPeerGroup failed", failed);
484 } catch (RuntimeException e) {
485 if (Logging.SHOW_SEVERE && LOG.isLoggable(Level.SEVERE)) {
486 LOG.log(Level.SEVERE, "newNetPeerGroup failed", e);
490 } catch (Exception e) {
491 // should be all other checked exceptions
492 if (Logging.SHOW_SEVERE && LOG.isLoggable(Level.SEVERE)) {
493 LOG.log(Level.SEVERE, "newNetPeerGroup failed", e);
495 // Simplify exception scheme for caller: every sort of problem
496 // wrapped in a PeerGroupException.
497 throw new PeerGroupException("newNetPeerGroup failed", e);
503 * Holds the construction tunables for the Net Peer Group. This consists of
504 * the peer group id, the peer group name and the peer group description.
506 static class NetGroupTunables {
510 final XMLElement desc;
513 * Constructor for loading the default Net Peer Group construction
517 id = PeerGroupID.defaultNetPeerGroupID;
518 name = "NetPeerGroup";
519 desc = (XMLElement) StructuredDocumentFactory.newStructuredDocument(MimeMediaType.XMLUTF8, "desc", "default Net Peer Group");
523 * Constructor for loading the default Net Peer Group construction
526 * @param pgid the PeerGroupID
527 * @param pgname the group name
528 * @param pgdesc the group description
530 NetGroupTunables(ID pgid, String pgname, XMLElement pgdesc) {
537 * Constructor for loading the Net Peer Group construction
538 * tunables from the provided resource bundle.
540 * @param rsrcs The resource bundle from which resources will be loaded.
541 * @param defaults default values
543 NetGroupTunables(ResourceBundle rsrcs, NetGroupTunables defaults) {
549 String idTmpStr = rsrcs.getString("NetPeerGroupID").trim();
551 if (idTmpStr.startsWith(ID.URNNamespace + ":")) {
552 idTmpStr = idTmpStr.substring(5);
554 idTmp = IDFactory.fromURI(new URI(ID.URIEncodingName + ":" + ID.URNNamespace + ":" + idTmpStr));
555 nameTmp = rsrcs.getString("NetPeerGroupName").trim();
556 descTmp = (XMLElement) StructuredDocumentFactory.newStructuredDocument(MimeMediaType.XMLUTF8, "desc",
557 rsrcs.getString("NetPeerGroupDesc").trim());
558 } catch (Exception failed) {
559 if (null != defaults) {
560 if (Logging.SHOW_FINE && LOG.isLoggable(Level.FINE)) {
561 LOG.log(Level.FINE, "NetPeerGroup tunables not defined or could not be loaded. Using defaults.", failed);
565 nameTmp = defaults.name;
566 descTmp = defaults.desc;
568 if (Logging.SHOW_SEVERE && LOG.isLoggable(Level.SEVERE)) {
569 LOG.log(Level.SEVERE, "NetPeerGroup tunables not defined or could not be loaded.", failed);
572 throw new IllegalStateException("NetPeerGroup tunables not defined or could not be loaded.");