View Javadoc

1   package org.apache.velocity.runtime.directive;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.    
20   */
21  
22  import java.io.Writer;
23  import java.io.IOException;
24  
25  import org.apache.velocity.runtime.RuntimeConstants;
26  import org.apache.velocity.runtime.RuntimeServices;
27  
28  import org.apache.velocity.context.InternalContextAdapter;
29  import org.apache.velocity.runtime.parser.node.Node;
30  
31  import org.apache.velocity.exception.MethodInvocationException;
32  import org.apache.velocity.exception.ParseErrorException;
33  import org.apache.velocity.exception.ResourceNotFoundException;
34  import org.apache.velocity.exception.TemplateInitException;
35  
36  
37  /**
38   * Base class for all directives used in Velocity.
39   *
40   * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
41   * @author Nathan Bubna
42   * @version $Id: Directive.java 778045 2009-05-23 22:17:46Z nbubna $
43   */
44  public abstract class Directive implements DirectiveConstants, Cloneable
45  {
46      private int line = 0;
47      private int column = 0;
48      private boolean provideScope = false;
49      private String templateName;
50  
51      /**
52       *
53       */
54      protected RuntimeServices rsvc = null;
55  
56      /**
57       * Return the name of this directive.
58       * @return The name of this directive.
59       */
60      public abstract String getName();
61  
62      /**
63       * Get the directive type BLOCK/LINE.
64       * @return The directive type BLOCK/LINE.
65       */
66      public abstract int getType();
67  
68      /**
69       * Allows the template location to be set.
70       * @param line
71       * @param column
72       */
73      public void setLocation( int line, int column )
74      {
75          this.line = line;
76          this.column = column;
77      }
78  
79      /**
80       * Allows the template location to be set.
81       * @param line
82       * @param column
83       */
84      public void setLocation(int line, int column, String templateName)
85      {
86          setLocation(line, column);
87          this.templateName = templateName;
88      }
89  
90      /**
91       * for log msg purposes
92       * @return The current line for log msg purposes.
93       */
94      public int getLine()
95      {
96          return line;
97      }
98  
99      /**
100      * for log msg purposes
101      * @return The current column for log msg purposes.
102      */
103     public int getColumn()
104     {
105         return column;
106     }
107     
108     /**
109      * @return The template file name this directive was defined in, or null if not 
110      * defined in a file.
111      */
112     public String getTemplateName()
113     {
114       return templateName;
115     }
116 
117     /**
118      * @returns the name to be used when a scope control is provided for this
119      * directive.
120      */
121     public String getScopeName()
122     {
123         return getName();
124     }
125 
126     /**
127      * @return true if there will be a scope control injected into the context
128      * when rendering this directive.
129      */
130     public boolean isScopeProvided()
131     {
132         return provideScope;
133     }
134 
135     /**
136      * How this directive is to be initialized.
137      * @param rs
138      * @param context
139      * @param node
140      * @throws TemplateInitException
141      */
142     public void init( RuntimeServices rs, InternalContextAdapter context,
143                       Node node)
144         throws TemplateInitException
145     {
146         rsvc = rs;
147 
148         String property = getScopeName()+'.'+RuntimeConstants.PROVIDE_SCOPE_CONTROL;
149         this.provideScope = rsvc.getBoolean(property, provideScope);
150     }
151 
152     /**
153      * How this directive is to be rendered
154      * @param context
155      * @param writer
156      * @param node
157      * @return True if the directive rendered successfully.
158      * @throws IOException
159      * @throws ResourceNotFoundException
160      * @throws ParseErrorException
161      * @throws MethodInvocationException
162      */
163     public abstract boolean render( InternalContextAdapter context,
164                                     Writer writer, Node node )
165            throws IOException, ResourceNotFoundException, ParseErrorException,
166                 MethodInvocationException;
167 
168 
169     /**
170      * This creates and places the scope control for this directive
171      * into the context (if scope provision is turned on).
172      */
173     protected void preRender(InternalContextAdapter context)
174     {
175         if (isScopeProvided())
176         {
177             String name = getScopeName();
178             Object previous = context.get(name);
179             context.put(name, makeScope(previous));
180         }
181     }
182 
183     protected Scope makeScope(Object prev)
184     {
185         return new Scope(this, prev);
186     }
187 
188     /**
189      * This cleans up any scope control for this directive after rendering,
190      * assuming the scope control was turned on.
191      */
192     protected void postRender(InternalContextAdapter context)
193     {
194         if (isScopeProvided())
195         {
196             String name = getScopeName();
197             Object obj = context.get(name);
198             
199             try
200             {
201                 Scope scope = (Scope)obj;
202                 if (scope.getParent() != null)
203                 {
204                     context.put(name, scope.getParent());
205                 }
206                 else if (scope.getReplaced() != null)
207                 {
208                     context.put(name, scope.getReplaced());
209                 }
210                 else
211                 {
212                     context.remove(name);
213                 }
214             }
215             catch (ClassCastException cce)
216             {
217                 // the user can override the scope with a #set,
218                 // since that means they don't care about a replaced value
219                 // and obviously aren't too keen on their scope control,
220                 // and especially since #set is meant to be handled globally,
221                 // we'll assume they know what they're doing and not worry
222                 // about replacing anything superseded by this directive's scope
223             }
224         }
225     }
226 
227 }