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 */ 017 package org.apache.commons.discovery.tools; 018 019 import java.lang.reflect.Constructor; 020 import java.lang.reflect.InvocationTargetException; 021 import java.lang.reflect.Method; 022 import java.lang.reflect.Modifier; 023 024 import org.apache.commons.discovery.DiscoveryException; 025 026 import org.apache.commons.discovery.log.DiscoveryLogFactory; 027 import org.apache.commons.logging.Log; 028 029 030 /** 031 * @author Richard A. Sitze 032 */ 033 public class ClassUtils { 034 private static Log log = DiscoveryLogFactory.newLog(ClassUtils.class); 035 public static void setLog(Log _log) { 036 log = _log; 037 } 038 039 /** 040 * Get package name. 041 * Not all class loaders 'keep' package information, 042 * in which case Class.getPackage() returns null. 043 * This means that calling Class.getPackage().getName() 044 * is unreliable at best. 045 */ 046 public static String getPackageName(Class clazz) { 047 Package clazzPackage = clazz.getPackage(); 048 String packageName; 049 if (clazzPackage != null) { 050 packageName = clazzPackage.getName(); 051 } else { 052 String clazzName = clazz.getName(); 053 packageName = clazzName.substring(0, clazzName.lastIndexOf('.')); 054 } 055 return packageName; 056 } 057 058 /** 059 * @return Method 'public static returnType methodName(paramTypes)', 060 * if found to be <strong>directly</strong> implemented by clazz. 061 */ 062 public static Method findPublicStaticMethod(Class clazz, 063 Class returnType, 064 String methodName, 065 Class[] paramTypes) { 066 boolean problem = false; 067 Method method = null; 068 069 // verify '<methodName>(<paramTypes>)' is directly in class. 070 try { 071 method = clazz.getDeclaredMethod(methodName, paramTypes); 072 } catch(NoSuchMethodException e) { 073 problem = true; 074 log.debug("Class " + clazz.getName() + ": missing method '" + methodName + "(...)", e); 075 } 076 077 // verify 'public static <returnType>' 078 if (!problem && 079 !(Modifier.isPublic(method.getModifiers()) && 080 Modifier.isStatic(method.getModifiers()) && 081 method.getReturnType() == returnType)) { 082 if (log.isDebugEnabled()) { 083 if (!Modifier.isPublic(method.getModifiers())) { 084 log.debug(methodName + "() is not public"); 085 } 086 if (!Modifier.isStatic(method.getModifiers())) { 087 log.debug(methodName + "() is not static"); 088 } 089 if (method.getReturnType() != returnType) { 090 log.debug("Method returns: " + method.getReturnType().getName() + "@@" + method.getReturnType().getClassLoader()); 091 log.debug("Should return: " + returnType.getName() + "@@" + returnType.getClassLoader()); 092 } 093 } 094 problem = true; 095 method = null; 096 } 097 098 return method; 099 } 100 101 /** 102 * Instantiate a new 103 */ 104 public static Object newInstance(Class impl, Class paramClasses[], Object params[]) 105 throws DiscoveryException, 106 InstantiationException, 107 IllegalAccessException, 108 NoSuchMethodException, 109 InvocationTargetException 110 { 111 if (paramClasses == null || params == null) { 112 return impl.newInstance(); 113 } else { 114 Constructor constructor = impl.getConstructor(paramClasses); 115 return constructor.newInstance(params); 116 } 117 } 118 119 /** 120 * Throws exception if <code>impl</code> does not 121 * implement or extend the SPI. 122 */ 123 public static void verifyAncestory(Class spi, Class impl) 124 throws DiscoveryException 125 { 126 if (spi == null) { 127 throw new DiscoveryException("No interface defined!"); 128 } 129 130 if (impl == null) { 131 throw new DiscoveryException("No implementation defined for " + spi.getName()); 132 } 133 134 if (!spi.isAssignableFrom(impl)) { 135 throw new DiscoveryException("Class " + impl.getName() + 136 " does not implement " + spi.getName()); 137 } 138 } 139 }