1   package org.apache.velocity.test.sql;
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.BufferedWriter;
23  import java.io.FileOutputStream;
24  import java.io.OutputStreamWriter;
25  import java.io.StringWriter;
26  import java.io.Writer;
27  
28  import javax.sql.DataSource;
29  
30  import junit.framework.Test;
31  import junit.framework.TestSuite;
32  
33  import org.apache.velocity.Template;
34  import org.apache.velocity.VelocityContext;
35  import org.apache.velocity.app.Velocity;
36  import org.apache.velocity.runtime.RuntimeSingleton;
37  import org.apache.velocity.test.misc.TestLogChute;
38  import org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader;
39  
40  
41  public class DataSourceResourceLoaderTestCase
42          extends BaseSQLTest
43  {
44      /**
45       * Comparison file extension.
46       */
47      private static final String CMP_FILE_EXT = "cmp";
48  
49      /**
50       * Comparison file extension.
51       */
52      private static final String RESULT_FILE_EXT = "res";
53  
54      /**
55       * Path to template file.  This will get combined with the
56       * application directory to form an absolute path
57       */
58      private final static String DATA_PATH = TEST_COMPARE_DIR + "/ds";
59  
60      /**
61       * Results relative to the build directory.
62       */
63      private static final String RESULTS_DIR = TEST_RESULT_DIR + "/ds";
64  
65      /**
66       * Results relative to the build directory.
67       */
68      private static final String COMPARE_DIR = TEST_COMPARE_DIR + "/ds/templates";
69  
70      /**
71       * String (not containing any VTL) used to test unicode
72       */
73      private String UNICODE_TEMPLATE = "\\u00a9 test \\u0410 \\u0411";
74      
75      /**
76       * Name of template for testing unicode.
77       */
78      private String UNICODE_TEMPLATE_NAME = "testUnicode";
79  
80      public DataSourceResourceLoaderTestCase(final String name)
81      	throws Exception
82      {
83          super(name, DATA_PATH);
84          setUpUnicode();
85      }
86  
87      public static Test suite()
88      {
89          return new TestSuite(DataSourceResourceLoaderTestCase.class);
90      }
91  
92      public void setUp()
93              throws Exception
94      {
95  
96          assureResultsDirectoryExists(RESULTS_DIR);
97  
98  	    DataSource ds = new HsqlDataSource("jdbc:hsqldb:.");
99  
100         DataSourceResourceLoader rl = new DataSourceResourceLoader();
101         rl.setDataSource(ds);
102 
103         // pass in an instance to Velocity
104         Velocity.addProperty( "resource.loader", "ds" );
105         Velocity.setProperty( "ds.resource.loader.instance", rl );
106 
107         Velocity.setProperty( "ds.resource.loader.resource.table",           "velocity_template");
108         Velocity.setProperty( "ds.resource.loader.resource.keycolumn",       "id");
109         Velocity.setProperty( "ds.resource.loader.resource.templatecolumn",  "def");
110         Velocity.setProperty( "ds.resource.loader.resource.timestampcolumn", "timestamp");
111 
112         Velocity.setProperty(
113                 Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS, TestLogChute.class.getName());
114 
115         Velocity.init();
116     }
117     
118     public void setUpUnicode()
119     throws Exception
120     {
121         String insertString = "insert into velocity_template  (id, timestamp, def) VALUES " +
122         		"( '" + UNICODE_TEMPLATE_NAME + "', NOW(), '" + UNICODE_TEMPLATE + "');";
123         executeSQL(insertString);
124     }
125 
126     /**
127      * Tests loading and rendering of a simple template. If that works, we are able to get data
128      * from the database.
129      */
130     public void testSimpleTemplate()
131             throws Exception
132     {
133         Template t = executeTest("testTemplate1");
134         assertFalse("Timestamp is 0", 0 == t.getLastModified());
135     }
136 
137     public void testUnicode()
138     throws Exception
139     {
140         Template template = RuntimeSingleton.getTemplate(UNICODE_TEMPLATE_NAME);
141 
142         Writer writer = new StringWriter();
143         VelocityContext context = new VelocityContext();
144         template.merge(context, writer);
145         writer.flush();
146         writer.close();
147 
148         String outputText = writer.toString();
149         
150         if (!normalizeNewlines(UNICODE_TEMPLATE).equals(
151                 normalizeNewlines( outputText ) ))
152         {
153             fail("Output incorrect for Template: " + UNICODE_TEMPLATE_NAME);
154         }
155     }
156 
157     /**
158      * Now we have a more complex example. Run a very simple tool.
159      * from the database.
160      */
161     public void testRenderTool()
162             throws Exception
163     {
164 	Template t = executeTest("testTemplate2");
165         assertFalse("Timestamp is 0", 0 == t.getLastModified());
166     }
167 
168     /**
169      * Will a NULL timestamp choke the loader?
170      */
171     public void testNullTimestamp()
172             throws Exception
173     {
174         Template t = executeTest("testTemplate3");
175         assertEquals("Timestamp is not 0", 0, t.getLastModified());
176     }
177 
178     /**
179      * Does it load the global Macros from the DB?
180      */
181     public void testMacroInvocation()
182             throws Exception
183     {
184         Template t = executeTest("testTemplate4");
185         assertFalse("Timestamp is 0", 0 == t.getLastModified());
186     }
187 
188     protected Template executeTest(final String templateName)
189     	throws Exception
190     {
191         Template template = RuntimeSingleton.getTemplate(templateName);
192 
193         FileOutputStream fos =
194                 new FileOutputStream (
195                         getFileName(RESULTS_DIR, templateName, RESULT_FILE_EXT));
196 
197         Writer writer = new BufferedWriter(new OutputStreamWriter(fos));
198 
199         VelocityContext context = new VelocityContext();
200         context.put("tool", new DSRLTCTool());
201 
202         template.merge(context, writer);
203         writer.flush();
204         writer.close();
205 
206         if (!isMatch(RESULTS_DIR, COMPARE_DIR, templateName,
207                         RESULT_FILE_EXT, CMP_FILE_EXT))
208         {
209             fail("Output incorrect for Template: " + templateName);
210         }
211 
212         return template;
213     }
214 
215     public static final class DSRLTCTool
216     {
217 	public int add(final int a, final int b)
218 	{
219 	    return a + b;
220 	}
221 
222 	public String getMessage()
223 	{
224 	    return "And the result is:";
225 	}
226     }
227 }