View Javadoc

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