001: /* JFox, the OpenSource J2EE Application Server
002: *
003: * Copyright (C) 2002 huihoo.org
004: * Distributable under GNU LGPL license
005: * See the GNU Lesser General Public License for more details.
006: */
007:
008: package javax.management.modelmbean;
009:
010: import java.util.HashMap;
011: import java.util.StringTokenizer;
012: import java.util.Set;
013: import java.util.Iterator;
014: import java.util.HashSet;
015: import java.util.Map;
016: import javax.management.Descriptor;
017: import javax.management.MBeanException;
018: import javax.management.RuntimeOperationsException;
019:
020: /**
021: * This class represents the metadata set for a ModelMBean element.
022: * A descriptor is part of the ModelMBeanInfo, ModelMBeanNotificationInfo, ModelMBeanAttributeInfo,
023: * ModelMBeanConstructorInfo, and ModelMBeanParameterInfo.
024: * <P>
025: * A descriptor consists of a collection of fields. Each field is in fieldname=fieldvalue format.
026: * Field names are not case sensitive, case will be preserved on field values.
027: * <P>
028: * All field names and values are not predefined. New fields can be defined and added by any program.
029: * Some fields have been predefined for consistency of implmentation and support by the ModelMBeanInfo
030: * ModelMBean*Info, and ModelMBean classes.
031: *<P>
032: *
033: * @author <a href="mailto:young_yy@hotmail.org">Young Yang</a>
034: */
035:
036: public class DescriptorSupport implements Descriptor {
037:
038: Map descriptor = new HashMap();
039:
040: public DescriptorSupport() {
041:
042: }
043:
044: /**
045: * Descriptor constructor.
046: * Takes as parameter the initial capacity of the Map that stores the descriptor fields.
047: * Capacity will grow as needed.
048: *
049: * @param initNumFields The initial capacity of the Map that stores the descriptor fields.
050: * @exception RuntimeOperationsException for illegal value for maxNumFields ( <= 0)
051: */
052: public DescriptorSupport(int initNumFields) throws MBeanException,
053: RuntimeOperationsException {
054: if (initNumFields <= 0) {
055: throw new RuntimeOperationsException(
056: new IllegalArgumentException(
057: "Descriptor field limit is invalid"),
058: "Exception occured trying to construct a descriptor");
059: }
060: descriptor = new HashMap(initNumFields);
061: }
062:
063: /**
064: * Descriptor constructor taking a Descriptor as parameter.
065: * Creates a new descriptor initialized to the values of the descriptor passed in parameter.
066: *
067: * @param initDescriptor the descriptor to be used to initialize the constructed descriptor. If it is
068: * null or contains no descriptor fields, an empty Descriptor will be created.
069: * @exception RuntimeOperationsException for illegal value for inDescr. inDescr cannot be
070: * null. If the descriptor fails for any reason, this exception will be thrown.
071: */
072: public DescriptorSupport(DescriptorSupport initDescriptor) {
073: if (initDescriptor != null && initDescriptor.descriptor != null) {
074: descriptor = new HashMap(initDescriptor.descriptor);
075: }
076: }
077:
078: /**
079: * Descriptor constructor taking an XML String. This method is part of this implementation
080: * and not required by the JMX Specification
081: *
082: * @param xmlString An XML-formatted string used to populate this Descriptor.
083: * The format will be:
084: * <Descriptor>
085: * <field name="name" value="current_descriptor_name"></field>
086: * <field name="descriptorType" value="current_descriptor_type"></field>
087: * ...
088: * </Descriptor>
089: *
090: * All fields values will be created as Strings. If the field values are not Strings,
091: * the programmer will have to reset or convert these fields correctly. Fields which are not
092: * String objects will have toString() called on them to doCreate the value.
093: * You will not be able to reconstruct these objects unless they have been specifically setup
094: * to support toString() into a meaningfull format and have a matching constructor that
095: * accepts a String in the same format.
096: *
097: * @throws MBeanException
098: * @throws RuntimeOperationsException
099: * @throws XMLParseException
100: */
101: public DescriptorSupport(String xmlString) throws MBeanException,
102: RuntimeOperationsException, XMLParseException {
103: String descTag = "DESCRIPTOR";
104: String descTagEnd = "/" + descTag;
105: String xmlDescTagStart = "<" + descTag + ">";
106: String xmlDescTagEnd = "<" + descTagEnd + ">";
107: String fieldTag = "FIELD";
108: String fieldTagEnd = "/" + fieldTag;
109: String fieldTagName = "NAME";
110: String fieldTagValue = "VALUE";
111:
112: if (xmlString == null) {
113: throw new RuntimeOperationsException(
114: new IllegalArgumentException(
115: "String in parameter is null"),
116: "Exception occured trying to construct a descTag");
117: }
118:
119: xmlString = xmlString.trim();
120:
121: if (!xmlString.toUpperCase().startsWith(xmlDescTagStart)
122: || !xmlString.toUpperCase().endsWith(xmlDescTagEnd))
123: throw new XMLParseException("No " + xmlDescTagStart
124: + " or " + xmlDescTagEnd + " found");
125:
126: xmlString = xmlString.substring(xmlDescTagStart.length(),
127: xmlString.length() - xmlDescTagEnd.length()).trim();
128:
129: StringTokenizer st = new StringTokenizer(xmlString,
130: "<> \t\n\r\f");
131: boolean fieldFound = false;
132: String fieldName = null;
133: String fieldValue = null;
134: while (st.hasMoreTokens()) {
135: String token = st.nextToken();
136: if (token.equalsIgnoreCase(fieldTag))
137: fieldFound = true;
138: else if (token.equalsIgnoreCase(fieldTagEnd)) {
139: if (fieldName != null && fieldValue != null) {
140: setField(fieldName, fieldValue);
141: }
142: fieldName = null;
143: fieldValue = null;
144: fieldFound = false;
145: } else { // find name or value
146: if (fieldFound) {
147: int index = token.indexOf("=");
148: if (index > 0) {
149: String _fieldType = token.substring(0, index)
150: .trim();
151: String _fieldTypeValue = token.substring(
152: index + 1).trim();
153: if (!_fieldTypeValue.startsWith("\"")
154: || !_fieldTypeValue.endsWith("\"")) {
155: throw new XMLParseException(_fieldTypeValue
156: + " must be quoted");
157: }
158: _fieldTypeValue = _fieldTypeValue.substring(1,
159: _fieldTypeValue.length() - 1);
160: if (_fieldType.equalsIgnoreCase(fieldTagName))
161: fieldName = _fieldTypeValue;
162: else if (_fieldType
163: .equalsIgnoreCase(fieldTagValue))
164: fieldValue = _fieldTypeValue;
165: else
166: throw new XMLParseException(
167: "expected a field value, received '"
168: + token + "'");
169: } else {
170: throw new XMLParseException(
171: "expected keyword=value, received '"
172: + token + "'");
173: }
174: } else {
175: throw new XMLParseException(
176: "expected keyword=value, received '"
177: + token + "'");
178: }
179: }
180: }
181: }
182:
183: /**
184: * Constructor taking field names and field values. The array and array elements cannot be null.
185: *
186: * @param fieldNames String array of field names. No elements of this array can be null.
187: * @param fieldValues Object array of the corresponding field values.
188: * Elements of the array can be null. The fieldValue must be valid for the fieldName.
189: *
190: * Note: array sizes of parameters should match. If both arrays are null or empty, then
191: * an empty descriptor is created. No exception is thrown.
192: *
193: * @exception RuntimeOperationsException for illegal value for field URLName or field Values.
194: * The array lengths must be equal.
195: * If the descriptor construction fails for any reason, this exception will be thrown.
196: *
197: */
198: public DescriptorSupport(String fieldNames[], Object fieldValues[])
199: throws RuntimeOperationsException {
200: if (fieldNames == null || fieldValues == null
201: || fieldNames.length != fieldValues.length) {
202: throw new RuntimeOperationsException(
203: new IllegalArgumentException(
204: "FieldNames or FieldValues are null or invalid"),
205: "Exception occured trying to construct a descriptor");
206: }
207: descriptor = new HashMap(fieldNames.length);
208: for (int i = 0; i < fieldNames.length; i++) {
209: setField(fieldNames[i], fieldValues[i]);
210: }
211: }
212:
213: /**
214: * Constructor taking fields in the <i>fieldName=fieldValue</i> format.
215: *
216: * @param fields String array of with each element containing a field name and value.
217: * If this array is null or empty, then the default constructor will be executed. Null strings
218: * or empty strings will be ignored.
219: *
220: * Note: each string should be of the form <i>fieldName=fieldValue</i>,
221: * with no imbedded blanks or other punctuation.
222: *
223: * @exception RuntimeOperationsException for illegal value for field URLName or field Values.
224: * The field must contain an "=". "=fieldValue", "fieldName", and "fieldValue" are illegal.
225: * FieldName cannot be null. "fieldName=" will cause the value to be null.
226: * If the descriptor construction fails for any reason, this exception will be thrown.
227: *
228: */
229: public DescriptorSupport(String fields[]) {
230: if (fields == null || fields.length == 0)
231: return;
232: for (int i = 0; i < fields.length; i++) {
233: if (fields[i] != null && !fields[i].equals("")) {
234: int index = fields[i].indexOf("=");
235: if (index < 0) {
236: throw new RuntimeOperationsException(
237: new IllegalArgumentException(
238: "Field in invalid format: no equals sign"),
239: "Exception occured trying to construct a descriptor");
240: }
241: String fieldName = fields[i].substring(0, index);
242: String fieldValue = null;
243: if (index < fields[i].length())
244: fieldValue = fields[i].substring(index + 1);
245: if (fieldName == null || fieldName.equals("")) {
246: throw new RuntimeOperationsException(
247: new IllegalArgumentException(
248: "Field in invalid format: no fieldName"),
249: "Exception occured trying to construct a descriptor");
250: }
251: setField(fieldName, fieldValue);
252: }
253: }
254: }
255:
256: /**
257: * returns the string value for a specific fieldname
258: * @param fieldName The field name in question; if not found, null is returned.
259: *
260: * @return String Field value
261: *
262: * @exception RuntimeOperationsException for illegal value (null or empty string) for field URLName.
263: *
264: */
265: public Object getFieldValue(String fieldName)
266: throws RuntimeOperationsException {
267: if (fieldName == null || fieldName.equals("")) {
268: throw new RuntimeOperationsException(
269: new IllegalArgumentException(
270: "Fieldname requested is null"),
271: "Exception occured trying to get a field from a descriptor");
272: }
273: Object obj = descriptor.get(fieldName.toLowerCase());
274: return obj;
275: }
276:
277: /**
278: * Sets the string value for a specific fieldname. The value must be valid for the field.
279: * If the field does not exist, it is added. if it does exist, the value is replaced.
280: *
281: * @param fieldName: The field name to be set. Must not be null or empty string.
282: * @param fieldValue: The field value to be set for the field name. Can be null.
283: *
284: * @exception RuntimeOperationsException for illegal value for field URLName.
285: *
286: */
287: public void setField(String fieldName, Object fieldValue)
288: throws RuntimeOperationsException {
289: if (fieldName == null || fieldName.equals("")) {
290: throw new RuntimeOperationsException(
291: new IllegalArgumentException(
292: "Fieldname to be set is null or empty"),
293: "Exception occured trying to set a field from a descriptor");
294: }
295: if (fieldValue != null && fieldValue.equals("")) {
296: throw new RuntimeOperationsException(
297: new IllegalArgumentException("Field value is empty"),
298: "Exception occured trying to set a field from a descriptor");
299: }
300: String lowerFieldName = fieldName.toLowerCase();
301: if (validateField(lowerFieldName, fieldValue)) {
302: descriptor.put(lowerFieldName, fieldValue);
303: } else {
304: throw new RuntimeOperationsException(
305: new IllegalArgumentException(
306: "Field value invalid: " + lowerFieldName
307: + "=" + fieldValue),
308: "Field "
309: + lowerFieldName
310: + "="
311: + fieldValue
312: + " is invalid. Exception occured trying to set a field from a descriptor");
313: }
314: }
315:
316: /**
317: * Returns all the fields in the descriptor
318: *
319: * @return String array of fields in the format <i>fieldName=fieldValue</i>. If there
320: * are no fields in the descriptor, then String[0] is returned. If a fieldValue is an
321: * object then the toString() method is called on it and its returned value is used
322: * as the value for the field enclosed in parens.
323: *
324: * @exception RuntimeOperationsException for illegal value for field URLName or Values.
325: *
326: */
327: public String[] getFields() {
328: if (descriptor == null)
329: return new String[0];
330: int size = descriptor.size();
331: String[] fields = new String[size];
332: Iterator it = descriptor.entrySet().iterator();
333: int i = 0;
334: while (it.hasNext()) {
335: java.util.Map.Entry entry = (java.util.Map.Entry) it.next();
336: if (entry != null) {
337: Object fieldValue = entry.getValue();
338: if (fieldValue == null) {
339: fields[i] = entry.getKey().toString() + "=";
340: } else if (fieldValue instanceof String) {
341: fields[i] = entry.getKey().toString() + "="
342: + fieldValue;
343: } else {
344: fields[i] = entry.getKey().toString() + "=("
345: + fieldValue.toString() + ")";
346: }
347: }
348: i++;
349: }
350:
351: return fields;
352: }
353:
354: /**
355: * Returns all the fields names in the descriptor.
356: *
357: * @return String array of fields names. If the descriptor is empty, you will get
358: * an empty array.
359: *
360: */
361: public String[] getFieldNames() {
362: if (descriptor == null)
363: return new String[0];
364: String fieldNames[] = new String[descriptor.size()];
365: Iterator it = descriptor.entrySet().iterator();
366: int j = 0;
367: while (it.hasNext()) {
368: java.util.Map.Entry entry = (java.util.Map.Entry) it.next();
369: if (entry != null && entry.getKey() != null) {
370: fieldNames[j] = entry.getKey().toString();
371: }
372: j++;
373: }
374: return fieldNames;
375: }
376:
377: /**
378: * Returns all the field values in the descriptor as an array of Objects. The
379: * retuned values are in the same order as the fieldNames String array parameter.
380: *
381: * @param fieldNames String array of the names of the fields that the values
382: * should be returned for. If the array is empty then an empty array will be
383: * returned. If the array is 'null' then all values will be returned. If a field
384: * name in the array does not exist, then null is returned for the matching array
385: * element being returned.
386: *
387: * @return Object array of field values. If the descriptor is empty, you will get
388: * an empty array.
389: *
390: */
391: public Object[] getFieldValues(String[] fieldNames) {
392: if (descriptor == null || fieldNames != null
393: && fieldNames.length == 0)
394: return new Object[0];
395:
396: Object fieldValues[];
397: int i = 0;
398: if (fieldNames == null) {
399: fieldValues = new Object[descriptor.size()];
400: for (Iterator iterator = descriptor.entrySet().iterator(); iterator
401: .hasNext();) {
402: java.util.Map.Entry entry = (java.util.Map.Entry) iterator
403: .next();
404: if (entry == null || entry.getKey() == null) {
405: fieldValues[i] = null;
406: } else {
407: fieldValues[i] = entry.getValue();
408: }
409: i++;
410: }
411:
412: } else {
413: fieldValues = new Object[fieldNames.length];
414: while (i < fieldNames.length) {
415: if (fieldNames[i] == null || fieldNames[i].equals(""))
416: fieldValues[i] = null;
417: else
418: fieldValues[i] = getFieldValue(fieldNames[i]);
419: i++;
420: }
421: }
422: return fieldValues;
423: }
424:
425: /**
426: * Sets all Fields in the list to the new value in with the same index
427: * in the fieldValue array. Array sizes must match.
428: * The field value will be validated before it is set.
429: * If it is not valid, then an exception will be thrown.
430: * If the arrays are empty, then no change will take effect.
431: *
432: * @param fieldNames String array of field names. The array and array elements cannot be null.
433: * @param fieldValues Object array of the corresponding field values. The array cannot be null.
434: * Elements of the array can be null.
435: *
436: * @exception RuntimeOperationsException for illegal value for field URLName or field Values.
437: * Niether can be null. The array lengths must be equal.
438: * If the descriptor construction fails for any reason, this exception will be thrown.
439: *
440: */
441: public void setFields(String[] fieldNames, Object[] fieldValues)
442: throws RuntimeOperationsException {
443: if (fieldNames == null || fieldValues == null
444: || fieldNames.length != fieldValues.length) {
445: throw new RuntimeOperationsException(
446: new IllegalArgumentException(
447: "FieldNames and FieldValues are null or invalid"),
448: "Exception occured trying to set object fields a descriptor");
449: }
450: for (int i = 0; i < fieldNames.length; i++) {
451: if (fieldNames[i] == null || fieldNames[i].equals("")) {
452: throw new RuntimeOperationsException(
453: new IllegalArgumentException(
454: "FieldNames is null or invalid"),
455: "Exception occured trying to set object fields a descriptor");
456: }
457: setField(fieldNames[i], fieldValues[i]);
458: }
459: }
460:
461: /**
462: * Returns a new Descriptor which is a duplicate of the Descriptor.
463: *
464: * @exception RuntimeOperationsException for illegal value for field URLName or field Values.
465: * If the descriptor construction fails for any reason, this exception will be thrown.
466: */
467: public Object clone() throws RuntimeOperationsException {
468: return new DescriptorSupport(this );
469: }
470:
471: /**
472: * Removes a field from the descriptor
473: *
474: * @param fieldName String name of the field to be removed.
475: * If the field is not found no exception is thrown.
476: */
477: public void removeField(String fieldName) {
478: if (fieldName == null || fieldName.length() == 0)
479: return;
480: Set set = new HashSet(descriptor.keySet());
481: for (Iterator iterator = set.iterator(); iterator.hasNext();) {
482: String _fieldName = (String) iterator.next();
483: if (_fieldName.equalsIgnoreCase(fieldName)) {
484: descriptor.remove(_fieldName);
485: break;
486: }
487: }
488:
489: }
490:
491: /**
492: * Returns true if fieldValues are checked to be sure they are legal for the fieldNames.
493: *
494: * This implementation returns false if:
495: * name or descriptorType fields are null
496: * class, role, getMethod and setMethod, if defined, must not be null
497: * persistPeriod, currencyTimeLimit, lastUpdatedTimeStamp, lastReturnedTimeStamp
498: * must numerics greater than -1.
499: * iterable, log, export must be t, f, true, or false
500: * visibility must be between 1 and 4
501: * severity must be betwen 0 and 5
502: * persistPolicy must be OnUpdate,OnTimer,NoMoreOftenThan,Always,or Never is must not
503: * be case sensitive.
504: *
505: *
506: * @exception RuntimeOperationsException If the validity checking fails for any reason, this exception will be thrown.
507: */
508: public boolean isValid() throws RuntimeOperationsException {
509: Set set = descriptor.entrySet();
510: if (set == null) {
511: return false;
512: }
513: String nameField = (String) getFieldValue(DescriptorConstants.NAME);
514: String descTypeField = (String) getFieldValue(DescriptorConstants.DESCRIPTORTYPE);
515: if (nameField == null || descTypeField == null
516: || nameField.equals("") || descTypeField.equals("")) {
517: return false;
518: }
519: for (Iterator iterator = set.iterator(); iterator.hasNext();) {
520: Map.Entry entry = (Map.Entry) iterator.next();
521: if (entry != null
522: && entry.getValue() != null
523: && !validateField(entry.getKey().toString(), entry
524: .getValue().toString())) {
525: return false;
526: }
527: }
528: return true;
529: }
530:
531: /*
532: // worker routine for isValid()
533: // name is not null
534: // descriptorType is not null
535: // getMethod and setMethod are not null
536: // persistPeriod is numeric
537: // currencyTimeLimit is numeric
538: // lastUpdatedTimeStamp is numeric
539: // iterable is T or F
540: // visibility is 1-4
541: // severity is 0-5
542: // log is T or F
543: // role is not null
544: // class is not null
545: // lastReturnedTimeStamp is numeric
546: */
547: private boolean validateField(String fieldName, Object fieldValue) {
548: if (fieldName == null || fieldName.equals(""))
549: return false;
550: String _fieldValue = "";
551: boolean isString = false;
552: if (fieldValue != null && (fieldValue instanceof String)) {
553: _fieldValue = (String) fieldValue;
554: isString = true;
555: }
556: if (fieldName.equalsIgnoreCase(DescriptorConstants.NAME)
557: || fieldName
558: .equalsIgnoreCase(DescriptorConstants.DESCRIPTORTYPE)
559: || fieldName
560: .equalsIgnoreCase(DescriptorConstants.ATTRIBUTE_SETMETHOD)
561: || fieldName
562: .equalsIgnoreCase(DescriptorConstants.ATTRIBUTE_GETMETHOD)
563: || fieldName
564: .equalsIgnoreCase(DescriptorConstants.OPERATION_ROLE)
565: || fieldName
566: .equalsIgnoreCase(DescriptorConstants.OPERATION_CLASS))
567: return fieldValue != null && isString;
568: if (fieldName.equalsIgnoreCase(DescriptorConstants.VISIBILITY)) {
569: long l;
570: if (fieldValue != null && isString)
571: l = toNumeric(_fieldValue);
572: else if (fieldValue != null
573: && (fieldValue instanceof Integer))
574: l = ((Integer) fieldValue).intValue();
575: else
576: return false;
577: return l >= 1L && l <= 4L;
578: }
579: if (fieldName.equalsIgnoreCase("severity")) {
580: long l;
581: if (fieldValue != null && isString)
582: l = toNumeric(_fieldValue);
583: else if (fieldValue != null
584: && (fieldValue instanceof Integer))
585: l = ((Integer) fieldValue).intValue();
586: else
587: return false;
588: return l >= 1L && l <= 5L;
589: }
590: if (fieldName.equalsIgnoreCase("PersistPolicy"))
591: return fieldValue != null
592: && isString
593: && (_fieldValue.equalsIgnoreCase("OnUpdate")
594: || _fieldValue.equalsIgnoreCase("OnTimer")
595: || _fieldValue
596: .equalsIgnoreCase("NoMoreOftenThan")
597: || _fieldValue.equalsIgnoreCase("Always") || _fieldValue
598: .equalsIgnoreCase("Never"));
599: if (fieldName.equalsIgnoreCase("PersistPeriod")
600: || fieldName.equalsIgnoreCase("CurrencyTimeLimit")
601: || fieldName.equalsIgnoreCase("LastUpdatedTimeStamp")
602: || fieldName.equalsIgnoreCase("LastReturnedTimeStamp")) {
603: // System.out.println("DescriptorSupport:324 " + fieldValue);
604: long l;
605: if (fieldValue != null && isString)
606: l = toNumeric(_fieldValue);
607: else if (fieldValue != null
608: && (fieldValue instanceof Integer))
609: l = ((Integer) fieldValue).intValue();
610: else if (fieldValue != null && (fieldValue instanceof Long))
611: l = ((Long) fieldValue).longValue();
612: else
613: return false;
614: return l >= -1L;
615: }
616: if (fieldName.equalsIgnoreCase("export")
617: || fieldName.equalsIgnoreCase("log")
618: || fieldName.equalsIgnoreCase("Iterable"))
619: return (fieldValue instanceof Boolean)
620: || isString
621: && (_fieldValue.equalsIgnoreCase("T")
622: || _fieldValue.equalsIgnoreCase("true")
623: || _fieldValue.equalsIgnoreCase("F") || _fieldValue
624: .equalsIgnoreCase("false"));
625:
626: return true;
627: }
628:
629: public String toXMLString() {
630: String xmlString = "<Descriptor>";
631: for (Iterator iterator = descriptor.entrySet().iterator(); iterator
632: .hasNext();) {
633: java.util.Map.Entry entry = (java.util.Map.Entry) iterator
634: .next();
635: if (entry != null) {
636: Object obj = entry.getValue();
637: if (obj == null)
638: xmlString += "<field name=\""
639: + entry.getKey().toString()
640: + "\" value=\"null\"></field>";
641: else if (obj instanceof String)
642: xmlString += "<field name=\""
643: + entry.getKey().toString() + "\" value=\""
644: + obj + "\"></field>";
645: else
646: xmlString += "<field name=\""
647: + entry.getKey().toString() + "\" value=\""
648: + "(" + obj.toString() + ")"
649: + "\"></field>";
650: }
651: }
652:
653: xmlString += "</Descriptor>";
654: return xmlString;
655: }
656:
657: public String toString() {
658: String desc = "";
659: String[] fields = getFields();
660: if (fields == null || fields.length == 0) {
661: return desc;
662: }
663: for (int i = 0; i < fields.length; i++)
664: if (i == fields.length - 1)
665: desc += fields[i];
666: else
667: desc += fields[i] + ", ";
668:
669: return desc;
670: }
671:
672: private long toNumeric(String s) {
673: long l = -2L;
674: try {
675: l = Long.parseLong(s);
676: } catch (Exception exception) {
677: return -2L;
678: }
679: return l;
680: }
681:
682: public static void main(String[] args) throws Exception {
683: String xmlString = "<Descriptor><field name=\"name\" value=\"current_descriptor_name\"></field><field name=\"descriptorType\" value=\"current_descriptor_type\"></field></Descriptor>";
684: DescriptorSupport ds = new DescriptorSupport(xmlString);
685: System.out.println(ds.toString());
686: System.out.println(ds.toXMLString());
687: }
688: }
|