001    /*
002     * Copyright (C) 2005 The Guava Authors
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package com.google.common.reflect;
018    
019    import static com.google.common.base.Preconditions.checkArgument;
020    import static com.google.common.base.Preconditions.checkNotNull;
021    
022    import com.google.common.annotations.Beta;
023    
024    import java.lang.reflect.InvocationHandler;
025    import java.lang.reflect.Proxy;
026    
027    /**
028     * Static utilities relating to Java reflection.
029     *
030     * @since 12.0
031     */
032    @Beta
033    public final class Reflection {
034    
035      /**
036       * Returns the package name of {@code cls} according to the Java Language Specification (section
037       * 6.7). Unlike {@link Class#getPackage}, this method only parses the class name, without
038       * attempting to define the {@link Package} and hence load files.
039       */
040      public static String getPackageName(Class<?> cls) {
041        return getPackageName(cls.getName());
042      }
043    
044      /**
045       * Returns the package name of {@code classFullName} according to the Java Language Specification
046       * (section 6.7). Unlike {@link Class#getPackage}, this method only parses the class name, without
047       * attempting to define the {@link Package} and hence load files.
048       */
049      public static String getPackageName(String classFullName) {
050        int lastDot = classFullName.lastIndexOf('.');
051        if (lastDot < 0) {
052          return "";
053        } else {
054          return classFullName.substring(0, lastDot);
055        }
056      }
057    
058      /**
059       * Ensures that the given classes are initialized, as described in
060       * <a href="http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.4.2">
061       * JLS Section 12.4.2</a>.
062       *
063       * <p>WARNING: Normally it's a smell if a class needs to be explicitly initialized, because static
064       * state hurts system maintainability and testability. In cases when you have no choice while
065       * inter-operating with a legacy framework, this method helps to keep the code less ugly.
066       *
067       * @throws ExceptionInInitializerError if an exception is thrown during
068       *   initialization of a class
069       */
070      public static void initialize(Class<?>... classes) {
071        for (Class<?> clazz : classes) {
072          try {
073            Class.forName(clazz.getName(), true, clazz.getClassLoader());
074          } catch (ClassNotFoundException e) {
075            throw new AssertionError(e);
076          }
077        }
078      }
079    
080      /**
081       * Returns a proxy instance that implements {@code interfaceType} by
082       * dispatching method invocations to {@code handler}. The class loader of
083       * {@code interfaceType} will be used to define the proxy class. To implement
084       * multiple interfaces or specify a class loader, use
085       * {@link Proxy#newProxyInstance}.
086       *
087       * @throws IllegalArgumentException if {@code interfaceType} does not specify
088       *     the type of a Java interface
089       */
090      public static <T> T newProxy(
091          Class<T> interfaceType, InvocationHandler handler) {
092        checkNotNull(interfaceType);
093        checkNotNull(handler);
094        checkArgument(interfaceType.isInterface());
095        Object object = Proxy.newProxyInstance(
096            interfaceType.getClassLoader(),
097            new Class<?>[] { interfaceType },
098            handler);
099        return interfaceType.cast(object);
100      }
101    
102      private Reflection() {}
103    }