com.landawn.abacus.util.ClassUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of abacus-util-se Show documentation
Show all versions of abacus-util-se Show documentation
A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.
/*
* Copyright (C) 2017 HaiYang Li
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.landawn.abacus.util;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
import java.sql.NClob;
import java.sql.RowId;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Deque;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.Stack;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.xml.datatype.XMLGregorianCalendar;
import com.landawn.abacus.DataSet;
import com.landawn.abacus.annotation.Id;
import com.landawn.abacus.annotation.Internal;
import com.landawn.abacus.annotation.ReadOnlyId;
import com.landawn.abacus.core.DirtyMarkerUtil;
import com.landawn.abacus.core.NameUtil;
import com.landawn.abacus.core.RowDataSet;
import com.landawn.abacus.exception.UncheckedIOException;
import com.landawn.abacus.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.parser.ParserUtil;
import com.landawn.abacus.parser.ParserUtil.EntityInfo;
import com.landawn.abacus.parser.ParserUtil.PropInfo;
import com.landawn.abacus.type.ObjectType;
import com.landawn.abacus.type.Type;
import com.landawn.abacus.util.Tuple.Tuple1;
import com.landawn.abacus.util.Tuple.Tuple2;
import com.landawn.abacus.util.Tuple.Tuple3;
import com.landawn.abacus.util.Tuple.Tuple4;
import com.landawn.abacus.util.Tuple.Tuple5;
import com.landawn.abacus.util.Tuple.Tuple6;
import com.landawn.abacus.util.Tuple.Tuple7;
import com.landawn.abacus.util.Tuple.Tuple8;
import com.landawn.abacus.util.Tuple.Tuple9;
import com.landawn.abacus.util.u.Nullable;
import com.landawn.abacus.util.u.Optional;
import com.landawn.abacus.util.u.OptionalBoolean;
import com.landawn.abacus.util.u.OptionalByte;
import com.landawn.abacus.util.u.OptionalChar;
import com.landawn.abacus.util.u.OptionalDouble;
import com.landawn.abacus.util.u.OptionalFloat;
import com.landawn.abacus.util.u.OptionalInt;
import com.landawn.abacus.util.u.OptionalLong;
import com.landawn.abacus.util.u.OptionalShort;
// TODO: Auto-generated Javadoc
/**
* The Class ClassUtil.
*
* @author Haiyang Li
* @since 0.9
*/
public final class ClassUtil {
/**
* Instantiates a new class util.
*/
private ClassUtil() {
// singleton
}
/** The Constant logger. */
private static final Logger logger = LoggerFactory.getLogger(ClassUtil.class);
/** The Constant JAR_POSTFIX. */
private static final String JAR_POSTFIX = ".jar";
/** The Constant CLASS_POSTFIX. */
private static final String CLASS_POSTFIX = ".class";
/** The Constant PROP_NAME_SEPARATOR. */
// ...
private static final String PROP_NAME_SEPARATOR = ".";
/** The Constant GET. */
// ...
private static final String GET = "get".intern();
/** The Constant SET. */
private static final String SET = "set".intern();
/** The Constant IS. */
private static final String IS = "is".intern();
/** The Constant HAS. */
private static final String HAS = "has".intern();
// ... it has to be big enough to make it's safety to add element to
/** The Constant POOL_SIZE. */
// ArrayBlockingQueue.
private static final int POOL_SIZE = Internals.POOL_SIZE;
/** The Constant entityClassPool. */
// ...
private static final Map, Boolean> entityClassPool = new ObjectPool<>(POOL_SIZE);
/** The Constant BUILT_IN_TYPE. */
// formalized property name list.
private static final Map> BUILT_IN_TYPE = new ObjectPool<>(POOL_SIZE); // new LinkedHashMap<>();
static {
BUILT_IN_TYPE.put(boolean.class.getCanonicalName(), boolean.class);
BUILT_IN_TYPE.put(char.class.getCanonicalName(), char.class);
BUILT_IN_TYPE.put(byte.class.getCanonicalName(), byte.class);
BUILT_IN_TYPE.put(short.class.getCanonicalName(), short.class);
BUILT_IN_TYPE.put(int.class.getCanonicalName(), int.class);
BUILT_IN_TYPE.put(long.class.getCanonicalName(), long.class);
BUILT_IN_TYPE.put(float.class.getCanonicalName(), float.class);
BUILT_IN_TYPE.put(double.class.getCanonicalName(), double.class);
BUILT_IN_TYPE.put(Boolean.class.getCanonicalName(), Boolean.class);
BUILT_IN_TYPE.put(Character.class.getCanonicalName(), Character.class);
BUILT_IN_TYPE.put(Byte.class.getCanonicalName(), Byte.class);
BUILT_IN_TYPE.put(Short.class.getCanonicalName(), Short.class);
BUILT_IN_TYPE.put(Integer.class.getCanonicalName(), Integer.class);
BUILT_IN_TYPE.put(Long.class.getCanonicalName(), Long.class);
BUILT_IN_TYPE.put(Float.class.getCanonicalName(), Float.class);
BUILT_IN_TYPE.put(Double.class.getCanonicalName(), Double.class);
BUILT_IN_TYPE.put(String.class.getCanonicalName(), String.class);
BUILT_IN_TYPE.put(Enum.class.getCanonicalName(), Enum.class);
BUILT_IN_TYPE.put(Class.class.getCanonicalName(), Class.class);
BUILT_IN_TYPE.put(Object.class.getCanonicalName(), Object.class);
BUILT_IN_TYPE.put(BigInteger.class.getCanonicalName(), BigInteger.class);
BUILT_IN_TYPE.put(BigDecimal.class.getCanonicalName(), BigDecimal.class);
BUILT_IN_TYPE.put(java.util.Date.class.getCanonicalName(), java.util.Date.class);
BUILT_IN_TYPE.put(Calendar.class.getCanonicalName(), Calendar.class);
BUILT_IN_TYPE.put(GregorianCalendar.class.getCanonicalName(), GregorianCalendar.class);
BUILT_IN_TYPE.put(XMLGregorianCalendar.class.getCanonicalName(), XMLGregorianCalendar.class);
BUILT_IN_TYPE.put(Collection.class.getCanonicalName(), Collection.class);
BUILT_IN_TYPE.put(List.class.getCanonicalName(), List.class);
BUILT_IN_TYPE.put(ArrayList.class.getCanonicalName(), ArrayList.class);
BUILT_IN_TYPE.put(LinkedList.class.getCanonicalName(), LinkedList.class);
BUILT_IN_TYPE.put(Stack.class.getCanonicalName(), Stack.class);
BUILT_IN_TYPE.put(Vector.class.getCanonicalName(), Vector.class);
BUILT_IN_TYPE.put(Set.class.getCanonicalName(), Set.class);
BUILT_IN_TYPE.put(HashSet.class.getCanonicalName(), HashSet.class);
BUILT_IN_TYPE.put(LinkedHashSet.class.getCanonicalName(), LinkedHashSet.class);
BUILT_IN_TYPE.put(SortedSet.class.getCanonicalName(), SortedSet.class);
BUILT_IN_TYPE.put(NavigableSet.class.getCanonicalName(), NavigableSet.class);
BUILT_IN_TYPE.put(TreeSet.class.getCanonicalName(), TreeSet.class);
BUILT_IN_TYPE.put(Queue.class.getCanonicalName(), Queue.class);
BUILT_IN_TYPE.put(Deque.class.getCanonicalName(), Deque.class);
BUILT_IN_TYPE.put(BlockingDeque.class.getCanonicalName(), BlockingDeque.class);
BUILT_IN_TYPE.put(ArrayDeque.class.getCanonicalName(), ArrayDeque.class);
BUILT_IN_TYPE.put(ArrayBlockingQueue.class.getCanonicalName(), ArrayBlockingQueue.class);
BUILT_IN_TYPE.put(LinkedBlockingQueue.class.getCanonicalName(), LinkedBlockingQueue.class);
BUILT_IN_TYPE.put(ConcurrentLinkedQueue.class.getCanonicalName(), ConcurrentLinkedQueue.class);
BUILT_IN_TYPE.put(LinkedBlockingDeque.class.getCanonicalName(), LinkedBlockingDeque.class);
BUILT_IN_TYPE.put(ConcurrentLinkedDeque.class.getCanonicalName(), ConcurrentLinkedDeque.class);
BUILT_IN_TYPE.put(PriorityQueue.class.getCanonicalName(), PriorityQueue.class);
BUILT_IN_TYPE.put(DelayQueue.class.getCanonicalName(), DelayQueue.class);
BUILT_IN_TYPE.put(Map.class.getCanonicalName(), Map.class);
BUILT_IN_TYPE.put(HashMap.class.getCanonicalName(), HashMap.class);
BUILT_IN_TYPE.put(LinkedHashMap.class.getCanonicalName(), LinkedHashMap.class);
BUILT_IN_TYPE.put(IdentityHashMap.class.getCanonicalName(), IdentityHashMap.class);
BUILT_IN_TYPE.put(ConcurrentMap.class.getCanonicalName(), ConcurrentMap.class);
BUILT_IN_TYPE.put(ConcurrentHashMap.class.getCanonicalName(), ConcurrentHashMap.class);
BUILT_IN_TYPE.put(SortedMap.class.getCanonicalName(), SortedMap.class);
BUILT_IN_TYPE.put(NavigableMap.class.getCanonicalName(), NavigableMap.class);
BUILT_IN_TYPE.put(TreeMap.class.getCanonicalName(), TreeMap.class);
BUILT_IN_TYPE.put(Iterator.class.getCanonicalName(), Iterator.class);
BUILT_IN_TYPE.put(File.class.getCanonicalName(), File.class);
BUILT_IN_TYPE.put(InputStream.class.getCanonicalName(), InputStream.class);
BUILT_IN_TYPE.put(ByteArrayInputStream.class.getCanonicalName(), ByteArrayInputStream.class);
BUILT_IN_TYPE.put(FileInputStream.class.getCanonicalName(), FileInputStream.class);
BUILT_IN_TYPE.put(OutputStream.class.getCanonicalName(), OutputStream.class);
BUILT_IN_TYPE.put(ByteArrayOutputStream.class.getCanonicalName(), ByteArrayOutputStream.class);
BUILT_IN_TYPE.put(FileOutputStream.class.getCanonicalName(), FileOutputStream.class);
BUILT_IN_TYPE.put(Reader.class.getCanonicalName(), Reader.class);
BUILT_IN_TYPE.put(StringReader.class.getCanonicalName(), StringReader.class);
BUILT_IN_TYPE.put(FileReader.class.getCanonicalName(), FileReader.class);
BUILT_IN_TYPE.put(InputStreamReader.class.getCanonicalName(), InputStreamReader.class);
BUILT_IN_TYPE.put(Writer.class.getCanonicalName(), Writer.class);
BUILT_IN_TYPE.put(StringWriter.class.getCanonicalName(), StringWriter.class);
BUILT_IN_TYPE.put(FileWriter.class.getCanonicalName(), FileWriter.class);
BUILT_IN_TYPE.put(OutputStreamWriter.class.getCanonicalName(), OutputStreamWriter.class);
BUILT_IN_TYPE.put(Date.class.getCanonicalName(), Date.class);
BUILT_IN_TYPE.put(Time.class.getCanonicalName(), Time.class);
BUILT_IN_TYPE.put(Timestamp.class.getCanonicalName(), Timestamp.class);
BUILT_IN_TYPE.put(Blob.class.getCanonicalName(), Blob.class);
BUILT_IN_TYPE.put(Clob.class.getCanonicalName(), Clob.class);
BUILT_IN_TYPE.put(NClob.class.getCanonicalName(), NClob.class);
BUILT_IN_TYPE.put(SQLXML.class.getCanonicalName(), SQLXML.class);
BUILT_IN_TYPE.put(RowId.class.getCanonicalName(), RowId.class);
BUILT_IN_TYPE.put(URL.class.getCanonicalName(), URL.class);
BUILT_IN_TYPE.put(MutableBoolean.class.getCanonicalName(), MutableBoolean.class);
BUILT_IN_TYPE.put(MutableChar.class.getCanonicalName(), MutableChar.class);
BUILT_IN_TYPE.put(MutableByte.class.getCanonicalName(), MutableByte.class);
BUILT_IN_TYPE.put(MutableShort.class.getCanonicalName(), MutableShort.class);
BUILT_IN_TYPE.put(MutableInt.class.getCanonicalName(), MutableInt.class);
BUILT_IN_TYPE.put(MutableLong.class.getCanonicalName(), MutableLong.class);
BUILT_IN_TYPE.put(MutableFloat.class.getCanonicalName(), MutableFloat.class);
BUILT_IN_TYPE.put(MutableDouble.class.getCanonicalName(), MutableDouble.class);
BUILT_IN_TYPE.put(OptionalBoolean.class.getCanonicalName(), OptionalBoolean.class);
BUILT_IN_TYPE.put(OptionalChar.class.getCanonicalName(), OptionalChar.class);
BUILT_IN_TYPE.put(OptionalByte.class.getCanonicalName(), OptionalByte.class);
BUILT_IN_TYPE.put(OptionalShort.class.getCanonicalName(), OptionalShort.class);
BUILT_IN_TYPE.put(OptionalInt.class.getCanonicalName(), OptionalInt.class);
BUILT_IN_TYPE.put(OptionalLong.class.getCanonicalName(), OptionalLong.class);
BUILT_IN_TYPE.put(OptionalFloat.class.getCanonicalName(), OptionalFloat.class);
BUILT_IN_TYPE.put(OptionalDouble.class.getCanonicalName(), OptionalDouble.class);
BUILT_IN_TYPE.put(Optional.class.getCanonicalName(), Optional.class);
BUILT_IN_TYPE.put(Nullable.class.getCanonicalName(), Nullable.class);
BUILT_IN_TYPE.put(Fraction.class.getCanonicalName(), Fraction.class);
BUILT_IN_TYPE.put(Range.class.getCanonicalName(), Range.class);
BUILT_IN_TYPE.put(Duration.class.getCanonicalName(), Duration.class);
BUILT_IN_TYPE.put(Pair.class.getCanonicalName(), Pair.class);
BUILT_IN_TYPE.put(Triple.class.getCanonicalName(), Triple.class);
BUILT_IN_TYPE.put(Tuple.class.getCanonicalName(), Tuple.class);
BUILT_IN_TYPE.put(Tuple1.class.getCanonicalName(), Tuple1.class);
BUILT_IN_TYPE.put(Tuple2.class.getCanonicalName(), Tuple2.class);
BUILT_IN_TYPE.put(Tuple3.class.getCanonicalName(), Tuple3.class);
BUILT_IN_TYPE.put(Tuple4.class.getCanonicalName(), Tuple4.class);
BUILT_IN_TYPE.put(Tuple5.class.getCanonicalName(), Tuple5.class);
BUILT_IN_TYPE.put(Tuple6.class.getCanonicalName(), Tuple6.class);
BUILT_IN_TYPE.put(Tuple7.class.getCanonicalName(), Tuple7.class);
BUILT_IN_TYPE.put(Tuple8.class.getCanonicalName(), Tuple8.class);
BUILT_IN_TYPE.put(Tuple9.class.getCanonicalName(), Tuple9.class);
BUILT_IN_TYPE.put(ArrayHashMap.class.getCanonicalName(), ArrayHashMap.class);
BUILT_IN_TYPE.put(LinkedArrayHashMap.class.getCanonicalName(), LinkedArrayHashMap.class);
BUILT_IN_TYPE.put(ArrayHashSet.class.getCanonicalName(), ArrayHashSet.class);
BUILT_IN_TYPE.put(LinkedArrayHashSet.class.getCanonicalName(), LinkedArrayHashSet.class);
BUILT_IN_TYPE.put(BiMap.class.getCanonicalName(), BiMap.class);
BUILT_IN_TYPE.put(ListMultimap.class.getCanonicalName(), ListMultimap.class);
BUILT_IN_TYPE.put(SetMultimap.class.getCanonicalName(), SetMultimap.class);
BUILT_IN_TYPE.put(Multimap.class.getCanonicalName(), Multimap.class);
BUILT_IN_TYPE.put(Multiset.class.getCanonicalName(), Multiset.class);
BUILT_IN_TYPE.put(Type.class.getCanonicalName(), Type.class);
BUILT_IN_TYPE.put(DataSet.class.getCanonicalName(), DataSet.class);
BUILT_IN_TYPE.put(RowDataSet.class.getCanonicalName(), RowDataSet.class);
//
BUILT_IN_TYPE.put(Map.Entry.class.getCanonicalName(), Map.Entry.class);
BUILT_IN_TYPE.put("java.util.Map.Entry", Map.Entry.class);
BUILT_IN_TYPE.put("Map.Entry", Map.Entry.class);
List> classes = new ArrayList<>(BUILT_IN_TYPE.values());
for (Class> cls : classes) {
Class> arrayClass = cls;
for (int i = 0; i < 7; i++) {
arrayClass = java.lang.reflect.Array.newInstance(arrayClass, 0).getClass();
BUILT_IN_TYPE.put(arrayClass.getCanonicalName(), arrayClass);
}
}
classes = new ArrayList<>(BUILT_IN_TYPE.values());
for (Class> cls : classes) {
if (cls.getCanonicalName().startsWith("java.util.Date")) {
continue;
}
BUILT_IN_TYPE.put(cls.getSimpleName(), cls);
}
//
// N.println("#########################################Builtin types================================");
// N.println("size = " + BUILT_IN_TYPE.size());
//
// for (Map.Entry> entry : BUILT_IN_TYPE.entrySet()) {
// N.println(entry.getKey() + " = " + entry.getValue());
// }
}
/** The symbol of primitive array class name. */
private static Map SYMBOL_OF_PRIMITIVE_ARRAY_CLASS_NAME = new HashMap<>();
static {
SYMBOL_OF_PRIMITIVE_ARRAY_CLASS_NAME.put(boolean.class.getName(), "Z");
SYMBOL_OF_PRIMITIVE_ARRAY_CLASS_NAME.put(char.class.getName(), "C");
SYMBOL_OF_PRIMITIVE_ARRAY_CLASS_NAME.put(byte.class.getName(), "B");
SYMBOL_OF_PRIMITIVE_ARRAY_CLASS_NAME.put(short.class.getName(), "S");
SYMBOL_OF_PRIMITIVE_ARRAY_CLASS_NAME.put(int.class.getName(), "I");
SYMBOL_OF_PRIMITIVE_ARRAY_CLASS_NAME.put(long.class.getName(), "J");
SYMBOL_OF_PRIMITIVE_ARRAY_CLASS_NAME.put(float.class.getName(), "F");
SYMBOL_OF_PRIMITIVE_ARRAY_CLASS_NAME.put(double.class.getName(), "D");
}
/** The Constant camelCasePropNamePool. */
private static final Map camelCasePropNamePool = new ObjectPool<>(POOL_SIZE * 2);
/** The Constant lowerCaseWithUnderscorePropNamePool. */
private static final Map lowerCaseWithUnderscorePropNamePool = new ObjectPool<>(POOL_SIZE * 2);
/** The Constant upperCaseWithUnderscorePropNamePool. */
private static final Map upperCaseWithUnderscorePropNamePool = new ObjectPool<>(POOL_SIZE * 2);
/** The Constant registeredXMLBindingClassList. */
private static final Map, Boolean> registeredXMLBindingClassList = new ObjectPool<>(POOL_SIZE);
/** The Constant registeredNonPropGetSetMethodPool. */
private static final Map, Set> registeredNonPropGetSetMethodPool = new ObjectPool<>(POOL_SIZE);
/** The Constant entityDeclaredPropNameListPool. */
private static final Map, ImmutableList> entityDeclaredPropNameListPool = new ObjectPool<>(POOL_SIZE);
/** The Constant entityPropFieldPool. */
private static final Map, ImmutableMap> entityDeclaredPropFieldPool = new ObjectPool<>(POOL_SIZE);
/** The Constant entityPropFieldPool. */
private static final Map, Map> entityPropFieldPool = new ObjectPool<>(POOL_SIZE);
/** The Constant entityDeclaredPropGetMethodPool. */
private static final Map, ImmutableMap> entityDeclaredPropGetMethodPool = new ObjectPool<>(POOL_SIZE);
/** The Constant entityDeclaredPropSetMethodPool. */
private static final Map, ImmutableMap> entityDeclaredPropSetMethodPool = new ObjectPool<>(POOL_SIZE);
/** The Constant entityPropGetMethodPool. */
private static final Map, Map> entityPropGetMethodPool = new ObjectPool<>(POOL_SIZE);
/** The Constant entityPropSetMethodPool. */
private static final Map, Map> entityPropSetMethodPool = new ObjectPool<>(POOL_SIZE);
/** The Constant entityInlinePropGetMethodPool. */
private static final Map, Map>> entityInlinePropGetMethodPool = new ObjectPool<>(POOL_SIZE);
/** The Constant entityInlinePropSetMethodPool. */
private static final Map, Map>> entityInlinePropSetMethodPool = new ObjectPool<>(POOL_SIZE);
/** The Constant formalizedPropNamePool. */
// ...
private static final Map formalizedPropNamePool = new ObjectPool<>(POOL_SIZE * 2);
/** The Constant methodPropNamePool. */
private static final Map methodPropNamePool = new ObjectPool<>(POOL_SIZE * 2);
/** The Constant fieldTypeArgumentsPool. */
private static final Map[]> fieldTypeArgumentsPool = new ObjectPool<>(POOL_SIZE * 2);
/** The Constant methodTypeArgumentsPool. */
private static final Map[]> methodTypeArgumentsPool = new ObjectPool<>(POOL_SIZE * 2);
/** The Constant fieldParameterizedTypeNamePool. */
private static final Map fieldParameterizedTypeNamePool = new ObjectPool<>(POOL_SIZE * 2);
/** The Constant methodParameterizedTypeNamePool. */
private static final Map methodParameterizedTypeNamePool = new ObjectPool<>(POOL_SIZE * 2);
/** The Constant keyWordMapper. */
// reserved words.
private static final Map keyWordMapper = new HashMap<>(16);
static {
keyWordMapper.put("class", "clazz");
}
/** The Constant nonGetMethodName. */
private static final Set nonGetSetMethodName = N.newHashSet(16);
static {
nonGetSetMethodName.add("getClass");
nonGetSetMethodName.add("hashCode");
}
/** The Constant packagePool. */
private static final Map, Package> packagePool = new ObjectPool<>(POOL_SIZE);
/** The Constant packageNamePool. */
private static final Map, String> packageNamePool = new ObjectPool<>(POOL_SIZE);
/** The Constant clsNamePool. */
private static final Map> clsNamePool = new ObjectPool<>(POOL_SIZE);
/** The Constant simpleClassNamePool. */
private static final Map, String> simpleClassNamePool = new ObjectPool<>(POOL_SIZE);
/** The Constant nameClassPool. */
private static final Map, String> nameClassPool = new ObjectPool<>(POOL_SIZE);
/** The Constant canonicalClassNamePool. */
private static final Map, String> canonicalClassNamePool = new ObjectPool<>(POOL_SIZE);
/** The Constant enclosingClassPool. */
private static final Map, Class>> enclosingClassPool = new ObjectPool<>(POOL_SIZE);
/** The Constant classDeclaredConstructorPool. */
private static final Map, Map[], Constructor>>> classDeclaredConstructorPool = new ObjectPool<>(POOL_SIZE);
/** The Constant classDeclaredMethodPool. */
private static final Map, Map[], Method>>> classDeclaredMethodPool = new ObjectPool<>(POOL_SIZE);
/** The Constant registeredNonEntityClass. */
private static final Map, Class>> registeredNonEntityClass = new ObjectPool<>(POOL_SIZE);
static {
registeredNonEntityClass.put(Object.class, Object.class);
registeredNonEntityClass.put(Class.class, Class.class);
registeredNonEntityClass.put(Calendar.class, Calendar.class);
registeredNonEntityClass.put(java.util.Date.class, java.util.Date.class);
registeredNonEntityClass.put(java.sql.Date.class, java.sql.Date.class);
registeredNonEntityClass.put(java.sql.Time.class, java.sql.Time.class);
registeredNonEntityClass.put(java.sql.Timestamp.class, java.sql.Timestamp.class);
}
/**
* The Constant CLASS_MASK.
*
* @deprecated for internal only.
*/
@Deprecated
@Internal
public static final Class> CLASS_MASK = ClassMask.class;
/**
* The Constant METHOD_MASK.
*
* @deprecated for internal only.
*/
@Deprecated
@Internal
public static final Method METHOD_MASK = ClassUtil.internalGetDeclaredMethod(ClassMask.class, "methodMask");
/**
* The Constant FIELD_MASK.
*
* @deprecated for internal only.
*/
@Deprecated
@Internal
public static final Field FIELD_MASK;
static {
try {
FIELD_MASK = ClassMask.class.getDeclaredField(ClassMask.FIELD_MASK);
} catch (Exception e) {
throw N.toRuntimeException(e);
}
}
/**
* The property maybe only has get method if its type is collection or map by xml binding specification
* Otherwise, it will be ignored if not registered by calling this method.
*
* @param cls
*/
@SuppressWarnings("deprecation")
public static void registerXMLBindingClass(final Class> cls) {
if (registeredXMLBindingClassList.containsKey(cls)) {
return;
}
synchronized (entityDeclaredPropGetMethodPool) {
registeredXMLBindingClassList.put(cls, false);
if (entityDeclaredPropGetMethodPool.containsKey(cls)) {
entityDeclaredPropGetMethodPool.remove(cls);
entityDeclaredPropSetMethodPool.remove(cls);
entityPropFieldPool.remove(cls);
loadPropGetSetMethodList(cls);
}
ParserUtil.refreshEntityPropInfo(cls);
}
}
/**
* Register non entity class.
*
* @param cls
*/
@SuppressWarnings("deprecation")
public static void registerNonEntityClass(final Class> cls) {
registeredNonEntityClass.put(cls, cls);
synchronized (entityDeclaredPropGetMethodPool) {
registeredXMLBindingClassList.put(cls, false);
if (entityDeclaredPropGetMethodPool.containsKey(cls)) {
entityDeclaredPropGetMethodPool.remove(cls);
entityDeclaredPropSetMethodPool.remove(cls);
entityPropFieldPool.remove(cls);
loadPropGetSetMethodList(cls);
}
ParserUtil.refreshEntityPropInfo(cls);
}
}
/**
* Register non prop get set method.
*
* @param cls
* @param propName
*/
public static void registerNonPropGetSetMethod(final Class> cls, final String propName) {
Set set = registeredNonPropGetSetMethodPool.get(cls);
if (set == null) {
synchronized (registeredNonPropGetSetMethodPool) {
set = registeredNonPropGetSetMethodPool.get(cls);
if (set == null) {
set = N.newHashSet();
registeredNonPropGetSetMethodPool.put(cls, set);
}
}
}
set.add(propName);
}
/**
* Register prop get set method.
*
* @param propName
* @param method
*/
public static void registerPropGetSetMethod(final String propName, final Method method) {
Class> cls = method.getDeclaringClass();
synchronized (entityDeclaredPropGetMethodPool) {
if (isGetMethod(method)) {
Map propMethodMap = entityPropGetMethodPool.get(cls);
if (propMethodMap == null) {
loadPropGetSetMethodList(cls);
propMethodMap = entityPropGetMethodPool.get(cls);
}
if (propMethodMap.containsKey(propName)) {
if (method.equals(propMethodMap.get(propName)) == false) {
throw new IllegalArgumentException(
propName + " has already been regiestered with different method: " + propMethodMap.get(propName).getName());
}
} else {
propMethodMap.put(propName, method);
}
} else if (isSetMethod(method)) {
Map propMethodMap = entityPropSetMethodPool.get(cls);
if (propMethodMap == null) {
loadPropGetSetMethodList(cls);
propMethodMap = entityPropSetMethodPool.get(cls);
}
if (propMethodMap.containsKey(propName)) {
if (method.equals(propMethodMap.get(propName)) == false) {
throw new IllegalArgumentException(
propName + " has already been regiestered with different method: " + propMethodMap.get(propName).getName());
}
} else {
propMethodMap.put(propName, method);
}
} else {
throw new IllegalArgumentException("The name of property getter/setter method must start with 'get/is/has' or 'set': " + method.getName());
}
}
}
/**
* Checks if is entity.
*
* @param cls
* @return true, if is entity
*/
public static boolean isEntity(final Class> cls) {
Boolean b = entityClassPool.get(cls);
if (b == null) {
b = !registeredNonEntityClass.containsKey(cls) && N.notNullOrEmpty(ClassUtil.getPropNameList(cls));
entityClassPool.put(cls, b);
}
return b;
}
/**
*
* @param cls
* @return
*/
public static boolean isDirtyMarker(final Class> cls) {
return DirtyMarkerUtil.isDirtyMarker(cls);
}
/**
* Supports primitive types: boolean, char, byte, short, int, long, float, double. And array type with format {@code java.lang.String[]}
*
* @param
* @param clsName
* @return
* @throws IllegalArgumentException if class not found.
*/
@SuppressWarnings("unchecked")
public static Class forClass(final String clsName) throws IllegalArgumentException {
return (Class) forClass(clsName, true);
}
/**
* Supports primitive types: boolean, char, byte, short, int, long, float, double. And array type with format {@code java.lang.String[]}
*
* @param
* @param clsName
* @param cacheResult
* @return
* @throws IllegalArgumentException if class not found.
*/
@SuppressWarnings("unchecked")
static Class forClass(final String clsName, final boolean cacheResult) throws IllegalArgumentException {
Class> cls = clsNamePool.get(clsName);
if (cls == null) {
cls = BUILT_IN_TYPE.get(clsName);
if (cls == null) {
try {
cls = Class.forName(clsName);
} catch (ClassNotFoundException e) {
String newClassName = clsName;
if (newClassName.indexOf(WD._PERIOD) < 0) {
int index = newClassName.indexOf("[]");
if (((index < 0) && !SYMBOL_OF_PRIMITIVE_ARRAY_CLASS_NAME.containsKey(newClassName))
|| ((index > 0) && !SYMBOL_OF_PRIMITIVE_ARRAY_CLASS_NAME.containsKey(newClassName.substring(0, index)))) {
newClassName = "java.lang." + newClassName;
try {
cls = Class.forName(newClassName);
BUILT_IN_TYPE.put(clsName, cls);
} catch (ClassNotFoundException e1) {
// ignore.
}
}
}
if (cls == null) {
newClassName = clsName;
int index = newClassName.indexOf("[]");
if (index > 0) {
String componentTypeName = newClassName.substring(0, index);
String temp = newClassName.replaceAll("\\[\\]", "");
if (componentTypeName.equals(temp)) {
int dimensions = (newClassName.length() - temp.length()) / 2;
String prefixOfArray = "";
while (dimensions-- > 0) {
prefixOfArray += "[";
}
String symbolOfPrimitiveArraryClassName = SYMBOL_OF_PRIMITIVE_ARRAY_CLASS_NAME.get(componentTypeName);
if (symbolOfPrimitiveArraryClassName != null) {
try {
cls = Class.forName(prefixOfArray + symbolOfPrimitiveArraryClassName);
BUILT_IN_TYPE.put(clsName, cls);
} catch (ClassNotFoundException e2) {
// ignore.
}
} else {
try {
final Type> componentType = N.typeOf(componentTypeName);
if (componentType.clazz().equals(Object.class) && !componentType.name().equals(ObjectType.OBJECT)) {
throw new IllegalArgumentException("No Class found by name: " + clsName);
}
cls = Class.forName(prefixOfArray + "L" + componentType.clazz().getCanonicalName() + ";");
} catch (ClassNotFoundException e3) {
// ignore.
}
}
}
}
if (cls == null) {
newClassName = clsName;
int lastIndex = -1;
while ((lastIndex = newClassName.lastIndexOf(WD._PERIOD)) > 0) {
newClassName = newClassName.substring(0, lastIndex) + "$" + newClassName.substring(lastIndex + 1);
try {
cls = Class.forName(newClassName);
break;
} catch (ClassNotFoundException e3) {
// ignore.
}
}
}
}
}
}
if (cls == null) {
throw new IllegalArgumentException("No class found by name: " + clsName);
}
if (cacheResult) {
clsNamePool.put(clsName, cls);
}
}
return (Class) cls;
}
// Superclasses/Superinterfaces. Copied from Apache Commons Lang under Apache License v2.
// ----------------------------------------------------------------------
/**
* Copied from Apache Commons Lang under Apache License v2.
*
* Gets a {@code List} of super classes for the given class, excluding {@code Object.class}.
*
cls the class to look up.
* @return
*/
public static List> getAllSuperclasses(final Class> cls) {
final List> classes = new ArrayList<>();
Class> superclass = cls.getSuperclass();
while (superclass != null && !superclass.equals(Object.class)) {
classes.add(superclass);
superclass = superclass.getSuperclass();
}
return classes;
}
/**
* Copied from Apache Commons Lang under Apache License v2.
*
* Gets a {@code List} of all interfaces implemented by the given
* class and its super classes.
*
* The order is determined by looking through each interface in turn as
* declared in the source file and following its hierarchy up. Then each
* superclass is considered in the same way. Later duplicates are ignored,
* so the order is maintained.
*
cls the class to look up.
* @return
*/
public static Set> getAllInterfaces(final Class> cls) {
final Set> interfacesFound = N.newLinkedHashSet();
getAllInterfaces(cls, interfacesFound);
return interfacesFound;
}
/**
* Gets the all interfaces.
*
* @param cls
* @param interfacesFound
* @return
*/
private static void getAllInterfaces(Class> cls, final Set> interfacesFound) {
while (cls != null) {
final Class>[] interfaces = cls.getInterfaces();
for (final Class> i : interfaces) {
if (interfacesFound.add(i)) {
getAllInterfaces(i, interfacesFound);
}
}
cls = cls.getSuperclass();
}
}
/**
* Returns all the interfaces and super classes the specified class implements or extends, excluding {@code Object.class}.
*
* @param cls
* @return
*/
public static Set> getAllSuperTypes(final Class> cls) {
final Set> superTypesFound = N.newLinkedHashSet();
getAllSuperTypes(cls, superTypesFound);
return superTypesFound;
}
/**
* Gets the all super types.
*
* @param cls
* @param superTypesFound
* @return
*/
private static void getAllSuperTypes(Class> cls, final Set> superTypesFound) {
while (cls != null) {
final Class>[] interfaces = cls.getInterfaces();
for (final Class> i : interfaces) {
if (superTypesFound.add(i)) {
getAllInterfaces(i, superTypesFound);
}
}
Class> superclass = cls.getSuperclass();
if (superclass != null && !superclass.equals(Object.class) && superTypesFound.add(superclass)) {
getAllSuperTypes(superclass, superTypesFound);
}
cls = cls.getSuperclass();
}
}
/**
* Gets the parameterized type name by method.
*
* @param field
* @return
*/
public static String getParameterizedTypeNameByField(final Field field) {
String parameterizedTypeName = fieldParameterizedTypeNamePool.get(field);
if (parameterizedTypeName == null) {
parameterizedTypeName = formatParameterizedTypeName((field.getGenericType()).toString());
fieldParameterizedTypeNamePool.put(field, parameterizedTypeName);
}
return parameterizedTypeName;
}
/**
* Gets the parameterized type name by method.
*
* @param method
* @return
*/
public static String getParameterizedTypeNameByMethod(final Method method) {
String parameterizedTypeName = methodParameterizedTypeNamePool.get(method);
if (parameterizedTypeName == null) {
parameterizedTypeName = formatParameterizedTypeName(
(N.isNullOrEmpty(method.getGenericParameterTypes()) ? method.getGenericReturnType() : method.getGenericParameterTypes()[0]).toString());
methodParameterizedTypeNamePool.put(method, parameterizedTypeName);
}
return parameterizedTypeName;
}
/**
* Format parameterized type name.
*
* @param parameterizedTypeName
* @return
*/
static String formatParameterizedTypeName(final String parameterizedTypeName) {
String res = parameterizedTypeName.replaceAll("java.lang.", "").replaceAll("class ", "");
final int idx = res.lastIndexOf('$');
if (idx > 0) {
final StringBuilder sb = new StringBuilder();
for (int len = res.length(), i = len - 1; i >= 0; i--) {
char ch = res.charAt(i);
sb.append(ch);
if (ch == '$') {
int j = i;
char x = 0;
while (--i >= 0 && (Character.isLetterOrDigit(x = res.charAt(i)) || x == '_' || x == '.')) {
}
final String tmp = res.substring(i + 1, j);
if (tmp.substring(0, tmp.length() / 2).equals(tmp.substring(tmp.length() / 2 + 1))) {
sb.append(StringUtil.reverse(tmp.substring(0, tmp.length() / 2)));
} else {
sb.append(StringUtil.reverse(tmp));
}
i++;
}
}
res = sb.reverse().toString();
}
return res;
}
/**
* Gets the type arguments by method.
*
* @param method
* @return
*/
public static Class>[] getTypeArgumentsByField(final Field field) {
Class>[] typeParameterClasses = fieldTypeArgumentsPool.get(field);
if (typeParameterClasses == null) {
final java.lang.reflect.Type genericParameterType = field.getGenericType();
typeParameterClasses = getTypeArguments(genericParameterType);
fieldTypeArgumentsPool.put(field, typeParameterClasses);
}
return typeParameterClasses.length == 0 ? typeParameterClasses : typeParameterClasses.clone();
}
/**
* Gets the type arguments by method.
*
* @param method
* @return
*/
public static Class>[] getTypeArgumentsByMethod(final Method method) {
Class>[] typeParameterClasses = methodTypeArgumentsPool.get(method);
if (typeParameterClasses == null) {
final java.lang.reflect.Type genericParameterType = N.isNullOrEmpty(method.getGenericParameterTypes()) ? method.getGenericReturnType()
: method.getGenericParameterTypes()[0];
typeParameterClasses = getTypeArguments(genericParameterType);
methodTypeArgumentsPool.put(method, typeParameterClasses);
}
return typeParameterClasses.length == 0 ? typeParameterClasses : typeParameterClasses.clone();
}
public static Class>[] getTypeArguments(java.lang.reflect.Type genericParameterType) {
if (genericParameterType instanceof ParameterizedType) {
final ParameterizedType aType = (ParameterizedType) genericParameterType;
final java.lang.reflect.Type[] parameterArgTypes = aType.getActualTypeArguments();
final Class>[] typeParameterClasses = new Class[parameterArgTypes.length];
for (int i = 0; i < parameterArgTypes.length; i++) {
if (parameterArgTypes[i] instanceof Class) {
typeParameterClasses[i] = (Class>) parameterArgTypes[i];
} else if (parameterArgTypes[i] instanceof ParameterizedType && ((ParameterizedType) parameterArgTypes[i]).getRawType() instanceof Class) {
typeParameterClasses[i] = (Class>) ((ParameterizedType) parameterArgTypes[i]).getRawType();
} else {
return new Class>[0];
}
}
return typeParameterClasses;
} else {
return new Class>[0];
}
}
/**
* Gets the package.
*
* @param cls
* @return null
if it's primitive type or no package defined for the class.
*/
public static Package getPackage(final Class> cls) {
Package pkg = packagePool.get(cls);
if (pkg == null) {
if (Primitives.isPrimitiveType(cls)) {
return null;
}
pkg = cls.getPackage();
if (pkg != null) {
packagePool.put(cls, pkg);
}
}
return pkg;
}
/**
* Gets the package name.
*
* @param cls
* @return null
if it's primitive type or no package defined for the class.
*/
public static String getPackageName(final Class> cls) {
String pkgName = packageNamePool.get(cls);
if (pkgName == null) {
Package pkg = ClassUtil.getPackage(cls);
pkgName = pkg == null ? "" : pkg.getName();
packageNamePool.put(cls, pkgName);
}
return pkgName;
}
// private static Class[] getTypeArguments(Class cls) {
// java.lang.reflect.Type[] typeArgs = null;
// java.lang.reflect.Type[] genericInterfaces = cls.getGenericInterfaces();
//
// if (notNullOrEmpty(genericInterfaces)) {
// for (java.lang.reflect.Type type : genericInterfaces) {
// typeArgs = ((ParameterizedType) type).getActualTypeArguments();
//
// if (notNullOrEmpty(typeArgs)) {
// break;
// }
// }
// } else {
// java.lang.reflect.Type genericSuperclass = cls.getGenericSuperclass();
//
// if (genericSuperclass != null) {
// typeArgs = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
// }
// }
//
// if (notNullOrEmpty(typeArgs)) {
// Class[] clses = new Class[typeArgs.length];
//
// for (int i = 0; i < typeArgs.length; i++) {
// clses[i] = (Class) typeArgs[i];
// }
//
// return clses;
// } else {
// return null;
// }
// }
// /**
// * Returns the method declared in the specified {@code cls} with the specified method name.
// *
// * @param cls
// * @param methodName is case insensitive
// * @return {@code null} if no method is found by specified name
// */
// public static Method findDeclaredMethodByName(Class> cls, String methodName) {
// Method method = null;
//
// Method[] methods = cls.getDeclaredMethods();
//
// for (Method m : methods) {
// if (m.getName().equalsIgnoreCase(methodName)) {
// if ((method == null) || Modifier.isPublic(m.getModifiers())
// || (Modifier.isProtected(m.getModifiers()) && (!Modifier.isProtected(method.getModifiers())))
// || (!Modifier.isPrivate(m.getModifiers()) && Modifier.isPrivate(method.getModifiers()))) {
//
// method = m;
// }
//
// if (Modifier.isPublic(method.getModifiers())) {
// break;
// }
// }
// }
//
// // SHOULD NOT set it true here.
// // if (method != null) {
// // ClassUtil.setAccessible(method, true);
// // }
//
// return method;
// }
/**
* Gets the classes by package.
*
* @param pkgName
* @param isRecursive
* @param skipClassLoaddingException
* @return
* @throws UncheckedIOException the unchecked IO exception
*/
public static List> getClassesByPackage(String pkgName, boolean isRecursive, boolean skipClassLoaddingException) throws UncheckedIOException {
return getClassesByPackage(pkgName, isRecursive, skipClassLoaddingException, Fn.alwaysTrue());
}
/**
* Gets the classes by package.
*
* @param
* @param pkgName
* @param isRecursive
* @param skipClassLoaddingException
* @param predicate
* @return
* @throws UncheckedIOException the unchecked IO exception
* @throws E the e
*/
public static List> getClassesByPackage(String pkgName, boolean isRecursive, boolean skipClassLoaddingException,
Throwables.Predicate super Class>, E> predicate) throws UncheckedIOException, E {
if (logger.isInfoEnabled()) {
logger.info("Looking for classes in package: " + pkgName);
}
String pkgPath = packageName2FilePath(pkgName);
List resourceList = getResources(pkgName);
if (N.isNullOrEmpty(resourceList)) {
throw new IllegalArgumentException("No resource found by package " + pkgName);
}
List> classes = new ArrayList<>();
for (URL resource : resourceList) {
// Get a File object for the package
String fullPath = resource.getPath().replace("%20", " ").replaceFirst("[.]jar[!].*", JAR_POSTFIX).replaceFirst("file:", "");
if (logger.isInfoEnabled()) {
logger.info("ClassDiscovery: FullPath = " + fullPath);
}
File file = new File(fullPath);
if (file.exists() && file.isDirectory()) {
// Get the list of the files contained in the package
File[] files = file.listFiles();
if (N.isNullOrEmpty(files)) {
continue;
}
for (int i = 0; i < files.length; i++) {
if (files[i] == null) {
continue;
}
// we are only interested in .class files
if (files[i].isFile() && files[i].getName().endsWith(CLASS_POSTFIX)) {
// removes the .class extension
String className = pkgName + '.' + files[i].getName().substring(0, files[i].getName().length() - CLASS_POSTFIX.length());
try {
Class> clazz = ClassUtil.forClass(className, false);
if (clazz.getCanonicalName() != null && predicate.test(clazz)) {
classes.add(clazz);
}
} catch (Throwable e) {
if (logger.isWarnEnabled()) {
logger.warn("ClassNotFoundException loading " + className);
}
if (!skipClassLoaddingException) {
throw new RuntimeException("ClassNotFoundException loading " + className);
}
}
} else if (files[i].isDirectory() && isRecursive) {
String subPkgName = pkgName + WD._PERIOD + files[i].getName();
classes.addAll(getClassesByPackage(subPkgName, isRecursive, skipClassLoaddingException, predicate));
}
}
} else if (file.exists() && file.getName().endsWith(JAR_POSTFIX)) {
JarFile jarFile = null;
try {
jarFile = new JarFile(file.getPath());
Enumeration entries = jarFile.entries();
JarEntry entry = null;
String entryName = null;
while (entries.hasMoreElements()) {
entry = entries.nextElement();
entryName = entry.getName();
if (entryName.startsWith(pkgPath)) {
if (entryName.endsWith(CLASS_POSTFIX) && (entryName.indexOf("/", pkgPath.length()) < 0)) {
String className = filePath2PackageName(entryName).replace(CLASS_POSTFIX, "");
try {
Class> clazz = ClassUtil.forClass(className, false);
if ((clazz.getCanonicalName() != null) && (clazz.getPackage().getName().equals(pkgName)
|| (clazz.getPackage().getName().startsWith(pkgName) && isRecursive)) && predicate.test(clazz)) {
classes.add(clazz);
}
} catch (Throwable e) {
if (logger.isWarnEnabled()) {
logger.warn("ClassNotFoundException loading " + className);
}
if (!skipClassLoaddingException) {
IOUtil.close(jarFile);
jarFile = null;
throw new RuntimeException("ClassNotFoundException loading " + className);
}
}
} else if (entry.isDirectory() && (entryName.length() > (pkgPath.length() + 1)) && isRecursive) {
String subPkgName = filePath2PackageName(entryName);
classes.addAll(getClassesByPackage(subPkgName, isRecursive, skipClassLoaddingException, predicate));
}
}
}
} catch (IOException e) {
throw new UncheckedIOException(pkgName + " (" + file + ") does not appear to be a valid package", e);
} finally {
IOUtil.close(jarFile);
}
}
}
return classes;
}
/**
* Package name 2 file path.
*
* @param pkgName
* @return
*/
private static String packageName2FilePath(String pkgName) {
String pkgPath = pkgName.replace('.', '/');
pkgPath = pkgPath.endsWith("/") ? pkgPath : (pkgPath + "/");
return pkgPath;
}
/**
* Gets the resources.
*
* @param pkgName
* @return
*/
private static List getResources(String pkgName) {
List resourceList = new ArrayList<>();
String pkgPath = packageName2FilePath(pkgName);
ClassLoader localClassLoader = ClassUtil.class.getClassLoader();
ClassLoader sysClassLoader = ClassLoader.getSystemClassLoader();
try {
Enumeration resources = localClassLoader.getResources(pkgPath);
while (resources != null && resources.hasMoreElements()) {
resourceList.add(resources.nextElement());
}
if (N.isNullOrEmpty(resourceList)) {
resources = sysClassLoader.getResources(pkgPath);
while (resources != null && resources.hasMoreElements()) {
resourceList.add(resources.nextElement());
}
}
if (N.isNullOrEmpty(resourceList)) {
resources = localClassLoader.getResources(pkgName);
while (resources != null && resources.hasMoreElements()) {
resourceList.add(resources.nextElement());
}
}
if (N.isNullOrEmpty(resourceList)) {
resources = sysClassLoader.getResources(pkgName);
while (resources != null && resources.hasMoreElements()) {
resourceList.add(resources.nextElement());
}
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
if (logger.isInfoEnabled()) {
logger.info("Found resources: " + resourceList + " by package name(" + pkgName + ")");
}
return resourceList;
}
/**
* File path 2 package name.
*
* @param entryName
* @return
*/
private static String filePath2PackageName(String entryName) {
String pkgName = entryName.replace('/', '.').replace('\\', '.');
pkgName = pkgName.endsWith(".") ? pkgName.substring(0, pkgName.length() - 1) : pkgName;
return pkgName;
}
/**
* Gets the class name.
*
* @param cls
* @return
*/
public static String getClassName(final Class> cls) {
String clsName = nameClassPool.get(cls);
if (clsName == null) {
clsName = cls.getName();
nameClassPool.put(cls, clsName);
}
return clsName;
}
/**
* Gets the simple class name.
*
* @param cls
* @return
*/
public static String getSimpleClassName(final Class> cls) {
String clsName = simpleClassNamePool.get(cls);
if (clsName == null) {
clsName = cls.getSimpleName();
simpleClassNamePool.put(cls, clsName);
}
return clsName;
}
/**
* Gets the canonical class name.
*
* @param cls
* @return
*/
public static String getCanonicalClassName(final Class> cls) {
String clsName = canonicalClassNamePool.get(cls);
if (clsName == null) {
clsName = cls.getCanonicalName();
if (clsName != null) {
canonicalClassNamePool.put(cls, clsName);
}
}
return clsName;
}
/**
* Gets the enclosing class.
*
* @param cls
* @return
*/
public static Class> getEnclosingClass(final Class> cls) {
Class> enclosingClass = enclosingClassPool.get(cls);
if (enclosingClass == null) {
enclosingClass = cls.getEnclosingClass();
if (enclosingClass == null) {
enclosingClass = CLASS_MASK;
}
enclosingClassPool.put(cls, enclosingClass);
}
return (enclosingClass == CLASS_MASK) ? null : enclosingClass;
}
/**
* Returns the constructor declared in the specified {@code cls} with the specified {@code parameterTypes}.
*
* @param
* @param cls
* @param parameterTypes
* @return {@code null} if no constructor is found
*/
@SafeVarargs
public static Constructor getDeclaredConstructor(final Class cls, final Class>... parameterTypes) {
Map[], Constructor>> constructorPool = classDeclaredConstructorPool.get(cls);
Constructor constructor = null;
if (constructorPool != null) {
constructor = (Constructor) constructorPool.get(parameterTypes);
}
if (constructor == null) {
try {
constructor = cls.getDeclaredConstructor(parameterTypes);
// SHOULD NOT set it true here.
// ClassUtil.setAccessible(constructor, true);
} catch (NoSuchMethodException e) {
// ignore.
}
if (constructor != null) {
if (constructorPool == null) {
constructorPool = new ArrayHashMap<>(ConcurrentHashMap.class);
classDeclaredConstructorPool.put(cls, constructorPool);
}
constructorPool.put(parameterTypes.clone(), constructor);
}
}
return constructor;
}
/**
* Returns the method declared in the specified {@code cls} with the specified {@code methodName} and {@code parameterTypes}.
*
* @param cls
* @param methodName
* @param parameterTypes
* @return {@code null} if no method is found
*/
@SafeVarargs
public static Method getDeclaredMethod(final Class> cls, final String methodName, final Class>... parameterTypes) {
Map[], Method>> methodNamePool = classDeclaredMethodPool.get(cls);
Map[], Method> methodPool = methodNamePool == null ? null : methodNamePool.get(methodName);
Method method = null;
if (methodPool != null) {
method = methodPool.get(parameterTypes);
}
if (method == null) {
method = internalGetDeclaredMethod(cls, methodName, parameterTypes);
// SHOULD NOT set it true here.
// if (method != null) {
// ClassUtil.setAccessible(method, true);
// }
if (method != null) {
if (methodNamePool == null) {
methodNamePool = new ConcurrentHashMap<>();
classDeclaredMethodPool.put(cls, methodNamePool);
}
if (methodPool == null) {
methodPool = new ArrayHashMap<>(ConcurrentHashMap.class);
methodNamePool.put(methodName, methodPool);
}
methodPool.put(parameterTypes.clone(), method);
}
}
return method;
}
/**
* Internal get declared method.
*
* @param cls
* @param methodName
* @param parameterTypes
* @return
*/
static Method internalGetDeclaredMethod(final Class> cls, final String methodName, final Class>... parameterTypes) {
Method method = null;
try {
method = cls.getDeclaredMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
// ignore.
}
if (method == null) {
Method[] methods = cls.getDeclaredMethods();
for (Method m : methods) {
if (m.getName().equalsIgnoreCase(methodName) && N.equals(parameterTypes, m.getParameterTypes())) {
method = m;
break;
}
}
}
return method;
}
/**
*
* @param
* @param constructor
* @param args
* @return
*/
@SafeVarargs
public static T invokeConstructor(final Constructor constructor, final Object... args) {
try {
return constructor.newInstance(args);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw N.toRuntimeException(e);
}
}
/**
*
* @param
* @param method
* @param args
* @return
*/
@SuppressWarnings("unchecked")
@SafeVarargs
public static T invokeMethod(final Method method, final Object... args) {
return invokeMethod(null, method, args);
}
/**
*
* @param
* @param instance
* @param method
* @param args
* @return
*/
@SuppressWarnings("unchecked")
@SafeVarargs
public static T invokeMethod(final Object instance, final Method method, final Object... args) {
try {
return (T) method.invoke(instance, args);
} catch (IllegalAccessException | InvocationTargetException e) {
throw N.toRuntimeException(e);
}
}
/**
* Returns an immutable entity property name List by the specified class.
*
* @param cls
* @return
*/
public static ImmutableList getPropNameList(final Class> cls) {
ImmutableList propNameList = entityDeclaredPropNameListPool.get(cls);
if (propNameList == null) {
loadPropGetSetMethodList(cls);
propNameList = entityDeclaredPropNameListPool.get(cls);
}
return propNameList;
}
/**
* Gets the prop name list exclusively.
*
* @param cls
* @param propNameToExcluded
* @return
*/
public static List getPropNamesExclusively(final Class> cls, final Set propNameToExcluded) {
final List propNameList = getPropNameList(cls);
if (N.isNullOrEmpty(propNameToExcluded)) {
return new ArrayList<>(propNameList);
} else {
final List result = new ArrayList<>(propNameList.size() - propNameToExcluded.size());
for (String propName : propNameList) {
if (!propNameToExcluded.contains(propName)) {
result.add(propName);
}
}
return result;
}
}
/**
* Gets the prop name list exclusively.
*
* @param cls
* @param propNameToExcluded
* @return
*/
@SuppressWarnings("rawtypes")
public static List getPropNamesExclusively(final Class> cls, final Collection propNameToExcluded) {
if (N.isNullOrEmpty(propNameToExcluded)) {
return new ArrayList<>(getPropNameList(cls));
} else if (propNameToExcluded instanceof Set) {
return getPropNamesExclusively(cls, (Set) propNameToExcluded);
} else {
return getPropNamesExclusively(cls, N.newHashSet(propNameToExcluded));
}
}
/**
*
* @param entity
* @return
*/
public static List getNonNullPropNames(final Object entity) {
return getPropNames(entity, Fn.
© 2015 - 2025 Weber Informatics LLC | Privacy Policy