001: // THIS SOFTWARE IS PROVIDED BY SOFTARIS PTY.LTD. AND OTHER METABOSS
002: // CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
003: // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
004: // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTARIS PTY.LTD.
005: // OR OTHER METABOSS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
006: // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
007: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
008: // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
009: // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
010: // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
011: // EVEN IF SOFTARIS PTY.LTD. OR OTHER METABOSS CONTRIBUTORS ARE ADVISED OF THE
012: // POSSIBILITY OF SUCH DAMAGE.
013: //
014: // Copyright 2000-2005 © Softaris Pty.Ltd. All Rights Reserved.
015: package com.metaboss.util;
016:
017: /** Set of useful utilites todo with java.lang.reflection capabilities */
018: public class ReflectionUtils {
019: /** @param pInnerClassName local name of the class without package and encapsulating class name
020: * @return inner class or inner interface if there is one declared inside the given class.
021: * @throws ClassNotFoundException if desired class has not been found. */
022: public static Class getInnerClass(Class pEncapsulatingClass,
023: String pInnerClassName) throws ClassNotFoundException {
024: String lInnerClassFullRuntimeName = pEncapsulatingClass
025: .getName()
026: + "$" + pInnerClassName;
027: Class[] lAllClasses = pEncapsulatingClass.getClasses();
028: if (lAllClasses != null && lAllClasses.length > 0) {
029: for (int i = 0; i < lAllClasses.length; i++) {
030: Class lInnerClass = lAllClasses[i];
031: if (lInnerClass != null
032: && lInnerClass.getName().equals(
033: lInnerClassFullRuntimeName))
034: return lInnerClass;
035: }
036: }
037: // Clas not found
038: String lInnerClassFullLanguageName = pEncapsulatingClass
039: .getName()
040: + "." + pInnerClassName;
041: throw new ClassNotFoundException(lInnerClassFullLanguageName);
042: }
043:
044: /** This method uses reflection to find out whether the class being tested is of specified type (i.e. can be
045: * casted to it). Does the analysis regardless of whether classes are interfaces or not */
046: public static boolean isSubtype(Class pClassBeingTested,
047: Class pPossibleSuperclass) {
048: if (pClassBeingTested == null)
049: return false; // Nothing to look at
050: if (pPossibleSuperclass == null)
051: return false; // Nothing to look at
052: if (pClassBeingTested.isPrimitive())
053: return false; // Can not have primitive class extending anything
054: if (pPossibleSuperclass.isPrimitive())
055: return false; // Can not extend primitive type
056: if (pClassBeingTested.isArray())
057: return false; // Do not work with arrays
058: if (pPossibleSuperclass.isArray())
059: return false; // Do not work with arrays
060: // Test for subclass or subinterface
061: if (pPossibleSuperclass.isInterface())
062: return isSubinterfaceHelper(pClassBeingTested,
063: pPossibleSuperclass);
064: return isSubclassHelper(pClassBeingTested, pPossibleSuperclass);
065: }
066:
067: /** Uses reflection to find out whether the class being tested is a subclass of the other class
068: * @return true only if pClassBeingTested represents class, pPossibleSuperclass also represents class
069: * and pClassBeingTested extends pPossibleSuperclass at any depth of the hierarchy */
070: public static boolean isSubclass(Class pClassBeingTested,
071: Class pPossibleSuperclass) {
072: if (pClassBeingTested == null)
073: return false; // Nothing to look at
074: if (pPossibleSuperclass == null)
075: return false; // Nothing to look at
076: if (pClassBeingTested.isPrimitive())
077: return false; // Can not have primitive class extending anything
078: if (pPossibleSuperclass.isPrimitive())
079: return false; // Can not extend primitive type
080: if (pClassBeingTested.isArray())
081: return false; // Do not work with arrays
082: if (pPossibleSuperclass.isArray())
083: return false; // Do not work with arrays
084: if (pClassBeingTested.isInterface())
085: return false; // Can not have interface extending class
086: if (pPossibleSuperclass.isInterface())
087: return false; // Can not extend interface
088: return isSubclassHelper(pClassBeingTested, pPossibleSuperclass);
089: }
090:
091: // This recursive helper does exact same thing as isSubclass(), but it does not waste
092: // time checking for arrays, primitives and non-classes
093: private static boolean isSubclassHelper(Class pClassBeingTested,
094: Class pPossibleSuperclass) {
095: if (pClassBeingTested == null)
096: return false; // Nothing to look at
097: if (pPossibleSuperclass == null)
098: return false; // Nothing to look at
099: if (pClassBeingTested.equals(pPossibleSuperclass))
100: return true;
101: return isSubclassHelper(pClassBeingTested.getSuperclass(),
102: pPossibleSuperclass);
103: }
104:
105: /** Uses reflection to find out whether the class being tested is a subinterface of the other interface
106: * @return true only if pPossibleSuperinterface represents interface and class/interface pClassBeingTested implements
107: * pPossibleSuperinterface at any depth of the hierarchy */
108: public static boolean isSubinterface(Class pClassBeingTested,
109: Class pPossibleSuperinterface) {
110: if (pClassBeingTested == null)
111: return false; // Nothing to look at
112: if (pPossibleSuperinterface == null)
113: return false; // Nothing to look at
114: if (pClassBeingTested.isPrimitive())
115: return false; // Can not have primitive class extending anything
116: if (pPossibleSuperinterface.isPrimitive())
117: return false; // Can not extend primitive type
118: if (pClassBeingTested.isArray())
119: return false; // Do not work with arrays
120: if (pPossibleSuperinterface.isArray())
121: return false; // Do not work with arrays
122: if (!pPossibleSuperinterface.isInterface())
123: return false; // Can not have a class as a superinterface
124: return isSubinterfaceHelper(pClassBeingTested,
125: pPossibleSuperinterface);
126: }
127:
128: // This recursive helper does exact same thing as isSubinterface(), but it does not waste
129: // time checking for arrays, primitives and non-interfaces
130: private static boolean isSubinterfaceHelper(
131: Class pClassBeingTested, Class pPossibleSuperclass) {
132: if (pClassBeingTested == null)
133: return false; // Nothing to look at
134: if (pPossibleSuperclass == null)
135: return false; // Nothing to look at
136: if (pClassBeingTested.equals(pPossibleSuperclass))
137: return true;
138: // Check interfaces
139: Class[] lSuperinterfaces = pClassBeingTested.getInterfaces();
140: for (int i = 0; i < lSuperinterfaces.length; i++) {
141: if (isSubinterfaceHelper(lSuperinterfaces[i],
142: pPossibleSuperclass))
143: return true;
144: }
145: return isSubinterfaceHelper(pClassBeingTested.getSuperclass(),
146: pPossibleSuperclass);
147: }
148: }
|