1 package org.apache.velocity.runtime.resource.loader;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.InputStream;
23 import java.io.IOException;
24 import java.lang.reflect.Method;
25 import java.net.URL;
26 import java.net.URLConnection;
27 import java.util.HashMap;
28 import org.apache.commons.collections.ExtendedProperties;
29 import org.apache.commons.lang.StringUtils;
30 import org.apache.velocity.exception.VelocityException;
31 import org.apache.velocity.exception.ResourceNotFoundException;
32 import org.apache.velocity.runtime.resource.Resource;
33
34
35
36
37
38
39
40
41
42 public class URLResourceLoader extends ResourceLoader
43 {
44 private String[] roots = null;
45 protected HashMap templateRoots = null;
46 private int timeout = -1;
47 private Method[] timeoutMethods;
48
49
50
51
52 public void init(ExtendedProperties configuration)
53 {
54 log.trace("URLResourceLoader : initialization starting.");
55
56 roots = configuration.getStringArray("root");
57 if (log.isDebugEnabled())
58 {
59 for (int i=0; i < roots.length; i++)
60 {
61 log.debug("URLResourceLoader : adding root '" + roots[i] + "'");
62 }
63 }
64
65 timeout = configuration.getInt("timeout", -1);
66 if (timeout > 0)
67 {
68 try
69 {
70 Class[] types = new Class[] { Integer.TYPE };
71 Method conn = URLConnection.class.getMethod("setConnectTimeout", types);
72 Method read = URLConnection.class.getMethod("setReadTimeout", types);
73 timeoutMethods = new Method[] { conn, read };
74 log.debug("URLResourceLoader : timeout set to "+timeout);
75 }
76 catch (NoSuchMethodException nsme)
77 {
78 log.debug("URLResourceLoader : Java 1.5+ is required to customize timeout!", nsme);
79 timeout = -1;
80 }
81 }
82
83
84 templateRoots = new HashMap();
85
86 log.trace("URLResourceLoader : initialization complete.");
87 }
88
89
90
91
92
93
94
95
96
97
98 public synchronized InputStream getResourceStream(String name)
99 throws ResourceNotFoundException
100 {
101 if (StringUtils.isEmpty(name))
102 {
103 throw new ResourceNotFoundException("URLResourceLoader : No template name provided");
104 }
105
106 InputStream inputStream = null;
107 Exception exception = null;
108 for(int i=0; i < roots.length; i++)
109 {
110 try
111 {
112 URL u = new URL(roots[i] + name);
113 URLConnection conn = u.openConnection();
114 tryToSetTimeout(conn);
115 inputStream = conn.getInputStream();
116
117 if (inputStream != null)
118 {
119 if (log.isDebugEnabled()) log.debug("URLResourceLoader: Found '"+name+"' at '"+roots[i]+"'");
120
121
122 templateRoots.put(name, roots[i]);
123 break;
124 }
125 }
126 catch(IOException ioe)
127 {
128 if (log.isDebugEnabled()) log.debug("URLResourceLoader: Exception when looking for '"+name+"' at '"+roots[i]+"'", ioe);
129
130
131 if (exception == null)
132 {
133 exception = ioe;
134 }
135 }
136 }
137
138
139 if (inputStream == null)
140 {
141 String msg;
142 if (exception == null)
143 {
144 msg = "URLResourceLoader : Resource '" + name + "' not found.";
145 }
146 else
147 {
148 msg = exception.getMessage();
149 }
150
151 throw new ResourceNotFoundException(msg);
152 }
153
154 return inputStream;
155 }
156
157
158
159
160
161
162
163 public boolean isSourceModified(Resource resource)
164 {
165 long fileLastModified = getLastModified(resource);
166
167 if (fileLastModified == 0 ||
168 fileLastModified != resource.getLastModified())
169 {
170 return true;
171 }
172 return false;
173 }
174
175
176
177
178
179
180
181 public long getLastModified(Resource resource)
182 {
183
184 String name = resource.getName();
185 String root = (String)templateRoots.get(name);
186
187 try
188 {
189
190 URL u = new URL(root + name);
191 URLConnection conn = u.openConnection();
192 tryToSetTimeout(conn);
193 return conn.getLastModified();
194 }
195 catch (IOException ioe)
196 {
197
198 String msg = "URLResourceLoader: '"+name+"' is no longer reachable at '"+root+"'";
199 log.error(msg, ioe);
200 throw new ResourceNotFoundException(msg, ioe);
201 }
202 }
203
204
205
206
207
208 public int getTimeout()
209 {
210 return timeout;
211 }
212
213 private void tryToSetTimeout(URLConnection conn)
214 {
215 if (timeout > 0)
216 {
217 Object[] arg = new Object[] { new Integer(timeout) };
218 try
219 {
220 timeoutMethods[0].invoke(conn, arg);
221 timeoutMethods[1].invoke(conn, arg);
222 }
223 catch (Exception e)
224 {
225 String msg = "Unexpected exception while setting connection timeout for "+conn;
226 log.error(msg, e);
227 throw new VelocityException(msg, e);
228 }
229 }
230 }
231
232 }