KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > info > magnolia > cms > servlets > ClasspathSpool


1 package info.magnolia.cms.servlets;
2
3 import info.magnolia.cms.util.ClasspathResourcesUtil;
4
5 import java.io.IOException JavaDoc;
6 import java.io.InputStream JavaDoc;
7 import java.net.URL JavaDoc;
8 import java.net.URLConnection JavaDoc;
9 import java.util.Hashtable JavaDoc;
10 import java.util.Map JavaDoc;
11
12 import javax.servlet.ServletException JavaDoc;
13 import javax.servlet.ServletOutputStream JavaDoc;
14 import javax.servlet.http.HttpServlet JavaDoc;
15 import javax.servlet.http.HttpServletRequest JavaDoc;
16 import javax.servlet.http.HttpServletResponse JavaDoc;
17
18 import org.apache.commons.io.IOUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23
24 /**
25  * A simple spool servlet that load resources from the classpath. A simple rule for accessible resources: only files
26  * into a <code>mgnl-resources</code> folder will be loaded by this servlet (corresponding to the mapped url
27  * <code>/.resources/*</code>. This servlet should be used for authoring-only resources, like rich editor images and
28  * scripts. It's not suggested for public website resources. Content length and last modification date are not set on
29  * files returned from the classpath.
30  * @author Fabrizio Giustina
31  * @version $Revision: 6589 $ ($Author: philipp $)
32  */

