1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.services.webpage;
18
19
20 import java.io.IOException;
21 import java.io.FileOutputStream;
22 import java.io.InputStream;
23 import java.io.ByteArrayOutputStream;
24
25
26 import java.util.HashMap;
27
28
29 import java.net.URL;
30 import java.net.URLConnection;
31 import java.net.HttpURLConnection;
32 import java.net.MalformedURLException;
33
34 import org.apache.log4j.Logger;
35
36
37
38
39
40
41
42
43
44 public class WebPageCache
45 {
46
47
48 private static HashMap cache = new HashMap();
49
50
51 static Logger log = Logger.getLogger(WebPageCache.class);
52
53 /***
54 * Given a cacheable web resource, writes the content of that resource to the servlet
55 * output stream. The first time that the resource is requested, the content is
56 * fetched from the proxied host. From then on, the resource content is served up from
57 * the cache.
58 *
59 * @param resource the resource that is being cached.
60 * @param neid the network element id.
61 * @param base the proxied host's base URL.
62 * @param host the Proxy Server base URL.
63 * @param data the RunData for the request.
64 * @return boolean true if the resource was read from the cache,
65 * false if read from the server.
66 */
67 public static boolean getResourceFromCache(String resource,
68 long sid,
69 String base,
70 String host,
71 ProxyRunData data)
72 {
73 try
74 {
75 CachedResource cr = (CachedResource)cache.get(resource);
76 if (null != cr)
77 {
78
79 byte[] bytes = cr.getContent();
80 data.getResponse().getOutputStream().write(bytes, 0, bytes.length);
81 return true;
82 }
83
84
85 URL baseURL = new URL(base);
86 URL u = new URL(baseURL, resource);
87 HttpURLConnection con = (HttpURLConnection)u.openConnection();
88
89 con.setDoInput(true);
90 con.setAllowUserInteraction(false);
91
92 int contentType = WebPageHelper.getContentType(con.getHeaderField("content-type"), resource);
93
94 byte[] content;
95
96
97 if (WebPageHelper.CT_JS == contentType)
98 content = rewriteScript(con, sid, host, data, resource, base);
99 else
100 content = getContentAndWrite(con, data);
101
102
103 cr = new CachedResource(contentType, content);
104 cache.put(resource, cr);
105
106 }
107 catch (MalformedURLException ex)
108 {
109 log.error("CACHE URL EX:" + ex);
110 return false;
111
112 }
113 catch (IOException ex)
114 {
115 log.error("CACHE IO:" + ex);
116 return false;
117 }
118 return true;
119 }
120
121
122 /***
123 * Determines if a resource is cacheable, dependent on the extension:
124 * defined in CACHEABLE_RESOURCES (gif, jpeg, jpg, png, js, css)
125 *
126 * @param resource the resource that is being proxied.
127 * @return boolean true if the resource is a cacheable, otherwise false.
128 *
129 */
130 public static String[] CACHEABLE_RESOURCES = {
131 ".gif", ".jpeg", ".jpg", ".png", ".js", ".css" };
132
133 public static boolean isCacheableResource(String resource)
134 {
135 int pos = resource.lastIndexOf('.');
136 if (pos == -1)
137 return false;
138
139 if (resource.endsWith(".html"))
140 return false;
141
142 int length = resource.length();
143 if (pos >= length)
144 return false;
145
146 String ext = resource.substring(pos);
147 for (int ix=0; ix < CACHEABLE_RESOURCES.length; ix++) {
148 if (ext.equalsIgnoreCase(CACHEABLE_RESOURCES[ix])) {
149 return true;
150 }
151 }
152 return false;
153 }
154
155
156 /***
157 * Retrieves the content from the proxied host for the requested.
158 * Per cacheable resource, this is only called once. All further requests will
159 * return the cached content. The content is immediately written to the servlet's
160 * response output stream.
161 *
162 * @param con the HTTP connection to the proxied host.
163 * @param response the servlet response.
164 * @return byte[] the resource content, which will be stored in the cache.
165 */
166 public static byte[] getContentAndWrite(URLConnection con,
167 ProxyRunData data) throws IOException
168 {
169 int CAPACITY = 4096;
170
171 InputStream is = con.getInputStream();
172 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
173 byte[] bytes = new byte[CAPACITY];
174
175 int readCount = 0;
176 while( ( readCount = is.read( bytes )) > 0 ) {
177
178 buffer.write( bytes, 0, readCount);
179 data.getResponse().getOutputStream().write(bytes, 0, readCount);
180 }
181
182 is.close();
183 return buffer.toByteArray();
184 }
185
186 /***
187 * Retrieves the script content from the proxied host for the requested.
188 * Per cacheable resource, this is only called once. All further requests will
189 * return the cached content. The content is first rewritten, rewriting all links
190 * found in the script back to the Proxy server. Then, the content is immediately
191 * written to the servlet's response output stream.
192 *
193 * @param con the HTTP connection to the proxied host.
194 * @param response the servlet response.
195 * @return byte[] the resource content, which will be stored in the cache.
196 */
197 public static byte[] rewriteScript(URLConnection con,
198 long sid,
199 String host,
200 ProxyRunData data,
201 String resource,
202 String base)
203 throws IOException
204 {
205 int CAPACITY = 4096;
206
207 Configuration config = Configuration.getInstance();
208 InputStream is = con.getInputStream();
209 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
210 byte[] bytes = new byte[CAPACITY];
211
212 FileOutputStream fos = null;
213 boolean logging = config.getEnableContentLog();
214
215
216 if (logging)
217 {
218 String fileName = data.getServlet().getServletContext().getRealPath(
219 config.getLogLocation() );
220 fos = new FileOutputStream(fileName, true);
221 WebPageHelper.writeHeader(fos, resource);
222 }
223
224 int readCount = 0;
225
226
227 while( ( readCount = is.read( bytes )) > 0 ) {
228
229 buffer.write( bytes, 0, readCount);
230 if (logging)
231 fos.write( bytes, 0, readCount);
232 }
233
234 if (logging)
235 fos.close();
236
237 is.close();
238
239
240 String script = buffer.toString();
241
242
243 if (sid == -1)
244 {
245
246 }
247 return script.getBytes();
248
249
250
251
252 }
253
254
255 }