1/*2 * Copyright 2000-2004 The Apache Software Foundation.3 * 4 * Licensed under the Apache License, Version 2.0 (the "License");5 * you may not use this file except in compliance with the License.6 * You may obtain a copy of the License at7 * 8 * http://www.apache.org/licenses/LICENSE-2.09 * 10 * Unless required by applicable law or agreed to in writing, software11 * distributed under the License is distributed on an "AS IS" BASIS,12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13 * See the License for the specific language governing permissions and14 * limitations under the License.15 */1617packageorg.apache.jetspeed.services.webpage;
1819// java.io20import java.io.IOException;
21import java.io.FileOutputStream;
22import java.io.InputStream;
23import java.io.ByteArrayOutputStream;
2425// java.util26import java.util.HashMap;
2728// java.net29import java.net.URL;
30import java.net.URLConnection;
31import java.net.HttpURLConnection;
32import java.net.MalformedURLException;
3334import org.apache.log4j.Logger;
353637/*38 * Implements the WebPage service's static resource cache, for optimizing access to 39 * static resources from proxied hosts. Resources currently cached are read-only, static40 * resources such as images, style sheets and scripts.41 *42 */4344publicclassWebPageCache45 {
4647// The Cache48privatestatic HashMap cache = new HashMap();
4950// the log file singleton instance51static Logger log = Logger.getLogger(WebPageCache.class);
5253/***54 * Given a cacheable web resource, writes the content of that resource to the servlet55 * output stream. The first time that the resource is requested, the content is56 * fetched from the proxied host. From then on, the resource content is served up from57 * 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 */67publicstaticboolean getResourceFromCache(String resource,
68long sid,
69 String base,
70 String host,
71ProxyRunData data)
72 {
73try74 {
75CachedResource cr = (CachedResource)cache.get(resource);
76if (null != cr) // is it in the cache...77 {
78// yes, return cached item79 byte[] bytes = cr.getContent();
80 data.getResponse().getOutputStream().write(bytes, 0, bytes.length);
81returntrue;
82 }
8384// not found in cache, so get it from proxied host85 URL baseURL = new URL(base);
86 URL u = new URL(baseURL, resource);
87 HttpURLConnection con = (HttpURLConnection)u.openConnection();
8889 con.setDoInput(true);
90 con.setAllowUserInteraction(false);
9192int contentType = WebPageHelper.getContentType(con.getHeaderField("content-type"), resource);
9394 byte[] content;
9596// get the proxied content, if its script, rewrite it97if (WebPageHelper.CT_JS == contentType)
98 content = rewriteScript(con, sid, host, data, resource, base);
99else100 content = getContentAndWrite(con, data);
101102// create a new cached resource and put it in the cache103 cr = newCachedResource(contentType, content);
104 cache.put(resource, cr);
105106 }
107catch (MalformedURLException ex)
108 {
109 log.error("CACHE URL EX:" + ex);
110return false;
111112 }
113catch (IOException ex)
114 {
115 log.error("CACHE IO:" + ex);
116return false;
117 }
118returntrue;
119 }
120121122/***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 */130publicstatic String[] CACHEABLE_RESOURCES = {
131".gif", ".jpeg", ".jpg", ".png", ".js", ".css" };
132133publicstaticboolean isCacheableResource(String resource)
134 {
135int pos = resource.lastIndexOf('.');
136if (pos == -1)
137return false;
138139if (resource.endsWith(".html"))
140return false;
141142int length = resource.length();
143if (pos >= length)
144return false;
145146 String ext = resource.substring(pos);
147for (int ix=0; ix < CACHEABLE_RESOURCES.length; ix++) {
148if (ext.equalsIgnoreCase(CACHEABLE_RESOURCES[ix])) {
149returntrue;
150 }
151 }
152return false;
153 }
154155156/***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 */166publicstatic byte[] getContentAndWrite(URLConnection con,
167ProxyRunData data) throws IOException
168 {
169int CAPACITY = 4096;
170171 InputStream is = con.getInputStream();
172 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
173 byte[] bytes = new byte[CAPACITY];
174175int readCount = 0;
176while( ( readCount = is.read( bytes )) > 0 ) {
177178 buffer.write( bytes, 0, readCount);
179 data.getResponse().getOutputStream().write(bytes, 0, readCount);
180 }
181182 is.close();
183return buffer.toByteArray();
184 }
185186/***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 links190 * 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 */197publicstatic byte[] rewriteScript(URLConnection con,
198long sid,
199 String host,
200ProxyRunData data,
201 String resource,
202 String base)
203 throws IOException
204 {
205int CAPACITY = 4096;
206207Configuration config = Configuration.getInstance();
208 InputStream is = con.getInputStream();
209 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
210 byte[] bytes = new byte[CAPACITY];
211212 FileOutputStream fos = null;
213boolean logging = config.getEnableContentLog();
214215// log content to a file if enabled216if (logging)
217 {
218 String fileName = data.getServlet().getServletContext().getRealPath(
219 config.getLogLocation() );
220 fos = new FileOutputStream(fileName, true);
221 WebPageHelper.writeHeader(fos, resource);
222 }
223224int readCount = 0;
225226// read in the script 227while( ( readCount = is.read( bytes )) > 0 ) {
228229 buffer.write( bytes, 0, readCount);
230if (logging)
231 fos.write( bytes, 0, readCount);
232 }
233234if (logging)
235 fos.close();
236237 is.close();
238239240 String script = buffer.toString();
241242243if (sid == -1)
244 { // FIXME: I seem to have lost this code....245// return HTMLRewriter.rewriteScript(script, resource, host, base);246 }
247return script.getBytes();
248249// FIXME: not rewriting scripts...250// return Rewriter.rewriteScript(script, sid, proxyHost, base);251252 }
253254255 }