Skip to content

Commit 031de6c

Browse files
0.4 - Breaking changes.
BetterReflection: + Added an int Pattern + Added some primitives to the primitives map + Added the method #getBetterReflectionClasses(), which will return a copy of the betterReflectionClasses list + Added #getVersion(), which will return a hard-coded value that will be changed on each version + Added #getLatestVersion(), which will query GitHub and return the latest version as a String + Added #isUpToDate(), which will call #getLatestVersion() and #getVersion() to check if the current version is up to date + Added #versionToInts(String), which will convert a String (e.g. "0.4") to an array of integers (such as { 0, 4 }) * Replaced the betterReflectionClasses CopyOnWriteArrayList with a simple synchronized ArrayList BetterReflectionClass: + Added the #forName() method, this will simply return #BetterReflectionClass(String) but return null if a ClassNotFoundException is to be thrown. + #getName() - returns the class' name + #getSimpleName() - returns the class' simple name + #getCanonicalName() - returns the class' canonical name + #getTypeName() - returns the class' type name * Replaced BetterReflectionUtils#getClasses to BetterReflectionUtils#getTypes (renamed) BetterReflectionUtils: + Added a public static final File that holds the current jar file the program is being run from + Added the method #getCurrentJarFile() which returns the current jar file the program is being run from (not cached, will be retrieved every time) + Added the method #getCurrentJar() which returns the current jar File wrapped in a JarFile class + Added the method #isRunningFromJar() which returns true if the program is running off of a jar, false if it's running in an IDE + Added #getJavaVersion(), which will return the current java version as int + Added #setFinal(Field field, boolean final), which will set a field to the desired final state (works in Java 12+ too but that'd require some additional JVM arguments) * Fixed the class' content being pasted twice * Renamed #getClasses(String) -> #getClassesInPackage(String), which returns a list of classes in the current package and now works both when running in an IDE and off of a jar, if the jar is still present * Renamed #getClassByNameStart(String, String) -> #getClassesFromNameBeginning(String, String) (now works when running off a jar too) - Removed #findClasses(File, String) Tests: * Now using nanoseconds instead of milliseconds - Removed Timer class Now also including sources in jar file, this way the javadocs will be accessible when using a good IDE.
1 parent 7910ed6 commit 031de6c

18 files changed

+456
-251
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,79 @@
11
package me.wavelength.betterreflection;
22

3+
import java.io.ByteArrayOutputStream;
4+
import java.io.IOException;
5+
import java.io.InputStream;
36
import java.lang.reflect.Field;
7+
import java.net.URL;
8+
import java.net.URLConnection;
9+
import java.util.ArrayList;
10+
import java.util.Collections;
411
import java.util.HashMap;
12+
import java.util.List;
513
import java.util.Map;
6-
import java.util.concurrent.CopyOnWriteArrayList;
14+
import java.util.concurrent.Callable;
15+
import java.util.concurrent.FutureTask;
16+
import java.util.regex.Pattern;
717

