EMMA Coverage Report (generated Tue May 18 22:13:27 CDT 2004)
[all classes][org.apache.velocity.runtime]

COVERAGE SUMMARY FOR SOURCE FILE [VelocimacroManager.java]

nameclass, %method, %block, %line, %
VelocimacroManager.java100% (2/2)71%  (15/21)69%  (281/407)73%  (79/108)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class VelocimacroManager$MacroEntry100% (1/1)38%  (3/8)46%  (59/128)59%  (19/32)
getFromLibrary (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
getNodeTree (): SimpleNode 0%   (0/1)0%   (0/3)0%   (0/1)
getSourceTemplate (): String 0%   (0/1)0%   (0/3)0%   (0/1)
parseTree (InternalContextAdapter): void 0%   (0/1)0%   (0/53)0%   (0/7)
setup (InternalContextAdapter): void 0%   (0/1)0%   (0/7)0%   (0/3)
VelocimacroManager$MacroEntry (VelocimacroManager, VelocimacroManager, String... 100% (1/1)100% (30/30)100% (10/10)
createVelocimacro (String): VelocimacroProxy 100% (1/1)100% (25/25)100% (7/7)
setFromLibrary (boolean): void 100% (1/1)100% (4/4)100% (2/2)
     
class VelocimacroManager100% (1/1)92%  (12/13)80%  (222/279)79%  (60/76)
getLibraryName (String, String): String 0%   (0/1)0%   (0/34)0%   (0/10)
addNamespace (String): Hashtable 100% (1/1)64%  (14/22)60%  (3/5)
dumpNamespace (String): boolean 100% (1/1)69%  (24/35)67%  (6/9)
addVM (String, String, String [], String): boolean 100% (1/1)94%  (67/71)93%  (14/15)
<static initializer> 100% (1/1)100% (3/3)100% (1/1)
VelocimacroManager (RuntimeServices): void 100% (1/1)100% (32/32)100% (10/10)
get (String, String): VelocimacroProxy 100% (1/1)100% (37/37)100% (10/10)
getNamespace (String): Hashtable 100% (1/1)100% (5/5)100% (1/1)
getNamespace (String, boolean): Hashtable 100% (1/1)100% (16/16)100% (4/4)
setNamespaceUsage (boolean): void 100% (1/1)100% (4/4)100% (2/2)
setRegisterFromLib (boolean): void 100% (1/1)100% (4/4)100% (2/2)
setTemplateLocalInlineVM (boolean): void 100% (1/1)100% (4/4)100% (2/2)
usingNamespaces (String): boolean 100% (1/1)100% (12/12)100% (5/5)

1package org.apache.velocity.runtime;
2 
3/*
4 * Copyright 2000-2002,2004 The Apache Software Foundation.
5 * 
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 * 
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 * 
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 
19import java.util.Hashtable;
20 
21import java.io.StringReader;
22import java.io.BufferedReader;
23 
24import org.apache.velocity.runtime.directive.VelocimacroProxy;
25import org.apache.velocity.runtime.parser.node.SimpleNode;
26import org.apache.velocity.util.StringUtils;
27 
28import org.apache.velocity.context.InternalContextAdapter;
29 
30/**
31 * Manages VMs in namespaces.  Currently, two namespace modes are
32 * supported:
33 *
34 * <ul>
35 * <li>flat - all allowable VMs are in the global namespace</li>
36 * <li>local - inline VMs are added to it's own template namespace</li>
37 * </ul>
38 *
39 * Thanks to <a href="mailto:JFernandez@viquity.com">Jose Alberto Fernandez</a>
40 * for some ideas incorporated here.
41 *
42 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
43 * @author <a href="mailto:JFernandez@viquity.com">Jose Alberto Fernandez</a>
44 * @version $Id: VelocimacroManager.java,v 1.17.4.1 2004/03/03 23:22:55 geirm Exp $ 
45 */
46public class VelocimacroManager
47{
48    private RuntimeServices rsvc = null;
49    private static String GLOBAL_NAMESPACE = "";
50 
51    private boolean registerFromLib = false;
52 
53    /** Hash of namespace hashes. */
54    private Hashtable namespaceHash = new Hashtable();
55    
56    /** map of names of library tempates/namespaces */
57    private Hashtable libraryMap = new Hashtable();
58    
59    /* 
60     * big switch for namespaces.  If true, then properties control 
61     * usage. If false, no. 
62     */
63    private boolean namespacesOn = true;
64    private boolean  inlineLocalMode = false;
65 
66    /**
67     * Adds the global namespace to the hash.
68     */
69    VelocimacroManager(RuntimeServices rs)
70    {
71        this.rsvc = rs;
72 
73        /*
74         *  add the global namespace to the namespace hash. We always have that.
75         */
76 
77        addNamespace( GLOBAL_NAMESPACE );
78    }
79 
80    /**
81     * Adds a VM definition to the cache.
82     * @return Whether everything went okay.
83     */
84    public boolean addVM(String vmName, String macroBody, String argArray[],
85                         String namespace)
86    {
87        MacroEntry me = new MacroEntry(this, vmName, macroBody, argArray,
88                                       namespace);
89 
90        me.setFromLibrary(registerFromLib);
91    
92        /*
93         *  the client (VMFactory) will signal to us via
94         *  registerFromLib that we are in startup mode registering
95         *  new VMs from libraries.  Therefore, we want to
96         *  addto the library map for subsequent auto reloads
97         */
98         
99        boolean isLib = true;
100        
101        if (registerFromLib)
102        {
103           libraryMap.put(namespace, namespace);
104        }
105        else
106        {
107            /*
108             *  now, we first want to check to see if this namespace (template)
109             *  is actually a library - if so, we need to use the global namespace
110             *  we don't have to do this when registering, as namespaces should
111             *  be shut off. If not, the default value is true, so we still go
112             *  global
113             */
114         
115            isLib = libraryMap.containsKey(namespace);
116        }
117               
118        if ( !isLib && usingNamespaces(namespace) )
119        {
120            /*
121             *  first, do we have a namespace hash already for this namespace?
122             *  if not, add it to the namespaces, and add the VM
123             */
124 
125            Hashtable local = getNamespace(namespace, true);
126            local.put((String) vmName, me);
127         
128            return true;
129        }
130        else
131        {        
132            /*
133             *  otherwise, add to global template.  First, check if we
134             *  already have it to preserve some of the autoload information
135             */
136 
137            MacroEntry exist = (MacroEntry) getNamespace(GLOBAL_NAMESPACE).get(vmName);
138            
139            if (exist != null)
140            {
141                me.setFromLibrary(exist.getFromLibrary());
142            }
143 
144            /*
145             *  now add it
146             */
147 
148            getNamespace(GLOBAL_NAMESPACE).put(vmName, me);
149 
150            return true;
151        }
152    }
153 
154    /**
155     * gets a new living VelocimacroProxy object by the 
156     * name / source template duple
157     */
158    public VelocimacroProxy get(String vmName, String namespace)
159    {
160 
161        if (usingNamespaces(namespace))
162        {
163            Hashtable local =  getNamespace(namespace, false);
164         
165            /*
166             *  if we have macros defined for this template
167             */
168 
169            if (local != null)
170            {
171                MacroEntry me = (MacroEntry) local.get(vmName);
172               
173                if (me != null)
174                {
175                    return me.createVelocimacro(namespace);
176                }
177            }
178        }
179 
180        /*
181         * if we didn't return from there, we need to simply see 
182         * if it's in the global namespace
183         */
184        
185        MacroEntry me = (MacroEntry) getNamespace(GLOBAL_NAMESPACE).get( vmName );
186        
187        if (me != null)
188        {
189            return me.createVelocimacro(namespace);
190        }
191 
192        return null;
193    }
194 
195    /**
196     * Removes the VMs and the namespace from the manager.
197     * Used when a template is reloaded to avoid 
198     * accumulating drek
199     *
200     * @param namespace namespace to dump
201     * @return boolean representing success
202     */
203    public boolean dumpNamespace(String namespace)
204    {
205        synchronized(this)
206        {
207            if (usingNamespaces(namespace))
208            {
209                Hashtable h = (Hashtable) namespaceHash.remove(namespace);
210 
211                if (h == null)
212                    return false;
213            
214                h.clear();
215               
216                return true;
217            }
218 
219            return false;
220        }
221    }
222 
223    /**
224     *  public switch to let external user of manager to control namespace
225     *  usage indep of properties.  That way, for example, at startup the 
226     *  library files are loaded into global namespace
227     */
228    public void setNamespaceUsage(boolean b)
229    {
230        namespacesOn = b;
231    }
232 
233    public void setRegisterFromLib(boolean b)
234    {
235        registerFromLib = b;
236    }
237 
238    public void setTemplateLocalInlineVM(boolean b)
239    {
240        inlineLocalMode = b;
241    }
242 
243    /**
244     *  returns the hash for the specified namespace.  Will not create a new one
245     *  if it doesn't exist
246     *
247     *  @param namespace  name of the namespace :)
248     *  @return namespace Hashtable of VMs or null if doesn't exist
249     */
250    private Hashtable getNamespace(String namespace)
251    {
252        return getNamespace(namespace, false);
253    }
254 
255    /**
256     *  returns the hash for the specified namespace, and if it doesn't exist
257     *  will create a new one and add it to the namespaces
258     *
259     *  @param namespace  name of the namespace :)
260     *  @param addIfNew  flag to add a new namespace if it doesn't exist
261     *  @return namespace Hashtable of VMs or null if doesn't exist
262     */
263    private Hashtable getNamespace(String namespace, boolean addIfNew)
264    {
265        Hashtable h = (Hashtable) namespaceHash.get(namespace);
266 
267        if (h == null && addIfNew)
268        {
269            h = addNamespace(namespace);
270        }
271  
272        return h;
273    }
274 
275    /**
276     *   adds a namespace to the namespaces
277     *
278     *  @param namespace name of namespace to add
279     *  @return Hash added to namespaces, ready for use
280     */
281    private Hashtable addNamespace(String namespace)
282    {
283        Hashtable h = new Hashtable();
284        Object oh;
285 
286        if ((oh = namespaceHash.put(namespace, h)) != null)
287        {
288          /*
289           * There was already an entry on the table, restore it!
290           * This condition should never occur, given the code
291           * and the fact that this method is private.
292           * But just in case, this way of testing for it is much
293           * more efficient than testing before hand using get().
294           */
295          namespaceHash.put(namespace, oh);
296          /*
297           * Should't we be returning the old entry (oh)?
298           * The previous code was just returning null in this case.
299           */
300          return null;
301        }
302        
303        return h;
304    }
305 
306    /**
307     *  determines if currently using namespaces.
308     *
309     *  @param namespace currently ignored
310     *  @return true if using namespaces, false if not
311     */
312    private boolean usingNamespaces(String namespace)
313    {
314        /*
315         *  if the big switch turns of namespaces, then ignore the rules
316         */
317 
318        if (!namespacesOn)
319        {
320            return false;
321        }
322 
323        /*
324         *  currently, we only support the local template namespace idea
325         */
326 
327        if (inlineLocalMode)
328        {
329            return true;
330        }
331 
332        return false;
333    }
334 
335    public String getLibraryName(String vmName, String namespace)
336    {
337        if (usingNamespaces(namespace))
338        {
339            Hashtable local =  getNamespace(namespace, false);
340         
341            /*
342             *  if we have this macro defined in this namespace, then
343             *  it is masking the global, library-based one, so 
344             *  just return null
345             */
346 
347            if ( local != null)
348            {
349                MacroEntry me = (MacroEntry) local.get(vmName);
350               
351                if (me != null)
352                {
353                    return null;
354                }
355            }
356        }
357 
358        /*
359         * if we didn't return from there, we need to simply see 
360         * if it's in the global namespace
361         */
362        
363        MacroEntry me = (MacroEntry) getNamespace(GLOBAL_NAMESPACE).get(vmName);
364        
365        if (me != null)
366        {
367            return me.getSourceTemplate();
368        }
369 
370        return null;
371    }
372 
373 
374    /**
375     *  wrapper class for holding VM information
376     */
377    protected class MacroEntry
378    {
379        String macroname;
380        String[] argarray;
381        String macrobody;
382        String sourcetemplate;
383        SimpleNode nodeTree = null;
384        VelocimacroManager manager = null;
385        boolean fromLibrary = false;
386 
387        MacroEntry(VelocimacroManager vmm, String vmName, String macroBody,
388                   String argArray[],  String sourceTemplate)
389        {
390            this.macroname = vmName;
391            this.argarray = argArray;
392            this.macrobody = macroBody;
393            this.sourcetemplate = sourceTemplate;
394            this.manager = vmm;
395        }
396 
397        public void setFromLibrary(boolean b)
398        {
399            fromLibrary = b;
400        }
401        
402        public boolean getFromLibrary()
403        {
404            return fromLibrary;
405        }
406 
407        public SimpleNode getNodeTree()
408        {
409            return nodeTree;
410        }
411 
412        public String getSourceTemplate()
413        {
414            return sourcetemplate;
415        }
416 
417        VelocimacroProxy createVelocimacro(String namespace)
418        {
419            VelocimacroProxy vp = new VelocimacroProxy();
420            vp.setName(this.macroname);
421            vp.setArgArray(this.argarray);
422            vp.setMacrobody(this.macrobody);
423            vp.setNodeTree(this.nodeTree);
424            vp.setNamespace(namespace);
425            return vp;
426        }
427 
428        void setup( InternalContextAdapter ica)
429        {
430            /*
431             *  if not parsed yet, parse!
432             */
433            
434            if( nodeTree == null)
435                parseTree(ica);
436        }
437 
438        void parseTree(InternalContextAdapter ica)
439        {
440            try 
441            {
442                BufferedReader br = new BufferedReader(new StringReader(macrobody));
443 
444                nodeTree = rsvc.parse(br, "VM:" + macroname, true);
445                nodeTree.init(ica,null);
446            } 
447            catch ( Exception e ) 
448            {
449                rsvc.error("VelocimacroManager.parseTree() : exception " +
450                           macroname + " : "  + StringUtils.stackTrace(e));
451            }
452        }
453    }
454}

[all classes][org.apache.velocity.runtime]
EMMA 2.0.4015 (stable) (C) Vladimir Roubtsov