Coverage Report - at.ipsquare.commons.core.util.ClassLoaders
 
Classes in this File Line Coverage Branch Coverage Complexity
ClassLoaders
87%
42/48
93%
15/16
2.25
 
 1  
 /**
 2  
  * Copyright (C) 2013 Matthias Langer
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *         http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package at.ipsquare.commons.core.util;
 17  
 
 18  
 import java.lang.ref.WeakReference;
 19  
 import java.util.Collections;
 20  
 import java.util.Set;
 21  
 
 22  
 import net.jcip.annotations.GuardedBy;
 23  
 
 24  
 import com.google.common.collect.Sets;
 25  
 
 26  
 /**
 27  
  * A global registry for class loaders that is used throughout all IP SQUARE commons components.
 28  
  * 
 29  
  * @since 2.1.0
 30  
  * @author Matthias Langer
 31  
  */
 32  
 public final class ClassLoaders
 33  
 {
 34  2
     private static final Object lock = new Object();
 35  
     
 36  
     @GuardedBy("lock")
 37  2
     private static Set<WeakReference<ClassLoader>> clRefs = Collections.emptySet();
 38  
     
 39  
     /**
 40  
      * Registers a {@link ClassLoader}.
 41  
      * 
 42  
      * <p>
 43  
      *  Please note that this class only keeps weak references to the {@link ClassLoaders}
 44  
      *  you pass to avoid potential memory leaks.
 45  
      * </p>
 46  
      * 
 47  
      * @param cl a {@link ClassLoader}.
 48  
      * @return true if the loader has not been registered before.
 49  
      * @see #unregister(ClassLoader)
 50  
      */
 51  
     public static boolean register(ClassLoader cl)
 52  
     {
 53  12
         if(cl == null)
 54  2
             throw new NullPointerException();
 55  
         
 56  10
         synchronized(lock)
 57  
         {
 58  10
             Set<ClassLoader> cls = resolveWeakReferences(clRefs);
 59  10
             boolean ret = cls.add(cl);
 60  10
             if(ret)
 61  8
                 clRefs = toWeakReferences(cls);
 62  10
             return ret;
 63  0
         }
 64  
     }
 65  
     
 66  
     /**
 67  
      * Unregisters a {@link ClassLoader}.
 68  
      * 
 69  
      * @param cl the {@link ClassLoader} that should be removed from the registry.
 70  
      * @return true if the loader was registered before.
 71  
      * @see #register(ClassLoader)
 72  
      */
 73  
     public static boolean unregister(ClassLoader cl)
 74  
     {
 75  8
         if(cl == null)
 76  2
             throw new NullPointerException();
 77  
         
 78  6
         synchronized(lock)
 79  
         {
 80  6
             Set<ClassLoader> resolved = resolveWeakReferences(clRefs);
 81  6
             boolean ret = resolved.remove(cl);
 82  6
             if(ret)
 83  4
                 clRefs = toWeakReferences(resolved);
 84  6
             return ret;
 85  0
         }
 86  
     }
 87  
     
 88  
     /**
 89  
      * Unregisters all {@link ClassLoader}s.
 90  
      * 
 91  
      * @see #register(ClassLoader)
 92  
      * @see #unregister(ClassLoader)
 93  
      */
 94  
     public static void clear()
 95  
     {
 96  2
         synchronized(lock)
 97  
         {
 98  2
             clRefs = Collections.emptySet();
 99  2
         }
 100  2
     }
 101  
     
 102  
     /**
 103  
      * Returns a set of all explicitly registered {@link ClassLoader}s.
 104  
      * 
 105  
      * @return a snapshot of the previously registered {@link ClassLoader}s in the order they have been registered.
 106  
      * @see #get()
 107  
      */
 108  
     public static Set<ClassLoader> registered()
 109  
     {
 110  4
         synchronized(lock)
 111  
         {
 112  4
             return resolveWeakReferences(clRefs);
 113  0
         }
 114  
     }
 115  
     
 116  
     /**
 117  
      * Returns a set of all explicitly registered {@link ClassLoader}s as well as the {@link ClassLoader} that 
 118  
      * loaded this class and the current context class loader if set.
 119  
      * 
 120  
      * @return the previously registered {@link ClassLoader}s in the order the have been registered, followed by the {@link ClassLoader}
 121  
      *  that loaded this class and the context {@link ClassLoader} if set.
 122  
      */
 123  
     public static Set<ClassLoader> get()
 124  
     {
 125  116
         synchronized(lock)
 126  
         {
 127  116
             Set<ClassLoader> ret = resolveWeakReferences(clRefs);
 128  116
             ret.add(ClassLoaders.class.getClassLoader());
 129  
             
 130  116
             ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
 131  116
             if(contextClassLoader != null)
 132  98
                 ret.add(contextClassLoader);
 133  116
             return ret;
 134  0
         }
 135  
     }
 136  
     
 137  
     private static Set<WeakReference<ClassLoader>> toWeakReferences(Set<ClassLoader> cls)
 138  
     {
 139  12
         Set<WeakReference<ClassLoader>> ret = Sets.newLinkedHashSetWithExpectedSize(cls.size());
 140  12
         for(ClassLoader cl : cls)
 141  14
             ret.add(new WeakReference<ClassLoader>(cl));
 142  12
         return ret;
 143  
     }
 144  
 
 145  
     private static Set<ClassLoader> resolveWeakReferences(Set<WeakReference<ClassLoader>> cls)
 146  
     {
 147  136
         Set<ClassLoader> ret = Sets.newLinkedHashSetWithExpectedSize(cls.size() + 2);
 148  136
         for(WeakReference<ClassLoader> clRef : cls)
 149  
         {
 150  28
             ClassLoader cl = clRef.get();
 151  28
             if(cl != null)
 152  28
                 ret.add(cl);
 153  28
         }
 154  136
         return ret;
 155  
     }
 156  
 
 157  
     private ClassLoaders()
 158  0
     {
 159  
         
 160  0
     }
 161  
 }