KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sape > carbon > core > config > format > AbstractConfigurationProxy


1 /*
2  * The contents of this file are subject to the Sapient Public License
3  * Version 1.0 (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  * http://carbon.sf.net/License.html.
6  *
7  * Software distributed under the License is distributed on an "AS IS" basis,
8  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9  * the specific language governing rights and limitations under the License.
10  *
11  * The Original Code is The Carbon Component Framework.
12  *
13  * The Initial Developer of the Original Code is Sapient Corporation
14  *
15  * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
16  */

17
18 package org.sape.carbon.core.config.format;
19
20 import java.beans.BeanInfo JavaDoc;
21 import java.beans.IntrospectionException JavaDoc;
22 import java.beans.Introspector JavaDoc;
23 import java.beans.PropertyDescriptor JavaDoc;
24 import java.io.Serializable JavaDoc;
25 import java.lang.reflect.Array JavaDoc;
26 import java.lang.reflect.Field JavaDoc;
27 import java.lang.reflect.InvocationTargetException JavaDoc;
28 import java.lang.reflect.Method JavaDoc;
29 import java.util.Map JavaDoc;
30
31 import org.jdom.Document;
32 import org.jdom.Element;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37 import org.sape.carbon.core.config.Configuration;
38 import org.sape.carbon.core.config.InvalidConfigurationException;
39 import org.sape.carbon.core.exception.InvalidParameterException;
40 import org.sape.carbon.core.util.reflection.GenericProxy;
41 import org.sape.carbon.core.util.string.StringUtil;
42
43 /**
44  * <p>This abstract class includes basic support for configuration objects
45  * in XML. This class implements the Dynamic Proxy
46  * <class>InvocationHandler</class> interface. By utilizing Dynamic Proxies this
47  * class can implement any subclass of
48  * {@link org.sape.carbon.core.config.Configuration} and automatically support
49  * reading and writing the data of that object to XML.
50  * </p>
51  *
52  * <P>This abstract class implements the basic functionality for managing a
53  * JDOM {@link org.jdom.Document}. It also provides abstract method declarations
54  * that allow a subclass to choose exactly the format for that XML and how it
55  * is treated by a Configuration object.
56  * </P>
57  *
58  * Copyright 2002 Sapient
59  * @since carbon 1.0
60  * @author Greg Hinkle, January 2002
61  * @version $Revision: 1.58 $($Author: dvoet $ / $Date: 2003/11/26 20:30:18 $)
62  */

