1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package no.sesat.search.view.velocity;
18
19 import java.io.IOException;
20 import java.net.URL;
21 import java.net.MalformedURLException;
22 import java.io.InputStream;
23 import java.util.regex.Matcher;
24 import no.sesat.search.http.HTTPClient;
25 import no.sesat.search.site.config.UrlResourceLoader;
26 import no.sesat.search.site.Site;
27 import org.apache.log4j.Logger;
28 import org.apache.velocity.runtime.resource.Resource;
29 import org.apache.velocity.runtime.resource.loader.ResourceLoader;
30 import org.apache.velocity.exception.ResourceNotFoundException;
31 import org.apache.commons.collections.ExtendedProperties;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class URLResourceLoader extends ResourceLoader {
53
54 public interface Context{
55 boolean doesUrlExist(final URL url);
56 URL getURL(final String resource, final Site site);
57 }
58
59
60
61 private static final Logger LOG = Logger.getLogger(URLResourceLoader.class);
62
63 private static final String ERR_RESOURCE_NOT_FOUND = "Cannot find resource ";
64 private static final String DEBUG_LOOKING_FOR = "Looking for ";
65 private static final String DEBUG_EXISTS = "Positive HEAD on ";
66 private static final String DEBUG_FULL_URL_IS = "Real URL is ";
67 private static final String DEBUG_HOST_HEADER_IS = "URL's host-header is ";
68 private static final String DEBUG_DOESNT_EXIST = "Using fallback URL";
69
70
71
72
73 private Site site;
74
75
76
77
78 private static Context context = new DefaultContext();
79
80
81 static void setContext(final Context context){
82 URLResourceLoader.context = context;
83 }
84
85
86
87
88
89
90
91
92 public void init(final ExtendedProperties configuration) {
93
94 site = (Site)rsvc.getProperty(Site.NAME_KEY);
95 }
96
97
98
99
100
101
102
103
104
105
106 public
107
108 LOG.trace("start getResourceStream( " + url + " )");
109 try{
110 synchronized( url.intern() ){
111 return getStream(findUrl(url, site));
112 }
113
114 }catch( IOException e ){
115 LOG.debug( ERR_RESOURCE_NOT_FOUND + url);
116 throw new ResourceNotFoundException( ERR_RESOURCE_NOT_FOUND + url );
117 }
118 }
119
120
121
122 public boolean isSourceModified(Resource resource){
123
124 final boolean result = getLastModified(resource) > resource.getLastModified();
125 LOG.debug("isSourceModified( "+resource.getName()+" ): "+result);
126 return result;
127 }
128
129
130
131 public long getLastModified(Resource resource){
132 try{
133 final URL url = findUrl(resource.getName(), site);
134 final HTTPClient client = HTTPClient.instance(url, "localhost");
135
136 return client.getLastModified("");
137 }catch( ResourceNotFoundException e ){
138 LOG.error( ERR_RESOURCE_NOT_FOUND + resource.getName() );
139 }catch( IOException e ){
140 LOG.error( ERR_RESOURCE_NOT_FOUND + resource.getName() );
141 }
142 return 0;
143 }
144
145
146
147
148
149
150
151
152 private static URL findUrl(final String url, final Site currentSite) throws ResourceNotFoundException{
153
154 try{
155 LOG.trace(DEBUG_LOOKING_FOR + url );
156 return findUrlImpl(url, currentSite);
157
158 }catch( IOException e ){
159 LOG.error( ERR_RESOURCE_NOT_FOUND + url, e );
160 throw new ResourceNotFoundException( ERR_RESOURCE_NOT_FOUND + url );
161 }
162 }
163
164 private static URL findUrlImpl(final String url, final Site currentSite)
165 throws IOException, ResourceNotFoundException {
166
167 final URL u = context.getURL(url, currentSite);
168
169 if (context.doesUrlExist(u)) {
170 return u;
171 } else {
172 final Site parent = currentSite.getParent();
173
174 if (null == parent) {
175 throw new ResourceNotFoundException( ERR_RESOURCE_NOT_FOUND + url );
176 }
177
178 if (LOG.isTraceEnabled()) {
179 LOG.trace(DEBUG_DOESNT_EXIST + parent.getName());
180 }
181
182
183 return findUrlImpl(getFallbackURL(url, currentSite, parent), parent);
184 }
185 }
186
187 private static String getFallbackURL(final String url, final Site currSite, final Site ancestorSite) {
188
189 final String oldUrl = currSite.getName() + currSite.getConfigContext();
190 final String newUrl = ancestorSite.getName() + ancestorSite.getConfigContext();
191
192 return url.replaceFirst(Matcher.quoteReplacement(oldUrl), newUrl);
193 }
194
195
196 private static InputStream getStream(final URL url) throws IOException{
197
198 final HTTPClient client = HTTPClient.instance(url, "localhost");
199 try{
200 return client.getBufferedStream("");
201 }catch(IOException ioe){
202 throw client.interceptIOException(ioe);
203 }
204 }
205
206
207
208
209 private static final class DefaultContext implements Context{
210 public boolean doesUrlExist(final URL url) {
211 return UrlResourceLoader.doesUrlExist(url);
212 }
213
214 public URL getURL(final String resource, final Site site) {
215 try {
216 return new URL(resource);
217 } catch (MalformedURLException e) {
218 throw new ResourceNotFoundException(e);
219 }
220 }
221 }
222 }
223