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