FileDocCategorySizeDatePackage
JWSSystemServlet.javaAPI DocGlassfish v2 API18739Mon Jun 18 16:14:54 BST 2007com.sun.enterprise.appclient.jws

JWSSystemServlet

public class JWSSystemServlet extends HttpServlet
Servlet that responds to all Java Web Start requests for app client-related content.

This servlet uses the path info from the incoming request and tries to locate a Content object in the shared Java Web Start information data structure, using the path info as a key. If such content exists and is dynamic, then the servlet substitutes some request-based properties (such as host and port) in the content and writes the result as the response.

If the content exists and is static, the servlet wraps the request setting the wrapped request's path from the relative path stored with the Content object. directory tree. It then invokes the default servlet's method to process the request. This is made easy because this class extends the default servlet class.

If the path info from the request does not map to any content, then the servlet rejects the request as not-found.

author
tjquinn

Fields Summary
private static final String
ARG_QUERY_PARAM_NAME
private static final String
PROP_QUERY_PARAM_NAME
private static final String
VMARG_QUERY_PARAM_NAME
private static final String
LAST_MODIFIED_HEADER_NAME
private static final String
DATE_HEADER_NAME
private static final String
GET_METHOD_NAME
private final String
lineSep
private AppclientJWSSupportInfo
jwsInfo
private Logger
_logger
RequestDispatcher
defaultDispatcher
Constructors Summary
public JWSSystemServlet()
Creates a new instance of JWSSystemServlet


           
      
    
Methods Summary
public voidinit()
Initializes the servlet.

        super.init();
        String dispatcherName = getInitParameter("defaultDispatcherName");
        if (dispatcherName==null)
        	dispatcherName = "default";
         defaultDispatcher = getServletConfig().getServletContext().getNamedDispatcher(dispatcherName);
        try {
            /*
             *Locate - or create - the data structure object.
             */
            jwsInfo = AppclientJWSSupportInfo.getInstance();
        } catch (Throwable thr) {
            throw new ServletException(thr);
        }
    
private java.util.PropertiesprepareRequestPlaceholders(javax.servlet.http.HttpServletRequest request, DynamicContent content)
Initializes a Properties object with the token names and values for substitution in the dynamic content template.

param
the incoming request
return
Properties object containing the token names and values
throws
ServletException in case of an error preparing the placeholders

        Properties answer = new Properties();
        
        answer.setProperty("request.scheme", request.getScheme());
        answer.setProperty("request.host", request.getServerName());
        answer.setProperty("request.port", Integer.toString(request.getServerPort()));
        
        /*
         *Treat query parameters with the name "arg" as command line arguments to the
         *app client.
         */

        String queryString = request.getQueryString();
        StringBuilder queryStringPropValue = new StringBuilder();
        if (queryString != null && queryString.length() > 0) {
            queryStringPropValue.append("?").append(queryString);
        }
        answer.setProperty("request.web.app.context.root", NamingConventions.SYSTEM_WEBAPP_URL);
        answer.setProperty("request.path", request.getPathInfo());
        answer.setProperty("request.query.string", queryStringPropValue.toString());

        answer.setProperty("security.setting", content.getJNLPSecuritySetting());
        
        /*
         *If the content origin is a user content origin, then find out if
         *the app client jar file recorded with this origin is signed or not.
         *Then use that to set the property for substitution in the dynamic JNLP.
         */
        ContentOrigin origin = content.getOrigin();
        answer.setProperty("appclient.user.code.is.signed", Boolean.toString(content.requiresElevatedPermissions()));

        processQueryParameters(queryString, answer);

        return answer;
    
private voidprocessDynamicContent(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp, Content content)
Handles requests for dynamic content.

