2 * Copyright (c) 2002-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.
56 package net.jxta.impl.peergroup;
58 import net.jxta.exception.ServiceNotFoundException;
59 import net.jxta.id.ID;
60 import net.jxta.peergroup.PeerGroup;
61 import net.jxta.service.Service;
63 import java.util.Arrays;
64 import java.util.Collections;
65 import java.util.Iterator;
69 * RefCountPeerGroupInterface is a PeerGroupInterface object that
70 * also serves as a peergroup very-strong reference. When the last
71 * such goes away, the peergroup terminates itself despite the existence
72 * of aeternal strong references from the various service's threads
73 * that would prevent it from ever being finalized.
74 * The alternative: to give only weak references to threads seems impractical.
76 class RefCountPeerGroupInterface extends PeerGroupInterface {
81 * Constructs an interface object that front-ends a given
84 * @param theRealThing the peer group
86 RefCountPeerGroupInterface(GenericPeerGroup theRealThing) {
90 RefCountPeerGroupInterface(GenericPeerGroup theRealThing, Map roleMap) {
92 this.roleMap = roleMap;
98 * Normally it is ignored. By definition, the interface object
99 * protects the real object's start/stop methods from being called.
101 * However we have to make an exception for groups: even the creator
102 * of a group does not have access to the real object. So the interface
103 * has to forward startApp to the group, which is responsible for
104 * ensuring that it is executed only once (if needed).
106 * @param arg A table of strings arguments.
107 * @return int status indication.
110 public int startApp(String[] arg) {
111 // Unlike our superclass's method, we do call the real
113 PeerGroup temp = groupImpl;
116 throw new IllegalStateException("This Peer Group interface object has been unreferenced and can no longer be used.");
119 return temp.startApp(arg);
125 * This is here for temporary class hierarchy reasons.
126 * it is normally ignored. By definition, the interface object
127 * protects the real object's start/stop methods from being called
129 * In that case we have to make an exception. Most applications
130 * currently assume that they do not share the group object and that they do
131 * refer to the real object directly. They call stopApp to signify their
132 * intention of no-longer using the group. Now that groups are shared,
133 * we convert stopApp() to unref() for compatibility.
134 * We could also just do nothing and let the interface be GC'd but
135 * calling unref() makes the group go away immediately if not shared,
136 * which is what applications that call stopApp expect.
139 public void stopApp() {
146 * Since THIS is already such an object, it could return itself.
147 * However, we want the group to know about the number of interfaces
148 * objects floating around, so, we'll have the group make a new one.
149 * That way, applications which want to use unref() on interfaces can
150 * avoid sharing interface objects by using getInterface() as a sort of
151 * clone with the additional ref-counting semantics.
153 * @return Service An interface object that implements
154 * this service and nothing more.
157 public Service getInterface() {
158 PeerGroup temp = groupImpl;
160 throw new IllegalStateException("This Peer Group interface object has been unreferenced and can no longer be used.");
162 return temp.getInterface();
168 * Returns a weak interface object that refers to this interface
169 * object rather than to the group directly. The reason for that
170 * is that we want the owner of this interface object to be able
171 * to invalidate all weak interface objects made out of this interface
172 * object, without them keeping a reference to the group object, and
173 * without necessarily having to terminate the group.
175 * @return PeerGroup A weak interface object that implements
176 * this group and nothing more.
180 public PeerGroup getWeakInterface() {
181 return new PeerGroupInterface(this);
185 * Can only be called once. After that the reference is no-longer usuable.
188 public void unref() {
189 GenericPeerGroup theGrp;
191 synchronized (this) {
192 if (groupImpl == null) {
196 theGrp = (GenericPeerGroup) groupImpl;
199 theGrp.decRefCount();
203 * Service-specific role mapping is implemented here.
210 public Service lookupService(ID name) throws ServiceNotFoundException {
212 return lookupService(name, 0);
219 public Service lookupService(ID name, int roleIndex) throws ServiceNotFoundException {
221 if (roleMap != null) {
222 ID[] map = (ID[]) roleMap.get(name);
224 // If there is a map, remap; else, identity is the default for
225 // role 0 only; the default mapping has only index 0.
228 if (roleIndex < 0 || roleIndex >= map.length) {
229 throw new ServiceNotFoundException(name + "[" + roleIndex + "]");
232 // We have a translation; look it up directly
233 return groupImpl.lookupService(map[roleIndex]);
237 // No translation; use the name as-is, provided roleIndex is 0.
238 // Do not call groupImpl.lookupService(name, id); group impls
239 // should not have to implement it at all.
241 if (roleIndex != 0) {
242 throw new ServiceNotFoundException(name + "[" + roleIndex + "]");
244 return groupImpl.lookupService(name);
251 public Iterator getRoleMap(ID name) {
253 if (roleMap != null) {
254 ID[] map = (ID[]) roleMap.get(name);
256 // If there is a map, remap; else, identity is the default for
257 // role 0 only; the default mapping has only index 0.
260 // return an iterator on it.
261 return Collections.unmodifiableList(Arrays.asList(map)).iterator();
264 // No translation; use the given name in a singleton.
265 return Collections.singletonList(name).iterator();