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.config;
20  
21  import java.util.HashMap;
22  import java.util.Map;
23  
24  import jgroup.core.ConfigurationException;
25  
26  
27  /**
28   *  Object for holding service information.
29   *
30   *  @author Hein Meling
31   *  @since Jgroup 1.2
32   */
33  public final class ServiceConfig
34    implements ConfigurationObject
35  {
36  
37    ////////////////////////////////////////////////////////////////////////////////////////////
38    // Tags
39    ////////////////////////////////////////////////////////////////////////////////////////////
40  
41    // Attributes for the Service tag
42    private static final String NAME_ATTRIB      = "name";
43    private static final String INTERFACE_ATTRIB = "interface";
44    private static final String LISTENER_ATTRIB  = "listener";
45    private static final String EQUALS_ATTRIB    = "equals";
46  
47  
48    ////////////////////////////////////////////////////////////////////////////////////////////
49    // Static collections
50    ////////////////////////////////////////////////////////////////////////////////////////////
51  
52    /**
53     * Map of services (association from service name to Service object).
54     * Note that this map must be static to allow cross access between
55     * instances of the ServiceConfig class.  This is because the parser
56     * creates a new ServiceConfig object for each Service entry in the
57     * XML file.
58     */
59    private static final Map<String, ServiceConfig> services =
60      new HashMap<String, ServiceConfig>();
61  
62  
63    ////////////////////////////////////////////////////////////////////////////////////////////
64    // Fields
65    ////////////////////////////////////////////////////////////////////////////////////////////
66  
67    /** The service interface */
68    private String iface;
69    private Class serviceIface;
70  
71    /** The listener interface */
72    private String listener;
73    private Class listenerIface;
74  
75    /** True if the listener interface is an empty marker interface */
76    private boolean listenerIsMarker;
77  
78  
79    ////////////////////////////////////////////////////////////////////////////////////////////
80    // Constructors
81    ////////////////////////////////////////////////////////////////////////////////////////////
82  
83    /**
84     *  Constructs an empty service object.
85     */
86    public ServiceConfig() { }
87  
88  
89    /**
90     *  Constructs a service config object without listener interface.
91     */
92    public ServiceConfig(String iface)
93      throws ConfigurationException
94    {
95      this.iface = iface;
96      this.listener = null;
97      /*
98       * Set marker to false; that is we should never call addListener()
99       * for services that does not provide a marker interface.
100      */
101     listenerIsMarker = false;
102   }
103 
104 
105   /**
106    *  Constructs a service info object.
107    */
108   public ServiceConfig(String iface, String listener)
109     throws ConfigurationException
110   {
111     this.iface = iface;
112     this.listener = listener;
113   }
114 
115 
116   ////////////////////////////////////////////////////////////////////////////////////////////
117   // Private methods
118   ////////////////////////////////////////////////////////////////////////////////////////////
119 
120   private Class checkInterface(String clname)
121     throws ConfigurationException
122   {
123     Class cl;
124     try {
125       cl = Class.forName(clname);
126     } catch (ClassNotFoundException e) {
127       throw new ConfigurationException("Service interface not found: " + clname);
128     }
129     if (!cl.isInterface())
130       throw new ConfigurationException("Service " + clname + " is not an interface");
131     return cl;
132   }
133 
134 
135   ////////////////////////////////////////////////////////////////////////////////////////////
136   // Methods from ConfigurationObject
137   ////////////////////////////////////////////////////////////////////////////////////////////
138 
139   /**
140    *  Parses the specified element.
141    */
142   public void parse(org.w3c.dom.Element elm)
143     throws ConfigurationException
144   {
145     String servicename  = ConfigParser.getAttrib(elm, NAME_ATTRIB,      true);
146     String iface        = ConfigParser.getAttrib(elm, INTERFACE_ATTRIB, false);
147     String listener     = ConfigParser.getAttrib(elm, LISTENER_ATTRIB, false);
148     String equalService = ConfigParser.getAttrib(elm, EQUALS_ATTRIB, false);
149 
150     ServiceConfig serviceConfig = null;
151     if (iface != null && iface.length() > 0) {
152       if (listener != null && listener.length() > 0) {
153         /* Create a new service object with the parsed information */
154         serviceConfig = new ServiceConfig(iface, listener);
155       } else {
156         /* Create a new service object with the parsed information */
157         serviceConfig = new ServiceConfig(iface);
158       }
159     } else if (equalService != null && equalService.length() > 0) {
160       serviceConfig = ServiceConfig.getService(equalService);
161     } else {
162       throw new ConfigurationException("Service interfaces not defined: " + servicename);
163     }
164     services.put(servicename, serviceConfig);
165   }
166 
167 
168   ////////////////////////////////////////////////////////////////////////////////////////////
169   // Access methods
170   ////////////////////////////////////////////////////////////////////////////////////////////
171 
172   public static ServiceConfig getService(String serviceName)
173     throws ConfigurationException
174   {
175     ServiceConfig serviceInfo = (ServiceConfig) services.get(serviceName);
176     if (serviceInfo == null)
177       throw new ConfigurationException("The service " + serviceName + " is not specified");
178     return serviceInfo;
179   }
180   
181 
182   public static Class getServiceIface(String serviceName)
183     throws ConfigurationException
184   {
185     ServiceConfig serviceInfo = (ServiceConfig) services.get(serviceName);
186     if (serviceInfo == null)
187       throw new ConfigurationException("The service " + serviceName + " is not specified");
188     return serviceInfo.getInterface();
189   }
190   
191 
192   public static Class getListenerIface(String serviceName)
193     throws ConfigurationException
194   {
195     ServiceConfig serviceInfo = (ServiceConfig) services.get(serviceName);
196     if (serviceInfo == null)
197       throw new ConfigurationException("The service " + serviceName + " is not specified");
198     return serviceInfo.getListener();
199   }
200 
201 
202   public static boolean contains(String serviceName)
203   {
204     return services.containsKey(serviceName);
205   }
206 
207 
208   public Class getInterface()
209     throws ConfigurationException
210   {
211     serviceIface = checkInterface(iface);
212     return serviceIface;
213   }
214 
215 
216   public Class getListener()
217     throws ConfigurationException
218   {
219     listenerIface = checkInterface(listener);
220     return listenerIface;
221   }
222 
223 
224   /**
225    *  Returns true if the listener interface is a marker (empty) interface;
226    *  otherwise false is returned.
227    *
228    *  @throws ConfigurationException
229    *    Thrown if the expected listener interface does not exist.
230    */
231   public boolean isMarker()
232     throws ConfigurationException
233   {
234     if (listenerIface == null) {
235       listenerIface = checkInterface(listener);
236     }
237     java.lang.reflect.Method[] methods = listenerIface.getDeclaredMethods();
238     listenerIsMarker = (methods.length == 0) ? true : false;
239     return listenerIsMarker;
240   }
241 
242 
243   public String toString()
244   {
245     return "[service=" + iface + ", listener=" + listener + "]";
246   }
247 
248 } // END ServiceConfig