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 import java.io.IOException;
24 import java.net.URL;
25 import java.net.URLConnection;
26 import java.util.HashMap;
27 import org.apache.commons.collections.ExtendedProperties;
28 import org.apache.commons.lang.StringUtils;
29 import org.apache.velocity.exception.ResourceNotFoundException;
30 import org.apache.velocity.runtime.resource.Resource;
31
32 /**
33 * This is a simple URL-based loader.
34 *
35 * @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
36 * @author <a href="mailto:nbubna@apache.org">Nathan Bubna</a>
37 * @version $Id: URLResourceLoader.java 191743 2005-06-21 23:22:20Z dlr $
38 */
39 public class URLResourceLoader extends ResourceLoader
40 {
41 private String[] roots = null;
42 protected HashMap templateRoots = null;
43
44 /**
45 * @see org.apache.velocity.runtime.resource.loader.ResourceLoader#init(org.apache.commons.collections.ExtendedProperties)
46 */
47 public void init(ExtendedProperties configuration)
48 {
49 log.trace("URLResourceLoader : initialization starting.");
50
51 roots = configuration.getStringArray("root");
52
53 if (log.isInfoEnabled())
54 {
55 for (int i=0; i < roots.length; i++)
56 {
57 log.info("URLResourceLoader : adding root '" + roots[i] + "'");
58 }
59 }
60
61 // init the template paths map
62 templateRoots = new HashMap();
63
64 log.trace("URLResourceLoader : initialization complete.");
65 }
66
67 /**
68 * Get an InputStream so that the Runtime can build a
69 * template with it.
70 *
71 * @param name name of template to fetch bytestream of
72 * @return InputStream containing the template
73 * @throws ResourceNotFoundException if template not found
74 * in the file template path.
75 */
76 public synchronized InputStream getResourceStream(String name)
77 throws ResourceNotFoundException
78 {
79 if (StringUtils.isEmpty(name))
80 {
81 throw new ResourceNotFoundException("URLResourceLoader : No template name provided");
82 }
83
84 InputStream inputStream = null;
85 Exception exception = null;
86 for(int i=0; i < roots.length; i++)
87 {
88 try
89 {
90 URL u = new URL(roots[i] + name);
91 inputStream = u.openStream();
92
93 if (inputStream != null)
94 {
95 if (log.isDebugEnabled()) log.debug("URLResourceLoader: Found '"+name+"' at '"+roots[i]+"'");
96
97 // save this root for later re-use
98 templateRoots.put(name, roots[i]);
99 break;
100 }
101 }
102 catch(IOException ioe)
103 {
104 if (log.isDebugEnabled()) log.debug("URLResourceLoader: Exception when looking for '"+name+"' at '"+roots[i]+"'", ioe);
105
106 // only save the first one for later throwing
107 if (exception == null)
108 {
109 exception = ioe;
110 }
111 }
112 }
113
114 // if we never found the template
115 if (inputStream == null)
116 {
117 String msg;
118 if (exception == null)
119 {
120 msg = "URLResourceLoader : Resource '" + name + "' not found.";
121 }
122 else
123 {
124 msg = exception.getMessage();
125 }
126 // convert to a general Velocity ResourceNotFoundException
127 throw new ResourceNotFoundException(msg);
128 }
129
130 return inputStream;
131 }
132
133 /**
134 * Checks to see if a resource has been deleted, moved or modified.
135 *
136 * @param resource Resource The resource to check for modification
137 * @return boolean True if the resource has been modified, moved, or unreachable
138 */
139 public boolean isSourceModified(Resource resource)
140 {
141 long fileLastModified = getLastModified(resource);
142 // if the file is unreachable or otherwise changed
143 if (fileLastModified == 0 ||
144 fileLastModified != resource.getLastModified())
145 {
146 return true;
147 }
148 return false;
149 }
150
151 /**
152 * Checks to see when a resource was last modified
153 *
154 * @param resource Resource the resource to check
155 * @return long The time when the resource was last modified or 0 if the file can't be reached
156 */
157 public long getLastModified(Resource resource)
158 {
159 // get the previously used root
160 String name = resource.getName();
161 String root = (String)templateRoots.get(name);
162
163 try
164 {
165 // get a connection to the URL
166 URL u = new URL(root + name);
167 URLConnection conn = u.openConnection();
168 return conn.getLastModified();
169 }
170 catch (IOException ioe)
171 {
172 // the file is not reachable at its previous address
173 log.warn("URLResourceLoader: '" + name +
174 "' is no longer reachable at '" + root + "'", ioe);
175 return 0;
176 }
177 }
178
179 }