Merge "Added headers to the concepts bundles"
[yangtools.git] / concepts / src / main / java / org / opendaylight / yangtools / concepts / util / ClassLoaderUtils.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.concepts.util;
9
10 import static org.opendaylight.yangtools.concepts.util.ClassLoaderUtils.findParameterizedType;
11
12 import java.lang.reflect.ParameterizedType;
13 import java.lang.reflect.Type;
14 import java.util.concurrent.Callable;
15 import java.util.concurrent.locks.Lock;
16
17
18 public final class ClassLoaderUtils {
19
20     private ClassLoaderUtils() {
21         throw new UnsupportedOperationException("Utility class");
22     }
23
24     public static <V> V withClassLoader(ClassLoader cls, Callable<V> function) throws Exception {
25         return withClassLoaderAndLock(cls, null, function);
26     }
27
28     public static <V> V withClassLoaderAndLock(ClassLoader cls, Lock lock, Callable<V> function) throws Exception {
29         if (cls == null) {
30             throw new IllegalArgumentException("Classloader should not be null");
31         }
32         if (function == null) {
33             throw new IllegalArgumentException("Function should not be null");
34         }
35
36         if (lock != null) {
37             lock.lock();
38         }
39         ClassLoader oldCls = Thread.currentThread().getContextClassLoader();
40         try {
41             Thread.currentThread().setContextClassLoader(cls);
42             return function.call();
43         } finally {
44             Thread.currentThread().setContextClassLoader(oldCls);
45             if (lock != null) {
46                 lock.unlock();
47             }
48         }
49     }
50
51     public static ParameterizedType findParameterizedType(Class<?> subclass, Class<?> genericType) {
52         if(subclass == null || genericType == null) {
53             throw new IllegalArgumentException("Class was not specified.");
54         }
55         for (Type type : subclass.getGenericInterfaces()) {
56             if (type instanceof ParameterizedType && genericType.equals(((ParameterizedType) type).getRawType())) {
57                 return (ParameterizedType) type;
58             }
59         }
60         return null;
61     }
62
63     public static <S,G,P> Class<P> findFirstGenericArgument(final Class<S> scannedClass, final Class<G> genericType) {
64         try {
65             return withClassLoader(scannedClass.getClassLoader(), ClassLoaderUtils.<S,G,P>findFirstGenericArgumentTask(scannedClass, genericType));
66         } catch (Exception e) {
67             return null;
68         }
69     }
70     
71     private static <S,G,P> Callable<Class<P>> findFirstGenericArgumentTask(final Class<S> scannedClass, final Class<G> genericType) {
72         return new Callable<Class<P>>() {
73             @Override
74             @SuppressWarnings("unchecked")
75             public Class<P> call() throws Exception {
76                 final ParameterizedType augmentationGeneric = findParameterizedType(scannedClass,
77                         genericType);
78                 if (augmentationGeneric == null) {
79                     return null;
80                 }
81                 return (Class<P>) augmentationGeneric.getActualTypeArguments()[0];
82             }
83         };
84     }
85
86     public static Type getFirstGenericParameter(Type type) {
87         if(type instanceof ParameterizedType) {
88             return ((ParameterizedType) type).getActualTypeArguments()[0];
89         }
90         return null;
91     }
92
93 }