velocity-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cbris...@apache.org
Subject svn commit: r1752784 - in /velocity/engine/trunk: src/changes/ velocity-engine-core/src/main/java/org/apache/velocity/ velocity-engine-core/src/main/java/org/apache/velocity/io/ velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ v...
Date Fri, 15 Jul 2016 07:13:01 GMT
Author: cbrisson
Date: Fri Jul 15 07:13:01 2016
New Revision: 1752784

URL: http://svn.apache.org/viewvc?rev=1752784&view=rev
Log:
ResourceLoaders now use Readers rather than InputStreams. InputStream API has been deprecated.

Modified:
    velocity/engine/trunk/src/changes/changes.xml
    velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/Template.java
    velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/io/UnicodeInputStream.java
    velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ContentResource.java
    velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java
    velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java
    velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/FileResourceLoader.java
    velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java
    velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ResourceLoader.java
    velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java
    velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/URLResourceLoader.java
    velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/misc/ExceptionGeneratingResourceLoader.java

Modified: velocity/engine/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/changes/changes.xml?rev=1752784&r1=1752783&r2=1752784&view=diff
==============================================================================
--- velocity/engine/trunk/src/changes/changes.xml (original)
+++ velocity/engine/trunk/src/changes/changes.xml Fri Jul 15 07:13:01 2016
@@ -27,6 +27,12 @@
   <body>
     <release version="2.0" date="In Subversion">
 
+      <action type="add" dev="cbrisson" issue="VELOCITY-793">
+        The ResourceLoader API now provides a Reader rather than an InputStream.
+        The InputStream getter method has been deprecated.
+        Also fixes VELOCITY-599.
+      </action>
+      
       <action type="fix" dev="cbrisson" issue="VELOCITY-553">
         InvalidReferenceHandler events should not be triggered by quiet references, null
values,
         or by references testing inside #if / #elseif. Thanks to Renato Steiner

Modified: velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/Template.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/Template.java?rev=1752784&r1=1752783&r2=1752784&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/Template.java
(original)
+++ velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/Template.java
Fri Jul 15 07:13:01 2016
@@ -23,6 +23,7 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.Reader;
 import java.io.UnsupportedEncodingException;
 import java.io.Writer;
 import java.util.List;
