KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > kohsuke > stapler > AbstractTearOff


1 package org.kohsuke.stapler;
2
3 import org.apache.commons.jelly.JellyContext;
4 import org.apache.commons.jelly.Script;
5 import org.apache.commons.jelly.Tag;
6
7 import java.lang.ref.WeakReference JavaDoc;
8 import java.net.URL JavaDoc;
9 import java.util.HashMap JavaDoc;
10 import java.util.Map JavaDoc;
11
12 /**
13  * Partial default implementation of tear-off class, for convenience of derived classes.
14  *
15  * @author Kohsuke Kawaguchi
16  */

17 public abstract class AbstractTearOff<CLT,S,E extends Exception JavaDoc> {
18     protected final MetaClass owner;
19     protected final CLT classLoader;
20
21     protected AbstractTearOff(MetaClass owner, Class JavaDoc<CLT> cltClass) {
22         this.owner = owner;
23         if(owner.classLoader!=null)
24             classLoader = owner.classLoader.loadTearOff(cltClass);
25         else
26             classLoader = null;
27     }
28
29     /**
30      * Locates the view script of the given name.
31      *
32      * @param name
33      * if this is a relative path, such as "foo.jelly" or "foo/bar.groovy",
34      * then it is assumed to be relative to this class, so
35      * "org/acme/MyClass/foo.jelly" or "org/acme/MyClass/foo/bar.groovy"
36      * will be searched.
37      * <p>
38      * If this starts with "/", then it is assumed to be absolute,
39      * and that name is searched from the classloader. This is useful
40      * to do mix-in.
41      */

42     public S findScript(String JavaDoc name) throws E {
43         S script;
44
45         synchronized(this) {
46             script = getScripts().get(name);
47             if(script==null || MetaClass.NO_CACHE) {
48                 ClassLoader JavaDoc cl = owner.clazz.getClassLoader();
49                 if(cl!=null) {
50
51                     URL JavaDoc res = findResource(name, cl);
52                     if(res!=null) {
53                         script = parseScript(res);
54                         getScripts().put(name,script);
55                     }
56                 }
57             }
58         }
59         if(script!=null)
60             return script;
61
62         // not found on this class, delegate to the parent
63
if(owner.baseClass!=null)
64             return ((AbstractTearOff<CLT,S,E>)owner.baseClass.loadTearOff(getClass())).findScript(name);
65
66         return null;
67     }
68
69     /**
70      * Compiles a script into the compiled form.
71      */

72     protected abstract S parseScript(URL JavaDoc res) throws E;
73
74     /**
75      * Compiled jelly script views of this class.
76      * Access needs to be synchronized.
77      * <p>
78      * Jelly leaks memory (because {@link Script}s hold on to {@link Tag})
79      * which usually holds on to {@link JellyContext} that was last used to run it,
80      * which often holds on to some big/heavy objects.)
81      *
82      * So it's important to allow {@link Script}s to be garbage collected.
83      * This is not an ideal fix, but it works.
84      */

85     private volatile WeakReference JavaDoc<Map JavaDoc<String JavaDoc,S>> scripts;
86
87     private Map JavaDoc<String JavaDoc,S> getScripts() {
88         Map JavaDoc<String JavaDoc,S> r=null;
89         if(scripts!=null)
90             r = scripts.get();
91
92         if(r!=null)
93             return r;
94
95         r = new HashMap JavaDoc<String JavaDoc,S>();
96         scripts = new WeakReference JavaDoc<Map JavaDoc<String JavaDoc,S>>(r);
97         return r;
98     }
99
100     protected final URL JavaDoc findResource(String JavaDoc name, ClassLoader JavaDoc cl) {
101         URL JavaDoc res = null;
102         if (MetaClassLoader.debugLoader != null)
103             res = getResource(name, MetaClassLoader.debugLoader.loader);
104         if (res == null)
105             res = getResource(name, cl);
106         return res;
107     }
108
109     private URL JavaDoc getResource(String JavaDoc name, ClassLoader JavaDoc cl) {
110         URL JavaDoc res;
111         if(name.startsWith("/")) {
112             // try name as full path to the Jelly script
113
res = cl.getResource(name.substring(1));
114         } else {
115             // assume that it's a view of this class
116
res = cl.getResource(owner.clazz.getName().replace('.','/').replace('$','/')+'/'+name);
117         }
118         return res;
119     }
120 }
121
Popular Tags