001    package com.softnetConsult.utils.reflect;
002    
003    import java.io.DataInputStream;
004    import java.io.IOException;
005    import java.io.InputStream;
006    
007    import com.softnetConsult.utils.exceptions.Bug;
008    
009    
010    /**
011     * Defines static utilities for dealing with classes and reflection.
012     * 
013     * <p style="font-size:smaller;">This product includes software developed by the
014     *    <strong>SoftNet-Consult Java Utility Library</strong> project and its contributors.<br />
015     *    (<a href="http://java-tools.sourceforge.net" target="_blank">http://java-tools.sourceforge.net</a>)<br />
016     *    Copyright (c) 2007-2008 SoftNet-Consult.<br />
017     *    Copyright (c) 2007-2008 G. Paperin.<br />
018     *    All rights reserved.
019     * </p>
020     * <p style="font-size:smaller;">File: ClassTools.java<br />
021     *    Library API version: {@value com.softnetConsult.utils.APIProperties#apiVersion}<br />
022     *    Java compliance version: {@value com.softnetConsult.utils.APIProperties#javaComplianceVersion}
023     * </p>
024     * <p style="font-size:smaller;">Redistribution and use in source and binary forms, with or
025     *    without modification, are permitted provided that the following terms and conditions are met:
026     * </p>
027     * <p style="font-size:smaller;">1. Redistributions of source code must retain the above
028     *    acknowledgement of the SoftNet-Consult Java Utility Library project, the above copyright
029     *    notice, this list of conditions and the following disclaimer.<br />
030     *    2. Redistributions in binary form must reproduce the above acknowledgement of the
031     *    SoftNet-Consult Java Utility Library project, the above copyright notice, this list of
032     *    conditions and the following disclaimer in the documentation and/or other materials
033     *    provided with the distribution.<br />
034     *    3. All advertising materials mentioning features or use of this software or any derived
035     *    software must display the following acknowledgement:<br />
036     *    <em>This product includes software developed by the SoftNet-Consult Java Utility Library
037     *    project and its contributors.</em>
038     * </p>
039     * <p style="font-size:smaller;">THIS SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY
040     *    OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
041     *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL
042     *    THE AUTHORS, CONTRIBUTORS OR COPYRIGHT  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
043     *    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  FROM, OUT OF OR
044     *    IN CONNECTION WITH THE SOFTWARE OR THE USE OR  OTHER DEALINGS IN THE SOFTWARE.
045     * </p> 
046     * @author Greg Paperin (<a href="http://www.paperin.org" target="_blank">http://www.paperin.org</a>)
047     * @version {@value com.softnetConsult.utils.APIProperties#apiVersion}
048     *
049     */
050    public final class ClassTools {
051    
052    
053    /**
054     * Prevents instances of this class from being created
055     * as this class contains only static utility methods.
056     */
057    private ClassTools() {}
058    
059    
060    /**
061     * The magic number that must be contained in the first two bytes of all Java class binaries.
062     */
063    public static final int JAVA_CLASSFILE_MAGIC_NUMBER = 0xCAFEBABE;
064    
065    
066    /**
067     * Find the correct wrapper class for a primitive type.
068     * If the specified class type does not describe a primitive type, it is simply returned.
069     * If the specified class type describes a primitive type, the corresponding warpper
070     * class type is returned. For instance:<br />
071     * {@code int} => {@code Integer.class} <br />
072     * {@code double} => {@code Double.class} <br />
073     * {@code Object} => {@code Object} <br />
074     * {@code null} => {@code null} <br />
075     * 
076     * @param type An object representing a Java class or interface.
077     * @return The wrapper class type corresponding to the specified class type.
078     */
079    public static Class<?> getWrapperClass(Class<?> type) {
080            
081            if (null == type)
082                    return null;
083            
084            if (!type.isPrimitive())
085                    return type;
086            
087            if (type.equals(Boolean.TYPE))
088                    return Boolean.class;
089            
090            if (type.equals(Character.TYPE))
091                    return Character.class;
092            
093            if (type.equals(Byte.TYPE))
094                    return Byte.class;
095            
096            if (type.equals(Short.TYPE))
097                    return Short.class;
098            
099            if (type.equals(Integer.TYPE))
100                    return Integer.class;
101            
102            if (type.equals(Long.TYPE))
103                    return Long.class;
104            
105            if (type.equals(Float.TYPE))
106                    return Float.class;
107            
108            if (type.equals(Double.TYPE))
109                    return Double.class;
110            
111            if (type.equals(Void.TYPE))
112                    return Void.class;
113            
114            throw new Bug("Should never get to this line!");
115    }
116    
117    
118    /**
119     * Determines the minimum JVM version required to run a class binary of the specified version.
120     * The current version of this method supports class binaries up to version 50.0 (which
121     * corresponds to JVM 1.6). 
122     * 
123     * @param classBinaryMajorVersion Major version of a class binary.
124     * @param classBinaryMinorVersion Minor version of a class binary.
125     * @return A string specifying the <em>minimum</em> version of a Java virtual machine
126     * required to run a class binary with the specified version number. If the specified
127     * class binary version is unknown, the string {@code "<unknown>"} is returned.
128     */
129    public static final String getMinimumRequiredJavaVersion(int classBinaryMajorVersion,
130                                                                                                                     int classBinaryMinorVersion) {
131            
132            final int major = classBinaryMajorVersion;
133            final int minor = classBinaryMinorVersion;
134            
135            if (major == 45 && minor >= 0 && minor <= 3)
136                    return "1.0.2";
137            
138            if (major == 45 && minor >= 0 && minor <= 65535)
139                    return "1.1";
140            
141            if ((major == 45 && minor >= 0) || (major == 46 && minor == 0))
142                    return "1.2";
143            
144            if (major == 47 && minor == 0)
145                    return "1.3";
146            
147            if (major == 48 && minor == 0)
148                    return "1.4";
149            
150            if (major == 49 && minor == 0)
151                    return "1.5";
152            
153            if (major == 50 && minor == 0)
154                    return "1.6";
155    
156            return "<unknown>";
157    }
158    
159    
160    /**
161     * Parses the version information from a a Java class binary.
162     * 
163     * @param classdata A stream containing the Java class binary data.
164     * @return The version information of the specified class binary.
165     * @throws IOException If an error occurs when reading from the specified class binary stream.
166     */
167    public static ClassVersionInfo getClassVersionInfo(InputStream classdata) throws IOException {
168            DataInputStream in = new DataInputStream(classdata);
169            int magic = in.readInt();
170            if (JAVA_CLASSFILE_MAGIC_NUMBER != magic)
171                    return null;
172            
173            int minor = in.readShort();
174            int major = in.readShort();
175            String reqJavaVer = getMinimumRequiredJavaVersion(major, minor);
176            return new ClassVersionInfo(major, minor, reqJavaVer);
177    }
178    
179    } // public final class ClassTools