@@ -97,7 +98,7 @@ public class Template extends Resource
         throws ResourceNotFoundException, ParseErrorException
     {
         data = null;
-        InputStream is = null;
+        Reader reader = null;
         errorCondition = null;
 
         /*
@@ -105,7 +106,7 @@ public class Template extends Resource
          */
         try
         {
-            is = resourceLoader.getResourceStream(name);
+            reader = resourceLoader.getResourceReader(name, getEncoding());
         }
         catch( ResourceNotFoundException rnfe )
         {
@@ -122,7 +123,7 @@ public class Template extends Resource
          *  forgets to throw a proper exception
          */
 
-        if (is != null)
+        if (reader != null)
         {
             /*
              *  now parse the template
@@ -130,19 +131,11 @@ public class Template extends Resource
 
             try
             {
-                BufferedReader br = new BufferedReader( new InputStreamReader( is, encoding
) );
+                BufferedReader br = new BufferedReader( reader );
                 data = rsvc.parse( br, name);
                 initDocument();
                 return true;
             }
-            catch( UnsupportedEncodingException  uce )
-            {
-                String msg = "Template.process : Unsupported input encoding : " + encoding
-                + " for template " + name;
-
-                errorCondition  = new ParseErrorException( msg );
-                throw errorCondition;
-            }
             catch ( ParseException pex )
             {
                 /*
@@ -172,7 +165,7 @@ public class Template extends Resource
                  */
                 try
                 {
-                    is.close();
+                    reader.close();
                 }
                 catch(IOException e)
                 {

Modified: velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/io/UnicodeInputStream.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/io/UnicodeInputStream.java?rev=1752784&r1=1752783&r2=1752784&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/io/UnicodeInputStream.java
(original)
+++ velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/io/UnicodeInputStream.java
Fri Jul 15 07:13:01 2016
@@ -56,14 +56,12 @@ public class UnicodeInputStream
     /**
      * BOM Marker for UTF 32, little endian. See http://www.unicode.org/unicode/faq/utf_bom.html
      *
-     * TODO: Does Java actually support this?
      */
     public static final UnicodeBOM UTF32LE_BOM = new UnicodeBOM("UTF-32LE", new byte [] {
(byte)0xff, (byte)0xfe, (byte)0x00, (byte)0x00 });
 
     /**
      * BOM Marker for UTF 32, big endian. See http://www.unicode.org/unicode/faq/utf_bom.html
      *
-     * TODO: Does Java actually support this?
      */
     public static final UnicodeBOM UTF32BE_BOM = new UnicodeBOM("UTF-32BE", new byte [] {
(byte)0x00, (byte)0x00, (byte)0xfe, (byte)0xff });
 
@@ -340,6 +338,17 @@ public class UnicodeInputStream
         return inputStream.skip(n);
     }
 
+
+    /**
+     * Helper function to compare encodings
+     */
+    public static boolean sameEncoding(String left, String right)
+    {
+        left = left.toUpperCase().replace("-", "");
+        right = right.toUpperCase().replace("-", "");
+        return left.equals(right);
+    }
+
     /**
      * Helper class to bundle encoding and BOM marker.
      *

Modified: velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ContentResource.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ContentResource.java?rev=1752784&r1=1752783&r2=1752784&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ContentResource.java
(original)
+++ velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/ContentResource.java
Fri Jul 15 07:13:01 2016
@@ -62,9 +62,7 @@ public class ContentResource extends Res
         {
             StringWriter sw = new StringWriter();
 
-            reader = new BufferedReader(
-                new InputStreamReader(resourceLoader.getResourceStream(name),
-                                      encoding));
+            reader = new BufferedReader(resourceLoader.getResourceReader(name, encoding));
 
             char buf[] = new char[1024];
             int len = 0;

Modified: velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java?rev=1752784&r1=1752783&r2=1752784&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java
(original)
+++ velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ClasspathResourceLoader.java
Fri Jul 15 07:13:01 2016
@@ -19,7 +19,10 @@ package org.apache.velocity.runtime.reso
  * under the License.
  */
 
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
 
 import org.apache.commons.collections.ExtendedProperties;
 import org.apache.commons.lang3.StringUtils;
@@ -97,8 +100,9 @@ public class ClasspathResourceLoader ext
      * @return InputStream containing the template
      * @throws ResourceNotFoundException if template not found
      *         in  classpath.
+     * @deprecated use {@link #getResourceReader(String, String)}
      */
-    public InputStream getResourceStream( String name )
+    public @Deprecated InputStream getResourceStream( String name )
         throws ResourceNotFoundException
     {
         InputStream result = null;
@@ -131,6 +135,64 @@ public class ClasspathResourceLoader ext
         }
 
         return result;
+    }
+
+    /**
+     * Get a Reader so that the Runtime can build a
+     * template with it.
+     *
+     * @param name name of template to get
+     * @param encoding asked encoding
+     * @return InputStream containing the template
+     * @throws ResourceNotFoundException if template not found
+     *         in  classpath.
+     * @since 2.0
+     */
+    public Reader getResourceReader( String name, String encoding )
+            throws ResourceNotFoundException
+    {
+        Reader result = null;
+
+        if (StringUtils.isEmpty(name))
+        {
+            throw new ResourceNotFoundException ("No template name provided");
+        }
+
+        /**
+         * look for resource in thread classloader first (e.g. WEB-INF\lib in
+         * a servlet container) then fall back to the system classloader.
+         */
+
+        InputStream rawStream = null;
+        try
+        {
+            rawStream = ClassUtils.getResourceAsStream( getClass(), name );
+            if (rawStream != null)
+            {
+                result = buildReader(rawStream, encoding);
+            }
+        }
+        catch( Exception fnfe )
+        {
+            if (rawStream != null)
+            {
+                try
+                {
+                    rawStream.close();
+                }
+                catch (IOException ioe) {}
+            }
+            throw new ResourceNotFoundException("ClasspathResourceLoader problem with template:
" + name, fnfe );
+        }
+
+        if (result == null)
+        {
+            String msg = "ClasspathResourceLoader Error: cannot find resource " + name;
+
+            throw new ResourceNotFoundException( msg );
+        }
+
+        return result;
     }
 
     /**

Modified: velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java?rev=1752784&r1=1752783&r2=1752784&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java
(original)
+++ velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/DataSourceResourceLoader.java
Fri Jul 15 07:13:01 2016
@@ -20,7 +20,9 @@ package org.apache.velocity.runtime.reso
  */
 
 import java.io.BufferedInputStream;
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.Reader;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
@@ -209,8 +211,9 @@ public class DataSourceResourceLoader ex
      *  @param name name of template
      *  @return InputStream containing template
      * @throws ResourceNotFoundException
+     * @deprecated Use {@link #getResourceReader(String,String)}
      */
-    public synchronized InputStream getResourceStream(final String name)
+    public synchronized @Deprecated InputStream getResourceStream(final String name)
         throws ResourceNotFoundException
     {
         if (org.apache.commons.lang3.StringUtils.isEmpty(name))
@@ -262,6 +265,93 @@ public class DataSourceResourceLoader ex
 
             log.error(msg, ne);
             throw new ResourceNotFoundException(msg);
+        }
+        finally
+        {
+            closeResultSet(rs);
+            closeStatement(ps);
+            closeDbConnection(conn);
+        }
+    }
+
+    /**
+     * Get an InputStream so that the Runtime can build a
+     * template with it.
+     *
+     * @param name name of template
+     * @param encoding asked encoding
+     * @return InputStream containing template
+     * @throws ResourceNotFoundException
+     * @since 2.0
+     */
+    public synchronized Reader getResourceReader(final String name, String encoding)
+            throws ResourceNotFoundException
+    {
+        if (org.apache.commons.lang3.StringUtils.isEmpty(name))
+        {
+            throw new ResourceNotFoundException("DataSourceResourceLoader: Template name
was empty or null");
+        }
+
+        Connection conn = null;
+        ResultSet rs = null;
+        PreparedStatement ps = null;
+        try
+        {
+            conn = openDbConnection();
+            ps = getStatement(conn, templateColumn, tableName, keyColumn, name);
+            rs = ps.executeQuery();
+
+            if (rs.next())
+            {
+                InputStream rawStream = rs.getBinaryStream(templateColumn);
+                if (rawStream == null)
+                {
+                    throw new ResourceNotFoundException("DataSourceResourceLoader: "
+                            + "template column for '"
+                            + name + "' is null");
+                }
+                try
+                {
+                    return buildReader(rawStream, encoding);
+                }
+                catch (Exception e)
+                {
+                    if (rawStream != null)
+                    {
+                        try
+                        {
+                            rawStream.close();
+                        }
+                        catch(IOException ioe) {}
+                    }
+                    String msg = "Exception while loading Template column for " + name;
+                    log.error(msg, e);
+                    throw new VelocityException(msg, e);
+                }
+            }
+            else
+            {
+                throw new ResourceNotFoundException("DataSourceResourceLoader: "
+                        + "could not find resource '"
+                        + name + "'");
+
+            }
+        }
+        catch (SQLException sqle)
+        {
+            String msg = "DataSourceResourceLoader: database problem while getting resource
'"
+                    + name + "': ";
+
+            log.error(msg, sqle);
+            throw new ResourceNotFoundException(msg);
+        }
+        catch (NamingException ne)
+        {
+            String msg = "DataSourceResourceLoader: database problem while getting resource
'"
+                    + name + "': ";
+
+            log.error(msg, ne);
+            throw new ResourceNotFoundException(msg);
         }
         finally
         {

Modified: velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/FileResourceLoader.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/FileResourceLoader.java?rev=1752784&r1=1752783&r2=1752784&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/FileResourceLoader.java
(original)
+++ velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/FileResourceLoader.java
Fri Jul 15 07:13:01 2016
@@ -25,6 +25,7 @@ import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Reader;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -63,9 +64,6 @@ public class FileResourceLoader extends
      */
     private Map templatePaths = Collections.synchronizedMap(new HashMap());
 
-    /** Shall we inspect unicode files to see what encoding they contain?. */
-    private boolean unicode = false;
-
     /**
      * @see org.apache.velocity.runtime.resource.loader.ResourceLoader#init(org.apache.commons.collections.ExtendedProperties)
      */
@@ -78,15 +76,7 @@ public class FileResourceLoader extends
 
         paths.addAll( configuration.getVector("path") );
 
-        // unicode files may have a BOM marker at the start, but Java
-        // has problems recognizing the UTF-8 bom. Enabling unicode will
-        // recognize all unicode boms.
-        unicode = configuration.getBoolean("unicode", false);
-
-        if (log.isDebugEnabled())
-        {
-            log.debug("Do unicode file recognition: {}", unicode);
-        }
+        // unicode files may have a BOM marker at the start,
 
         if (log.isDebugEnabled())
         {
@@ -110,9 +100,10 @@ public class FileResourceLoader extends
      * @param templateName name of template to get
      * @return InputStream containing the template
      * @throws ResourceNotFoundException if template not found
+     * @deprecated Use {@link #getResourceReader(String,String)}
      *         in the file template path.
      */
-    public InputStream getResourceStream(String templateName)
+    public @Deprecated InputStream getResourceStream(String templateName)
         throws ResourceNotFoundException
     {
         /*
@@ -145,14 +136,18 @@ public class FileResourceLoader extends
         for (int i = 0; i < size; i++)
         {
             String path = (String) paths.get(i);
-            InputStream inputStream = null;
+            InputStream rawStream = null;
+            UnicodeInputStream inputStream = null;
 
             try
             {
-                inputStream = findTemplate(path, template);
+                rawStream = findTemplate(path, template);
+                inputStream = new UnicodeInputStream(rawStream, true);
+
             }
             catch (IOException ioe)
             {
+                closeQuiet(rawStream);
                 String msg = "Exception while loading Template " + template;
                 log.error(msg, ioe);
                 throw new VelocityException(msg, ioe);
@@ -179,6 +174,87 @@ public class FileResourceLoader extends
     }
 
     /**
+     * Get a Reader so that the Runtime can build a
+     * template with it.
+     *
+     * @param templateName name of template to get
+     * @return Reader containing the template
+     * @throws ResourceNotFoundException if template not found
+     *         in the file template path.
+     * @since 2.0
+     */
+    public Reader getResourceReader(String templateName, String encoding)
+            throws ResourceNotFoundException
+    {
+        /*
+         * Make sure we have a valid templateName.
+         */
+        if (org.apache.commons.lang3.StringUtils.isEmpty(templateName))
+        {
+            /*
+             * If we don't get a properly formed templateName then
+             * there's not much we can do. So we'll forget about
+             * trying to search any more paths for the template.
+             */
+            throw new ResourceNotFoundException(
+                    "Need to specify a file name or file path!");
+        }
+
+        String template = StringUtils.normalizePath(templateName);
+        if ( template == null || template.length() == 0 )
+        {
+            String msg = "File resource error : argument " + template +
+                    " contains .. and may be trying to access " +
+                    "content outside of template root.  Rejected.";
+
+            log.error("FileResourceLoader : " + msg);
+
+            throw new ResourceNotFoundException ( msg );
+        }
+
+        int size = paths.size();
+        for (int i = 0; i < size; i++)
+        {
+            String path = (String) paths.get(i);
+            InputStream rawStream = null;
+            Reader reader = null;
+
+            try
+            {
+                rawStream = findTemplate(path, template);
+                if (rawStream != null)
+                {
+                    reader = buildReader(rawStream, encoding);
+                }
+            }
+            catch (IOException ioe)
+            {
+                closeQuiet(rawStream);
+                String msg = "Exception while loading Template " + template;
+                log.error(msg, ioe);
+                throw new VelocityException(msg, ioe);
+            }
+            if (reader != null)
+            {
+                /*
+                 * Store the path that this template came
+                 * from so that we can check its modification
+                 * time.
+                 */
+                templatePaths.put(templateName, path);
+                return reader;
+            }
+        }
+
+        /*
+         * We have now searched all the paths for
+         * templates and we didn't find anything so
+         * throw an exception.
+         */
+        throw new ResourceNotFoundException("FileResourceLoader : cannot find " + template);
+    }
+
+    /**
      * Overrides superclass for better performance.
      * @since 1.6
      */
@@ -227,7 +303,7 @@ public class FileResourceLoader extends
     {
         try
         {
-            File file = getFile(path,template);
+            File file = getFile(path, template);
 
             if (file.canRead())
             {
@@ -235,32 +311,7 @@ public class FileResourceLoader extends
                 try
                 {
                     fis = new FileInputStream(file.getAbsolutePath());
-
-                    if (unicode)
-                    {
-                        UnicodeInputStream uis = null;
-
-                        try
-                        {
-                            uis = new UnicodeInputStream(fis, true);
-
-                            if (log.isDebugEnabled())
-                            {
-                                log.debug("File Encoding for {} is: {}", file, uis.getEncodingFromStream());
-                            }
-
-                            return new BufferedInputStream(uis);
-                        }
-                        catch(IOException e)
-                        {
-                            closeQuiet(uis);
-                            throw e;
-                        }
-                    }
-                    else
-                    {
-                        return new BufferedInputStream(fis);
-                    }
+                    return fis;
                 }
                 catch (IOException e)
                 {

Modified: velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java?rev=1752784&r1=1752783&r2=1752784&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java
(original)
+++ velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/JarResourceLoader.java
Fri Jul 15 07:13:01 2016
@@ -19,13 +19,17 @@ package org.apache.velocity.runtime.reso
  * under the License.
  */
 
+import java.io.IOException;
 import java.io.InputStream;
 
+import java.io.InputStreamReader;
+import java.io.Reader;
 import java.util.Hashtable;
 import java.util.Vector;
 import java.util.Map;
 import java.util.HashMap;
 
+import org.apache.velocity.exception.VelocityException;
 import org.apache.velocity.util.StringUtils;
 import org.apache.velocity.runtime.resource.Resource;
 import org.apache.velocity.exception.ResourceNotFoundException;
@@ -137,9 +141,9 @@ public class JarResourceLoader extends R
         // Create a new JarHolder
         JarHolder temp = new JarHolder( rsvc,  path );
         // Add it's entries to the entryCollection
-        addEntries( temp.getEntries() );
+        addEntries(temp.getEntries());
         // Add it to the Jar table
-        jarfiles.put( temp.getUrlPath(), temp );
+        jarfiles.put(temp.getUrlPath(), temp);
     }
 
     /**
@@ -172,8 +176,9 @@ public class JarResourceLoader extends R
      * @return InputStream containing the template
      * @throws ResourceNotFoundException if template not found
      *         in the file template path.
+     * @deprecated Use {@link #getResourceReader(String, String)}
      */
-    public InputStream getResourceStream( String source )
+    public @Deprecated InputStream getResourceStream( String source )
         throws ResourceNotFoundException
     {
         InputStream results = null;
@@ -221,6 +226,81 @@ public class JarResourceLoader extends R
 
     }
 
+    /**
+     * Get a Reader so that the Runtime can build a
+     * template with it.
+     *
+     * @param source name of template to get
+     * @param encoding asked encoding
+     * @return InputStream containing the template
+     * @throws ResourceNotFoundException if template not found
+     *         in the file template path.
+     * @since 2.0
+    */
+    public Reader getResourceReader( String source, String encoding )
+            throws ResourceNotFoundException
+    {
+        Reader result = null;
+
+        if (org.apache.commons.lang3.StringUtils.isEmpty(source))
+        {
+            throw new ResourceNotFoundException("Need to have a resource!");
+        }
+
+        String normalizedPath = StringUtils.normalizePath( source );
+
+        if ( normalizedPath == null || normalizedPath.length() == 0 )
+        {
+            String msg = "JAR resource error : argument " + normalizedPath +
+                    " contains .. and may be trying to access " +
+                    "content outside of template root.  Rejected.";
+
+            log.error( "JarResourceLoader : " + msg );
+
+            throw new ResourceNotFoundException ( msg );
+        }
+
+        /*
+         *  if a / leads off, then just nip that :)
+         */
+        if ( normalizedPath.startsWith("/") )
+        {
+            normalizedPath = normalizedPath.substring(1);
+        }
+
+        if ( entryDirectory.containsKey( normalizedPath ) )
+        {
+            String jarurl  = (String)entryDirectory.get( normalizedPath );
+
+            if ( jarfiles.containsKey( jarurl ) )
+            {
+                JarHolder holder = (JarHolder)jarfiles.get( jarurl );
+                InputStream rawStream = holder.getResource( normalizedPath );
+                try
+                {
+                    return buildReader(rawStream, encoding);
+                }
+                catch (Exception e)
+                {
+                    if (rawStream != null)
+                    {
+                        try
+                        {
+                            rawStream.close();
+                        }
+                        catch (IOException ioe) {}
+                    }
+                    String msg = "JAR resource error : Exception while loading " + source;
+                    log.error(msg, e);
+                    throw new VelocityException(msg, e);
+                }
+            }
+        }
+
+        throw new ResourceNotFoundException( "JarResourceLoader Error: cannot find resource
" +
+                source );
+
+    }
 
     // TODO: SHOULD BE DELEGATED TO THE JARHOLDER
 

Modified: velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ResourceLoader.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ResourceLoader.java?rev=1752784&r1=1752783&r2=1752784&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ResourceLoader.java
(original)
+++ velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/ResourceLoader.java
Fri Jul 15 07:13:01 2016
@@ -20,7 +20,13 @@ package org.apache.velocity.runtime.reso
  */
 
 import java.io.InputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
 
+import org.apache.velocity.io.UnicodeInputStream;
+import org.apache.velocity.runtime.RuntimeConstants;
 import org.slf4j.Logger;
 
 import org.apache.velocity.runtime.RuntimeServices;
@@ -44,7 +50,7 @@ public abstract class ResourceLoader
      * Does this loader want templates produced with it
      * cached in the Runtime.
      */
-     protected boolean isCachingOn = false;
+    protected boolean isCachingOn = false;
 
     /**
      * This property will be passed on to the templates
@@ -65,10 +71,11 @@ public abstract class ResourceLoader
      * This initialization is used by all resource
      * loaders and must be called to set up common
      * properties shared by all resource loaders
+     *
      * @param rs
      * @param configuration
      */
-    public void commonInit( RuntimeServices rs, ExtendedProperties configuration)
+    public void commonInit(RuntimeServices rs, ExtendedProperties configuration)
     {
         this.rsvc = rs;
         this.log = rsvc.getLog();
@@ -88,7 +95,7 @@ public abstract class ResourceLoader
         catch (Exception e)
         {
             isCachingOn = false;
-            String msg = "Exception parsing cache setting: "+configuration.getString("cache");
+            String msg = "Exception parsing cache setting: " + configuration.getString("cache");
             log.error(msg, e);
             throw new VelocityException(msg, e);
         }
@@ -99,7 +106,7 @@ public abstract class ResourceLoader
         catch (Exception e)
         {
             modificationCheckInterval = 0;
-            String msg = "Exception parsing modificationCheckInterval setting: "+configuration.getString("modificationCheckInterval");
+            String msg = "Exception parsing modificationCheckInterval setting: " + configuration.getString("modificationCheckInterval");
             log.error(msg, e);
             throw new VelocityException(msg, e);
         }
@@ -123,23 +130,41 @@ public abstract class ResourceLoader
     /**
      * Initialize the template loader with a
      * a resources class.
+     *
      * @param configuration
      */
-    public abstract void init( ExtendedProperties configuration);
+    public abstract void init(ExtendedProperties configuration);
 
     /**
      * Get the InputStream that the Runtime will parse
      * to create a template.
+     *
      * @param source
      * @return The input stream for the requested resource.
      * @throws ResourceNotFoundException
+     * @deprecated Use {@link #getResourceReader(String, String)}
      */
-    public abstract InputStream getResourceStream( String source )
-        throws ResourceNotFoundException;
+    public
+    @Deprecated
+    abstract InputStream getResourceStream(String source)
+            throws ResourceNotFoundException;
+
+    /**
+     * Get the Reader that the Runtime will parse
+     * to create a template.
+     *
+     * @param source
+     * @return The reader for the requested resource.
+     * @throws ResourceNotFoundException
+     * @since 2.0
+     */
+    public abstract Reader getResourceReader(String source, String encoding)
+            throws ResourceNotFoundException;
 
     /**
      * Given a template, check to see if the source of InputStream
      * has been modified.
+     *
      * @param resource
      * @return True if the resource has been modified.
      */
@@ -150,6 +175,7 @@ public abstract class ResourceLoader
      * that was used to create the template. We need the template
      * here because we have to extract the name of the template
      * in order to locate the InputStream source.
+     *
      * @param resource
      * @return Time in millis when the resource has been modified.
      */
@@ -157,6 +183,7 @@ public abstract class ResourceLoader
 
     /**
      * Return the class name of this resource Loader
+     *
      * @return Class name of the resource loader.
      */
     public String getClassName()
@@ -169,6 +196,7 @@ public abstract class ResourceLoader
      * would like the Runtime to cache templates that
      * have been created with InputStreams provided
      * by this loader.
+     *
      * @param value
      */
     public void setCachingOn(boolean value)
@@ -181,6 +209,7 @@ public abstract class ResourceLoader
      * template loader wants the Runtime to cache
      * templates created with InputStreams provided
      * by this loader.
+     *
      * @return True if this resource loader caches.
      */
     public boolean isCachingOn()
@@ -191,6 +220,7 @@ public abstract class ResourceLoader
     /**
      * Set the interval at which the InputStream source
      * should be checked for modifications.
+     *
      * @param modificationCheckInterval
      */
     public void setModificationCheckInterval(long modificationCheckInterval)
@@ -201,6 +231,7 @@ public abstract class ResourceLoader
     /**
      * Get the interval at which the InputStream source
      * should be checked for modifications.
+     *
      * @return The modification check interval.
      */
     public long getModificationCheckInterval()
@@ -211,7 +242,7 @@ public abstract class ResourceLoader
     /**
      * Check whether any given resource exists. This is not really
      * a very efficient test and it can and should be overridden in the
-     * subclasses extending ResourceLoader. 
+     * subclasses extending ResourceLoader.
      *
      * @param resourceName The name of a resource.
      * @return true if a resource exists and can be accessed.
@@ -219,26 +250,26 @@ public abstract class ResourceLoader
      */
     public boolean resourceExists(final String resourceName)
     {
-        InputStream is = null;
+        Reader reader = null;
         try
         {
-            is = getResourceStream(resourceName);
+            reader = getResourceReader(resourceName, null);
         }
         catch (ResourceNotFoundException e)
         {
             if (log.isDebugEnabled())
             {
                 log.debug("Could not load resource '{}' from ResourceLoader {}",
-                          resourceName, this.getClass().getName(), e);
+                        resourceName, this.getClass().getName(), e);
             }
         }
         finally
         {
             try
             {
-                if (is != null)
+                if (reader != null)
                 {
-                    is.close();
+                    reader.close();
                 }
             }
             catch (Exception e)
@@ -246,13 +277,64 @@ public abstract class ResourceLoader
                 if (log.isErrorEnabled())
                 {
                     String msg = "While closing InputStream for resource '" +
-                        resourceName + "' from ResourceLoader " +
-                        this.getClass().getName();
+                            resourceName + "' from ResourceLoader " +
+                            this.getClass().getName();
                     log.error(msg, e);
                     throw new VelocityException(msg, e);
                 }
             }
         }
-        return (is != null);
+        return (reader != null);
+    }
+
+    /**
+     * Builds a Reader given a raw InputStream and an encoding. Should be use
+     * by every subclass that whishes to accept optional BOMs in resources.
+     * This method does *not* close the given input stream whenever an exception is thrown.
+     *
+     * @param rawStream The raw input stream.
+     * @param encoding  The asked encoding.
+     * @return found reader
+     * @throws IOException, UnsupportedEncodingException
+     * @since 2.0
+     */
+    protected Reader buildReader(InputStream rawStream, String encoding)
+            throws IOException, UnsupportedEncodingException
+    {
+        UnicodeInputStream inputStream = new UnicodeInputStream(rawStream);
+        /*
+         * Check encoding
+         */
+        String foundEncoding = inputStream.getEncodingFromStream();
+        if (foundEncoding != null && encoding != null && !UnicodeInputStream.sameEncoding(foundEncoding,
encoding))
+        {
+            log.warn("Found BOM encoding '{}' differs from asked encoding: '{}' - using BOM
encoding to read resource.", foundEncoding, encoding);
+            encoding = foundEncoding;
+        }
+        if (encoding == null)
+        {
+            if (foundEncoding == null)
+            {
+                encoding = rsvc.getString(RuntimeConstants.INPUT_ENCODING);
+            } else
+            {
+                encoding = foundEncoding;
+            }
+        }
+
+        try
+        {
+            return new InputStreamReader(inputStream, encoding);
+        }
+        catch (UnsupportedEncodingException uee)
+        {
+            try
+            {
+                inputStream.close();
+            }
+            catch (IOException ioe) {}
+            throw uee;
+        }
     }
+
 }

Modified: velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java?rev=1752784&r1=1752783&r2=1752784&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java
(original)
+++ velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/StringResourceLoader.java
Fri Jul 15 07:13:01 2016
@@ -24,7 +24,11 @@ import java.util.HashMap;
 import java.util.Map;
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.Reader;
 import java.io.UnsupportedEncodingException;
+
 import org.apache.commons.collections.ExtendedProperties;
 import org.apache.velocity.exception.ResourceNotFoundException;
 import org.apache.velocity.exception.VelocityException;
@@ -344,8 +348,9 @@ public class StringResourceLoader extend
      * @return InputStream containing the template.
      * @throws ResourceNotFoundException Ff template not found
      *         in the RepositoryFactory.
+     * @deprecated use {@link #getResourceReader(String,String)}
      */
-    public InputStream getResourceStream(final String name)
+    public @Deprecated InputStream getResourceStream(final String name)
             throws ResourceNotFoundException
     {
         if (StringUtils.isEmpty(name))
@@ -373,6 +378,68 @@ public class StringResourceLoader extend
         }
     }
 
+    /**
+     * Get a reader so that the Runtime can build a
+     * template with it.
+     *
+     * @param name name of template to get.
+     * @param encoding asked encoding
+     * @return Reader containing the template.
+     * @throws ResourceNotFoundException Ff template not found
+     *         in the RepositoryFactory.
+     * @since 2.0
+     */
+    public Reader getResourceReader(String name, String encoding)
+            throws ResourceNotFoundException
+    {
+        if (StringUtils.isEmpty(name))
+        {
+            throw new ResourceNotFoundException("No template name provided");
+        }
+
+        StringResource resource = this.repository.getStringResource(name);
+
+        if(resource == null)
+        {
+            throw new ResourceNotFoundException("Could not locate resource '" + name + "'");
+        }
+
+        byte [] byteArray = null;
+        InputStream rawStream = null;
+
+        try
+        {
+            byteArray = resource.getBody().getBytes(resource.getEncoding());
+            rawStream = new ByteArrayInputStream(byteArray);
+            return new InputStreamReader(rawStream, resource.getEncoding());
+        }
+        catch(UnsupportedEncodingException ue)
+        {
+            if (rawStream != null)
+            {
+                try
+                {
+                    rawStream.close();
+                }
+                catch (IOException ioe) {}
+            }
+            throw new VelocityException("Could not convert String using encoding " + resource.getEncoding(),
ue);
+        }
+        catch(IOException ioe)
+        {
+            if (rawStream != null)
+            {
+                try
+                {
+                    rawStream.close();
+                }
+                catch (IOException e) {}
+            }
+            throw new VelocityException("Exception while loading string resource", ioe);
+
+        }
+    }
+
     /**
      * @see org.apache.velocity.runtime.resource.loader.ResourceLoader#isSourceModified(org.apache.velocity.runtime.resource.Resource)
      */

Modified: velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/URLResourceLoader.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/URLResourceLoader.java?rev=1752784&r1=1752783&r2=1752784&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/URLResourceLoader.java
(original)
+++ velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/runtime/resource/loader/URLResourceLoader.java
Fri Jul 15 07:13:01 2016
@@ -21,6 +21,8 @@ package org.apache.velocity.runtime.reso
 
 import java.io.InputStream;
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.net.URLConnection;
@@ -94,8 +96,9 @@ public class URLResourceLoader extends R
      * @return InputStream containing the template
      * @throws ResourceNotFoundException if template not found
      *         in the file template path.
+     * @deprecated Use {@link #findTemplateReader(source)}
      */
-    public synchronized InputStream getResourceStream(String name)
+    public synchronized @Deprecated InputStream getResourceStream(String name)
         throws ResourceNotFoundException
     {
         if (StringUtils.isEmpty(name))
@@ -155,6 +158,86 @@ public class URLResourceLoader extends R
     }
 
     /**
+     * Get a Reader so that the Runtime can build a
+     * template with it.
+     *
+     * @param name name of template to fetch bytestream of
+     * @param encoding asked encoding
+     * @return InputStream containing the template
+     * @throws ResourceNotFoundException if template not found
+     *         in the file template path.
+     * @since 2.0
+     */
+    public synchronized Reader getResourceReader(String name, String encoding)
+            throws ResourceNotFoundException
+    {
+        if (StringUtils.isEmpty(name))
+        {
+            throw new ResourceNotFoundException("URLResourceLoader : No template name provided");
+        }
+
+        Reader reader = null;
+        Exception exception = null;
+        for(int i=0; i < roots.length; i++)
+        {
+            InputStream rawStream = null;
+            try
+            {
+                URL u = new URL(roots[i] + name);
+                URLConnection conn = u.openConnection();
+                tryToSetTimeout(conn);
+                rawStream = conn.getInputStream();
+                reader = buildReader(rawStream, encoding);
+
+                if (reader != null)
+                {
+                    if (log.isDebugEnabled()) log.debug("URLResourceLoader: Found '{}' at
'{}'", name, roots[i]);
+
+                    // save this root for later re-use
+                    templateRoots.put(name, roots[i]);
+                    break;
+                }
+            }
+            catch(IOException ioe)
+            {
+                if (rawStream != null)
+                {
+                    try
+                    {
+                        rawStream.close();
+                    }
+                    catch (IOException e) {}
+                }
+                if (log.isDebugEnabled()) log.debug("URLResourceLoader: Exception when looking
for '{}' at '{}'", name, roots[i], ioe);
+
+                // only save the first one for later throwing
+                if (exception == null)
+                {
+                    exception = ioe;
+                }
+            }
+        }
+
+        // if we never found the template
+        if (reader == null)
+        {
+            String msg;
+            if (exception == null)
+            {
+                msg = "URLResourceLoader : Resource '" + name + "' not found.";
+            }
+            else
+            {
+                msg = exception.getMessage();
+            }
+            // convert to a general Velocity ResourceNotFoundException
+            throw new ResourceNotFoundException(msg);
+        }
+
+        return reader;
+    }
+
+    /**
      * Checks to see if a resource has been deleted, moved or modified.
      *
      * @param resource Resource  The resource to check for modification

Modified: velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/misc/ExceptionGeneratingResourceLoader.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/misc/ExceptionGeneratingResourceLoader.java?rev=1752784&r1=1752783&r2=1752784&view=diff
==============================================================================
--- velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/misc/ExceptionGeneratingResourceLoader.java
(original)
+++ velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/misc/ExceptionGeneratingResourceLoader.java
Fri Jul 15 07:13:01 2016
@@ -20,6 +20,7 @@ package org.apache.velocity.test.misc;
  */
 
 import java.io.InputStream;
+import java.io.Reader;
 
 import org.apache.commons.collections.ExtendedProperties;
 import org.apache.velocity.exception.ResourceNotFoundException;
@@ -40,7 +41,12 @@ public class ExceptionGeneratingResource
     {
     }
 
-    public InputStream getResourceStream(String source) throws ResourceNotFoundException
+    public @Deprecated InputStream getResourceStream(String source) throws ResourceNotFoundException
+    {
+        throw new RuntimeException("exception");
+    }
+
+    public Reader getResourceReader(String source, String encoding) throws ResourceNotFoundException
     {
         throw new RuntimeException("exception");
     }




Mime
View raw message