33 public class ClasspathSpool extends HttpServlet JavaDoc {
34
35     /**
36      * Root directory for resources streamed from the classath. Only resources in this folder can be accessed.
37      */

38     public static final String JavaDoc MGNL_RESOURCES_ROOT = "/mgnl-resources";
39
40     /**
41      * Stable serialVersionUID.
42      */

43     private static final long serialVersionUID = 222L;
44
45     /**
46      * Logger.
47      */

48     private static Logger log = LoggerFactory.getLogger(Spool.class);
49
50     protected long getLastModified(HttpServletRequest JavaDoc req) {
51         String JavaDoc filePath = this.getFilePath(req);
52         try {
53             URL JavaDoc url = ClasspathResourcesUtil.getResource(MGNL_RESOURCES_ROOT + filePath);
54             if(url != null){
55                 URLConnection JavaDoc connection = url.openConnection();
56                 return connection.getLastModified();
57             }
58         }
59         catch (IOException JavaDoc e) {
60             // just ignore
61
}
62
63         return -1;
64     }
65     
66     /**
67      * All static resource requests are handled here.
68      * @param request HttpServletRequest
69      * @param response HttpServletResponse
70      * @throws IOException for error in accessing the resource or the servlet output stream
71      */

72     public void doGet(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) throws IOException JavaDoc {
73
74         String JavaDoc filePath = getFilePath(request);
75         
76         if (StringUtils.contains(filePath, "*")) {
77             streamMultipleFile(response, filePath);
78         }
79         else if (StringUtils.contains(filePath, "|")) {
80             String JavaDoc[] paths = StringUtils.split(filePath, "|");
81             streamMultipleFile(response, paths);
82         }
83         else {
84             streamSingleFile(response, filePath);
85         }
86     }
87
88     protected String JavaDoc getFilePath(HttpServletRequest JavaDoc request) {
89         // handle includes
90
String JavaDoc filePath = (String JavaDoc) request.getAttribute("javax.servlet.include.path_info");
91
92         // handle forwards
93
if (StringUtils.isEmpty(filePath)) {
94             filePath = (String JavaDoc) request.getAttribute("javax.servlet.forward.path_info");
95         }
96
97         // standard request
98
if (StringUtils.isEmpty(filePath)) {
99             filePath = request.getPathInfo();
100         }
101         return filePath;
102     }
103
104     private Map JavaDoc multipleFilePathsCache;
105
106     /**
107      * @see javax.servlet.GenericServlet#init()
108      */

109     public void init() throws ServletException JavaDoc {
110         super.init();
111         multipleFilePathsCache = new Hashtable JavaDoc();
112     }
113
114     /**
115      * @see javax.servlet.GenericServlet#destroy()
116      */

117     public void destroy() {
118         super.destroy();
119         multipleFilePathsCache.clear();
120     }
121
122     /**
123      * Join and strem multiple files, using a "regexp-like" pattern. Only a single "*" is allowed as keyword in the
124      * request URI.
125      * @param response
126      * @param filePath
127      * @throws IOException
128      */

129     private void streamMultipleFile(HttpServletResponse JavaDoc response, String JavaDoc filePath) throws IOException JavaDoc {
130         if (log.isDebugEnabled()) {
131             log.debug("aggregating files for request {}", filePath);
132         }
133
134         String JavaDoc[] paths = (String JavaDoc[]) multipleFilePathsCache.get(filePath);
135         if (paths == null) {
136             final String JavaDoc startsWith = MGNL_RESOURCES_ROOT + StringUtils.substringBefore(filePath, "*");
137             final String JavaDoc endssWith = StringUtils.substringAfterLast(filePath, "*");
138
139             paths = ClasspathResourcesUtil.findResources(new ClasspathResourcesUtil.Filter() {
140
141                 public boolean accept(String JavaDoc name) {
142                     return name.startsWith(startsWith) && name.endsWith(endssWith);
143                 }
144             });
145         }
146         multipleFilePathsCache.put(filePath, paths);
147
148         if (paths.length == 0) {
149             response.sendError(HttpServletResponse.SC_NOT_FOUND);
150             return;
151         }
152
153         streamMultipleFile(response, paths);
154     }
155
156     /**
157      * @param response
158      * @param paths
159      * @throws IOException
160      */

161     private void streamMultipleFile(HttpServletResponse JavaDoc response, String JavaDoc[] paths) throws IOException JavaDoc {
162         ServletOutputStream JavaDoc out = response.getOutputStream();
163         InputStream JavaDoc in = null;
164
165         for (int j = 0; j < paths.length; j++) {
166             try {
167                 String JavaDoc path = paths[j];
168                 if (!path.startsWith(MGNL_RESOURCES_ROOT)) {
169                     path = MGNL_RESOURCES_ROOT + path;
170                 }
171                 in = ClasspathResourcesUtil.getStream(path);
172                 if (in != null) {
173                     IOUtils.copy(in, out);
174                 }
175             }
176             finally {
177                 IOUtils.closeQuietly(in);
178             }
179         }
180
181         out.flush();
182         IOUtils.closeQuietly(out);
183     }
184
185     /**
186      * @param response
187      * @param filePath
188      * @throws IOException
189      */

190     private void streamSingleFile(HttpServletResponse JavaDoc response, String JavaDoc filePath) throws IOException JavaDoc {
191         InputStream JavaDoc in = null;
192         // this method caches content if possible and checks the magnolia.develop property to avoid
193
// caching during the developement process
194
try {
195             in = ClasspathResourcesUtil.getStream(MGNL_RESOURCES_ROOT + filePath);
196         }
197         catch (IOException JavaDoc e) {
198             IOUtils.closeQuietly(in);
199         }
200
201         if (in == null) {
202             if (!response.isCommitted()) {
203                 response.sendError(HttpServletResponse.SC_NOT_FOUND);
204             }
205             return;
206         }
207
208         try {
209             ServletOutputStream JavaDoc out = response.getOutputStream();
210             IOUtils.copy(in, out);
211             out.flush();
212             IOUtils.closeQuietly(out);
213         }
214         catch (IOException JavaDoc e) {
215             // only log at debug level
216
// tomcat usually throws a ClientAbortException anytime the user stop loading the page
217
if (log.isDebugEnabled()) {
218                 log.debug("Unable to spool resource due to a {} exception", e.getClass().getName()); //$NON-NLS-1$
219
}
220             if (!response.isCommitted()) {
221                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
222             }
223         }
224         finally {
225             IOUtils.closeQuietly(in);
226         }
227     }
228
229 }
230
Popular Tags