Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (C) 2014 Zach Melamed
   * 
   * Latest version available online at https://github.com/zach-m/tectonica-commons
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
  * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package com.tectonica.jee;
 
 import java.io.Reader;
 import java.io.Writer;
 
 
 
 public abstract class StaticServlet extends HttpServlet
 {
 	private static final long serialVersionUID = 1L;
 
 	public static interface BasicAuthorizer
 	{
 		public boolean isAuthorized(String usernameString password);
 	}

Returns the exact path, within the WAR file, of the resource to return (given a requested URL, indicated in the passed request parameter). The path should be relative to the 'webapp' folder and start with a '/'.

If your goal is to serve resources without changing your tree structure (which will later allow you to activate/deactivate this servlet without having to change any URLs), first make sure to have a mapping like this in web.xml (assuming, of course, that the resources are under /webapp/apidocs):

 <servlet-mapping>
     <url-pattern>/apidocs/*</url-pattern>
 </servlet-mapping>
 
then, when overriding this function, simply return:
 return request.getServletPath() + request.getPathInfo();
 
This is probably the most typical scenario, certainly when the use-case is restricting access to the static content (but not the only one possible).

NOTE: returning null will result-in an HTTP-400 response.

Parameters:
request the request itself, from which the request URL can be obtained. one may also use it to set attributes for later use
 
 	protected abstract String getLocalPath(HttpServletRequest request);

Returns an (optionally null) search-replace resolver to apply on textual content before serving them. This resolver may be created like that:
 Map<String, String> tokens = new HashMap<String, String>();
 
 tokens.put("NAME", "zach");
 tokens.put("EMAIL", "zach@tectonica.co.il");
 
 return new MapTokenResolver(tokens);
 
When such resolver is applied, any occurrence of ${NAME} and ${EMAIL} will be replaced with the corresponding values listed above.
 
 	protected TokenResolver getTokenResolver(String localPathHttpServletRequest request)
 	{
 		return null;
 	}

Returns an (optionally null) authorizer to use before serving resources. If you wish to apply a more sophisticated authorization scheme, you need to override checkAuthorization(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse).
	{
		return null;
	}

Performs authorization check before serving a resource. The default behavior is to apply an HTTP BASIC AUTHORIZATION strategy using a user-supplied implementation of StaticServlet.BasicAuthorizer. If the user doesn't supply such implementation in getBasicAuthorizer(), the resource is assumed cleared to serve.

an example for using Google App Engine's Accounts API is as follows:

 @Override
 protected boolean checkAuthorization(HttpServletRequest request, HttpServletResponse response) throws IOException
 {
  boolean authorized = false;
 
  UserService userService = UserServiceFactory.getUserService();
  if (userService.isUserLoggedIn())
   authorized = ApiProxy.getCurrentEnvironment().getEmail().endsWith("@tectonica.co.il");
 
  if (!authorized)
   response.sendRedirect(userService.createLoginURL(request.getRequestURI()));
 
  return authorized;
 }
 

Returns:
whether or not the resource is authorized for serving. if false, the main doGet() execution stops.
	protected boolean checkAuthorization(HttpServletRequest requestHttpServletResponse responsethrows IOException
	{
		BasicAuthorizer basicAuthorizer = getBasicAuthorizer();
		if (basicAuthorizer == null)
			return true;
		String authHeader = request.getHeader("Authorization");
		if (authHeader != null && authHeader.startsWith("Basic "))
		{
			String[] values = new String(DatatypeConverter.parseBase64Binary(authHeader.substring("Basic ".length()))).split(":");
			return (values != null) && (values.length > 1) && (basicAuthorizer.isAuthorized(values[0], values[1]));
		}
		response.setHeader("WWW-Authenticate", String.format("Basic realm=\"%s\""request.getHeader("Host")));
		return false;
	}

Override if you wish to modify the response headers before the resource is served. This could be a good place to add client-side caching for the resource, like that:
 response.setHeader("Cache-Control", "max-age=900,must-revalidate"); // 15-minutes
 
	protected void setCustomHeaders(HttpServletRequest requestHttpServletResponse response)
	{}
	protected void doGet(HttpServletRequest requestHttpServletResponse responsethrows ServletExceptionIOException
	{
		String localPath = getLocalPath(request);
		if (localPath == null)
		{
			return;
		}
		if (is == null)
		{
			return;
		}
		if (!checkAuthorization(requestresponse))
			return;
		String mimeType = getMimeType(localPathrequest);
		response.setContentType(mimeType);
		setCustomHeaders(requestresponse);
		if (!(mimeType.startsWith("text/") && writeManipulatedChars(isoslocalPathrequest)))
			writeBytes(isos); // i.e. return as-is
		os.close();
	}
	protected String getMimeType(String pathHttpServletRequest request)
	{
		String mimeType = getServletContext().getMimeType(path);
		if (mimeType == null)
			mimeType = "application/octet-stream";
		return mimeType;
	}
	private boolean writeManipulatedChars(InputStream isOutputStream osString localPathHttpServletRequest request)
	{
		TokenResolver tokenResolver = getTokenResolver(localPathrequest);
		if (tokenResolver == null)
			return false;
		SearchReplaceReader reader = new SearchReplaceReader(new InputStreamReader(is), tokenResolver);
		writeChars(readerwriter);
		return true;
	}
	protected void writeBytes(InputStream inOutputStream outthrows IOException
	{
		int read;
		final byte[] data = new byte[8192];
		while ((read = in.read(data)) != -1)
			out.write(data, 0, read);
		out.flush();
	}
	protected void writeChars(Reader inWriter outthrows IOException
	{
		int read;
		final char[] data = new char[8192];
		while ((read = in.read(data)) != -1)
			out.write(data, 0, read);
		out.flush();
	}
New to GrepCode? Check out our FAQ X