⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classwebresource.java

📁 ZK 基础介绍 功能操作 模块 结合数据库操作
💻 JAVA
字号:
/* ClassWebResource.java{{IS_NOTE	Purpose:			Description:			History:		Tue Sep 20 16:49:45     2005, Created by tomyeh}}IS_NOTECopyright (C) 2005 Potix Corporation. All Rights Reserved.{{IS_RIGHT	This program is distributed under GPL Version 2.0 in the hope that	it will be useful, but WITHOUT ANY WARRANTY.}}IS_RIGHT*/package org.zkoss.web.util.resource;import java.util.Map;import java.util.HashMap;import java.net.URL;import java.io.InputStream;import java.io.IOException;import java.io.UnsupportedEncodingException;import javax.servlet.ServletContext;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.ServletOutputStream;import javax.servlet.ServletException;import javax.servlet.RequestDispatcher;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.zkoss.lang.D;import org.zkoss.io.Files;import org.zkoss.util.logging.Log;import org.zkoss.util.media.ContentTypes;import org.zkoss.util.resource.Locator;import org.zkoss.util.resource.Locators;import org.zkoss.web.servlet.Servlets;import org.zkoss.web.servlet.Charsets;import org.zkoss.web.servlet.http.Https;import org.zkoss.web.servlet.http.Encodes;/** * Used to access resouces located in class path and under /web. * It doesn't work alone. Rather, it is a helper for servlet, such as * ZK's update servlet or {@link ClassWebServlet}. * * <p>Typical use: * <ol> * <li>Declares a member in the servlet to * serve the request for the resource located in class path. * <li>Invoke {@link #getInstance} to init the member when * Servlet.init() is called. * <li>Calling {@link #service} when a request is receive. * </ol> * * @author tomyeh */public class ClassWebResource {	private static final Log log = Log.lookup(ClassWebResource.class);	private final ServletContext _ctx;	private final String _mappingURI;	private final ClassWebContext _cwc;	/** An array of extensions that have to be compressed (with gzip). */	private String[] _compressExts;	/** Map(String ext, Extendlet). */	private final Map _extlets = new HashMap(5);	/** The prefix of path of web resources ("/web"). */	public static final String PATH_PREFIX = "/web";	/** Returns the URL of the resource of the specified URI by searching	 * the class path (with {@link #PATH_PREFIX}).	 */	public static URL getResource(String uri) {		return Locators.getDefault().getResource(PATH_PREFIX + uri);	}	/** Returns the resource in a stream of the specified URI by searching	 * the class path (with {@link #PATH_PREFIX}).	 */	public static InputStream getResourceAsStream(String uri) {		return Locators.getDefault().getResourceAsStream(PATH_PREFIX + uri);	}	/** Returns the instance (singlton in the whole app) for	 * handling resources located in class path.	 */	public static final	ClassWebResource getInstance(ServletContext ctx, String mappingURI) {		synchronized (ctx) {			final ClassWebContext cwc =				(ClassWebContext)Servlets.getExtendletContext(ctx, ".");			if (cwc != null)				return cwc.getClassWebResource();			final ClassWebResource cwr = new ClassWebResource(ctx, mappingURI);			Servlets.addExtendletContext(ctx, ".", cwr._cwc);			return cwr;		}	}	/** Constructor. */	private ClassWebResource(ServletContext ctx, String mappingURI) {		if (!mappingURI.startsWith("/") || mappingURI.endsWith("/"))			throw new IllegalArgumentException("mappingURI must start with /, but not ends with /");		if (ctx == null)			throw new IllegalArgumentException("null ctx");		_ctx = ctx;		_mappingURI = mappingURI;		_cwc = new ClassWebContext();		addExtendlet("dsp", new DspExtendlet());	}	/** Process the request by retrieving the path from the path info.	 * It invokes {@link Https#getThisPathInfo} to retrieve the path info,	 * and then invoke {@link #service(HttpServletRequest,HttpServletResponse,String)}.	 *	 * <p>If the path info is not found, nothing is generated.	 *	 * @since 2.4.1	 */	public void service(HttpServletRequest request,	HttpServletResponse response)	throws ServletException, IOException {		final String pi = Https.getThisPathInfo(request);//		if (D.ON && log.debugable()) log.debug("Path info: "+pi);		if (pi != null)			service(request, response, pi.substring(PATH_PREFIX.length()));	}				/** Process the request with the specified path.	 *	 * @param path the path related to the class path	 * @since 3.0.0	 */	public void service(HttpServletRequest request,	HttpServletResponse response, String path)	throws ServletException, IOException {		final Object old = Charsets.setup(request, response, "UTF-8");		try {			web(request, response, path);		} finally {			Charsets.cleanup(request, old);		}	}	/** Returns the Extendlet (aka., resource processor) of the	 * specified extension, or null if not associated yet.	 *	 * @param ext the extension, e.g, "js" and "css".	 * @return the Extendlet (aka., resource processor),	 * or null if not associated yet.	 * @since 2.4.1	 */	public Extendlet getExtendlet(String ext) {		if (ext == null)			return null;		ext = ext.toLowerCase();		synchronized (_extlets) {			return (Extendlet)_extlets.get(ext);		}	}	/** Adds an Extendlet (aka., resource processor) to process	 * the resource of the specified extension.	 *	 * @param ext the extension, e.g, "js" and "css".	 * @param extlet the Extendlet (aka., resouce processor) to add	 * @return the previous Extendlet, or null if not associated before.	 * @since 2.4.1	 */	public Extendlet addExtendlet(String ext, Extendlet extlet) {		if (ext == null || extlet == null)			throw new IllegalArgumentException("null");		extlet.init(new ExtendletConfig() {			public ExtendletContext getExtendletContext() {				return _cwc;			}		});		ext = ext.toLowerCase();		synchronized (_extlets) {			return (Extendlet)_extlets.put(ext, extlet);		}	}	/** Removes the Extendlet (aka., resource processor)	 * for the specified extension.	 *	 * @param ext the extension, e.g, "js" and "css".	 * @return the previous Extendlet, or null if no Extendlet	 * was associated with the specified extension.	 * @since 2.4.1	 */	public Extendlet removeExtendlet(String ext) {		if (ext == null)			return null;		ext = ext.toLowerCase();		synchronized (_extlets) {			return (Extendlet)_extlets.remove(ext);		}	}	/** Sets the extension that shall be compressed if the browser	 * supports the compression encoding (accept-encoding).	 *	 * <p>Default: null (no compression at all).	 *	 * @param exts an array of extensions, e.g., {"js", "css"}.	 * If null or zero-length, it means no compression at all.	 *@since 2.4.1	 */	public void setCompress(String[] exts) {		_compressExts = exts != null && exts.length > 0 ? exts: null;	}	/**Returns  the extension that shall be compressed if the browser	 * supports the compression encoding (accept-encoding).	 *	 * <p>Default: null (no compression at all).	 *@since 2.4.1	 */	public String[] getCompress() {		return _compressExts;	}	//-- Work with ClassWebContext --//	/** Works with {@link ClassWebContext} to	 * load resources from class path (thru this servlet).	 */	private void web(HttpServletRequest request,	HttpServletResponse response, String pi)	throws ServletException, IOException {		//A trick used to enforce browser to load new version JavaScript		//How it work: client engine prefix URI with /_zver123, where		//123 is the build version that changes once reload is required		//Then, the server eliminate such prefix before locating resource		final String ZVER = "/_zver";		if (pi.startsWith(ZVER)) {			final int j = pi.indexOf('/', ZVER.length());			if (j >= 0) pi = pi.substring(j);			else log.warning("Unknown path info: "+pi);		}		//Notify the browser by calling back the code specified with /_zcb		String jsextra = null;		final String ZCB = "/_zcb"; //denote callback is required		if (pi.startsWith(ZCB)) {			final int j = pi.indexOf('/', ZCB.length());			if (j >= 0) {				jsextra = pi.substring(ZCB.length(), j);				pi = pi.substring(j);			} else {				jsextra = pi.substring(ZCB.length());				log.warning("Unknown path info: "+pi);			}			final int len = jsextra.length();			if (len == 0) jsextra = null;			else {				final char cc = jsextra.charAt(len - 1);				if (cc != ';') {					if (cc != ')') jsextra += "()";					jsextra += ';';				}			}		}		final String ext = Servlets.getExtension(pi);		if (ext != null) {			//Invoke the resource processor (Extendlet)			final Extendlet extlet = getExtendlet(ext);			if (extlet != null) {				extlet.service(request, response, pi, jsextra);				return;			}			if (!Servlets.isIncluded(request)) {								final String ctype = ContentTypes.getContentType(ext);				if (ctype != null)					response.setContentType(ctype);//				if (D.ON && log.debugable()) log.debug("Content type: "+ctype+" for "+pi);			}		}		byte[] extra = jsextra != null ? jsextra.getBytes("UTF-8"): null;		pi = Servlets.locate(_ctx, request, pi, _cwc.getLocator());		final InputStream is = getResourceAsStream(pi);		byte[] data;		if (is == null) {			if ("js".equals(ext)) {				//Don't sendError. Reason: 1) IE waits and no onerror fired				//2) better to debug (user will tell us what went wrong)				data = ("(zk.error?zk.error:alert)('"+pi+" not found');").getBytes();					//FUTURE: zweb shall not depend on zk			} else {				if (Servlets.isIncluded(request)) log.error("Resource not found: "+pi);				response.sendError(response.SC_NOT_FOUND, pi);				return;			}		} else {			//Note: don't compress images			data = shallCompress(request, ext) ?				Https.gzip(request, response, is, extra): null;			if (data != null) extra = null; //extra is compressed and output			else data = Files.readAll(is);				//since what is embedded in the jar is not big, so load completely		}		int len = data.length;		if (extra != null) len += extra.length;		response.setContentLength(len);		final ServletOutputStream out = response.getOutputStream();		out.write(data);		if (extra != null) out.write(extra);		out.flush();	}	private boolean shallCompress(ServletRequest request, String ext) {		if (ext != null && _compressExts != null		&& !Servlets.isIncluded(request))			for (int j = 0; j < _compressExts.length; ++j)				if (ext.equals(_compressExts[j]))					return true;		return false;	}	/**	 * An implementation of ExtendletContext to load resources from	 * the class path rooted at /web.	 */	private class ClassWebContext implements ExtendletContext {		private final Locator _locator = new Locator() {			public String getDirectory() {				return null;			}			public URL getResource(String name) {				return ClassWebResource.getResource(name);			}			public InputStream getResourceAsStream(String name) {				return ClassWebResource.getResourceAsStream(name);			}		};		/** Returns the associated class web resource. */		public ClassWebResource getClassWebResource() {			return ClassWebResource.this;		}		//-- ExtendletContext --//		public ServletContext getServletContext() {			return _ctx;		}		public Locator getLocator() {			return _locator;		}		public boolean shallCompress(ServletRequest request, String ext) {			return ClassWebResource.this.shallCompress(request, ext);		}			public String encodeURL(ServletRequest request,		ServletResponse response, String uri)		throws ServletException, UnsupportedEncodingException {			uri = Servlets.locate(_ctx, request, uri, getLocator()); //resolves "*"			uri = _mappingURI + PATH_PREFIX + uri; //prefix with mapping			//prefix context path			if (request instanceof HttpServletRequest) {				String ctxpath = ((HttpServletRequest)request).getContextPath();				final int ctxlen = ctxpath.length();				if (ctxlen > 0) {					final char cc = ctxpath.charAt(0);					if (cc != '/') ctxpath = '/' + ctxpath;						//Work around a bug for Pluto's RenderRequest (1.0.1)					else if (ctxlen == 1) ctxpath = ""; // "/" =>  ""						//Work around liferay's issue: Upload 1627928 (not verified)				}				uri = ctxpath + uri;			}			int j = uri.indexOf('?');			if (j < 0) {				uri = Encodes.encodeURI(uri);			} else {				uri = Encodes.encodeURI(uri.substring(0, j))					+ uri.substring(j);			}			//encode			if (response instanceof HttpServletResponse)				uri = ((HttpServletResponse)response).encodeURL(uri);			return uri;		}		public String encodeRedirectURL(HttpServletRequest request,		HttpServletResponse response, String uri, Map params, int mode) {			return Https.encodeRedirectURL(_ctx, request, response,				_mappingURI + PATH_PREFIX + uri, params, mode);		}		public RequestDispatcher getRequestDispatcher(String uri) {//			if (D.ON && log.debugable()) log.debug("getRequestDispatcher: "+uri);			return _ctx.getRequestDispatcher(_mappingURI + PATH_PREFIX + uri);		}		public URL getResource(String uri) {			return ClassWebResource.getResource(uri);		}		public InputStream getResourceAsStream(String uri) {			return ClassWebResource.getResourceAsStream(uri);		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -