KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > appclient > jws > JWSSystemServlet


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 package com.sun.enterprise.appclient.jws;
25
26 import com.sun.enterprise.appclient.AppClientInfo;
27 import com.sun.enterprise.appclient.MainWithModuleSupport;
28 import com.sun.logging.LogDomains;
29 import java.io.PrintWriter JavaDoc;
30 import java.io.UnsupportedEncodingException JavaDoc;
31 import java.net.URLDecoder JavaDoc;
32 import java.util.Date JavaDoc;
33 import java.util.Properties JavaDoc;
34 import java.util.logging.Level JavaDoc;
35 import java.util.logging.Logger JavaDoc;
36 import javax.servlet.ServletRequest JavaDoc;
37 import javax.servlet.ServletResponse JavaDoc;
38 import javax.servlet.ServletException JavaDoc;
39 import javax.servlet.http.HttpServletRequest JavaDoc;
40 import javax.servlet.http.HttpServletRequestWrapper JavaDoc;
41 import javax.servlet.http.HttpServletResponse JavaDoc;
42
43
44
45 /**
46  *Servlet that responds to all Java Web Start requests for app client-related
47  *content.
48  *<p>
49  *This servlet uses the path info from the incoming request and tries to locate
50  *a Content object in the shared Java Web Start information data structure,
51  *using the path info as a key. If such content exists and is dynamic, then
52  *the servlet substitutes some request-based properties (such as host and port)
53  *in the content and writes the result as the response.
54  *<p>
55  *If the content exists
56  *and is static, the servlet wraps the request setting the wrapped request's
57  *path from the relative path stored with the Content object.
58  *directory tree. It then invokes the default servlet's method to process
59  *the request. This is made easy because this class extends the default servlet
60  *class.
61  *<p>
62  *If the path info from the request does not map to any content, then the
63  *servlet rejects the request as not-found.
64  *
65  * @author tjquinn
66  */

