class XSSEscapeXmlELResolver extends ELResolver {

	@Override
	public Object getValue(ELContext context, Object base, Object property) {
		JspContext pageContext = (JspContext) context.getContext(JspContext.class);
		Boolean escapeScript = (Boolean) pageContext.getAttribute(ESCAPE_XSS_SCRIPT);
		Boolean javaScriptEscape = (Boolean) pageContext.getAttribute(UTF8_ESCAPE_XSS_SCRIPT);

		if (escapeScript != null && !escapeScript) {
			return null;
		}

		try {
			if (excludeMe.get()) {
				return null;
			}

			Object skipEscapePageAttrib = pageContext.getAttribute(SKIP_XSS_ESCAPE_REQ_ATTRIB);
			if (property == null
					// Tiles do not seem to have 'base' object in attrib. names.  By checking base == null,
					// we avoid attribute collisions such as frame.id (EL) and id (tiles attrib).
					|| (base == null && unescapedTileandELAttributes.contains(property.toString()))
					|| skipEscapePageAttrib != null) {
				return null;
			}

			// excludeMe.get() == false means that this is 1st invocation of the resolver
			// chain by the parent CompositeResolver.  This class is part of this chain.
			//
			// context.getELResolver() returns the parent CompositeResolver, which
			// invokes the ELResolver chain again inside getValue().  2nd invocation of
			// the resolver chain finds excludeMe.set(Boolean.TRUE), which prevents the infinite loop.
			excludeMe.set(Boolean.TRUE);

			Object obj = context.getELResolver().getValue(context, base, property);
			return escapeObj(obj, javaScriptEscape);
		} finally {
		  excludeMe.remove();
		}
	}

	public  XSSEscapeXmlELResolver();

}