1 /*
2 * Copyright (c) 1998-2002 The Jgroup Team.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 */
18
19 package jgroup.relacs.registry;
20
21 import java.rmi.NotBoundException;
22 import java.rmi.RemoteException;
23 import java.util.Iterator;
24 import java.util.LinkedList;
25 import java.util.List;
26
27 import jgroup.core.registry.DependableRegistry.RegistryEntry;
28 import jgroup.relacs.config.AppConfig;
29
30
31 /**
32 * In a registry, this class is used to contain the data associated
33 * to a service name.
34 *
35 * @author Alberto Montresor
36 * @author Hein Meling
37 * @since Jgroup 0.5
38 */
39 final class ServiceData
40 {
41
42 ////////////////////////////////////////////////////////////////////////////////////////////
43 // Fields
44 ////////////////////////////////////////////////////////////////////////////////////////////
45
46 /** List of interfaces implementented by this object */
47 private Class serverClass;
48
49 /** The name of the service */
50 private String serviceName;
51
52 /** Type of entries */
53 private RegistryEntry entriesType;
54
55 /** List of entries */
56 private final List<BindingList> list = new LinkedList<BindingList>();
57
58 /** Boolean for determining if a server class is upgradeEnabled */
59 private boolean upgradeEnabled = false;
60
61
62 ////////////////////////////////////////////////////////////////////////////////////////////
63 // Constructor
64 ////////////////////////////////////////////////////////////////////////////////////////////
65
66 /**
67 * Builds a new ServiceData object associated with the given service.
68 *
69 * @param serverClass
70 * The class of the remote interface associated with this object.
71 * @param serviceName
72 * The name of the associated service.
73 * @param entriesType
74 * The type of entries to store
75 */
76 ServiceData(Class serverClass, String serviceName, RegistryEntry entriesType)
77 {
78 this.serviceName = serviceName;
79 this.serverClass = serverClass;
80 this.entriesType = entriesType;
81
82 try {
83 AppConfig app = AppConfig.getApplication(serviceName);
84 if (app.hasService("Upgrade")) {
85 upgradeEnabled = true;
86 }
87 } catch (NullPointerException e) {
88 /*
89 * The service name for upgrade service is not defined in apps.xml.
90 * Catch it here and do nothing.
91 */
92 }
93 }
94
95
96 ////////////////////////////////////////////////////////////////////////////////////////////
97 // Methods
98 ////////////////////////////////////////////////////////////////////////////////////////////
99
100 /**
101 * Inserts a new binding related to this service.
102 *
103 * @param binding the binding to be inserted
104 * @throws RemoteException raised if the new binding is related to
105 * a server whose implementation class is different from those
106 * inserted in this group.
107 */
108 void add(BindingList binding)
109 throws RemoteException
110 {
111 if (serverClass != null) {
112 if (!entriesType.getType().equals(binding.entry.getType())) {
113 throw new RemoteException("Service name " + binding.servicename +
114 " uses entries of type " + entriesType.getType());
115 }
116
117 if (checkCompatibility(binding.serverClass)) {
118 list.add(binding);
119 } else {
120 throw new RemoteException("Service name " + binding.servicename +
121 " is reserved for members compatible with class " + serverClass.getName());
122 }
123 }
124 }
125
126 /**
127 * Returns true if the server class to be bound is
128 * considered compatible with the service interface
129 * represented by this <code>ServiceData</code> object.
130 *
131 * @param serverClassToBind
132 * The server class being bound to this service.
133 * @return
134 * True is returned if the server class to be bound is
135 * considered compatible with the service interface
136 * represented by this <code>ServiceData</code> object.
137 */
138 private boolean checkCompatibility(Class serverClassToBind)
139 {
140 if (serverClass.equals(serverClassToBind)) {
141 return true;
142 } else if (upgradeEnabled) {
143 // FIXME: add check whether the same application interface is implemented.
144 // Solution proposal: check all the interfaces implemented by both classes
145 // and compare the sets. In the current implemenation we check only whether
146 // ExternalGMIListener is implemented and assume that the application service
147 // is implemented as well. The latter is done elsewhere.
148 return true;
149 } else {
150 return false;
151 }
152 }
153
154 /**
155 * Remove a binding from the list.
156 *
157 * @param the binding to be removed
158 */
159 void remove(BindingList bl)
160 {
161 list.remove(bl);
162 }
163
164 /**
165 * Returns true if the are no bindings related to this service
166 */
167 boolean isEmpty()
168 {
169 return (list.size() == 0);
170 }
171
172 /**
173 * Returns the BindingList nodes for the given service
174 * data object.
175 */
176 public List getLinkedList()
177 {
178 return list;
179 }
180
181 /**
182 * Return entries type
183 */
184 public RegistryEntry getRegistryEntry()
185 {
186 return entriesType;
187 }
188
189 /**
190 * Get iterator to all entries
191 * @return <code>Iterator</code> for iterating over all entries
192 */
193 synchronized Iterator getEntries()
194 throws NotBoundException
195 {
196 final Iterator iter = list.iterator();
197 return new Iterator() {
198
199 public void remove() { throw new UnsupportedOperationException(); }
200 public boolean hasNext() { return iter.hasNext(); }
201
202 public Object next() {
203 BindingList b = (BindingList)iter.next();
204 return b.entry;
205 }
206 };
207 }
208
209 /**
210 * Returns the serverClass.
211 * @return Class
212 */
213 public Class getServerClass()
214 {
215 return serverClass;
216 }
217
218 /**
219 * Returns the serviceName.
220 * @return String
221 */
222 public String getServiceName()
223 {
224 return serviceName;
225 }
226
227 } // End ServiceData