67 public class JWSSystemServlet extends org.apache.catalina.servlets.DefaultServlet {
68     
69     private static final String JavaDoc ARG_QUERY_PARAM_NAME = "arg";
70     private static final String JavaDoc PROP_QUERY_PARAM_NAME = "prop";
71     private static final String JavaDoc VMARG_QUERY_PARAM_NAME = "vmarg";
72     
73     private static final String JavaDoc LAST_MODIFIED_HEADER_NAME = "Last-Modified";
74     private static final String JavaDoc DATE_HEADER_NAME = "Date";
75     
76     private static final String JavaDoc GET_METHOD_NAME = "GET";
77     
78     private final String JavaDoc lineSep = System.getProperty("line.separator");
79     
80     private AppclientJWSSupportInfo jwsInfo = null;
81
82     private Logger JavaDoc _logger=LogDomains.getLogger(NamingConventions.JWS_LOGGER);
83
84
85     /** Creates a new instance of JWSSystemServlet */
86     public JWSSystemServlet() {
87     }
88     
89     /**
90      *Initializes the servlet.
91      */

92     public void init() throws ServletException JavaDoc {
93         super.init();
94         try {
95             /*
96              *Locate - or create - the data structure object.
97              */

98             jwsInfo = AppclientJWSSupportInfo.getInstance();
99         } catch (Throwable JavaDoc thr) {
100             throw new ServletException JavaDoc(thr);
101         }
102     }
103     
104     /**
105      *Delegates the request to either this servlet's specialized handling for
106      *dynamic content or to the default servlet's handling for static content.
107      *@param request to be handled
108      *@param response to be sent
109      *@throws ServletException in case of any errors
110      */

111     public void service(ServletRequest JavaDoc request, ServletResponse JavaDoc response) throws ServletException JavaDoc {
112         if ( ! (request instanceof HttpServletRequest JavaDoc) || ! (response instanceof HttpServletResponse JavaDoc)) {
113             throw new ServletException JavaDoc("Expected HttpServletRequest and HttpServletResponse but received " + request.getClass().getName() + " and " + response.getClass().getName());
114         }
115         
116         boolean isFine = _logger.isLoggable(Level.FINE);
117         
118         HttpServletRequest JavaDoc req = (HttpServletRequest JavaDoc) request;
119         HttpServletResponse JavaDoc resp = (HttpServletResponse JavaDoc) response;
120         
121         /*
122          *See if there is Content info
123          *available for this request.
124          */

125         Content content = jwsInfo.getContent(req);
126         if (content == null) {
127             try {
128                 if (isFine) {
129                     _logger.fine("JWSSystemServlet: content not found for request: method=" + req.getMethod() + ", pathInfo=" + req.getPathInfo());
130                 }
131
132                 resp.sendError(resp.SC_NOT_FOUND, req.getPathInfo());
133             } catch (Throwable JavaDoc thr) {
134                 throw new ServletException JavaDoc("Error attempting to return not-found response", thr);
135             }
136         } else {
137             /*
138              *If the response is static, delegate to the default servlet logic.
139              *Otherwise, handle it here.
140              */

141             if (content instanceof StaticContent) {
142                 processStaticContent(req, resp, content);
143             } else {
144                 processDynamicContent(req, resp, content);
145             }
146         }
147         
148     }
149     
150     /**
151      *Handles requests for static content by delegating the request to
152      *the default servlet.
153      *@param the request to be processed
154      *@param the response to be composed
155      *@param the content, looked up from the data structure, that describes
156      *the static content itself
157      *@throws ServletException in case of any error
158      */

159     private void processStaticContent(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc resp, Content content) throws ServletException JavaDoc {
160         try {
161             StaticContent sc = (StaticContent) content;
162             
163             /*
164              *Set up the wrapped request with a URI to the file to be served that
165              *is relative to the app server's installation root directory. The
166              *web container has initialized this web app's docbase to the app
167              *server's installation root.
168              */

169             HttpServletRequest JavaDoc wrappedRequest = new JWSSystemServletRequestWrapper(req, sc.getRelativeURI());
170             if (_logger.isLoggable(Level.FINE)) {
171                 _logger.fine("JWSSystemServlet: serving static content: method=" + wrappedRequest.getMethod() + ", mapped path=" + wrappedRequest.getPathInfo());
172             }
173             
174             /*
175              *Delegate.
176              */

177             super.service(wrappedRequest, resp);
178         } catch (Throwable JavaDoc thr) {
179             throw new ServletException JavaDoc("Error processing static content for path " + content.getPath(), thr);
180         }
181     }
182     
183     /**
184      *Handles requests for dynamic content.
185      *@param the HTTP request to be serviced
186      *@param the HTTP response to be composed
187      *@param the content in which placeholders should be replaced before being written as the response
188      *@throws ServletException for any errors
189      */

190     private void processDynamicContent(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc resp, Content content) throws ServletException JavaDoc {
191         try {
192             DynamicContent dc = (DynamicContent) content;
193
194             /*
195              *Build the Properties object with the request-based tokens and values, then
196              *see if the DynamicContent that has already been retrieved already
197              *has an instance with matching content. During that search, if this
198              *is a GET request then add the text to the DynamicContent's cache
199              *if it is not already there. This helps Java Web Start manage its
200              *cache on the client side and avoid retrieving documents over the
201              *network that its cache already contains.
202              */

203             Properties JavaDoc requestPlaceholders = prepareRequestPlaceholders(req, dc);
204
205             boolean isGetMethod = req.getMethod().equals(GET_METHOD_NAME);
206             
207             DynamicContent.Instance instance = dc.findInstance(requestPlaceholders, isGetMethod /* if method == GET, then create if no instance */);
208
209             /*
210              *The findInstance invocation will return a null only if the request is an HTTP HEAD request
211              *(to check the timestamp) and the substituted content does not
212              *already appear in the DynamicContent's cache.
213              */

214             if (instance != null) {
215                 String JavaDoc responseText = instance.getText();
216                 Date JavaDoc instanceTimestamp = instance.getTimestamp();
217                 resp.setDateHeader(LAST_MODIFIED_HEADER_NAME, instanceTimestamp.getTime());
218                 resp.setDateHeader(DATE_HEADER_NAME, System.currentTimeMillis());
219                 resp.setContentType(dc.getMimeType());
220                 resp.setStatus(resp.SC_OK);
221                 /*
222                  *Only for GET should the response actually contain the content.
223                  */

224                 if (isGetMethod) {
225                     PrintWriter JavaDoc pw = resp.getWriter();
226                     pw.println(responseText);
227                     pw.flush();
228                 }
229                 if (_logger.isLoggable(Level.FINE)) {
230                     _logger.fine("JWSSystemServlet: serving dynamic content: method=" + req.getMethod() +
231                             ", pathInfo=" + req.getPathInfo() +
232                             ", queryString=" + req.getQueryString() +
233                             ", isGetMethod=" + isGetMethod +
234                             ", content timestamp=" + instanceTimestamp +
235                             ", content=" + responseText
236                             );
237                 }
238             } else {
239                 /*
240                  *The Java Web Start client has sent a HEAD request for
241                  *a URL that we recognize as one we should serve, but we have no
242                  *such document (yet). Report the requested
243                  *document as here with the current date/time. That will cause
244                  *Java Web Start on the client to re-request the full document
245                  *using a GET.
246                  */

247                 resp.setDateHeader(LAST_MODIFIED_HEADER_NAME, System.currentTimeMillis());
248                 resp.setDateHeader(DATE_HEADER_NAME, System.currentTimeMillis());
249                 resp.setContentType(dc.getMimeType());
250                 resp.setStatus(resp.SC_OK);
251             }
252         } catch (Throwable JavaDoc thr) {
253             throw new ServletException JavaDoc("Error processing dynamic content for path " + content.getPath(), thr);
254         }
255     }
256     
257     /**
258      *Initializes a Properties object with the token names and values for
259      *substitution in the dynamic content template.
260      *@param the incoming request
261      *@return Properties object containing the token names and values
262      *@throws ServletException in case of an error preparing the placeholders
263      */

264     private Properties JavaDoc prepareRequestPlaceholders(
265             HttpServletRequest JavaDoc request,
266             DynamicContent content) throws ServletException JavaDoc {
267         Properties JavaDoc answer = new Properties JavaDoc();
268         
269         answer.setProperty("request.scheme", request.getScheme());
270         answer.setProperty("request.host", request.getLocalName());
271         answer.setProperty("request.port", Integer.toString(request.getLocalPort()));
272         
273         /*
274          *Treat query parameters with the name "arg" as command line arguments to the
275          *app client.
276          */

277
278         String JavaDoc queryString = request.getQueryString();
279         StringBuilder JavaDoc queryStringPropValue = new StringBuilder JavaDoc();
280         if (queryString != null && queryString.length() > 0) {
281             queryStringPropValue.append("?").append(queryString);
282         }
283         answer.setProperty("request.web.app.context.root", NamingConventions.SYSTEM_WEBAPP_URL);
284         answer.setProperty("request.path", request.getPathInfo());
285         answer.setProperty("request.query.string", queryStringPropValue.toString());
286
287         answer.setProperty("security.setting", content.getJNLPSecuritySetting());
288         
289         /*
290          *If the content origin is a user content origin, then find out if
291          *the app client jar file recorded with this origin is signed or not.
292          *Then use that to set the property for substitution in the dynamic JNLP.
293          */

294         ContentOrigin origin = content.getOrigin();
295         answer.setProperty("appclient.user.code.is.signed", Boolean.toString(content.requiresElevatedPermissions()));
296
297         processQueryParameters(queryString, answer);
298
299         return answer;
300     }
301
302     private void processQueryParameters(String JavaDoc queryString, Properties JavaDoc answer) throws ServletException JavaDoc {
303         if (queryString == null) {
304             queryString = "";
305         }
306         String JavaDoc [] queryParams = null;
307         try {
308             queryParams = URLDecoder.decode(queryString, "UTF-8").split("&");
309         } catch (UnsupportedEncodingException JavaDoc uee) {
310             throw new ServletException JavaDoc("Error decoding query string", uee);
311         }
312
313         QueryParams arguments = new ArgQueryParams();
314         QueryParams properties = new PropQueryParams();
315         QueryParams vmArguments = new VMArgQueryParams();
316         QueryParams [] paramTypes = new QueryParams[] {arguments, properties, vmArguments};
317
318         for (String JavaDoc param : queryParams) {
319             for (QueryParams qpType : paramTypes) {
320                 if (qpType.processParameter(param)) {
321                     break;
322                 }
323             }
324         }
325         
326         answer.setProperty("request.arguments", arguments.toString());
327         answer.setProperty("request.properties", properties.toString());
328         answer.setProperty("request.vmargs", vmArguments.toString());
329     }
330         
331     private abstract class QueryParams {
332         private String JavaDoc prefix;
333         
334         protected QueryParams(String JavaDoc prefix) {
335             this.prefix = prefix;
336         }
337         
338         private boolean handles(String JavaDoc prefix) {
339             return prefix.equals(this.prefix);
340         }
341         
342         protected abstract void processValue(String JavaDoc value);
343         
344         public abstract String JavaDoc toString();
345         
346         public boolean processParameter(String JavaDoc param) {
347             boolean result = false;
348             int equalsSign = param.indexOf("=");
349             String JavaDoc value = "";
350             String JavaDoc prefix;
351             if (equalsSign != -1) {
352                 prefix = param.substring(0, equalsSign);
353             } else {
354                 prefix = param;
355             }
356             if (handles(prefix)) {
357                 result = true;
358                 if ((equalsSign + 1) < param.length()) {
359                     value = param.substring(equalsSign + 1);
360                 }
361                 processValue(value);
362             }
363             return result;
364         }
365     }
366     
367     private class ArgQueryParams extends QueryParams {
368         private StringBuilder JavaDoc arguments = new StringBuilder JavaDoc();
369         
370         public ArgQueryParams() {
371             super(ARG_QUERY_PARAM_NAME);
372         }
373         
374         public void processValue(String JavaDoc value) {
375             if (value.length() == 0) {
376                 value = "#missing#";
377             }
378             arguments.append("<argument>").append(value).append("</argument>").append(lineSep);
379         }
380         
381         public String JavaDoc toString() {
382             return arguments.toString();
383         }
384     }
385     
386     private class PropQueryParams extends QueryParams {
387         private StringBuilder JavaDoc properties = new StringBuilder JavaDoc();
388         
389         public PropQueryParams() {
390             super(PROP_QUERY_PARAM_NAME);
391         }
392         
393         public void processValue(String JavaDoc value) {
394             if (value.length() > 0) {
395                 int equalsSign = value.indexOf('=');
396                 String JavaDoc propValue = "";
397                 String JavaDoc propName;
398                 if (equalsSign > 0) {
399                     propName = value.substring(0, equalsSign);
400                     if ((equalsSign + 1) < value.length()) {
401                         propValue = value.substring(equalsSign + 1);
402                     }
403                     properties.append("<property name=\"" + propName + "\" value=\"" + propValue + "\"/>").append(lineSep);
404                 }
405             }
406         }
407         
408         public String JavaDoc toString() {
409             return properties.toString();
410         }
411         
412     }
413     
414     private class VMArgQueryParams extends QueryParams {
415         private StringBuilder JavaDoc vmArgs = new StringBuilder JavaDoc();
416         
417         public VMArgQueryParams() {
418             super(VMARG_QUERY_PARAM_NAME);
419         }
420         
421         public void processValue(String JavaDoc value) {
422             vmArgs.append(value).append(" ");
423         }
424         
425         public String JavaDoc toString() {
426             return vmArgs.length() > 0 ? " java-vm=args=\"" + vmArgs.toString() + "\"" : "";
427         }
428     }
429     
430     
431 }
432
Popular Tags