63 public abstract class AbstractConfigurationProxy
64     extends GenericProxy
65     implements Configuration, Serializable JavaDoc {
66
67     /**
68      * Provides a handle to Apache-commons logger
69      */

70     private Log log =
71         LogFactory.getLog(this.getClass());
72
73     /** Prefix for config values that reference other configs. */
74     protected static final String JavaDoc REF_PREFIX = "ref://";
75
76     /** Holds the length of reference prefix. */
77     protected static final int REF_PREFIX_LENGTH = REF_PREFIX.length();
78
79     /**
80      * JDOM Document object that holds the xml version of this configuration
81      * object's data.
82      */

83     protected Document document;
84
85     /**
86      * The root element of this configuration object. May represent the root
87      * node of the document or it may be a sub-element for included object
88      * types.
89      */

90     protected Element element;
91
92     /**
93      * The Class of object that this configuration object is implementing.
94      */

95     protected Class JavaDoc documentType;
96
97     /**
98      * The fully qualified configuration name for this configuration object
99      */

100     protected String JavaDoc name;
101
102     /** The root XML tag for configuration documnts */
103     private static final String JavaDoc ROOT_TAG = "Configuration";
104
105     /**
106      * True if this object may be altered, false if it should throw exceptions
107      * when attempts are made to alter it.
108      */

109     private boolean writable = true;
110
111     /**
112      * Constructs an AbstractConfigurationProxy for the supplied document.
113      *
114      * @param document The JDOM document object representing the XML for this
115      * configuration object
116      * @param root The root element of this configuration object, not
117      * necessarily the root of the document
118      * @param documentType the Class of object represented by the DynamicProxy
119      * form of this object
120      */

121     protected AbstractConfigurationProxy(
122         Document document,
123         Element root,
124         Class JavaDoc documentType) {
125
126         this.document = document;
127         this.element = root;
128         this.documentType = documentType;
129
130         this.element.setAttribute(
131             "ConfigurationInterface",
132             this.documentType.getName());
133     }
134
135     /**
136      * Constructs an AbstractConfigurationProxy for the supplied document.
137      *
138      * @param documentType the Class of object represented by the DynamicProxy
139      * form of this object
140      */

141     protected AbstractConfigurationProxy(Class JavaDoc documentType) {
142
143         this.element = new Element(ROOT_TAG);
144
145         this.documentType = documentType;
146
147         this.element.setAttribute(
148             "ConfigurationInterface",
149             this.documentType.getName());
150
151         this.document = new Document(this.element);
152     }
153
154     /**
155      * Retrieves this configuration object's name
156      *
157      * @return the fully qualified path name for this configuration object in
158      * the configuration service; <code>null</code> if this configuration
159      * object has not yet been stored in the configuration service
160      */

161     public String JavaDoc getConfigurationName() {
162         return this.name;
163     }
164
165     /**
166      * Sets the name of this configuration object
167      *
168      * @param name the fully qualified name of this configuration in the
169      * configuration service
170      */

171     public void setConfigurationName(String JavaDoc name) {
172         this.name = name;
173     }
174
175     /**
176      * Retrieves the primary type of this configuration
177      * @return the type of this configuration object. This is the primary
178      * class type of the DynamicProxy that was built to support the storage
179      * and retrieval of configurations for that interface
180      */

181     public Class JavaDoc getDocumentType() {
182         return this.documentType;
183     }
184
185     /**
186      * <P>This method provides the basic implementation of invocations
187      * from the standpoint of DynamicProxies. The base proxy class,
188      * <code>GenericProxy</code> provides a default implemenetation
189      * of an InvocationHandler and basic handling for the standad
190      * <code>Object</code> methods. Other methods are passed to this
191      * method for invocation.</P>
192      *
193      * <P>This <code>AbstractConfigurationProxy</code> will handle basic
194      * bean based calls into an object graph and utilize method name
195      * and JavaBean based naming standards to determine the proper data
196      * item to query.</P>
197      *
198      * <P>Sublcasses of <code>AbstractConfigurationProxy</code> will be able
199      * to provide specific implementations of these methods based on what
200      * the underlying datastore type is.</P>
201      *
202      * @param proxy the proxy object on which the method was called
203      * @param m the method which was called to be executed
204      * @param args the array of arguments to the specified method call
205      * @throws Throwable when an invoke fails with any exception -
206      * this is cast by standard dynamic proxy functionality into an
207      * appropriate exception for the type of method that was actually called.
208      * @return the object value returned from the real delegated method call
209      */

210     protected Object JavaDoc handleInvoke(Object JavaDoc proxy, Method JavaDoc m, Object JavaDoc[] args)
211         throws Throwable JavaDoc {
212         String JavaDoc methodName = m.getName();
213         Object JavaDoc returnObject = null;
214
215         if (m.getDeclaringClass() == Configuration.class) {
216             // all methods defined by the Configuration interface are handled
217
// by this class
218
try {
219                 returnObject = m.invoke(this, args);
220             } catch (InvocationTargetException JavaDoc ite) {
221                 // unwrap exception and throw it
222
throw ite.getTargetException();
223             }
224
225         } else if (methodName.startsWith("get")) {
226             String JavaDoc attrName = m.getName().substring(3);
227             Class JavaDoc returnType = m.getReturnType();
228
229             if (returnType.isArray()) {
230                 returnObject =
231                     getArray(attrName, m.getReturnType().getComponentType());
232
233             } else if (returnType.equals(Map JavaDoc.class)) {
234
235
236                 returnObject =
237                     getMap(attrName, getCollectionComponentType(attrName));
238             } else {
239
240                 if ((args == null) || (args.length == 0)) {
241                     // Simple get retrieval
242
returnObject = lookupAttribute(attrName, m.getReturnType());
243
244                 } else if (args.length == 1) {
245                     // Could be an array or a map lookup
246
if (isMapAttribute(attrName)) {
247                         returnObject =
248                             getMap(attrName,
249                                 getCollectionComponentType(attrName)).
250                                 get(args[0]);
251
252                     } else {
253                         // Array retrieval
254
returnObject =
255                             getArrayValue(
256                                 attrName,
257                                 m.getReturnType(),
258                                 ((Integer JavaDoc) args[0]).intValue());
259                     }
260                 }
261             }
262
263         } else if (methodName.startsWith("is")) {
264             String JavaDoc attrName = m.getName().substring(2);
265             returnObject = lookupAttribute(attrName, m.getReturnType());
266
267         } else if (methodName.startsWith("set")) {
268             // Only allow if document is writable
269
if (!this.isConfigurationWritable()) {
270                 throw new java.lang.UnsupportedOperationException JavaDoc(
271                     this.getClass().getName()
272                     + "Configuration Document is read-only, write "
273                     + "not supported.");
274             }
275
276             String JavaDoc attrName = m.getName().substring(3);
277             if (args.length == 1) {
278                 // Simple value set
279
alterAttribute(attrName, m.getParameterTypes()[0], args[0]);
280
281             } else if (args.length == 2) {
282
283                 if (isMapAttribute(attrName)) {
284                     //Set the map value
285
setMapValue(
286                         attrName,
287                         getCollectionComponentType(attrName),
288                         args[0], args[1]);
289
290                 } else {
291                     // Array index value set
292
setArrayValue(
293                         attrName,
294                         m.getParameterTypes()[1],
295                         ((Integer JavaDoc) args[0]).intValue(),
296                         args[1]);
297                 }
298             }
299
300         } else if (methodName.startsWith("add")) {
301             // Only allow if document is writable
302
if (!this.isConfigurationWritable()) {
303                 throw new java.lang.UnsupportedOperationException JavaDoc(
304                     this.getClass().getName()
305                     + "Configuration Document is read-only, write "
306                     + "not supported.");
307             }
308
309             String JavaDoc attrName = m.getName().substring(3);
310             addAttribute(attrName, m.getParameterTypes()[0], args[0]);
311
312         } else {
313             throw new UnsupportedOperationException JavaDoc(
314                 this.getClass().getName()
315                     + ": Method named ["
316                     + methodName
317                     + "] in configuration "
318                     + "interface ["
319                     + m.getDeclaringClass()
320                     + "] is not a supported "
321                     + "method within a Configuration interface. Methods must "
322                     + "conform to the JavaBeans specification.");
323         }
324
325         return returnObject;
326     }
327
328     /**
329      * Gets the value from an configuration array.
330      *
331      * @param attributeName the name of the attribute that holds the array
332      * @param type the type of class within the array
333      * @param index the index of the value to retreive
334      * @return the object at the given index in the array
335      * @throws InvalidParameterException indicates there was an error
336      * accessing the give index in the array such as an
337      * IndexOutOfBoundsException
338      */

339     protected Object JavaDoc getArrayValue(
340             String JavaDoc attributeName, Class JavaDoc type, int index) {
341
342         Object JavaDoc array =
343             getArray(attributeName, type);
344
345         Object JavaDoc returnObject = null;
346         try {
347             returnObject = Array.get(array, index);
348         } catch (IndexOutOfBoundsException JavaDoc ioobe) {
349             throw new InvalidParameterException(
350                 this.getClass(),
351                 "Indexed configuration out of bounds on document ["
352                 + this.getConfigurationName() + "] attribute ["
353                 + attributeName + "] index [" + index + "]",
354                 ioobe);
355         }
356         return returnObject;
357     }
358
359     /**
360      * Checks if the given attribute contains a map.
361      *
362      * @param attrName the attribute to test for being a map
363      * @return true if the given attribute is for a map
364      */

365     protected boolean isMapAttribute(String JavaDoc attrName) {
366         boolean isMapAttribute = false;
367         
368         try {
369             Method JavaDoc readMethod = this.documentType.getMethod(
370                 "get" + attrName, new Class JavaDoc[0]);
371                 
372             isMapAttribute = readMethod.getReturnType().equals(Map JavaDoc.class);
373         } catch (NoSuchMethodException JavaDoc e) {
374             // read method does not exist, so leave isMapAttribute as false
375
}
376         
377         return isMapAttribute;
378     }
379
380     /**
381      * Gets the type of class contained within a map.
382      *
383      * @param attrName the name of the attribute to determine the
384      * class type of
385      * @return the type of class contained within the array or null
386      * if it is unable to determine the type.
387      */

388     protected Class JavaDoc getCollectionComponentType(String JavaDoc attrName) {
389         Class JavaDoc componentType = null;
390         
391         try {
392             Method JavaDoc readMethod = this.documentType.getMethod(
393                 "get" + attrName, new Class JavaDoc[] { String JavaDoc.class });
394                 
395             componentType = readMethod.getReturnType();
396         } catch (NoSuchMethodException JavaDoc e) {
397             // read method does not exist, so leave componentType as null
398
}
399         
400         return componentType;
401     }
402
403     /**
404      * Retrieves the type of a JavaBean attribute by introspecting for its
405      * retrieval method and checking its return type.
406      * @param attributeName the name of the attribute to get the type of
407      * @return the class type of the attribute
408      */

409     public Class JavaDoc getChildType(String JavaDoc attributeName) {
410         attributeName = StringUtil.capitalize(attributeName);
411         try {
412             Method JavaDoc method =
413                 this.documentType.getMethod(
414                     "get" + attributeName,
415                     new Class JavaDoc[0]);
416             return method.getReturnType();
417         } catch (NoSuchMethodException JavaDoc nsme) {
418             throw new InvalidParameterException(
419                 this.getClass(),
420                 "Unknown attribute [" + attributeName + "] on configuration ["
421                 + this.getConfigurationName() + "]");
422         }
423     }
424
425     /**
426      * Retrieves the default value for a requested configuration attribute
427      * from an interface static variable with the same name as the
428      * requested attribute.
429      *
430      * @param type the Class of the configuration interface that may
431      * contain a default value
432      * @param attributeName the name of the attribute being looked for
433      * @param returnType the return type of the method
434      * @return the default value of the specified attribute
435      */

436     protected Object JavaDoc lookupDefaultAttributeValue(
437         Class JavaDoc type,
438         String JavaDoc attributeName,
439         Class JavaDoc returnType) {
440
441         try {
442
443             Field JavaDoc field = type.getField(attributeName);
444             Object JavaDoc val = field.get(null);
445
446             if (val == null) {
447                 return null;
448             } else {
449                 if (field.getType().equals(returnType)) {
450                     // The attribute has a default and it is the right type
451
return val;
452                 } else {
453                     // Default value has the wrong type
454
StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
455                     buf.append("The Default value in the configuration of [");
456                     buf.append(type.getName());
457                     buf.append("] was of type [");
458                     buf.append(field.getType());
459                     buf.append(
460                         "], but the configuration interface requires a ");
461                     buf.append(" default of type [");
462                     buf.append(returnType);
463                     buf.append("].");
464
465                     throw new InvalidConfigurationException(
466                         this.getClass(),
467                         this.getConfigurationName(),
468                         buf.toString());
469
470                 }
471             }
472         } catch (NoSuchFieldException JavaDoc nsfe) {
473             // No field, no problem
474
// search super interfaces (depth first search)
475
Class JavaDoc[] superInterfaces = type.getInterfaces();
476             Object JavaDoc val = null;
477             for (int i = 0;
478                 ((i < superInterfaces.length) && (val == null));
479                 i++) {
480
481                 val =
482                     lookupDefaultAttributeValue(
483                         superInterfaces[i],
484                         attributeName,
485                         returnType);
486             }
487             return val;
488         } catch (IllegalAccessException JavaDoc iae) {
489             throw new InvalidConfigurationException(
490                 this.getClass(),
491                 this.getConfigurationName(),
492                 attributeName,
493                 "Could not access the default variable named ["
494                     + attributeName
495                     + "] in the configuration interface ["
496                     + type.getName()
497                     + "].",
498                 iae);
499         } catch (IllegalArgumentException JavaDoc iae) {
500             throw new InvalidConfigurationException(
501                 this.getClass(),
502                 this.getConfigurationName(),
503                 attributeName,
504                 "Could not access the default variable named ["
505                     + attributeName
506                     + "] in the configuration interface ["
507                     + type.getName()
508                     + "].",
509                 iae);
510         }
511
512     }
513
514     /**
515      * <P>Implementations of this method should provide the ability to alter an
516      * attribute within the configuration object setting its value to the
517      * provide <code>newValue</code>.
518      *
519      * @param attributeName the name of the attribute to be altered
520      * @param attributeType the type of the attribute
521      * @param newValue the new value to change that attribute to
522      */

523     public abstract void alterAttribute(
524         String JavaDoc attributeName,
525         Class JavaDoc attributeType,
526         Object JavaDoc newValue);
527
528     /**
529      * <P>Implementations of this method should retrieve a value from the
530      * configuration object with the specified name and Type. The Type
531      * information is gleaned from the providing configuration interface
532      * and allows the system to determine the proper mechanism for
533      * instantiating this value. This may involve the usage of the
534      * micro-level formatting for configuration values.</P>
535      *
536      * @return the object representing the specified confuguration value
537      * @param attributeName the name of the attribute to retrieve
538      * @param returnType the class type of the object that should be returned
539      */

540     public abstract Object JavaDoc lookupAttribute(
541         String JavaDoc attributeName,
542         Class JavaDoc returnType);
543
544
545
546     /**
547      * <P>Retrieves an array of objects of the specified type that have
548      * the specified name. This might get a list of dependent objects or
549      * a list of string values.</P>
550      *
551      * @param attributeName the name of the array to retrieve
552      * @param componentType the type of the objects that should be retrieved
553      * within the array
554      * @return an array of objects that match the name and type specified
555      */

556     public abstract Object JavaDoc getArray(String JavaDoc attributeName, Class JavaDoc componentType);
557
558     /**
559      * <P>Retrieves a java.util.Map of objects of the specified type that have
560      * the specified name. This might get a list of dependent objects or
561      * a list of string values.</P>
562      *
563      * @param attributeName the name of the array to retrieve
564      * @param contentType the type of the objects that should be retrieved
565      * within the Map
566      * @return a Map of objects that match the name and type specified
567      */

568     public abstract Map JavaDoc getMap(String JavaDoc attributeName, Class JavaDoc contentType);
569
570
571     /**
572      * <P>Sets the value of a specific index in an array of data in this
573      * configuration object. Implementing classes must set the specified index
574      * of the array named by <code>attributeName</code> to the specified value.
575      * </P>
576      *
577      * @param attributeName the name of the array to alter
578      * @param attributeType the type of the objects in the array
579      * @param index the indicie of the array to alter
580      * @param value the Object to set as the value of this indicie
581      */

582     public abstract void setArrayValue(
583         String JavaDoc attributeName,
584         Class JavaDoc attributeType,
585         int index,
586         Object JavaDoc value);
587
588     /**
589      * <P>Sets the value of a specific index in an array of data in this
590      * configuration object. Implementing classes must set the specified index
591      * of the array named by <code>attributeName</code> to the specified value.
592      * </P>
593      *
594      * @param attributeName the name of the array to alter
595      * @param attributeType the type of the objects in the map
596      * @param key the key within the map to set
597      * @param value the Object to set as the value of this indicie
598      */

599     public abstract void setMapValue(
600         String JavaDoc attributeName,
601         Class JavaDoc attributeType,
602         Object JavaDoc key,
603         Object JavaDoc value);
604
605
606     /**
607      * This method should add a child entity to this configuration entity
608      *
609      * @param entityName the name of the array on which to add a particular
610      * value
611      * @param type type of class of the child entity
612      * @param obj The object to be added as a configuration entity
613      * @return the element representing the added attribute
614      */

615     public abstract Element addAttribute(
616         String JavaDoc entityName,
617         Class JavaDoc type,
618         Object JavaDoc obj);
619
620     /**
621      * <P>Returns the simple class name without the prepended package
622      * structure</P>
623      *
624      * @param theClass the class whose name is returned
625      * @return the unqualifiedclass name of the supplied class
626      */

627     public static String JavaDoc getSimpleClassName(Class JavaDoc theClass) {
628         String JavaDoc className = theClass.getName();
629         if (className.lastIndexOf('.') > className.lastIndexOf('$')) {
630             return className.substring(className.lastIndexOf('.') + 1);
631         } else {
632             return className.substring(className.lastIndexOf('$') + 1);
633         }
634     }
635     /**
636      * @see Configuration#getConfigurationInterface()
637      */

638     public Class JavaDoc getConfigurationInterface() {
639         try {
640             String JavaDoc configurationInterfaceName =
641                 this.element.getAttributeValue("ConfigurationInterface");
642
643             if (configurationInterfaceName == null) {
644                 throw new InvalidConfigurationException(
645                     this.getClass(),
646                     getConfigurationName(),
647                     "ConfigurationInterface",
648                     "No value specifed");
649             }
650
651             return Class.forName(configurationInterfaceName);
652         } catch (ClassNotFoundException JavaDoc cnfe) {
653             throw new InvalidConfigurationException(
654                 this.getClass(),
655                 getConfigurationName(),
656                 "ConfigurationInterface",
657                 "Specifed class not found",
658                 cnfe);
659         }
660     }
661
662     /**
663      * @see Configuration#getDataStructure()
664      */

665     public Document getDataStructure() {
666         return this.document;
667     }
668
669     /**
670      * Retrieves the root element of the data being currently mapped by this
671      * configuration object. Child structures will have a different root then
672      * the root of the "Document" object.
673      *
674      * @return the root element being proxied by this object
675      */

676     public Element getRootElement() {
677         return this.element;
678     }
679
680     /**
681      * @see Object#clone()
682      */

683     public abstract Object JavaDoc clone();
684
685     /**
686      * Checks whether or not childElement is a child configuration or not
687      *
688      * @param childElement element to be tested.
689      * @return boolean true if childElement is a configuration
690      */

691     public boolean isChildConfiguration(Element childElement) {
692         return (
693             childElement.getAttribute("ConfigurationInterface") != null
694                 || isReference(childElement));
695     }
696
697     /**
698      * Checks whether or not element is a reference to another configuration.
699      *
700      * @param element element to check if it is a reference
701      * @return true is the text of element starts with REF_PREFIX
702      */

703     public boolean isReference(Element element) {
704         String JavaDoc textValue = element.getTextTrim();
705         return textValue.startsWith(REF_PREFIX);
706     }
707
708     /**
709      * Gets the ConfigurationInterface specifed in an element. If the
710      * ConfigurationInterface is not defined by the element of the class
711      * specified is not found, defaultInterface is returned.
712      *
713      * @param element the element to retreive the configuration element from
714      * @param defaultInterface the default interface if there is no
715      * configuration interface defined by the element
716      * @return ConfigurationInterface from the element or default
717      */

718     protected Class JavaDoc getConfigurationInterface(
719         Element element,
720         Class JavaDoc defaultInterface) {
721
722         Class JavaDoc configurationInterface = defaultInterface;
723
724         try {
725             String JavaDoc configTypeName =
726                 element.getAttributeValue("ConfigurationInterface");
727
728             if (configTypeName != null) {
729                 configurationInterface = Class.forName(configTypeName);
730             }
731
732
733             if (!Configuration.class.isAssignableFrom(configurationInterface)) {
734                 throw new InvalidConfigurationException(
735                     this.getClass(),
736                     this.getConfigurationName(),
737                     this.element.getName(),
738                     "The configured configuration interface does not extend "
739                         + "[org.sape.carbon.core.config.Configuration] and "
740                         + "therefore can not be instantiated. Please correct "
741                         + "the class ["
742                         + configurationInterface.getName() + "]");
743             }
744
745         } catch (ClassNotFoundException JavaDoc cnfe) {
746             throw new InvalidConfigurationException(
747                 this.getClass(),
748                 this.getConfigurationName(),
749                 element.getName(),
750                 "The child configuration has defined a configuration interface " +
751                 "class which can not be found. Check the configuration document " +
752                 "to ensure the class name is correct.",
753                 cnfe);
754         } catch (ExceptionInInitializerError JavaDoc eiie) {
755             if (log.isTraceEnabled()) {
756                 log.trace("Caught ExceptionInInitializerError ["
757                     + eiie
758                     + "], returning default interface");
759             }
760         }
761
762         return configurationInterface;
763     }
764     /**
765      * @see org.sape.carbon.core.util.reflection.GenericProxy#proxyEquals(Object, Object)
766      */

767     protected Boolean JavaDoc proxyEquals(Object JavaDoc proxy, Object JavaDoc other) {
768         try {
769             Element proxyElement = ((Configuration) proxy).getRootElement();
770             Element otherElement = ((Configuration) other).getRootElement();
771
772             if (proxyElement == otherElement) {
773                 return Boolean.TRUE;
774             } else {
775                 return Boolean.FALSE;
776             }
777         } catch (ClassCastException JavaDoc cce) {
778             return Boolean.FALSE;
779         }
780     }
781
782     /**
783      * @see org.sape.carbon.core.util.reflection.GenericProxy#proxyHashCode(Object)
784      */

785     protected Integer JavaDoc proxyHashCode(Object JavaDoc proxy) {
786         Element proxyElement = ((Configuration) proxy).getRootElement();
787         return new Integer JavaDoc(System.identityHashCode(proxyElement));
788     }
789
790     /**
791      * Is this configuration document writable or is it read-only. Shared cache
792      * instances of configuration objects should either be synchronized or
793      * marked not writable. When a configuration object is not writable, it
794      * should throw an exception if an attempt is made to modify it.
795      *
796      * @return true if this cofiguration object may be altered.
797      * @since carbon 1.1
798      */

799     public boolean isConfigurationWritable() {
800         return this.writable;
801     }
802
803     /**
804      * Sets whether this configuration may be altered.
805      * @since carbon 1.1
806      */

807     public void setConfigurationReadOnly() {
808         this.writable = false;
809     }
810
811 }
Popular Tags