001: /**
002: * The XMOJO Project 5
003: * Copyright © 2003 XMOJO.org. All rights reserved.
004:
005: * NO WARRANTY
006:
007: * BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
008: * THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
009: * OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
010: * PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
011: * OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
012: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
013: * TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE
014: * LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
015: * REPAIR OR CORRECTION.
016:
017: * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
018: * ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
019: * THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
020: * GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
021: * USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF
022: * DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
023: * PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE),
024: * EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
025: * SUCH DAMAGES.
026: **/package javax.management;
027:
028: import java.io.Serializable;
029: import java.io.ObjectInputStream;
030: import java.io.ObjectInputStream.GetField;
031: import java.io.ObjectOutputStream;
032: import java.io.ObjectOutputStream.PutField;
033: import java.io.ObjectStreamField;
034: import java.io.IOException;
035: import java.util.ArrayList;
036: import java.util.Enumeration;
037: import java.util.Hashtable;
038: import java.util.StringTokenizer;
039: import java.util.NoSuchElementException;
040:
041: import com.adventnet.jmx.utils.Sorter;
042:
043: /**
044: * This class represents the object name of an MBean.
045: * An instance of this class can be used to represent:
046: * <ul>
047: * <li> An object name
048: * <li> An object name pattern, within the context of a query
049: * </ul>
050: */
051: public class ObjectName implements Serializable {
052: /**
053: * Domain name.
054: */
055: private String domainName = null;
056:
057: private boolean noDomain = false;
058: /** **/
059: private Hashtable keyProperty = null;
060:
061: private String propertyString = null;
062:
063: /** **/
064: private Sorter qsort = null;
065:
066: /** **/
067: private boolean wildFlag = false;
068:
069: static final long serialVersionUID = 0xb41e7d55cfd55210L;
070:
071: /** **/
072: private boolean pattern = false;
073:
074: private transient String cachedKeyList = null;
075: private transient String toString = null;
076:
077: private static final ObjectStreamField[] serialPersistentFields = {
078: new ObjectStreamField("domain", java.lang.String.class),
079: new ObjectStreamField("propertyList",
080: java.util.Hashtable.class),
081: new ObjectStreamField("propertyListString",
082: java.lang.String.class),
083: new ObjectStreamField("canonicalName",
084: java.lang.String.class),
085: new ObjectStreamField("pattern", java.lang.Boolean.TYPE),
086: new ObjectStreamField("propertyPattern",
087: java.lang.Boolean.TYPE), };
088:
089: /** **/
090: private ObjectName() {
091: keyProperty = new Hashtable();
092: qsort = new Sorter();
093: }
094:
095: /**
096: * Allows an object name to be created from the given string. If the string
097: * does not have the right format an MalformedObjectNameException should be
098: * raised.
099: *
100: * @param name - A string representation of the object name.
101: *
102: * @throws MalformedObjectNameException - the string passed in parameter
103: * does not have the right format.
104: */
105: public ObjectName(String name) throws MalformedObjectNameException {
106: this ();
107:
108: try {
109: String props = null;
110:
111: if (name.startsWith(":"))
112: noDomain = true;
113:
114: if (name.equals("") || name == null) {
115: noDomain = true;
116: name = "*:*";
117: }
118:
119: if (name.indexOf(":") == -1) {
120: throw new MalformedObjectNameException(
121: "Invalid ObjectName");
122: }
123:
124: propertyString = name.substring(name.indexOf(":") + 1, name
125: .length());
126:
127: StringTokenizer st = new StringTokenizer(name, ":", true);
128:
129: if (st.countTokens() > 3) {
130: throw new MalformedObjectNameException(
131: "Invalid ObjectName");
132: }
133:
134: String temp = null;
135: if (st.countTokens() == 2) {
136: temp = st.nextToken();
137: if (temp.equals(":")) {
138: //Get the default domain from the MBeanserver
139: ArrayList list = MBeanServerFactory
140: .findMBeanServer(null);
141: if (list != null) {
142: if (list.toArray().length > 0) {
143: MBeanServer server = (MBeanServer) list
144: .toArray()[0];
145: domainName = server.getDefaultDomain();
146: } else
147: domainName = "DefaultDomain";
148: } else
149: domainName = "DefaultDomain";
150:
151: props = st.nextToken();
152: } else {
153: domainName = temp;
154: props = "*";
155: }
156: }
157:
158: if (st.countTokens() == 3) {
159: temp = st.nextToken();
160: if (temp.equals(":")) {
161: throw new MalformedObjectNameException(
162: "Invalid ObjectName");
163: } else {
164: domainName = temp;
165: st.nextToken();
166: temp = st.nextToken();
167: if (temp.equals(":")) {
168: throw new MalformedObjectNameException(
169: "Invalid ObjectName");
170: }
171: props = temp;
172: }
173: }
174:
175: checkDomain(domainName);
176: st = new StringTokenizer(props, ",", true);
177:
178: while (st.hasMoreTokens()) {
179: String key = null;
180: String value = null;
181: String prop = st.nextToken();
182:
183: /* For TCK. Consecutive comma(,) is not allowed in type seperation */
184: if (prop.equals(",")) {
185: try {
186: prop = st.nextToken();
187: } catch (NoSuchElementException ne) {
188: throw new MalformedObjectNameException(
189: "Invalid ObjectName");
190: }
191: if (prop.equals(",")) {
192: throw new MalformedObjectNameException(
193: "Invalid ObjectName");
194: }
195: }
196:
197: if (prop.equals("*")) {
198: wildFlag = true;
199: continue;
200: }
201: if (prop.indexOf("=") == -1) {
202: throw new MalformedObjectNameException(
203: "Invalid ObjectName");
204: }
205:
206: /* For TCK. More than one = in a type=val is wrong (e.g) type=r=t */
207: StringTokenizer tok = new StringTokenizer(prop, "=",
208: true);
209: if (tok.countTokens() != 3) {
210: throw new MalformedObjectNameException(
211: "Invalid ObjectName");
212: }
213: temp = null;
214:
215: while (tok.hasMoreTokens()) {
216: temp = tok.nextToken();
217: if (temp.equals("=")) {
218: throw new MalformedObjectNameException(
219: "Invalid ObjectName");
220: } else {
221: key = temp;
222: //this will be = for sure
223: tok.nextToken();
224: temp = tok.nextToken();
225: if (temp.equals("=")) {
226: throw new MalformedObjectNameException(
227: "Invalid ObjectName");
228: }
229: value = temp;
230: }
231: }
232: if (keyProperty.put(key, value) != null) {
233: throw new MalformedObjectNameException(
234: "Duplicate Key not allowed");
235: }
236: }
237: toString();
238: } catch (Exception e) {
239: throw new MalformedObjectNameException(e.getMessage());
240: }
241: }
242:
243: /**
244: * Allows an object name with several key properties to be created. If the
245: * parameters do not have the right format an MalformedObjectNameException
246: * should be raised.
247: *
248: * @param domain - The domain part of the object name.
249: *
250: * @param table - A hash table containing one or more search keys.
251: * Each search key is an attribute-value pair.
252: *
253: * @throws MalformedObjectNameException - the string passed in parameter
254: * does not have the right format.
255: */
256: public ObjectName(String domain, Hashtable table) throws javax.management.MalformedObjectNameException
257: {
258: this ();
259:
260: if(domain == null)
261: {
262: /* Tck Compliance */
263: throw new MalformedObjectNameException("Invalid ObjectName");
264: //domain = "DefaultDomain";
265: }
266:
267: if(domain.equals(""))
268: noDomain = true;
269:
270: this .domainName = domain;
271:
272: if(table != null && table.size() > 0)
273: {
274: Enumeration enum = table.keys();
275: String kkey = null;
276: String value = null;
277:
278: while(enum.hasMoreElements())
279: {
280: kkey = (enum.nextElement()).toString();
281: value = (table.get(kkey)).toString();
282: propertyString = kkey+"="+value+",";
283: }
284:
285: propertyString = propertyString.substring(0,propertyString.length() -1);
286:
287: Enumeration keys = table.keys();
288: String key = null;
289:
290: while(keys.hasMoreElements())
291: {
292: key = keys.nextElement().toString();
293: Object val = table.get(key);
294: if(!(val instanceof String))
295: {
296: throw new MalformedObjectNameException("Invalid ObjectName");
297: }
298: String str = (String)val;
299: if(str.equals(""))
300: {
301: throw new MalformedObjectNameException("Invalid ObjectName");
302: }
303: if(str.equals("temp"))
304: {
305: table.remove(key);
306: }
307: }
308: keyProperty = table;
309: }
310: else
311: {
312: throw new MalformedObjectNameException("Atleast one Key Property should be present");
313: }
314: toString();
315: }
316:
317: /**
318: * Allows an object name to be created using only one key property. If the
319: * parameters do not have the right format an MalformedObjectNameException
320: * should be raised.
321: *
322: * @param domain - The domain part of the object name.
323: *
324: * @param key - The attribute in the key property of the object name.
325: *
326: * @param value - The value in the key property of the object name.
327: *
328: * @throws MalformedObjectNameException - the string passed in parameter
329: * does not have the right format.
330: */
331: public ObjectName(String domain, String key, String value)
332: throws MalformedObjectNameException {
333: this ();
334:
335: if (domain == null) {
336: /** TCK compliance */
337: throw new MalformedObjectNameException("Invalid ObjectName");
338: //this.domainName = "DefaultDomain";
339: }
340:
341: this .domainName = domain;
342:
343: if (domain.equals(""))
344: noDomain = true;
345:
346: if (key == null || key.equals("") || value == null
347: || value.equals("")) {
348: throw new MalformedObjectNameException("Invalid ObjectName");
349: }
350:
351: keyProperty.put(key, value);
352: propertyString = key + "=" + value;
353:
354: toString();
355: }
356:
357: /**
358: * Returns the domain part.
359: *
360: * @return This returns the domain name
361: */
362: public String getDomain() {
363: if (noDomain)
364: return "";
365:
366: return domainName;
367: }
368:
369: /**
370: * Obtains the value of a key property in a key property.
371: *
372: * @param property - The property whose value is to be obtained.
373: *
374: * @return The value of the property.
375: */
376: public String getKeyProperty(String property) {
377: return (String) keyProperty.get(property);
378: }
379:
380: /**
381: * Returns a pointer to the list of key properties.
382: *
383: * @return This returns a HashTable of key properties
384: */
385: public Hashtable getKeyPropertyList() {
386: return keyProperty;
387: }
388:
389: /**
390: * Checks if a name to be used is a pattern for a query.
391: *
392: * @return True if the name is a pattern, otherwise false.
393: */
394: public boolean isPattern() {
395: String temp = toString();
396:
397: if (temp.indexOf("*") != -1 || temp.indexOf("?") != -1)
398: pattern = true;
399:
400: return pattern;
401: }
402:
403: /**
404: * Returns a string representation of the object name.
405: *
406: * @return This returns the string representation of the oject name
407: */
408: public String toString() {
409: if (toString != null) {
410: return toString;
411: }
412:
413: StringBuffer buff = new StringBuffer();
414: buff.append(domainName + ":");
415: buff.append(getKeyList());
416:
417: toString = buff.toString();
418: return toString;
419: }
420:
421: /**
422: * Compares the current object name with another object name.
423: *
424: * @param object - The object name that the current object name is to be
425: * compared with.
426: *
427: * @return True if the two object names are equal, otherwise false.
428: */
429: public boolean equals(Object object) {
430: return toString().equals(object.toString());
431: }
432:
433: /**
434: * Returns a hash code for this object name.
435: *
436: * @return This returns a hash code of type int for this object name
437: */
438: public int hashCode() {
439: return toString().hashCode();
440: }
441:
442: /**
443: * Returns the canonical form of the name; that is, a string representation
444: * where the properties are sorted in lexical order.
445: *
446: * @return Returns the canonical form of the name; that is, a string
447: * representation where the properties are sorted in lexical order.
448: */
449: public java.lang.String getCanonicalName() {
450: if (noDomain)
451: return ":" + getKeyList();
452:
453: return domainName + ":" + getKeyList();
454: }
455:
456: /**
457: * Returns a string representation of the list of key properties specified at creation
458: * time.
459: * @return This returns a string representation of the list of key properties
460: */
461: public java.lang.String getKeyPropertyListString() {
462: return propertyString;
463: }
464:
465: /**
466: * Returns a string representation of the list of key properties in which
467: * the key properties are sorted in lexical order. This is used in
468: * lexicographic comparisons performed in order to select MBeans based on
469: * their key property list.
470: *
471: * @return This returns a string representation of the list of key properties
472: * in which the key properties are sorted in lexical order.
473: */
474: public java.lang.String getCanonicalKeyPropertyListString() {
475: return getKeyList();
476: }
477:
478: /**
479: * Checks whether the object name is a pattern on the key properties.
480: *
481: * @return true if the name is a pattern, otherwise false
482: */
483: public boolean isPropertyPattern() {
484: String propertyString = getKeyPropertyListString();
485:
486: if (propertyString.indexOf("*") != -1)
487: return true;
488: else
489: return false;
490: }
491:
492: //-------------------------- Private method --------------------------//
493:
494: private String getKeyList() {
495: if (cachedKeyList != null) {
496: return cachedKeyList;
497: }
498:
499: StringBuffer buff = new StringBuffer();
500:
501: String[] keys = new String[keyProperty.size()];
502: Object[] values = new Object[keyProperty.size()];
503:
504: int i = 0;
505:
506: for (Enumeration e = keyProperty.keys(); e.hasMoreElements(); i++) {
507: keys[i] = (String) e.nextElement();
508: values[i] = keyProperty.get(keys[i]);
509: }
510:
511: try {
512: Object[][] obj = { values };
513: getSorter().sort(keys, obj);
514: } catch (Exception e) {
515: System.err.println("Exception = " + e);
516: //e.printStackTrace();
517: }
518:
519: for (i = 0; i < keyProperty.size(); i++) {
520: if (i == 0)
521: buff.append(keys[i] + "=" + values[i].toString());
522: else
523: buff.append("," + keys[i] + "=" + values[i].toString());
524: }
525:
526: if (wildFlag) {
527: if (keyProperty.size() == 0)
528: buff.append("*");
529: else
530: buff.append(",*");
531: }
532:
533: cachedKeyList = buff.toString();
534: return cachedKeyList;
535: }
536:
537: private Sorter getSorter() {
538: if (qsort == null)
539: qsort = new Sorter();
540:
541: return qsort;
542: }
543:
544: private void checkDomain(String domain)
545: throws MalformedObjectNameException {
546: if (domain.indexOf(':') >= 0)
547: throw new MalformedObjectNameException(
548: "Domain cannot contain ':' characters");
549: if (domain.indexOf(',') >= 0)
550: throw new MalformedObjectNameException(
551: "Domain cannot contain ',' characters");
552: if (domain.indexOf('=') >= 0)
553: throw new MalformedObjectNameException(
554: "Domain cannot contain '=' characters");
555: }
556:
557: private void readObject(ObjectInputStream objectinputstream)
558: throws IOException, ClassNotFoundException {
559: ObjectInputStream.GetField getfield = objectinputstream
560: .readFields();
561:
562: try {
563: domainName = (String) getfield.get("domain", "");
564: keyProperty = (Hashtable) getfield
565: .get("propertyList", null);
566: propertyString = (String) getfield.get(
567: "propertyListString", "");
568: pattern = getfield.get("pattern", false);
569: wildFlag = isPropertyPattern();
570: toString();
571: } catch (Exception exception) {
572: exception.printStackTrace();
573: }
574: }
575:
576: private void writeObject(ObjectOutputStream objectoutputstream)
577: throws IOException {
578: ObjectOutputStream.PutField putfield = objectoutputstream
579: .putFields();
580: putfield.put("domain", domainName);
581: putfield.put("propertyList", getKeyPropertyList());
582: putfield.put("propertyListString", getKeyPropertyListString());
583: putfield.put("canonicalName", getCanonicalName());
584: putfield.put("pattern", isPattern());
585: putfield.put("propertyPattern", isPropertyPattern());
586: objectoutputstream.writeFields();
587: }
588: }//End of class ObjectName
|