]> sjero.net Git - linphone/blob - p2pproxy/dependencies-src/jxse-src-2.5/impl/src/net/jxta/impl/peergroup/RefCountPeerGroupInterface.java
remove mediastreamer2 and add it as a submodule instead.
[linphone] / p2pproxy / dependencies-src / jxse-src-2.5 / impl / src / net / jxta / impl / peergroup / RefCountPeerGroupInterface.java
1 /*
2  * Copyright (c) 2002-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 package net.jxta.impl.peergroup;
57
58 import net.jxta.exception.ServiceNotFoundException;
59 import net.jxta.id.ID;
60 import net.jxta.peergroup.PeerGroup;
61 import net.jxta.service.Service;
62
63 import java.util.Arrays;
64 import java.util.Collections;
65 import java.util.Iterator;
66 import java.util.Map;
67
68 /**
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.
75  */
76 class RefCountPeerGroupInterface extends PeerGroupInterface {
77
78     private Map roleMap;
79
80     /**
81      * Constructs an interface object that front-ends a given
82      * PeerGroup object.
83      *
84      * @param theRealThing the peer group
85      */
86     RefCountPeerGroupInterface(GenericPeerGroup theRealThing) {
87         super(theRealThing);
88     }
89
90     RefCountPeerGroupInterface(GenericPeerGroup theRealThing, Map roleMap) {
91         super(theRealThing);
92         this.roleMap = roleMap;
93     }
94
95     /**
96      * {@inheritDoc}
97      * <p/>
98      * Normally it is ignored. By definition, the interface object
99      * protects the real object's start/stop methods from being called.
100      * <p/>
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).
105      *
106      * @param arg A table of strings arguments.
107      * @return int status indication.
108      */
109     @Override
110     public int startApp(String[] arg) {
111         // Unlike our superclass's method, we do call the real
112         // startApp method.
113         PeerGroup temp = groupImpl;
114
115         if (null == temp) {
116             throw new IllegalStateException("This Peer Group interface object has been unreferenced and can no longer be used.");
117         }
118
119         return temp.startApp(arg);
120     }
121
122     /**
123      * {@inheritDoc}
124      * <p/>
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
128      * <p/>
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.
137      */
138     @Override
139     public void stopApp() {
140         unref();
141     }
142
143     /**
144      * {@inheritDoc}
145      * <p/>
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.
152      *
153      * @return Service An interface object that implements
154      *         this service and nothing more.
155      */
156     @Override
157     public Service getInterface() {
158         PeerGroup temp = groupImpl;
159         if (null == temp) {
160             throw new IllegalStateException("This Peer Group interface object has been unreferenced and can no longer be used.");
161         }
162         return temp.getInterface();
163     }
164
165     /**
166      * {@inheritDoc}
167      * <p/>
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.
174      *
175      * @return PeerGroup A weak interface object that implements
176      *         this group and nothing more.
177      */
178
179     @Override
180     public PeerGroup getWeakInterface() {
181         return new PeerGroupInterface(this);
182     }
183
184     /**
185      * Can only be called once. After that the reference is no-longer usuable.
186      */
187     @Override
188     public void unref() {
189         GenericPeerGroup theGrp;
190
191         synchronized (this) {
192             if (groupImpl == null) {
193                 return;
194             }
195
196             theGrp = (GenericPeerGroup) groupImpl;
197             groupImpl = null;
198         }
199         theGrp.decRefCount();
200     }
201
202     /**
203      * Service-specific role mapping is implemented here.
204      **/
205
206     /**
207      * {@inheritDoc}
208      */
209     @Override
210     public Service lookupService(ID name) throws ServiceNotFoundException {
211
212         return lookupService(name, 0);
213     }
214
215     /**
216      * {@inheritDoc}
217      */
218     @Override
219     public Service lookupService(ID name, int roleIndex) throws ServiceNotFoundException {
220
221         if (roleMap != null) {
222             ID[] map = (ID[]) roleMap.get(name);
223
224             // If there is a map, remap; else, identity is the default for
225             // role 0 only; the default mapping has only index 0.
226
227             if (map != null) {
228                 if (roleIndex < 0 || roleIndex >= map.length) {
229                     throw new ServiceNotFoundException(name + "[" + roleIndex + "]");
230                 }
231
232                 // We have a translation; look it up directly
233                 return groupImpl.lookupService(map[roleIndex]);
234             }
235         }
236
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.
240
241         if (roleIndex != 0) {
242             throw new ServiceNotFoundException(name + "[" + roleIndex + "]");
243         }
244         return groupImpl.lookupService(name);
245     }
246
247     /**
248      * {@inheritDoc}
249      */
250     @Override
251     public Iterator getRoleMap(ID name) {
252
253         if (roleMap != null) {
254             ID[] map = (ID[]) roleMap.get(name);
255
256             // If there is a map, remap; else, identity is the default for
257             // role 0 only; the default mapping has only index 0.
258
259             if (map != null) {
260                 // return an iterator on it.
261                 return Collections.unmodifiableList(Arrays.asList(map)).iterator();
262             }
263         }
264         // No translation; use the given name in a singleton.
265         return Collections.singletonList(name).iterator();
266     }
267 }