View Javadoc

1   package org.apache.velocity.runtime.resource.loader;
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.InputStream;
23  
24  import org.apache.velocity.runtime.RuntimeServices;
25  import org.apache.velocity.runtime.log.Log;
26  import org.apache.velocity.runtime.resource.Resource;
27  import org.apache.velocity.runtime.resource.ResourceCacheImpl;
28  import org.apache.velocity.exception.ResourceNotFoundException;
29  import org.apache.velocity.exception.VelocityException;
30  import org.apache.commons.collections.ExtendedProperties;
31  
32  /**
33   * This is abstract class the all text resource loaders should
34   * extend.
35   *
36   * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
37   * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
38   * @version $Id: ResourceLoader.java 687518 2008-08-21 00:18:03Z nbubna $
39   */
40  public abstract class ResourceLoader
41  {
42      /**
43       * Does this loader want templates produced with it
44       * cached in the Runtime.
45       */
46       protected boolean isCachingOn = false;
47  
48      /**
49       * This property will be passed on to the templates
50       * that are created with this loader.
51       */
52      protected long modificationCheckInterval = 2;
53  
54      /**
55       * Class name for this loader, for logging/debuggin
56       * purposes.
57       */
58      protected String className = null;
59  
60      protected RuntimeServices rsvc = null;
61      protected Log log = null;
62  
63      /**
64       * This initialization is used by all resource
65       * loaders and must be called to set up common
66       * properties shared by all resource loaders
67       * @param rs
68       * @param configuration
69       */
70      public void commonInit( RuntimeServices rs, ExtendedProperties configuration)
71      {
72          this.rsvc = rs;
73          this.log = rsvc.getLog();
74  
75          /*
76           *  these two properties are not required for all loaders.
77           *  For example, for ClasspathLoader, what would cache mean?
78           *  so adding default values which I think are the safest
79           *
80           *  don't cache, and modCheckInterval irrelevant...
81           */
82  
83          try
84          {
85              isCachingOn = configuration.getBoolean("cache", false);
86          }
87          catch (Exception e)
88          {
89              isCachingOn = false;
90              String msg = "Exception parsing cache setting: "+configuration.getString("cache");
91              log.error(msg, e);
92              throw new VelocityException(msg, e);
93          }
94          try
95          {
96              modificationCheckInterval = configuration.getLong("modificationCheckInterval", 0);
97          }
98          catch (Exception e)
99          {
100             modificationCheckInterval = 0;
101             String msg = "Exception parsing modificationCheckInterval setting: "+configuration.getString("modificationCheckInterval");
102             log.error(msg, e);
103             throw new VelocityException(msg, e);
104         }
105 
106         /*
107          * this is a must!
108          */
109         className = ResourceCacheImpl.class.getName();
110         try
111         {
112             className = configuration.getString("class", className);
113         }
114         catch (Exception e)
115         {
116             String msg = "Exception retrieving resource cache class name";
117             log.error(msg, e);
118             throw new VelocityException(msg, e);
119         }
120     }
121 
122     /**
123      * Initialize the template loader with a
124      * a resources class.
125      * @param configuration
126      */
127     public abstract void init( ExtendedProperties configuration);
128 
129     /**
130      * Get the InputStream that the Runtime will parse
131      * to create a template.
132      * @param source
133      * @return The input stream for the requested resource.
134      * @throws ResourceNotFoundException
135      */
136     public abstract InputStream getResourceStream( String source )
137         throws ResourceNotFoundException;
138 
139     /**
140      * Given a template, check to see if the source of InputStream
141      * has been modified.
142      * @param resource
143      * @return True if the resource has been modified.
144      */
145     public abstract boolean isSourceModified(Resource resource);
146 
147     /**
148      * Get the last modified time of the InputStream source
149      * that was used to create the template. We need the template
150      * here because we have to extract the name of the template
151      * in order to locate the InputStream source.
152      * @param resource
153      * @return Time in millis when the resource has been modified.
154      */
155     public abstract long getLastModified(Resource resource);
156 
157     /**
158      * Return the class name of this resource Loader
159      * @return Class name of the resource loader.
160      */
161     public String getClassName()
162     {
163         return className;
164     }
165 
166     /**
167      * Set the caching state. If true, then this loader
168      * would like the Runtime to cache templates that
169      * have been created with InputStreams provided
170      * by this loader.
171      * @param value
172      */
173     public void setCachingOn(boolean value)
174     {
175         isCachingOn = value;
176     }
177 
178     /**
179      * The Runtime uses this to find out whether this
180      * template loader wants the Runtime to cache
181      * templates created with InputStreams provided
182      * by this loader.
183      * @return True if this resource loader caches.
184      */
185     public boolean isCachingOn()
186     {
187         return isCachingOn;
188     }
189 
190     /**
191      * Set the interval at which the InputStream source
192      * should be checked for modifications.
193      * @param modificationCheckInterval
194      */
195     public void setModificationCheckInterval(long modificationCheckInterval)
196     {
197         this.modificationCheckInterval = modificationCheckInterval;
198     }
199 
200     /**
201      * Get the interval at which the InputStream source
202      * should be checked for modifications.
203      * @return The modification check interval.
204      */
205     public long getModificationCheckInterval()
206     {
207         return modificationCheckInterval;
208     }
209 
210     /**
211      * Check whether any given resource exists. This is not really
212      * a very efficient test and it can and should be overridden in the
213      * subclasses extending ResourceLoader. 
214      *
215      * @param resourceName The name of a resource.
216      * @return true if a resource exists and can be accessed.
217      * @since 1.6
218      */
219     public boolean resourceExists(final String resourceName)
220     {
221         InputStream is = null;
222         try
223         {
224             is = getResourceStream(resourceName);
225         }
226         catch (ResourceNotFoundException e)
227         {
228             if (log.isDebugEnabled())
229             {
230                 log.debug("Could not load resource '" + resourceName 
231                         + "' from ResourceLoader " + this.getClass().getName() 
232                         + ": ", e);
233             }
234         }
235         finally
236         {
237             try
238             {
239                 if (is != null)
240                 {
241                     is.close();
242                 }
243             }
244             catch (Exception e)
245             {
246                 if (log.isErrorEnabled())
247                 {
248                     String msg = "While closing InputStream for resource '" + resourceName
249                         + "' from ResourceLoader "+this.getClass().getName();
250                     log.error(msg, e);
251                     throw new VelocityException(msg, e);
252                 }
253             }
254         }
255         return (is != null);
256     }
257 }