001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020package org.apache.isis.core.commons.lang; 021 022import java.io.IOException; 023import java.io.InputStream; 024import java.lang.reflect.Constructor; 025import java.lang.reflect.InvocationTargetException; 026import java.lang.reflect.Method; 027import java.lang.reflect.Modifier; 028import java.net.URL; 029import java.nio.charset.Charset; 030import java.util.HashMap; 031import java.util.Map; 032import java.util.Properties; 033 034import com.google.common.io.InputSupplier; 035import com.google.common.io.Resources; 036 037import org.apache.isis.core.commons.exceptions.IsisException; 038import org.apache.isis.core.metamodel.methodutils.MethodFinderUtils; 039 040public final class ClassExtensions { 041 042 043 044 045 // ////////////////////////////////////// 046 047 048 private ClassExtensions() { 049 } 050 051 public static Object newInstance(final Class<?> extendee, final Class<?> constructorParamType, final Object constructorArg) { 052 return ClassExtensions.newInstance(extendee, new Class[] { constructorParamType }, new Object[] { constructorArg }); 053 } 054 055 /** 056 * Tries to instantiate using a constructor accepting the supplied 057 * arguments; if no such constructor then falls back to trying the no-arg 058 * constructor. 059 */ 060 public static Object newInstance(final Class<?> extendee, final Class<?>[] constructorParamTypes, final Object[] constructorArgs) { 061 try { 062 Constructor<?> constructor; 063 try { 064 constructor = extendee.getConstructor(constructorParamTypes); 065 return constructor.newInstance(constructorArgs); 066 } catch (final NoSuchMethodException ex) { 067 try { 068 constructor = extendee.getConstructor(); 069 return constructor.newInstance(); 070 } catch (final NoSuchMethodException e) { 071 throw new IsisException(e); 072 } 073 } 074 } catch (final SecurityException ex) { 075 throw new IsisException(ex); 076 } catch (final IllegalArgumentException e) { 077 throw new IsisException(e); 078 } catch (final InstantiationException e) { 079 throw new IsisException(e); 080 } catch (final IllegalAccessException e) { 081 throw new IsisException(e); 082 } catch (final InvocationTargetException e) { 083 throw new IsisException(e); 084 } 085 } 086 087 public static String getSuperclass(final Class<?> extendee) { 088 final Class<?> superType = extendee.getSuperclass(); 089 090 if (superType == null) { 091 return null; 092 } 093 return superType.getName(); 094 } 095 096 public static boolean isAbstract(final Class<?> extendee) { 097 return Modifier.isAbstract(extendee.getModifiers()); 098 } 099 100 public static boolean isFinal(final Class<?> extendee) { 101 return Modifier.isFinal(extendee.getModifiers()); 102 } 103 104 public static boolean isPublic(final Class<?> extendee) { 105 return Modifier.isPublic(extendee.getModifiers()); 106 } 107 108 public static boolean isJavaClass(final Class<?> extendee) { 109 final String className = extendee.getName(); 110 return className.startsWith(ClassUtil.JAVA_CLASS_PREFIX) || 111 extendee.getName().startsWith("sun."); 112 } 113 114 static Class<?> implementingClassOrNull(final Class<?> extendee, final Class<?> requiredClass, final Class<?> constructorParamType) { 115 if (extendee == null) { 116 return null; 117 } 118 if (!requiredClass.isAssignableFrom(extendee)) { 119 return null; 120 } 121 try { 122 extendee.getConstructor(new Class[] { constructorParamType }); 123 } catch (final NoSuchMethodException ex) { 124 try { 125 extendee.getConstructor(new Class[] {}); 126 } catch (final NoSuchMethodException e) { 127 return null; 128 } 129 } catch (final SecurityException e) { 130 return null; 131 } 132 final int modifiers = extendee.getModifiers(); 133 if (!Modifier.isPublic(modifiers)) { 134 return null; 135 } 136 return extendee; 137 } 138 139 public static Method getMethod(final Class<?> clazz, final String methodName, final Class<?>... parameterClass) throws NoSuchMethodException { 140 return clazz.getMethod(methodName, parameterClass); 141 } 142 143 public static Method getMethodElseNull(final Class<?> clazz, final String methodName, final Class<?>... parameterClass) { 144 try { 145 return clazz.getMethod(methodName, parameterClass); 146 } catch (final NoSuchMethodException e) { 147 return null; 148 } 149 } 150 151 public static Method findMethodElseNull(final Class<?> clazz, final String[] candidateMethodNames, final Class<?>... parameterClass) { 152 for (final String candidateMethodName : candidateMethodNames) { 153 final Method method = getMethodElseNull(clazz, candidateMethodName, parameterClass); 154 if (method != null) { 155 return method; 156 } 157 } 158 return null; 159 } 160 161 public static Properties resourceProperties(final Class<?> extendee, final String suffix) { 162 try { 163 final URL url = Resources.getResource(extendee, extendee.getSimpleName()+suffix); 164 final InputSupplier<InputStream> inputSupplier = com.google.common.io.Resources.newInputStreamSupplier(url); 165 final Properties properties = new Properties(); 166 properties.load(inputSupplier.getInput()); 167 return properties; 168 } catch (Exception e) { 169 return null; 170 } 171 } 172 173 public static String resourceContent(final Class<?> cls, final String suffix) throws IOException { 174 final URL url = Resources.getResource(cls, cls.getSimpleName()+suffix); 175 return Resources.toString(url, Charset.defaultCharset()); 176 } 177 178 public static Class<?> asWrapped(final Class<?> primitiveClassExtendee) { 179 return ClassUtil.wrapperClasses.get(primitiveClassExtendee); 180 } 181 182 public static Class<? extends Object> asWrappedIfNecessary(final Class<?> cls) { 183 return cls.isPrimitive() ? asWrapped(cls) : cls; 184 } 185 186 public static Object toDefault(final Class<?> extendee) { 187 if(!extendee.isPrimitive()) { 188 return null; 189 } 190 return ClassUtil.defaultByPrimitiveClass.get(extendee); 191 } 192 193 /** 194 * Returns the corresponding 'null' value for the primitives, or just 195 * <tt>null</tt> if the class represents a non-primitive type. 196 */ 197 public static Object getNullOrDefault(final Class<?> type) { 198 return ClassUtil.defaultByPrimitiveType.get(type); 199 } 200 201 public static boolean isCompatibleAsReturnType(final Class<?> returnTypeExtendee, final boolean canBeVoid, final Class<?> type) { 202 if (returnTypeExtendee == null) { 203 return true; 204 } 205 if (canBeVoid && (type == void.class)) { 206 return true; 207 } 208 209 if (type.isPrimitive()) { 210 return returnTypeExtendee.isAssignableFrom(ClassUtil.wrapperClasses.get(type)); 211 } 212 213 return (returnTypeExtendee.isAssignableFrom(type)); 214 } 215 216}