KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > whack > container > ComponentServlet


1 /**
2  * $RCSfile: ComponentServlet.java,v $
3  * $Revision: 1.1 $
4  * $Date: 2005/04/12 07:06:38 $
5  *
6  * Copyright 2005 Jive Software.
7  *
8  * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */

20
21 package org.jivesoftware.whack.container;
22
23 import org.dom4j.Document;
24 import org.dom4j.Element;
25 import org.dom4j.io.SAXReader;
26 import org.xmpp.component.Component;
27 import org.xmpp.component.ComponentManager;
28
29 import javax.servlet.ServletConfig JavaDoc;
30 import javax.servlet.ServletException JavaDoc;
31 import javax.servlet.ServletOutputStream JavaDoc;
32 import javax.servlet.http.HttpServlet JavaDoc;
33 import javax.servlet.http.HttpServletRequest JavaDoc;
34 import javax.servlet.http.HttpServletResponse JavaDoc;
35 import java.io.*;
36 import java.util.HashMap JavaDoc;
37 import java.util.List JavaDoc;
38 import java.util.Map JavaDoc;
39 import java.util.concurrent.ConcurrentHashMap JavaDoc;
40
41 /**
42  * The component servlet acts as a proxy for web requests (in the web admin)
43  * to components. Since components can be dynamically loaded and live in a different place
44  * than normal Whack admin console files, it's not possible to have them
45  * added to the normal Whack admin console web app directory.<p>
46  * <p/>
47  * The servlet listens for requests in the form <tt>/components/[componentName]/[JSP File]</tt>
48  * (e.g. <tt>/components/foo/example.jsp</tt>). It also listens for image requests in the
49  * the form <tt>/components/[componentName]/images/*.png|gif</tt> (e.g.
50  * <tt>/components/foo/images/example.gif</tt>).<p>
51  * <p/>
52  * JSP files must be compiled and available via the component's class loader. The mapping
53  * between JSP name and servlet class files is defined in [componentName]/web/web.xml.
54  * Typically, this file is auto-generated by the JSP compiler when packaging the component.
55  *
56  * @author Matt Tucker
57  * @author Gaston Dombiak
58  */

