EMMA Coverage Report (generated Sat Nov 03 21:53:04 GMT 2007)
[all classes][sf.qof.util]

COVERAGE SUMMARY FOR SOURCE FILE [ClassGenerationCache.java]

nameclass, %method, %block, %line, %
ClassGenerationCache.java50%  (1/2)71%  (5/7)79%  (121/153)76%  (27.5/36)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ClassGenerationCache$GENERATION_PENDING0%   (0/1)0%   (0/1)0%   (0/3)0%   (0/1)
ClassGenerationCache$GENERATION_PENDING (): void 0%   (0/1)0%   (0/3)0%   (0/1)
     
class ClassGenerationCache100% (1/1)83%  (5/6)81%  (121/150)79%  (27.5/35)
ClassGenerationCache (): void 0%   (0/1)0%   (0/3)0%   (0/1)
getCachedClass (Class []): Class 100% (1/1)64%  (28/44)58%  (7/12)
putCachedClass (Class, Class []): void 100% (1/1)84%  (27/32)94%  (7.5/8)
getClassCache (Class []): Map 100% (1/1)85%  (29/34)88%  (7/8)
<static initializer> 100% (1/1)100% (5/5)100% (1/1)
createMapKey (Class []): String 100% (1/1)100% (32/32)100% (5/5)

1/*
2 * Copyright 2007 brunella ltd
3 *
4 * Licensed under the LGPL Version 3 (the "License");
5 * you may not use this file except in compliance with the License.
6 *
7 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
8 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
11 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
12 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
13 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
14 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
15 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
16 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
17 * THE POSSIBILITY OF SUCH DAMAGE.
18 */
19package sf.qof.util;
20 
21import java.util.HashMap;
22import java.util.Map;
23import java.util.WeakHashMap;
24 
25/**
26 * Caches generated classes according to a specified key.
27 * <code>ClassGenerationCache</code> is thread-safe.
28 * Classes are cached separately for each class loader. 
29 */
30public final class ClassGenerationCache {
31  
32  private ClassGenerationCache() { }
33 
34  private static final class GENERATION_PENDING { };
35 
36  private static final Map<ClassLoader, Map<String, Class<?>>> cache = new WeakHashMap<ClassLoader, Map<String, Class<?>>>();
37 
38  /**
39   * Returns a cached class for a specified key.
40   * If no class can be found for the specified key null is returned and
41   * the key is marked for generation. If a key is marked for generation
42   * by another thread this method waits till the other thread completes
43   * generation. 
44   * 
45   * @param key  key for the cached class
46   * @return     the cached class or null if not found
47   */
48  public static Class<?> getCachedClass(Class<?>... key) {
49    Map<String, Class<?>> classCache = getClassCache(key);
50    synchronized (classCache) {
51      Class<?> clazz = classCache.get(createMapKey(key));
52      while (clazz == GENERATION_PENDING.class) {
53        try {
54          // wait till the class is generated
55          classCache.wait();
56        } catch (InterruptedException e) {
57          // ignore
58        }
59        clazz = classCache.get(createMapKey(key));
60      }
61      if (clazz == null) {
62        classCache.put(createMapKey(key), GENERATION_PENDING.class);
63      }
64      return clazz;
65    }
66  }
67 
68  /**
69   * Puts a class into the class cache specified by a key.
70   * If the class is null the key is removed.
71   * 
72   * @param clazz  the cached class
73   * @param key    the key
74   */
75  public static void putCachedClass(Class<?> clazz, Class<?>... key) {
76    Map<String, Class<?>> classCache = getClassCache(key);
77    synchronized (classCache) {
78      if (clazz == null) {
79        classCache.remove(createMapKey(key));
80      } else {
81        classCache.put(createMapKey(key), clazz);
82      }
83      classCache.notifyAll();
84    }
85  }
86 
87  private static String createMapKey(Class<?>... key) {
88        StringBuilder sb = new StringBuilder();
89        for (Class<?> clazz : key) {
90          sb.append(clazz.getName());
91          sb.append('%');
92        }
93        return sb.toString();
94  }
95  
96  private static Map<String, Class<?>> getClassCache(Class<?>... key) {
97    ClassLoader classLoader = key[0].getClassLoader();
98    synchronized (cache) {
99      Map<String, Class<?>> classCache = cache.get(classLoader);
100      if (classCache == null) {
101        classCache = new HashMap<String, Class<?>>();
102        cache.put(classLoader, classCache);
103      }
104      return classCache;
105    }
106  }
107}

[all classes][sf.qof.util]
EMMA 2.0.5312 (C) Vladimir Roubtsov