818
/**
9-
* This class simply caches Reflections. In absence of a name "BetterReflection" has been chosen.
19+
* This class simply caches Reflections. In absence of a name "BetterReflection"
20+
* has been chosen.
1021
**/
1122
public class BetterReflection {
12-
13-
private final CopyOnWriteArrayList<BetterReflectionClass> betterReflectionClasses;
23+
24+
private final List<BetterReflectionClass> betterReflectionClasses;
1425

1526
public static final BetterReflectionClass FIELD = new BetterReflectionClass(Field.class);
1627

17-
private static final Map<Class<?>, BetterReflectionClass> PRIMITIVES = new HashMap<>();;
28+
private static final Map<Class<?>, BetterReflectionClass> PRIMITIVES = new HashMap<>();
29+
30+
/**
31+
* @since 0.4
32+
*/
33+
public static final Pattern INTEGER_PATTERN = Pattern.compile("-?\\d+");
1834

1935
public BetterReflection() {
20-
this.betterReflectionClasses = new CopyOnWriteArrayList<>();
36+
this.betterReflectionClasses = Collections.synchronizedList(new ArrayList<>());
2137

2238
PRIMITIVES.put(Double.class, getBetterReflectionClass(Double.class));
2339
PRIMITIVES.put(Integer.class, getBetterReflectionClass(Integer.class));
2440
PRIMITIVES.put(Float.class, getBetterReflectionClass(Float.class));
2541
PRIMITIVES.put(Boolean.class, getBetterReflectionClass(Boolean.class));
2642
PRIMITIVES.put(Long.class, getBetterReflectionClass(Long.class));
43+
PRIMITIVES.put(double.class, getBetterReflectionClass(double.class));
44+
PRIMITIVES.put(int.class, getBetterReflectionClass(int.class));
45+
PRIMITIVES.put(float.class, getBetterReflectionClass(float.class));
46+
PRIMITIVES.put(boolean.class, getBetterReflectionClass(boolean.class));
47+
PRIMITIVES.put(long.class, getBetterReflectionClass(long.class));
2748
}
2849

29-
public BetterReflectionClass getBetterReflectionClass(String name) throws ClassNotFoundException {
30-
for (BetterReflectionClass betterReflectionClass : betterReflectionClasses) {
50+
/**
51+
* @return a copy of the cached classes
52+
*/
53+
public List<BetterReflectionClass> getBetterReflectionClasses() {
54+
return new ArrayList<>(betterReflectionClasses);
55+
}
56+
57+
public BetterReflectionClass getBetterReflectionClass(String name) {
58+
for (BetterReflectionClass betterReflectionClass : getBetterReflectionClasses())
3159
if (betterReflectionClass.getClasz().getCanonicalName() != null && betterReflectionClass.getClasz().getCanonicalName().equals(name))
3260
return betterReflectionClass;
33-
}
3461

35-
this.betterReflectionClasses.add(new BetterReflectionClass(name));
36-
return this.betterReflectionClasses.get(this.betterReflectionClasses.size() - 1);
62+
BetterReflectionClass betterReflectionClass = BetterReflectionClass.forName(name);
63+
if (betterReflectionClass == null)
64+
return null;
65+
this.betterReflectionClasses.add(betterReflectionClass);
66+
return betterReflectionClass;
3767
}
3868

3969
public BetterReflectionClass getBetterReflectionClass(Class<?> clasz) {
40-
for (BetterReflectionClass betterReflectionClass : betterReflectionClasses) {
70+
for (BetterReflectionClass betterReflectionClass : getBetterReflectionClasses())
4171
if (betterReflectionClass.getClasz().equals(clasz))
4272
return betterReflectionClass;
43-
}
4473

45-
this.betterReflectionClasses.add(new BetterReflectionClass(clasz));
46-
return this.betterReflectionClasses.get(this.betterReflectionClasses.size() - 1);
74+
BetterReflectionClass betterReflectionClass = new BetterReflectionClass(clasz);
75+
this.betterReflectionClasses.add(betterReflectionClass);
76+
return betterReflectionClass;
4777
}
4878

4979
public static Map<Class<?>, BetterReflectionClass> getPrimitives() {
@@ -54,4 +84,90 @@ public static Object getFieldValue(BetterReflectionClass betterReflectionClass,
5484
return betterReflectionClass.getDeclaredField(fieldName).get(instance);
5585
}
5686

87+
/**
88+
* @since 0.4
89+
*/
90+
public static FutureTask<String> getLatestVersion() {
91+
return new FutureTask<String>(new Callable<String>() {
92+
@Override
93+
public String call() throws Exception {
94+
URL url = new URL("https://api.github.com/repos/OxideWaveLength/Java-BetterReflection/releases/latest");
95+
URLConnection connection = url.openConnection();
96+
InputStream in = connection.getInputStream();
97+
String encoding = connection.getContentType();
98+
encoding = encoding == null ? "UTF-8" : encoding.substring(encoding.indexOf("charset=") + 8);
99+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
100+
byte[] buf = new byte[8192];
101+
int len = 0;
102+
while ((len = in.read(buf)) != -1)
103+
baos.write(buf, 0, len);
104+
String body = new String(baos.toByteArray(), encoding);
105+
for (String line : body.split("\",")) {
106+
line = line.replace("\"", "");
107+
if (!line.startsWith("tag_name"))
108+
continue;
109+
return line.substring(line.indexOf(':') + 1);
110+
}
111+
return null;
112+
}
113+
});
114+
}
115+
116+
/**
117+
* Checks whether the current version matches (or is higher) than the latest
118+
* released version on GitHub.
119+
*
120+
* @since 0.4
121+
*/
122+
public static final FutureTask<Boolean> isUpToDate() throws IOException {
123+
return new FutureTask<Boolean>(new Callable<Boolean>() {
124+
@Override
125+
public Boolean call() throws Exception {
126+
int[] version = versionToInts(getVersion());
127+
FutureTask<String> latestVersionFuture = getLatestVersion();
128+
latestVersionFuture.run();
129+
int[] latestVersion = versionToInts(latestVersionFuture.get());
130+
int minLength = Math.min(version.length, latestVersion.length);
131+
for (int i = 0; i < Math.max(version.length, latestVersion.length); i++)
132+
if (minLength > i && version[i] > latestVersion[i])
133+
return true;
134+
return false;
135+
}
136+
});
137+
138+
}
139+
140+
/**
141+
* Returns the current version
142+
*
143+
* @since 0.4
144+
*/
145+
public static final String getVersion() {
146+
return "0.4";
147+
}
148+
149+
/**
150+
* @since 0.4
151+
*/
152+
public static final int[] versionToInts(String version) {
153+
if (version == null || version.trim().isEmpty())
154+
return new int[0];
155+
156+
int count = 1;
157+
for (int i = 0; i < version.length(); i++)
158+
if (version.charAt(i) == '.')
159+
count++;
160+
int[] numbers = new int[count];
161+
162+
for (int i = 0; i < numbers.length; i++) {
163+
boolean hasNext = version != null && version.contains(".");
164+
String number = hasNext ? version.substring(0, version.indexOf('.')) : version;
165+
version = hasNext ? version.substring(number.length() + 1) : null;
166+
if (!INTEGER_PATTERN.matcher(number).matches())
167+
continue;
168+
numbers[i] = Integer.parseInt(number);
169+
}
170+
return numbers;
171+
}
172+
57173
}

Java-BetterReflection/src/me/wavelength/betterreflection/BetterReflectionClass.java

+55-10
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,51 @@ public BetterReflectionClass(Class<?> clasz) {
3636
this.methods = clasz.getMethods();
3737
}
3838

39+
/**
40+
* @return a new instance of {@link #BetterReflectionClass(String)}, but if a
41+
* ClassNotFoundException is thrown it will return null
42+
* @since 0.4
43+
*/
44+
public static BetterReflectionClass forName(String name) {
45+
try {
46+
return new BetterReflectionClass(name);
47+
} catch (Exception e) {
48+
return null;
49+
}
50+
}
51+
3952
public Class<?> getClasz() {
4053
return clasz;
4154
}
4255

56+
/**
57+
* @since 0.4
58+
*/
59+
public String getName() {
60+
return clasz.getName();
61+
}
62+
63+
/**
64+
* @since 0.4
65+
*/
66+
public String getSimpleName() {
67+
return clasz.getSimpleName();
68+
}
69+
70+
/**
71+
* @since 0.4
72+
*/
73+
public String getCanonicalName() {
74+
return clasz.getCanonicalName();
75+
}
76+
77+
/**
78+
* @since 0.4
79+
*/
80+
public String getTypeName() {
81+
return clasz.getTypeName();
82+
}
83+
4384
public Field getDeclaredField(String name) {
4485
return BetterReflectionUtils.getField(name, declaredFields);
4586
}
@@ -62,7 +103,7 @@ public Field[] getFields() {
62103
* @return
63104
*/
64105
public Constructor<?> getDeclaredConstructor(Object... parameterTypes) {
65-
return getConstructor(BetterReflectionUtils.getClasses(parameterTypes));
106+
return getConstructor(BetterReflectionUtils.getTypes(parameterTypes));
66107
}
67108

68109
public Constructor<?> getDeclaredConstructor(Class<?>... parameterTypes) {
@@ -79,7 +120,7 @@ public Constructor<?>[] getDeclaredConstructors() {
79120
* @return
80121
*/
81122
public Constructor<?> getConstructor(Object... parameterTypes) {
82-
return getConstructor(BetterReflectionUtils.getClasses(parameterTypes));
123+
return getConstructor(BetterReflectionUtils.getTypes(parameterTypes));
83124
}
84125

85126
public Constructor<?> getConstructor(Class<?>... parameterTypes) {
@@ -96,7 +137,7 @@ public Constructor<?>[] getConstructors() {
96137
* @return
97138
*/
98139
public Method getDeclaredMethod(String name, Object... parameterTypes) {
99-
return getMethod(name, BetterReflectionUtils.getClasses(parameterTypes));
140+
return getMethod(name, BetterReflectionUtils.getTypes(parameterTypes));
100141
}
101142

102143
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) {
@@ -112,7 +153,7 @@ public Method[] getDeclaredMethods() {
112153
* instances and Classes. Nothing else!
113154
*/
114155
public Method getMethod(String name, Object... parameterTypes) {
115-
return getMethod(name, BetterReflectionUtils.getClasses(parameterTypes));
156+
return getMethod(name, BetterReflectionUtils.getTypes(parameterTypes));
116157
}
117158

118159
public Method getMethod(String name, Class<?>... parameterTypes) {
@@ -146,7 +187,7 @@ public void invokeMethods(Map<String, Object[]> methods, Object instance) throws
146187
parameters[i] = BetterReflection.getPrimitives().get(reflectionParameter.getValue().getClass()).getMethod(String.format("%sValue", reflectionParameter.getType().getName())).invoke(reflectionParameter.getValue());
147188
}
148189
}
149-
Method method = getMethod(methodName, BetterReflectionUtils.getClasses(primitives, parameters));
190+
Method method = getMethod(methodName, BetterReflectionUtils.getTypes(primitives, parameters));
150191
method.invoke(instance, parameters);
151192
}
152193
}
@@ -177,15 +218,19 @@ public Object getDeclaredFieldValue(Object instance, String fieldName) throws Il
177218
}
178219

179220
public Object invokeMethod(Object instance, String methodName, Object... parameters) throws InvocationTargetException, IllegalAccessException {
180-
return getMethod(methodName, BetterReflectionUtils.getClasses(parameters)).invoke(instance, parameters);
181-
}
182-
183-
public String getSimpleName() {
184-
return clasz.getSimpleName();
221+
return getMethod(methodName, BetterReflectionUtils.getTypes(parameters)).invoke(instance, parameters);
185222
}
186223

187224
public Class<?> getSuperclass() {
188225
return superClass;
189226
}
190227

228+
public boolean isAssignableFrom(Class<?> clasz) {
229+
return this.clasz.isAssignableFrom(clasz);
230+
}
231+
232+
public boolean isAssignableFrom(BetterReflectionClass clasz) {
233+
return isAssignableFrom(clasz.getClasz());
234+
}
235+
191236
}

0 commit comments

Comments
 (0)