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 "AS IS", 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