1   /*
2    * JBoss, the OpenSource J2EE webOS
3    *
4    * Distributable under LGPL license.
5    * See terms of license at gnu.org.
6    */
7   package net.sf.panoptes.model.component.registry;
8   
9   import java.util.ArrayList;
10  import java.util.HashMap;
11  import java.util.Hashtable;
12  import java.util.Iterator;
13  import java.util.List;
14  import java.util.Map;
15  
16  import net.sf.panoptes.model.component.Component;
17  import net.sf.panoptes.model.node.Node;
18  
19  import org.apache.log4j.Logger;
20  
21  /***
22   * The registry for component name - component reference mapping. Original code
23   * from JBoss.
24   * 
25   * @see net.sf.panoptes.model.component.IComponent
26   * @see net.sf.panoptes.model.component.registry.ComponentEntry
27   * 
28   */
29  public class ComponentRegistry {
30  	// Attributes ----------------------------------------------------
31  
32  	/***
33  	 * A map of domain name to another map containing object name canonical
34  	 * key properties to registry entries.
35  	 * domain -> canonicalKeyProperties -> MBeanEntry
36  	 */
37  	private Map domainMap = new HashMap();
38  
39  	/***
40  	 * The default domain for this registry
41  	 */
42  	private String defaultDomain;
43  
44  	/***
45  	 * Sequence number for the MBeanComponent server registration notifications.
46  	 */
47  	private long registrationNotificationSequence = 1;
48  
49  	/***
50  	 * Sequence number for the MBeanComponent server unregistration notifications.
51  	 */
52  	private long unregistrationNotificationSequence = 1;
53  
54  	// Static --------------------------------------------------------
55  
56  	/***
57  	 * The logger
58  	 */
59  	private static Logger log = Logger.getLogger(ComponentRegistry.class);
60  
61  	// Constructors --------------------------------------------------
62  
63  	/***
64  	 * Constructs a new ComponentRegistry.<p>
65  	 *
66  	 */
67  	public ComponentRegistry() {
68  	}
69  
70  	// MBeanRegistry Implementation ----------------------------------
71  
72  	public void registerComponent(Component component, ComponentName name)
73  		throws ComponentAlreadyExistsException {
74  		boolean registrationDone = true;
75  		ComponentName regName = name;
76  		try {
77  			regName = validateAndQualifyName(regName);
78  
79  			try {
80  
81  				ComponentEntry entry = new ComponentEntry(regName, component);
82  				add(entry);
83  				component.setComponentName(name);
84  				component.setComponentRegistry(this);
85  				component.init();
86  
87  				try {
88  					long sequence;
89  					synchronized (this) {
90  						sequence = registrationNotificationSequence++;
91  					}
92  
93  				} catch (Throwable t) {
94  					// Problem, remove the mbean from the registry
95  					remove(regName);
96  
97  					throw t;
98  				}
99  			}
100 			// Thrown by the registry
101 			catch (ComponentAlreadyExistsException e) {
102 				throw e;
103 			} catch (Throwable t) {
104 				// Something is broken
105 				log.error("Unexpected Exception:", t);
106 
107 				throw t;
108 			}
109 		} catch (ComponentAlreadyExistsException e) {
110 			// It was already registered
111 			registrationDone = false;
112 			throw e;
113 		} catch (Throwable t) {
114 			// Some other error
115 			registrationDone = false;
116 		}
117 	}
118 
119 	public void unregisterMBean(ComponentName name) throws ComponentNotFoundException {
120 		ComponentEntry entry = get(name);
121 		Object resource = entry.getComponent();
122 
123 		// It is no longer registered
124 		remove(name);
125 	}
126 
127 	public synchronized ComponentEntry get(ComponentName name) throws ComponentNotFoundException {
128 		if (name == null)
129 			throw new ComponentNotFoundException("null object name");
130 
131 		// Determine the domain and retrieve its entries
132 		String domain = name.getDomain();
133 
134 		if (domain.length() == 0)
135 			domain = defaultDomain;
136 
137 		String props = name.getCanonicalKeyPropertyListString();
138 		Map mbeanMap = (Map) domainMap.get(domain);
139 
140 		// Retrieve the mbean entry
141 		Object o = null;
142 		if (null == mbeanMap || null == (o = mbeanMap.get(props)))
143 			throw new ComponentNotFoundException(name + " is not registered.");
144 
145 		// We are done
146 		return (ComponentEntry) o;
147 	}
148 
149 	public String getDefaultDomain() {
150 		return defaultDomain;
151 	}
152 
153 	public synchronized Node getObjectInstance(ComponentName name) throws ComponentNotFoundException {
154 		if (!contains(name))
155 			throw new ComponentNotFoundException(name + " not registered.");
156 
157 		return get(name).getComponent();
158 	}
159 
160 
161 	public synchronized boolean contains(ComponentName name) {
162 		// null safety check
163 		if (name == null)
164 			return false;
165 
166 		// Determine the domain and retrieve its entries
167 		String domain = name.getDomain();
168 
169 		if (domain.length() == 0)
170 			domain = defaultDomain;
171 
172 		String props = name.getCanonicalKeyPropertyListString();
173 		Map mbeanMap = (Map) domainMap.get(domain);
174 
175 		// Return the result
176 		return (null != mbeanMap && mbeanMap.containsKey(props));
177 	}
178 
179 	public synchronized int getSize() {
180 		int retval = 0;
181 
182 		for (Iterator iterator = domainMap.values().iterator(); iterator.hasNext();) {
183 			retval += ((Map) iterator.next()).size();
184 		}
185 		return retval;
186 	}
187 
188 	public synchronized List findEntries(ComponentName pattern) {
189 		ArrayList retval = new ArrayList();
190 
191 		// There are a couple of shortcuts we can employ to make this a
192 		// bit faster - they're commented.
193 
194 		// First, if pattern == null or pattern.getCanonicalName() == "*:*" we want the
195 		// set of all MBeans.
196 		if (pattern == null || pattern.getCanonicalName().equals("*:*")) {
197 			for (Iterator domainIter = domainMap.values().iterator(); domainIter.hasNext();) {
198 				for (Iterator mbeanIter = ((Map) domainIter.next()).values().iterator(); mbeanIter.hasNext();) {
199 					retval.add(mbeanIter.next());
200 				}
201 			}
202 		}
203 		// Next, if !pattern.isPattern() then we are doing a simple get (maybe defaultDomain).
204 		else if (!pattern.isPattern()) {
205 			// simple get
206 			try {
207 				retval.add(get(pattern));
208 			} catch (ComponentNotFoundException e) {
209 				// we don't care
210 			}
211 		}
212 		// Now we have to do a brute force, oh well.
213 		else {
214 			String patternDomain = pattern.getDomain();
215 			if (patternDomain.length() == 0)
216 				patternDomain = defaultDomain;
217 			boolean patternIsPropertyPattern = true; pattern.isPropertyPattern();
218 			String patternCanonicalKPS = pattern.getCanonicalKeyPropertyListString();
219 			Object[] propkeys = null;
220 			Object[] propvals = null;
221 
222 			// prebuild arrays of keys and values for quick comparison
223 			// when isPropertyPattern().
224 			if (patternIsPropertyPattern) {
225 				Hashtable patternKPList = pattern.getKeyPropertyList();
226 				propkeys = new Object[patternKPList.size()];
227 				propvals = new Object[propkeys.length];
228 
229 				int i = 0;
230 				for (Iterator iterator = patternKPList.entrySet().iterator(); iterator.hasNext(); i++) {
231 					Map.Entry mapEntry = (Map.Entry) iterator.next();
232 					propkeys[i] = mapEntry.getKey();
233 					propvals[i] = mapEntry.getValue();
234 				}
235 			}
236 
237 			// Here we go, step through every domain and see if our pattern matches before optionally checking
238 			// each ObjectName's properties for a match.
239 			for (Iterator domainIter = domainMap.entrySet().iterator(); domainIter.hasNext();) {
240 				Map.Entry mapEntry = (Map.Entry) domainIter.next();
241 				if (domainMatches((String) mapEntry.getKey(), patternDomain)) {
242 					// yes it's a label, sue me.
243 					CHOOSE_MBEAN : for (
244 						Iterator mbeanIter = ((Map) mapEntry.getValue()).values().iterator(); mbeanIter.hasNext();) {
245 						ComponentEntry entry = (ComponentEntry) mbeanIter.next();
246 						ComponentName name = entry.getComponentName();
247 
248 						if (patternIsPropertyPattern) {
249 							// another shortcut - we only compare the key properties list of the registered MBeanComponent
250 							// if properties have been specifed in the pattern (i.e. something other than just "*")
251 							if (propkeys.length > 0) {
252 								Hashtable nameKPList = name.getKeyPropertyList();
253 
254 								for (int i = 0; i < propkeys.length; i++) {
255 									// skip the current MBeanComponent if there isn't a match
256 									if (!propvals[i].equals(nameKPList.get(propkeys[i]))) {
257 										continue CHOOSE_MBEAN;
258 									}
259 								}
260 							}
261 							retval.add(entry);
262 						} else {
263 							// Ok, it's a like-for-like comparison of the keyProperties.
264 							// Knowing how our implementation of ObjectName works, it's *much*
265 							// faster to compare the canonicalKeyProperties strings than it
266 							// is to compare the two hashtables.
267 							if (patternCanonicalKPS.equals(name.getCanonicalKeyPropertyListString())) {
268 								retval.add(entry);
269 							}
270 						}
271 					}
272 				}
273 			}
274 		}
275 
276 		return retval;
277 	}
278 
279 	/***
280 	 * Compare the src and pat strings where ? and * chars are significant.
281 	 *
282 	 * @author  <a href="mailto:trevor@protocool.com">Trevor Squires</a>.
283 	 */
284 	protected boolean domainMatches(String src, String pat) {
285 		if (src.equals("*")) // no point doing more that we have to...
286 			{
287 			return true;
288 		}
289 		return domainMatches(src.toCharArray(), 0, pat.toCharArray(), 0);
290 	}
291 
292 	/***
293 	 * Compare the src and pat char arrays where ? and * chars are significant.
294 	 *
295 	 * I arrived at this solution after quite a bit of trial and error - it's
296 	 * all a bit interwoven.  Obviously I'm no good at parsers and there must
297 	 * be a clearer or more elegant way to do this.  I'm suitably in awe of
298 	 * the perl regex hackers now.
299 	 *
300 	 * @author  <a href="mailto:trevor@protocool.com">Trevor Squires</a>.
301 	 */
302 	protected boolean domainMatches(char[] src, int spos, char[] pat, int ppos) {
303 		int slen = src.length;
304 		int plen = pat.length;
305 
306 		while (ppos < plen) {
307 			char c = pat[ppos++];
308 			if ('?' == c) {
309 				// eat a src character and make sure we're not
310 				// already at the end
311 				if (spos++ == slen) {
312 					return false;
313 				}
314 			} else if ('*' == c) {
315 				if (ppos == plen) // shortcut - * at the end of the pattern
316 					{
317 					return true;
318 				}
319 
320 				// hammer the src chars recursively until we
321 				// get a match or we drop off the end of src
322 				do {
323 					if (domainMatches(src, spos, pat, ppos)) {
324 						return true;
325 					}
326 				} while (++spos < slen);
327 			} else if (spos == slen || c != src[spos++]) {
328 				return false;
329 			}
330 		}
331 		// fell through with no falses so make sure all of src was examined
332 		return (spos == slen);
333 	}
334 
335 	/***
336 	 * Adds an MBeanComponent entry<p>
337 	 *
338 	 * WARNING: The object name should be fully qualified.
339 	 *
340 	 * @param entry the MBeanComponent entry to add
341 	 * @exception InstanceAlreadyExistsException when the MBeanComponent's object name
342 	 *            is already registered
343 	 */
344 	protected synchronized void add(ComponentEntry entry) throws ComponentAlreadyExistsException {
345 		// Determine the components's name and properties
346 		ComponentName name = entry.getComponentName();
347 		String domain = name.getDomain();
348 		String props = name.getCanonicalKeyPropertyListString();
349 
350 		// Create a properties -> entry map if we don't have one
351 		Map mbeanMap = (Map) domainMap.get(domain);
352 		if (mbeanMap == null) {
353 			mbeanMap = new HashMap();
354 			domainMap.put(domain, mbeanMap);
355 		}
356 
357 		// Make sure we aren't already registered
358 		if (mbeanMap.get(props) != null)
359 			throw new ComponentAlreadyExistsException(name + " already registered.");
360 
361 		// Ok, we are registered
362 		mbeanMap.put(props, entry);
363 	}
364 
365 	/***
366 	 * Removes an MBeanComponent entry
367 	 *
368 	 * WARNING: The object name should be fully qualified.
369 	 *
370 	 * @param name the object name of the entry to remove
371 	 * @exception InstanceNotFoundException when the object name is not
372 	 *            registered
373 	 */
374 	protected synchronized void remove(ComponentName name) throws ComponentNotFoundException {
375 		// Determine the MBeanComponent's name and properties
376 		String domain = name.getDomain();
377 		String props = name.getCanonicalKeyPropertyListString();
378 		Map mbeanMap = (Map) domainMap.get(domain);
379 
380 		// Remove the entry, raise an exception when it didn't exist
381 		if (null == mbeanMap || null == mbeanMap.remove(props))
382 			throw new ComponentNotFoundException(name + " not registered.");
383 	}
384 
385 	/***
386 	 * Validates and qualifies an MBeanComponent<p>
387 	 *
388 	 * Validates the name is not a pattern.<p>
389 	 *
390 	 * Adds the default domain if no domain is specified.<p>
391 	 *
392 	 * Checks the name is not in the reserved domain JMImplementation when
393 	 * the magicToken is not {@link org.jboss.mx.server.ServerConstants#JMI_DOMAIN JMI_DOMAIN}
394 	 *
395 	 * @param name the name to validate
396 	 * @param magicToken used to get access to the reserved domain
397 	 * @return the original name or the name prepended with the default domain
398 	 *         if no domain is specified.
399 	 * @exception RuntimeOperationException containing an
400 	 *            IllegalArgumentException for a problem with the name
401 	 */
402 	protected ComponentName validateAndQualifyName(ComponentName name) {
403 		// Check for qualification
404 		ComponentName result = qualifyName(name);
405 		return result;
406 	}
407 
408 	protected ComponentName qualifyName(ComponentName name) {
409 		try {
410 			if (name.getDomain().length() == 0)
411 				return new ComponentName(defaultDomain + ":" + name.getCanonicalKeyPropertyListString());
412 			else
413 				return name;
414 		} catch (MalformedComponentNameException e) {
415 			throw new IllegalArgumentException(e.toString());
416 		}
417 	}
418 
419 }
This page was automatically generated by Maven