param
the HTTP request to be serviced
param
the HTTP response to be composed
param
the content in which placeholders should be replaced before being written as the response
throws
ServletException for any errors

        try {
            DynamicContent dc = (DynamicContent) content; 

            /*
             *Build the Properties object with the request-based tokens and values, then
             *see if the DynamicContent that has already been retrieved already 
             *has an instance with matching content.  During that search, if this
             *is a GET request then add the text to the DynamicContent's cache
             *if it is not already there.  This helps Java Web Start manage its
             *cache on the client side and avoid retrieving documents over the
             *network that its cache already contains.  
             */
            Properties requestPlaceholders = prepareRequestPlaceholders(req, dc);

            boolean isGetMethod = req.getMethod().equals(GET_METHOD_NAME);
            
            DynamicContent.Instance instance = dc.findInstance(requestPlaceholders, isGetMethod /* if method == GET, then create if no instance */);

            /*
             *The findInstance invocation will return a null only if the request is an HTTP HEAD request
             *(to check the timestamp) and the substituted content does not 
             *already appear in the DynamicContent's cache.
             */
            if (instance != null) {
                String responseText = instance.getText();
                Date instanceTimestamp = instance.getTimestamp();
                resp.setDateHeader(LAST_MODIFIED_HEADER_NAME, instanceTimestamp.getTime());
                resp.setDateHeader(DATE_HEADER_NAME, System.currentTimeMillis());
                resp.setContentType(dc.getMimeType());
                resp.setStatus(resp.SC_OK);
                /*
                 *Only for GET should the response actually contain the content.
                 */
                if (isGetMethod) {
                    PrintWriter pw = resp.getWriter();
                    pw.println(responseText);
                    pw.flush();
                }
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.fine("JWSSystemServlet: serving dynamic content: method=" + req.getMethod() + 
                            ", pathInfo=" + req.getPathInfo() +
                            ", queryString=" + req.getQueryString() +
                            ", isGetMethod=" + isGetMethod +
                            ", content timestamp=" + instanceTimestamp + 
                            ", content=" + responseText
                            );
                }
            } else {
                /*
                 *The Java Web Start client has sent a HEAD request for 
                 *a URL that we recognize as one we should serve, but we have no
                 *such document (yet).  Report the requested
                 *document as here with the current date/time.  That will cause
                 *Java Web Start on the client to re-request the full document
                 *using a GET.
                 */
                resp.setDateHeader(LAST_MODIFIED_HEADER_NAME, System.currentTimeMillis());
                resp.setDateHeader(DATE_HEADER_NAME, System.currentTimeMillis());
                resp.setContentType(dc.getMimeType());
                resp.setStatus(resp.SC_OK);
            }
        } catch (Throwable thr) {
            throw new ServletException("Error processing dynamic content for path " + content.getPath(), thr);
        }
    
private voidprocessQueryParameters(java.lang.String queryString, java.util.Properties answer)

        if (queryString == null) {
            queryString = "";
        }
        String [] queryParams = null;
        try {
            queryParams = URLDecoder.decode(queryString, "UTF-8").split("&");
        } catch (UnsupportedEncodingException uee) {
            throw new ServletException("Error decoding query string",  uee);
        }

        QueryParams arguments = new ArgQueryParams();
        QueryParams properties = new PropQueryParams();
        QueryParams vmArguments = new VMArgQueryParams();
        QueryParams [] paramTypes = new QueryParams[] {arguments, properties, vmArguments};

        for (String param : queryParams) {
            for (QueryParams qpType : paramTypes) {
                if (qpType.processParameter(param)) {
                    break;
                }
            }
        }
        
        answer.setProperty("request.arguments", arguments.toString());
        answer.setProperty("request.properties", properties.toString());
        answer.setProperty("request.vmargs", vmArguments.toString());
    
private voidprocessStaticContent(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp, Content content)
Handles requests for static content by delegating the request to the default servlet.

param
the request to be processed
param
the response to be composed
param
the content, looked up from the data structure, that describes the static content itself
throws
ServletException in case of any error

        try {
            StaticContent sc = (StaticContent) content;
            
            /*
             *Set up the wrapped request with a URI to the file to be served that
             *is relative to the app server's installation root directory.  The
             *web container has initialized this web app's docbase to the app
             *server's installation root.
             */
            HttpServletRequest wrappedRequest = new JWSSystemServletRequestWrapper(req, sc.getRelativeURI());
            if (_logger.isLoggable(Level.FINE)) {
                _logger.fine("JWSSystemServlet: serving static content: method=" + wrappedRequest.getMethod() + ", mapped path=" + wrappedRequest.getPathInfo());
            }
            
            /*
             * Send to the dispatcher for the default servlet.
             */
            defaultDispatcher.forward(wrappedRequest, resp);

        } catch (Throwable thr) {
            throw new ServletException("Error processing static content for path " + content.getPath(), thr);
        }
    
public voidservice(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response)
Delegates the request to either this servlet's specialized handling for dynamic content or to the default servlet's handling for static content.

param
request to be handled
param
response to be sent
throws
ServletException in case of any errors

        if ( ! (request instanceof HttpServletRequest) || ! (response instanceof HttpServletResponse)) {
            throw new ServletException("Expected HttpServletRequest and HttpServletResponse but received " + request.getClass().getName() + " and " + response.getClass().getName());
        }
        
        boolean isFine = _logger.isLoggable(Level.FINE);
        
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        
        /*
         *See if there is Content info
         *available for this request.
         */
        Content content = jwsInfo.getContent(req);
        if (content == null) {
            try {
                if (isFine) {
                    _logger.fine("JWSSystemServlet: content not found for request: method=" + req.getMethod() + ", pathInfo=" + req.getPathInfo());
                }

                resp.sendError(resp.SC_NOT_FOUND, req.getPathInfo());
            } catch (Throwable thr) {
                throw new ServletException("Error attempting to return not-found response", thr);
            }
        } else {
            /*
             *If the response is static, delegate to the default servlet logic.
             *Otherwise, handle it here.
             */
            if (content instanceof StaticContent) {
                processStaticContent(req, resp, content);
            } else {
                processDynamicContent(req, resp, content);
            }
        }