59 public class ComponentServlet extends HttpServlet JavaDoc {
60
61     private static Map JavaDoc<String JavaDoc, HttpServlet JavaDoc> servlets;
62     private static File componentDirectory;
63     private static ServletConfig JavaDoc servletConfig;
64
65     private static ComponentManager manager;
66
67     static {
68         servlets = new ConcurrentHashMap JavaDoc<String JavaDoc, HttpServlet JavaDoc>();
69         componentDirectory = new File(ServerContainer.getInstance().getHomeDirectory(), "components");
70         manager = ServerContainer.getInstance().getManager();
71     }
72
73     public void init(ServletConfig JavaDoc config) throws ServletException JavaDoc {
74         super.init(config);
75         servletConfig = config;
76     }
77
78     public void service(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) throws ServletException JavaDoc, IOException {
79         String JavaDoc pathInfo = request.getPathInfo();
80         if (pathInfo == null) {
81             response.setStatus(HttpServletResponse.SC_NOT_FOUND);
82             return;
83         }
84         else {
85             try {
86                 // Handle JSP requests.
87
if (pathInfo.endsWith(".jsp")) {
88                     handleJSP(pathInfo, request, response);
89                     return;
90                 }
91                 // Handle image requests.
92
else if (pathInfo.endsWith(".gif") || pathInfo.endsWith(".png")) {
93                     handleImage(pathInfo, response);
94                     return;
95                 }
96                 // Handle servlet requests.
97
else if (servlets.containsKey(pathInfo.substring(1).toLowerCase())) {
98                     handleServlet(pathInfo, request, response);
99                 }
100                 // Anything else results in a 404.
101
else {
102                     response.setStatus(HttpServletResponse.SC_NOT_FOUND);
103                     return;
104                 }
105             }
106             catch (Exception JavaDoc e) {
107                 manager.getLog().error(e);
108                 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
109                 return;
110             }
111         }
112     }
113
114     /**
115      * Registers all JSP page servlets for a component.
116      *
117      * @param finder the component finder.
118      * @param component the component.
119      * @param webXML the web.xml file containing JSP page names to servlet class file
120      * mappings.
121      */

122     public static void registerServlets(ComponentFinder finder, Component component, File webXML) {
123         if (!webXML.exists()) {
124             manager.getLog().error("Could not register component servlets, file " + webXML.getAbsolutePath() +
125                     " does not exist.");
126             return;
127         }
128         // Find the name of the component directory given that the webXML file
129
// lives in plugins/[pluginName]/web/web.xml
130
String JavaDoc pluginName = webXML.getParentFile().getParentFile().getName();
131         try {
132             // Make the reader non-validating so that it doesn't try to resolve external
133
// DTD's. Trying to resolve external DTD's can break on some firewall configurations.
134
SAXReader saxReader = new SAXReader(false);
135             saxReader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",
136                     false);
137             Document doc = saxReader.read(webXML);
138             // Find all <servlet> entries to discover name to class mapping.
139
List JavaDoc classes = doc.selectNodes("//servlet");
140             Map JavaDoc<String JavaDoc, Class JavaDoc> classMap = new HashMap JavaDoc<String JavaDoc, Class JavaDoc>();
141             for (int i = 0; i < classes.size(); i++) {
142                 Element servletElement = (Element)classes.get(i);
143                 String JavaDoc name = servletElement.element("servlet-name").getTextTrim();
144                 String JavaDoc className = servletElement.element("servlet-class").getTextTrim();
145                 classMap.put(name, finder.loadClass(className, component));
146             }
147             // Find all <servelt-mapping> entries to discover name to URL mapping.
148
List JavaDoc names = doc.selectNodes("//servlet-mapping");
149             for (int i = 0; i < names.size(); i++) {
150                 Element nameElement = (Element)names.get(i);
151                 String JavaDoc name = nameElement.element("servlet-name").getTextTrim();
152                 String JavaDoc url = nameElement.element("url-pattern").getTextTrim();
153                 // Register the servlet for the URL.
154
Class JavaDoc servletClass = classMap.get(name);
155                 Object JavaDoc instance = servletClass.newInstance();
156                 if (instance instanceof HttpServlet JavaDoc) {
157                     // Initialize the servlet then add it to the map..
158
((HttpServlet JavaDoc)instance).init(servletConfig);
159                     servlets.put(pluginName + url, (HttpServlet JavaDoc)instance);
160                 }
161                 else {
162                     manager.getLog().warn("Could not load " + (pluginName + url) + ": not a servlet.");
163                 }
164             }
165         }
166         catch (Throwable JavaDoc e) {
167             manager.getLog().error(e);
168         }
169     }
170
171     /**
172      * Unregisters all JSP page servlets for a component.
173      *
174      * @param webXML the web.xml file containing JSP page names to servlet class file
175      * mappings.
176      */

177     public static void unregisterServlets(File webXML) {
178         if (!webXML.exists()) {
179             manager.getLog().error("Could not unregister component servlets, file " + webXML.getAbsolutePath() +
180                     " does not exist.");
181             return;
182         }
183         // Find the name of the component directory given that the webXML file
184
// lives in plugins/[pluginName]/web/web.xml
185
String JavaDoc pluginName = webXML.getParentFile().getParentFile().getName();
186         try {
187             SAXReader saxReader = new SAXReader(false);
188             saxReader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",
189                     false);
190             Document doc = saxReader.read(webXML);
191             // Find all <servelt-mapping> entries to discover name to URL mapping.
192
List JavaDoc names = doc.selectNodes("//servlet-mapping");
193             for (int i = 0; i < names.size(); i++) {
194                 Element nameElement = (Element)names.get(i);
195                 String JavaDoc url = nameElement.element("url-pattern").getTextTrim();
196                 // Destroy the servlet than remove from servlets map.
197
HttpServlet JavaDoc servlet = servlets.get(pluginName + url);
198                 servlet.destroy();
199                 servlets.remove(pluginName + url);
200                 servlet = null;
201             }
202         }
203         catch (Throwable JavaDoc e) {
204             manager.getLog().error(e);
205         }
206     }
207
208     /**
209      * Handles a request for a JSP page. It checks to see if a servlet is mapped
210      * for the JSP URL. If one is found, request handling is passed to it. If no
211      * servlet is found, a 404 error is returned.
212      *
213      * @param pathInfo the extra path info.
214      * @param request the request object.
215      * @param response the response object.
216      * @throws ServletException if a servlet exception occurs while handling the
217      * request.
218      * @throws IOException if an IOException occurs while handling the request.
219      */

