001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.internal; 014 015import java.lang.reflect.*; 016import java.util.function.*; 017 018import org.apache.juneau.*; 019import org.apache.juneau.reflect.*; 020 021/** 022 * Class-related utility methods. 023 * 024 * <h5 class='section'>See Also:</h5><ul> 025 026 * </ul> 027 */ 028public final class ClassUtils { 029 030 /** 031 * Predicate check to filter out void classes. 032 */ 033 public static final Predicate<Class<?>> NOT_VOID = ClassUtils::isNotVoid; 034 035 /** 036 * Returns the class types for the specified arguments. 037 * 038 * @param args The objects we're getting the classes of. 039 * @return The classes of the arguments. 040 */ 041 public static Class<?>[] getClasses(Object...args) { 042 Class<?>[] pt = new Class<?>[args.length]; 043 for (int i = 0; i < args.length; i++) 044 pt[i] = args[i] == null ? null : args[i].getClass(); 045 return pt; 046 } 047 048 /** 049 * Matches arguments to a list of parameter types. 050 * 051 * <p> 052 * Extra parameters are ignored. 053 * <br>Missing parameters are left null. 054 * 055 * @param paramTypes The parameter types. 056 * @param args The arguments to match to the parameter types. 057 * @return 058 * An array of parameters. 059 */ 060 public static Object[] getMatchingArgs(Class<?>[] paramTypes, Object... args) { 061 boolean needsShuffle = paramTypes.length != args.length; 062 if (! needsShuffle) { 063 for (int i = 0; i < paramTypes.length; i++) { 064 if (! paramTypes[i].isInstance(args[i])) 065 needsShuffle = true; 066 } 067 } 068 if (! needsShuffle) 069 return args; 070 Object[] params = new Object[paramTypes.length]; 071 for (int i = 0; i < paramTypes.length; i++) { 072 ClassInfo pt = ClassInfo.of(paramTypes[i]).getWrapperInfoIfPrimitive(); 073 for (Object arg : args) { 074 if (arg != null && pt.isParentOf(arg.getClass())) { 075 params[i] = arg; 076 break; 077 } 078 } 079 } 080 return params; 081 } 082 083 /** 084 * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. 085 * 086 * @param x The constructor. 087 * @return <jk>true</jk> if call was successful. 088 */ 089 public static boolean setAccessible(Constructor<?> x) { 090 try { 091 if (x != null) 092 x.setAccessible(true); 093 return true; 094 } catch (SecurityException e) { 095 return false; 096 } 097 } 098 099 /** 100 * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. 101 * 102 * @param x The method. 103 * @return <jk>true</jk> if call was successful. 104 */ 105 public static boolean setAccessible(Method x) { 106 try { 107 if (x != null) 108 x.setAccessible(true); 109 return true; 110 } catch (SecurityException e) { 111 return false; 112 } 113 } 114 115 /** 116 * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. 117 * 118 * @param x The field. 119 * @return <jk>true</jk> if call was successful. 120 */ 121 public static boolean setAccessible(Field x) { 122 try { 123 if (x != null) 124 x.setAccessible(true); 125 return true; 126 } catch (SecurityException e) { 127 return false; 128 } 129 } 130 131 /** 132 * Returns the specified type as a <c>Class</c>. 133 * 134 * <p> 135 * If it's already a <c>Class</c>, it just does a cast. 136 * <br>If it's a <c>ParameterizedType</c>, it returns the raw type. 137 * 138 * @param t The type to convert. 139 * @return The type converted to a <c>Class</c>, or <jk>null</jk> if it could not be converted. 140 */ 141 public static Class<?> toClass(Type t) { 142 if (t instanceof Class) 143 return (Class<?>)t; 144 if (t instanceof ParameterizedType) { 145 ParameterizedType pt = (ParameterizedType)t; 146 // The raw type should always be a class (right?) 147 return (Class<?>)pt.getRawType(); 148 } 149 return null; 150 } 151 152 /** 153 * Returns the fully-qualified class name for the specified object. 154 * 155 * @param value The object to get the class name for. 156 * @return The name of the class or <jk>null</jk> if the value was null. 157 */ 158 public static String className(Object value) { 159 return value == null ? null : value instanceof Class<?> ? ((Class<?>)value).getName() : value.getClass().getName(); 160 } 161 162 /** 163 * Returns the simple class name for the specified object. 164 * 165 * @param value The object to get the class name for. 166 * @return The name of the class or <jk>null</jk> if the value was null. 167 */ 168 public static String simpleClassName(Object value) { 169 if (value == null) 170 return null; 171 if (value instanceof ClassInfo) 172 return ((ClassInfo)value).getSimpleName(); 173 if (value instanceof ClassMeta) 174 return ((ClassMeta<?>)value).getSimpleName(); 175 if (value instanceof Class) 176 return ((Class<?>)value).getSimpleName(); 177 return value.getClass().getSimpleName(); 178 } 179 180 /** 181 * Returns <jk>true</jk> if the specific class is <jk>null</jk> or <c><jk>void</jk>.<jk>class</jk></c> or {@link Void} or has the simple name <js>"Void</js>. 182 * 183 * @param c The class to check. 184 * @return <jk>true</jk> if the specific class is <jk>null</jk> or <c><jk>void</jk>.<jk>class</jk></c> or {@link Void} or has the simple name <js>"Void</js>. 185 */ 186 @SuppressWarnings("rawtypes") 187 public static boolean isVoid(Class c) { 188 return (c == null || c == void.class || c == Void.class || c.getSimpleName().equalsIgnoreCase("void")); 189 } 190 191 /** 192 * Returns <jk>false</jk> if the specific class is <jk>null</jk> or <c><jk>void</jk>.<jk>class</jk></c> or {@link Void} or has the simple name <js>"Void</js>. 193 * 194 * @param c The class to check. 195 * @return <jk>false</jk> if the specific class is <jk>null</jk> or <c><jk>void</jk>.<jk>class</jk></c> or {@link Void} or has the simple name <js>"Void</js>. 196 */ 197 @SuppressWarnings("rawtypes") 198 public static boolean isNotVoid(Class c) { 199 return ! isVoid(c); 200 } 201}