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 }