220     private void handleJSP(String JavaDoc pathInfo, HttpServletRequest JavaDoc request,
221                            HttpServletResponse JavaDoc response) throws ServletException JavaDoc, IOException {
222         // Strip the starting "/" from the path to find the JSP URL.
223
String JavaDoc jspURL = pathInfo.substring(1);
224         HttpServlet JavaDoc servlet = servlets.get(jspURL);
225         if (servlet != null) {
226             servlet.service(request, response);
227             return;
228         }
229         else {
230             response.setStatus(HttpServletResponse.SC_NOT_FOUND);
231             return;
232         }
233     }
234
235     /**
236      * Handles a request for a Servlet. If one is found, request handling is passed to it. If no
237      * servlet is found, a 404 error is returned.
238      *
239      * @param pathInfo the extra path info.
240      * @param request the request object.
241      * @param response the response object.
242      * @throws ServletException if a servlet exception occurs while handling the
243      * request.
244      * @throws IOException if an IOException occurs while handling the request.
245      */

246     private void handleServlet(String JavaDoc pathInfo, HttpServletRequest JavaDoc request,
247                                HttpServletResponse JavaDoc response) throws ServletException JavaDoc, IOException {
248         // Strip the starting "/" from the path to find the JSP URL.
249
String JavaDoc jspURL = pathInfo.substring(1);
250         HttpServlet JavaDoc servlet = servlets.get(jspURL);
251         if (servlet != null) {
252             servlet.service(request, response);
253             return;
254         }
255         else {
256             response.setStatus(HttpServletResponse.SC_NOT_FOUND);
257             return;
258         }
259     }
260
261     /**
262      * Handles a request for an image.
263      *
264      * @param pathInfo the extra path info.
265      * @param response the response object.
266      * @throws IOException if an IOException occurs while handling the request.
267      */

268     private void handleImage(String JavaDoc pathInfo, HttpServletResponse JavaDoc response) throws IOException {
269         String JavaDoc[] parts = pathInfo.split("/");
270         // Image request must be in correct format.
271
if (parts.length != 4) {
272             response.setStatus(HttpServletResponse.SC_NOT_FOUND);
273             return;
274         }
275         File image = new File(componentDirectory, parts[1] + File.separator + "web" +
276                 File.separator + "images" + File.separator + parts[3]);
277         if (!image.exists()) {
278             response.setStatus(HttpServletResponse.SC_NOT_FOUND);
279             return;
280         }
281         else {
282             // Content type will be GIF or PNG.
283
String JavaDoc contentType = "image/gif";
284             if (pathInfo.endsWith(".png")) {
285                 contentType = "image/png";
286             }
287             response.setHeader("Content-disposition", "filename=\"" + image + "\";");
288             response.setContentType(contentType);
289             // Write out the image to the user.
290
InputStream in = null;
291             ServletOutputStream JavaDoc out = null;
292             try {
293                 in = new BufferedInputStream(new FileInputStream(image));
294                 out = response.getOutputStream();
295
296                 // Set the size of the file.
297
response.setContentLength((int)image.length());
298
299                 // Use a 1K buffer.
300
byte[] buf = new byte[1024];
301                 int len;
302                 while ((len = in.read(buf)) != -1) {
303                     out.write(buf, 0, len);
304                 }
305             }
306             finally {
307                 try {
308                     in.close();
309                 }
310                 catch (Exception JavaDoc ignored) {
311                 }
312                 try {
313                     out.close();
314                 }
315                 catch (Exception JavaDoc ignored) {
316                 }
317             }
318         }
319     }
320 }
321
Popular Tags