View Javadoc

1   package org.apache.velocity.runtime.parser.node;
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.IOException;
23  import java.io.Writer;
24  
25  import org.apache.commons.lang.builder.ToStringBuilder;
26  import org.apache.velocity.context.InternalContextAdapter;
27  import org.apache.velocity.exception.MethodInvocationException;
28  import org.apache.velocity.exception.ParseErrorException;
29  import org.apache.velocity.exception.ResourceNotFoundException;
30  import org.apache.velocity.exception.TemplateInitException;
31  import org.apache.velocity.runtime.directive.Directive;
32  import org.apache.velocity.runtime.directive.RuntimeMacro;
33  import org.apache.velocity.runtime.parser.ParseException;
34  import org.apache.velocity.runtime.parser.Parser;
35  import org.apache.velocity.util.ExceptionUtils;
36  
37  /**
38   * This class is responsible for handling the pluggable
39   * directives in VTL.
40   *
41   * For example :  #foreach()
42   *
43   * Please look at the Parser.jjt file which is
44   * what controls the generation of this class.
45   *
46   * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
47   * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
48   * @author <a href="mailto:kav@kav.dk">Kasper Nielsen</a>
49   * @version $Id: ASTDirective.java 720228 2008-11-24 16:58:33Z nbubna $
50   */
51  public class ASTDirective extends SimpleNode
52  {
53      private Directive directive = null;
54      private String directiveName = "";
55      private boolean isDirective;
56      private boolean isInitialized;
57  
58      /**
59       * @param id
60       */
61      public ASTDirective(int id)
62      {
63          super(id);
64      }
65  
66      /**
67       * @param p
68       * @param id
69       */
70      public ASTDirective(Parser p, int id)
71      {
72          super(p, id);
73      }
74  
75  
76      /**
77       * @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor, java.lang.Object)
78       */
79      public Object jjtAccept(ParserVisitor visitor, Object data)
80      {
81          return visitor.visit(this, data);
82      }
83  
84      /**
85       * @see org.apache.velocity.runtime.parser.node.SimpleNode#init(org.apache.velocity.context.InternalContextAdapter, java.lang.Object)
86       */
87      public synchronized Object init( InternalContextAdapter context, Object data)
88      throws TemplateInitException
89      {
90          /** method is synchronized to avoid concurrent directive initialization **/
91          
92          if (!isInitialized)
93          {
94              super.init( context, data );
95  
96              /*
97               *  only do things that are not context dependent
98               */
99      
100             if (parser.isDirective( directiveName ))
101             {
102                 isDirective = true;
103     
104                 try
105                 {
106                     directive = (Directive) parser.getDirective( directiveName )
107                         .getClass().newInstance();
108                 } 
109                 catch (InstantiationException e)
110                 {
111                     throw ExceptionUtils.createRuntimeException("Couldn't initialize " +
112                             "directive of class " +
113                             parser.getDirective(directiveName).getClass().getName(),
114                             e);
115                 }
116                 catch (IllegalAccessException e)
117                 {
118                     throw ExceptionUtils.createRuntimeException("Couldn't initialize " +
119                             "directive of class " +
120                             parser.getDirective(directiveName).getClass().getName(),
121                             e);
122                 }
123                     
124     
125                 directive.setLocation( getLine(), getColumn() );
126                 directive.init(rsvc, context,this);
127             }
128             else
129             {
130                 /**
131                  * Create a new RuntimeMacro
132                  */
133                 directive = new RuntimeMacro(directiveName, getTemplateName());
134                 directive.setLocation( getLine(), getColumn() );
135         
136                 /**
137                  * Initialize it
138                  */
139                 try
140                 {
141                     directive.init( rsvc, context, this );
142                 }
143     
144                 /**
145                  * correct the line/column number if an exception is caught
146                  */
147                 catch (TemplateInitException die)
148                 {
149                     throw new TemplateInitException(die.getMessage(),
150                             (ParseException) die.getWrappedThrowable(),
151                             die.getTemplateName(),
152                             die.getColumnNumber() + getColumn(),
153                             die.getLineNumber() + getLine());
154                 }
155                 isDirective = true;
156             }
157             
158             isInitialized = true;
159         }
160            
161         return data;
162     }
163 
164     /**
165      * @see org.apache.velocity.runtime.parser.node.SimpleNode#render(org.apache.velocity.context.InternalContextAdapter, java.io.Writer)
166      */
167     public boolean render( InternalContextAdapter context, Writer writer)
168         throws IOException,MethodInvocationException, ResourceNotFoundException, ParseErrorException
169     {
170         /*
171          *  normal processing
172          */
173 
174         if (isDirective)
175         {
176             directive.render(context, writer, this);
177         }
178         else
179         {
180             if (context.getAllowRendering())
181             {
182                 writer.write( "#");
183                 writer.write( directiveName );
184             }
185         }
186 
187         return true;
188     }
189 
190     /**
191      *   Sets the directive name.  Used by the parser.  This keeps us from having to
192      *   dig it out of the token stream and gives the parse the change to override.
193      * @param str
194      */
195     public void setDirectiveName( String str )
196     {
197         directiveName = str;
198     }
199 
200     /**
201      *  Gets the name of this directive.
202      *  @return The name of this directive.
203      */
204     public String getDirectiveName()
205     {
206         return directiveName;
207     }
208     
209     /**
210      * @since 1.5
211      */
212     public String toString()
213     {
214         return new ToStringBuilder(this)
215             .appendSuper(super.toString())
216             .append("directiveName", getDirectiveName())
217             .toString();
218     }
219 
220 }
221 
222 
223