blob: c97a26f04b5deeea71df49ae9fde0218d60f3822 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- saved from url=(0014)about:internet -->
<HTML>
<HEAD>
<!-- Generated by javadoc (build 1.5.0_19) on Sun Mar 20 20:56:05 PKT 2011 -->
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<TITLE>
PageInterceptor (Click Framework API - v2.3.0)
</TITLE>
<META NAME="keywords" CONTENT="org.apache.click.PageInterceptor interface">
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../stylesheet.css" TITLE="Style">
<SCRIPT type="text/javascript">
function windowTitle()
{
parent.document.title="PageInterceptor (Click Framework API - v2.3.0)";
}
</SCRIPT>
<NOSCRIPT>
</NOSCRIPT>
</HEAD>
<BODY BGCOLOR="white">
<!-- ========= START OF TOP NAVBAR ======= -->
<A NAME="navbar_top"><!-- --></A>
<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
<TR>
<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
<A NAME="navbar_top_firstrow"><!-- --></A>
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
<TR ALIGN="center" VALIGN="top">
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
</TR>
</TABLE>
</TD>
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
</EM>
</TD>
</TR>
<TR>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
&nbsp;<A HREF="../../../org/apache/click/Page.html" title="class in org.apache.click"><B>PREV CLASS</B></A>&nbsp;
&nbsp;<A HREF="../../../org/apache/click/Stateful.html" title="interface in org.apache.click"><B>NEXT CLASS</B></A></FONT></TD>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
<A HREF="../../../index.html?org/apache/click/PageInterceptor.html" target="_top"><B>FRAMES</B></A> &nbsp;
&nbsp;<A HREF="PageInterceptor.html" target="_top"><B>NO FRAMES</B></A> &nbsp;
&nbsp;<SCRIPT type="text/javascript">
<!--
if(window==top) {
document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
}
//-->
</SCRIPT>
<NOSCRIPT>
<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
</NOSCRIPT>
</FONT></TD>
</TR>
<TR>
<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;CONSTR&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
DETAIL:&nbsp;FIELD&nbsp;|&nbsp;CONSTR&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
</TR>
</TABLE>
<A NAME="skip-navbar_top"></A>
<!-- ========= END OF TOP NAVBAR ========= -->
<HR>
<!-- ======== START OF CLASS DATA ======== -->
<H2>
<FONT SIZE="-1">
org.apache.click</FONT>
<BR>
Interface PageInterceptor</H2>
<HR>
<DL>
<DT><PRE>public interface <B>PageInterceptor</B></DL>
</PRE>
<P>
Provides a Page life cycle interceptor. Classes implementing this interface
can be used to listen for key page life cycle events and abort further page
processing if required.
<p/>
PageInterceptors can be used for many different purposes including:
<ul>
<li>enforcing application wide page security policies</li>
<li>injecting dependencies into page objects</li>
<li>logging and profiling page performance</li>
</ul>
A Click application can define multiple page interceptors that are invoked in
the order in which they are returned by the <tt>ConfigService</tt>.
<h3><a name="scope"></a>Scope</h3>
Page interceptors can be defined with a request level scope, whereby a new
page interceptor will be created with each page request providing a thread
safe programming model.
<p/>
Please note, as new interceptor instances are created with each request, care
should be taken to ensure that these objects are light weight and do not
introduce a performance bottleneck into your application.
<p/>
Alternatively, page interceptors can be defined with application level scope
whereby a single instance is created for the application and is used for
all requests.
<p/>
Note application scope interceptors are more efficient that request scope
interceptors, but you are responsible for ensuring that they are thread safe
and support reentrant method invocations as multiple page requests are
processed at the same time.
<h3><a name="configuration"></a>Configuration</h3>
Application PageInterceptors are configured in the <tt>click.xml</tt>
configuration file. PageInterceptors must support construction using a
no-args public constructor.
<p/>
Page interceptors can have multiple properties configured with their XML
definition which are set after the constructor has been called. Properties
are set using OGNL via <A HREF="../../../org/apache/click/util/PropertyUtils.html" title="class in org.apache.click.util"><CODE>PropertyUtils</CODE></A>.
<p/>
An example configuration is provided below:
<pre class="prettyprint">
&lt;page-interceptor classname="com.mycorp.PageSecurityInterceptor" scope="application"&gt;
&lt;property name="notAuthenticatedPath" value="/not-authenticated.htm"/&gt;
&lt;property name="notAuthorizedPath" value="/not-authorized.htm"/&gt;
&lt;/page-interceptor&gt; </pre>
The default scope for page interceptors is "request", but this can be configured
as "application" as is done in the example configuration above.
<h3><a name="example"></a>Example</h3>
<pre class="prettyprint">
public class SecurityInterceptor implements PageInterceptor {
// The request not authenticated redirect path.
private String notAuthenticatedPath;
// The request not authorized redirect path.
private String notAuthorizedPath;
// Public Methods ---------------------------------------------------------
public boolean preCreate(Class<? extends Page> pageClass, Context context) {
// If authentication required, then ensure user is authenticated
Authentication authentication = pageClass.getAnnotation(Authentication.class);
// TODO: user context check.
if (authentication != null && authentication.required()) {
sendRedirect(getNotAuthenticatedPath(), context);
return false;
}
// If authorization permission defined, then ensure user is authorized to access the page
Authorization authorization = pageClass.getAnnotation(Authorization.class);
if (authorization != null) {
if (!UserContext.getThreadUserContext().hasPermission(authorization.permission())) {
sendRedirect(getNotAuthorizedPath(), context);
return false;
}
}
return true;
}
public boolean postCreate(Page page) {
return true;
}
public boolean preResponse(Page page) {
return true;
}
public void postDestroy(Page page) {
}
public String getNotAuthenticatedPath() {
return notAuthenticatedPath;
}
public void setNotAuthenticatedPath(String notAuthenticatedPath) {
this.notAuthenticatedPath = notAuthenticatedPath;
}
public String getNotAuthorizedPath() {
return notAuthorizedPath;
}
public void setNotAuthorizedPath(String notAuthorizedPath) {
this.notAuthorizedPath = notAuthorizedPath;
}
// Protected Methods ------------------------------------------------------
protected void sendRedirect(String location, Context context) {
if (StringUtils.isNotBlank(location)) {
if (location.charAt(0) == '/') {
String contextPath = context.getRequest().getContextPath();
// Guard against adding duplicate context path
if (!location.startsWith(contextPath + '/')) {
location = contextPath + location;
}
}
}
location = context.getResponse().encodeRedirectURL(location);
try {
context.getResponse().sendRedirect(location);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
} </pre>
<pre class="prettyprint">
// Page class authentication annotation
&#64;Retention(RetentionPolicy.RUNTIME)
public @interface Authentication {
boolean required() default true;
} </pre>
<pre class="prettyprint">
// Page class authorization annotation
&#64;Retention(RetentionPolicy.RUNTIME)
public @interface Authorization {
String permission();
}
</pre>
<P>
<P>
<HR>
<P>
<!-- ========== METHOD SUMMARY =========== -->
<A NAME="method_summary"><!-- --></A>
<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
<B>Method Summary</B></FONT></TH>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;boolean</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../org/apache/click/PageInterceptor.html#postCreate(org.apache.click.Page)">postCreate</A></B>(<A HREF="../../../org/apache/click/Page.html" title="class in org.apache.click">Page</A>&nbsp;page)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Provides a post page object creation interceptor method, which is passed
the instance of the newly created page.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;void</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../org/apache/click/PageInterceptor.html#postDestroy(org.apache.click.Page)">postDestroy</A></B>(<A HREF="../../../org/apache/click/Page.html" title="class in org.apache.click">Page</A>&nbsp;page)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Provides a post page destroy interceptor method.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;boolean</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../org/apache/click/PageInterceptor.html#preCreate(java.lang.Class, org.apache.click.Context)">preCreate</A></B>(<A HREF="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html" title="class or interface in java.lang">Class</A>&lt;? extends <A HREF="../../../org/apache/click/Page.html" title="class in org.apache.click">Page</A>&gt;&nbsp;pageClass,
<A HREF="../../../org/apache/click/Context.html" title="class in org.apache.click">Context</A>&nbsp;context)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Provides a before page object creation interceptor method, which is passed
the class of the page to be instantiated and the page request context.</TD>
</TR>
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
<CODE>&nbsp;boolean</CODE></FONT></TD>
<TD><CODE><B><A HREF="../../../org/apache/click/PageInterceptor.html#preResponse(org.apache.click.Page)">preResponse</A></B>(<A HREF="../../../org/apache/click/Page.html" title="class in org.apache.click">Page</A>&nbsp;page)</CODE>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Provides a page interceptor before response method.</TD>
</TR>
</TABLE>
&nbsp;
<P>
<!-- ============ METHOD DETAIL ========== -->
<A NAME="method_detail"><!-- --></A>
<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
<B>Method Detail</B></FONT></TH>
</TR>
</TABLE>
<A NAME="preCreate(java.lang.Class, org.apache.click.Context)"><!-- --></A><H3>
preCreate</H3>
<PRE>
boolean <B>preCreate</B>(<A HREF="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html" title="class or interface in java.lang">Class</A>&lt;? extends <A HREF="../../../org/apache/click/Page.html" title="class in org.apache.click">Page</A>&gt;&nbsp;pageClass,
<A HREF="../../../org/apache/click/Context.html" title="class in org.apache.click">Context</A>&nbsp;context)</PRE>
<DL>
<DD>Provides a before page object creation interceptor method, which is passed
the class of the page to be instantiated and the page request context.
If this method returns true then the normal page processing is performed,
otherwise if this method returns false the page instance is never created
and the request is considered to have been handled.
<P>
<DD><DL>
<DT><B>Parameters:</B><DD><CODE>pageClass</CODE> - the class of the page to be instantiated<DD><CODE>context</CODE> - the page request context
<DT><B>Returns:</B><DD>true to continue normal page processing or false whereby the
request is considered to be handled</DL>
</DD>
</DL>
<HR>
<A NAME="postCreate(org.apache.click.Page)"><!-- --></A><H3>
postCreate</H3>
<PRE>
boolean <B>postCreate</B>(<A HREF="../../../org/apache/click/Page.html" title="class in org.apache.click">Page</A>&nbsp;page)</PRE>
<DL>
<DD>Provides a post page object creation interceptor method, which is passed
the instance of the newly created page. This interceptor method is called
before the page <A HREF="../../../org/apache/click/Page.html#onSecurityCheck()"><CODE>Page.onSecurityCheck()</CODE></A> method is invoked.
<p/>
If this method returns true then the normal page processing is performed,
otherwise if this method returns false the request is considered to have
been handled.
<p/>
Please note the page <A HREF="../../../org/apache/click/Page.html#onDestroy()"><CODE>Page.onDestroy()</CODE></A> method will still be invoked.
<P>
<DD><DL>
<DT><B>Parameters:</B><DD><CODE>page</CODE> - the newly instantiated page instance
<DT><B>Returns:</B><DD>true to continue normal page processing or false whereby the
request is considered to be handled</DL>
</DD>
</DL>
<HR>
<A NAME="preResponse(org.apache.click.Page)"><!-- --></A><H3>
preResponse</H3>
<PRE>
boolean <B>preResponse</B>(<A HREF="../../../org/apache/click/Page.html" title="class in org.apache.click">Page</A>&nbsp;page)</PRE>
<DL>
<DD>Provides a page interceptor before response method. This method is invoked
prior to the page redirect, forward or rendering phase.
<p/>
If this method returns true then the normal page processing is performed,
otherwise if this method returns false request is considered to have been
handled.
<p/>
Please note the page <A HREF="../../../org/apache/click/Page.html#onDestroy()"><CODE>Page.onDestroy()</CODE></A> method will still be invoked.
<P>
<DD><DL>
<DT><B>Parameters:</B><DD><CODE>page</CODE> - the newly instantiated page instance
<DT><B>Returns:</B><DD>true to continue normal page processing or false whereby the
request is considered to be handled</DL>
</DD>
</DL>
<HR>
<A NAME="postDestroy(org.apache.click.Page)"><!-- --></A><H3>
postDestroy</H3>
<PRE>
void <B>postDestroy</B>(<A HREF="../../../org/apache/click/Page.html" title="class in org.apache.click">Page</A>&nbsp;page)</PRE>
<DL>
<DD>Provides a post page destroy interceptor method. This interceptor method
is called immediately after the page <A HREF="../../../org/apache/click/Page.html#onDestroy()"><CODE>Page.onDestroy()</CODE></A> method is
invoked.
<P>
<DD><DL>
<DT><B>Parameters:</B><DD><CODE>page</CODE> - the page object which has just been destroyed</DL>
</DD>
</DL>
<!-- ========= END OF CLASS DATA ========= -->
<HR>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<A NAME="navbar_bottom"><!-- --></A>
<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
<TR>
<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
<A NAME="navbar_bottom_firstrow"><!-- --></A>
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
<TR ALIGN="center" VALIGN="top">
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
</TR>
</TABLE>
</TD>
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
</EM>
</TD>
</TR>
<TR>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
&nbsp;<A HREF="../../../org/apache/click/Page.html" title="class in org.apache.click"><B>PREV CLASS</B></A>&nbsp;
&nbsp;<A HREF="../../../org/apache/click/Stateful.html" title="interface in org.apache.click"><B>NEXT CLASS</B></A></FONT></TD>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
<A HREF="../../../index.html?org/apache/click/PageInterceptor.html" target="_top"><B>FRAMES</B></A> &nbsp;
&nbsp;<A HREF="PageInterceptor.html" target="_top"><B>NO FRAMES</B></A> &nbsp;
&nbsp;<SCRIPT type="text/javascript">
<!--
if(window==top) {
document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
}
//-->
</SCRIPT>
<NOSCRIPT>
<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
</NOSCRIPT>
</FONT></TD>
</TR>
<TR>
<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;CONSTR&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
DETAIL:&nbsp;FIELD&nbsp;|&nbsp;CONSTR&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
</TR>
</TABLE>
<A NAME="skip-navbar_bottom"></A>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
<HR>
<style type='text/css'>.str{color:#2A00FF;}.kwd{color:#7F0055;font-weight:bold;}.com{color:#3F7F5F;}.typ{color:#000;}.lit{color:#066;}.pun{color:#660;}.pln{color:#000;}.tag{color:#000099;font-weight:bold;}.atn{color:#009900;}.atv{color:#000;}.dec{color:#606;}pre.prettyprint{padding:1em;border:1px solid #888;overflow:auto;}@media print{.str{color:#2A00FF;}.kwd{color:#7F0055;font-weight:bold;}.com{color:#3F7F5F;font-style:italic;}.typ{color:#000;font-weight:bold;}.lit{color:#044;}.pun{color:#440;}.pln{color:#000;}.tag{color:#000099;font-weight:bold;}.atn{color:#009900;}.atv{color:#000;}}</style><script type='text/javascript'>var PR_keywords={};(function(){var CPP_KEYWORDS='abstract bool break case catch char class const '+'const_cast continue default delete deprecated dllexport dllimport do '+'double dynamic_cast else enum explicit extern false float for friend '+'goto if inline int long mutable naked namespace new noinline noreturn '+'nothrow novtable operator private property protected public register '+'reinterpret_cast return selectany short signed sizeof static '+'static_cast struct switch template this thread throw true try typedef '+'typeid typename union unsigned using declaration, directive uuid '+'virtual void volatile while typeof';var CSHARP_KEYWORDS='as base by byte checked decimal delegate descending '+'event finally fixed foreach from group implicit in interface internal '+'into is lock null object override orderby params readonly ref sbyte '+'sealed stackalloc string select uint ulong unchecked unsafe ushort var';var JAVA_KEYWORDS='package synchronized boolean implements import throws '+'instanceof transient extends final strictfp native super';var JSCRIPT_KEYWORDS='debugger export function with NaN Infinity';var PERL_KEYWORDS='require sub unless until use elsif BEGIN END';var PYTHON_KEYWORDS='and assert def del elif except exec global lambda '+'not or pass print raise yield False True None';var RUBY_KEYWORDS='then end begin rescue ensure module when undef next '+'redo retry alias defined';var SH_KEYWORDS='done fi';var KEYWORDS=[CPP_KEYWORDS,CSHARP_KEYWORDS,JAVA_KEYWORDS,JSCRIPT_KEYWORDS,PERL_KEYWORDS,PYTHON_KEYWORDS,RUBY_KEYWORDS,SH_KEYWORDS];for(var k=0;k<KEYWORDS.length;k++){var kw=KEYWORDS[k].split(' ');for(var i=0;i<kw.length;i++){if(kw[i]){PR_keywords[kw[i]]=true;}}}}).call(this);var PR_STRING='str';var PR_KEYWORD='kwd';var PR_COMMENT='com';var PR_TYPE='typ';var PR_LITERAL='lit';var PR_PUNCTUATION='pun';var PR_PLAIN='pln';var PR_TAG='tag';var PR_DECLARATION='dec';var PR_SOURCE='src';var PR_ATTRIB_NAME='atn';var PR_ATTRIB_VALUE='atv';var PR_TAB_WIDTH=8;function PR_isWordChar(ch){return(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z');}function PR_spliceArrayInto(inserted,container,containerPosition,countReplaced){inserted.unshift(containerPosition,countReplaced||0);try{container.splice.apply(container,inserted);}finally{inserted.splice(0,2);}}var REGEXP_PRECEDER_PATTERN=(function(){var preceders=['!','!=','!==','#','%','%=','&','&&','&&=','&=','(','*','*=','+=',',','-=','->','/','/=',':','::',';','<','<<','<<=','<=','=','==','===','>','>=','>>','>>=','>>>','>>>=','?','@','[','^','^=','^^','^^=','{','|','|=','||','||=','~','break','case','continue','delete','do','else','finally','instanceof','return','throw','try','typeof'];var pattern='(?:'+'(?:(?:^|[^0-9\.])\\.{1,3})|'+'(?:(?:^|[^\\+])\\+)|'+'(?:(?:^|[^\\-])-)';for(var i=0;i<preceders.length;++i){var preceder=preceders[i];if(PR_isWordChar(preceder.charAt(0))){pattern+='|\\b'+preceder;}else{pattern+='|'+preceder.replace(/([^=<>:&])/g,'\\$1');}}pattern+='|^)\\s*$';return new RegExp(pattern);})();var pr_amp=/&/g;var pr_lt=/</g;var pr_gt=/>/g;var pr_quot=/"/g;function PR_attribToHtml(str){return str.replace(pr_amp,'&amp;').replace(pr_lt,'&lt;').replace(pr_gt,'&gt;').replace(pr_quot,'&quot;');}function PR_textToHtml(str){return str.replace(pr_amp,'&amp;').replace(pr_lt,'&lt;').replace(pr_gt,'&gt;');}var pr_ltEnt=/&lt;/g;var pr_gtEnt=/&gt;/g;var pr_aposEnt=/&apos;/g;var pr_quotEnt=/&quot;/g;var pr_ampEnt=/&amp;/g;function PR_htmlToText(html){var pos=html.indexOf('&');if(pos<0){return html;}for(--pos;(pos=html.indexOf('&#',pos+1))>=0;){var end=html.indexOf(';',pos);if(end>=0){var num=html.substring(pos+3,end);var radix=10;if(num&&num.charAt(0)=='x'){num=num.substring(1);radix=16;}var codePoint=parseInt(num,radix);if(!isNaN(codePoint)){html=(html.substring(0,pos)+String.fromCharCode(codePoint)+html.substring(end+1));}}}return html.replace(pr_ltEnt,'<').replace(pr_gtEnt,'>').replace(pr_aposEnt,"'").replace(pr_quotEnt,'"').replace(pr_ampEnt,'&');}function PR_isRawContent(node){return'XMP'==node.tagName;}var PR_innerHtmlWorks=null;function PR_getInnerHtml(node){if(null===PR_innerHtmlWorks){var testNode=document.createElement('PRE');testNode.appendChild(document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />'));PR_innerHtmlWorks=!/</.test(testNode.innerHTML);}if(PR_innerHtmlWorks){var content=node.innerHTML;if(PR_isRawContent(node)){content=PR_textToHtml(content);}return content;}var out=[];for(var child=node.firstChild;child;child=child.nextSibling){PR_normalizedHtml(child,out);}return out.join('');}function PR_normalizedHtml(node,out){switch(node.nodeType){case 1:var name=node.tagName.toLowerCase();out.push('\074',name);for(var i=0;i<node.attributes.length;++i){var attr=node.attributes[i];if(!attr.specified){continue;}out.push(' ');PR_normalizedHtml(attr,out);}out.push('>');for(var child=node.firstChild;child;child=child.nextSibling){PR_normalizedHtml(child,out);}if(node.firstChild||!/^(?:br|link|img)$/.test(name)){out.push('<\/',name,'>');}break;case 2:out.push(node.name.toLowerCase(),'="',PR_attribToHtml(node.value),'"');break;case 3:case 4:out.push(PR_textToHtml(node.nodeValue));break;}}function PR_tabExpander(tabWidth){var SPACES=' ';var charInLine=0;return function(plainText){var out=null;var pos=0;for(var i=0,n=plainText.length;i<n;++i){var ch=plainText.charAt(i);switch(ch){case'\t':if(!out){out=[];}out.push(plainText.substring(pos,i));var nSpaces=tabWidth-(charInLine%tabWidth);charInLine+=nSpaces;for(;nSpaces>=0;nSpaces-=SPACES.length){out.push(SPACES.substring(0,nSpaces));}pos=i+1;break;case'\n':charInLine=0;break;default:++charInLine;}}if(!out){return plainText;}out.push(plainText.substring(pos));return out.join('');};}var pr_chunkPattern=/(?:[^<]+|<!--[\s\S]*?-->|<!\[CDATA\[([\s\S]*?)\]\]>|<\/?[a-zA-Z][^>]*>|<)/g;var pr_commentPrefix=/^<!--/;var pr_cdataPrefix=/^<\[CDATA\[/;var pr_brPrefix=/^<br\b/i;function PR_extractTags(s){var matches=s.match(pr_chunkPattern);var sourceBuf=[];var sourceBufLen=0;var extractedTags=[];if(matches){for(var i=0,n=matches.length;i<n;++i){var match=matches[i];if(match.length>1&&match.charAt(0)==='<'){if(pr_commentPrefix.test(match)){continue;}if(pr_cdataPrefix.test(match)){sourceBuf.push(match.substring(9,match.length-3));sourceBufLen+=match.length-12;}else if(pr_brPrefix.test(match)){sourceBuf.push('\n');sourceBufLen+=1;}else{extractedTags.push(sourceBufLen,match);}}else{var literalText=PR_htmlToText(match);sourceBuf.push(literalText);sourceBufLen+=literalText.length;}}}return{source:sourceBuf.join(''),tags:extractedTags};}function PR_createSimpleLexer(shortcutStylePatterns,fallthroughStylePatterns){var shortcuts={};(function(){var allPatterns=shortcutStylePatterns.concat(fallthroughStylePatterns);for(var i=allPatterns.length;--i>=0;){var patternParts=allPatterns[i];var shortcutChars=patternParts[3];if(shortcutChars){for(var c=shortcutChars.length;--c>=0;){shortcuts[shortcutChars.charAt(c)]=patternParts;}}}})();var nPatterns=fallthroughStylePatterns.length;return function(sourceCode,opt_basePos){opt_basePos=opt_basePos||0;var decorations=[opt_basePos,PR_PLAIN];var lastToken='';var pos=0;var tail=sourceCode;while(tail.length){var style;var token=null;var patternParts=shortcuts[tail.charAt(0)];if(patternParts){var match=tail.match(patternParts[1]);token=match[0];style=patternParts[0];}else{for(var i=0;i<nPatterns;++i){patternParts=fallthroughStylePatterns[i];var contextPattern=patternParts[2];if(contextPattern&&!contextPattern.test(lastToken)){continue;}var match=tail.match(patternParts[1]);if(match){token=match[0];style=patternParts[0];break;}}if(!token){style=PR_PLAIN;token=tail.substring(0,1);}}decorations.push(opt_basePos+pos,style);pos+=token.length;tail=tail.substring(token.length);if(style!==PR_COMMENT&&/\S/.test(token)){lastToken=token;}}return decorations;};}var PR_C_STYLE_STRING_AND_COMMENT_LEXER=PR_createSimpleLexer([[PR_STRING,/^\'(?:[^\\\']|\\[\s\S])*(?:\'|$)/,null,"'"],[PR_STRING,/^"(?:[^\\"]|\\[\s\S])*(?:"|$)/,null,'"'],[PR_STRING,/^\`(?:[^\\\`]|\\[\s\S])*(?:\`|$)/,null,'`']],[[PR_PLAIN,/^(?:[^\'"\`\/\#]+)/,null,' \r\n'],[PR_COMMENT,/^#[^\r\n]*/,null,'#'],[PR_COMMENT,/^\/\/[^\r\n]*/,null],[PR_STRING,/^\/(?:[^\\\*\/]|\\[\s\S])+(?:\/|$)/,REGEXP_PRECEDER_PATTERN],[PR_COMMENT,/^\/\*[\s\S]*?(?:\*\/|$)/,null]]);function PR_splitStringAndCommentTokens(sourceCode){return PR_C_STYLE_STRING_AND_COMMENT_LEXER(sourceCode);}var PR_C_STYLE_LITERAL_IDENTIFIER_PUNC_RECOGNIZER=PR_createSimpleLexer([],[[PR_PLAIN,/^\s+/,null,' \r\n'],[PR_PLAIN,/^[a-z_$@][a-z_$@0-9]*/i,null],[PR_LITERAL,/^0x[a-f0-9]+[a-z]/i,null],[PR_LITERAL,/^(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?[a-z]*/i,null,'123456789'],[PR_PUNCTUATION,/^[^\s\w\.$@]+/,null]]);function PR_splitNonStringNonCommentTokens(source,decorations){for(var i=0;i<decorations.length;i+=2){var style=decorations[i+1];if(style===PR_PLAIN){var start=decorations[i];var end=i+2<decorations.length?decorations[i+2]:source.length;var chunk=source.substring(start,end);var subDecs=PR_C_STYLE_LITERAL_IDENTIFIER_PUNC_RECOGNIZER(chunk,start);for(var j=0,m=subDecs.length;j<m;j+=2){var subStyle=subDecs[j+1];if(subStyle===PR_PLAIN){var subStart=subDecs[j];var subEnd=j+2<m?subDecs[j+2]:chunk.length;var token=source.substring(subStart,subEnd);if(token=='.'){subDecs[j+1]=PR_PUNCTUATION;}else if(token in PR_keywords){subDecs[j+1]=PR_KEYWORD;}else if(/^@?[A-Z][A-Z$]*[a-z][A-Za-z$]*$/.test(token)){subDecs[j+1]=token.charAt(0)=='@'?PR_LITERAL:PR_TYPE;}}}PR_spliceArrayInto(subDecs,decorations,i,2);i+=subDecs.length-2;}}return decorations;}var PR_MARKUP_LEXER=PR_createSimpleLexer([],[[PR_PLAIN,/^[^<]+/,null],[PR_DECLARATION,/^<!\w[^>]*(?:>|$)/,null],[PR_COMMENT,/^<!--[\s\S]*?(?:-->|$)/,null],[PR_SOURCE,/^<\?[\s\S]*?(?:\?>|$)/,null],[PR_SOURCE,/^<%[\s\S]*?(?:%>|$)/,null],[PR_SOURCE,/^<(script|style|xmp)\b[^>]*>[\s\S]*?<\/\1\b[^>]*>/i,null],[PR_TAG,/^<\/?\w[^<>]*>/,null]]);var PR_SOURCE_CHUNK_PARTS=/^(<[^>]*>)([\s\S]*)(<\/[^>]*>)$/;function PR_tokenizeMarkup(source){var decorations=PR_MARKUP_LEXER(source);for(var i=0;i<decorations.length;i+=2){if(decorations[i+1]===PR_SOURCE){var start=decorations[i];var end=i+2<decorations.length?decorations[i+2]:source.length;var sourceChunk=source.substring(start,end);var match=(sourceChunk.match(PR_SOURCE_CHUNK_PARTS));if(match){decorations.splice(i,2,start,PR_TAG,start+match[1].length,PR_SOURCE,start+match[1].length+(match[2]||'').length,PR_TAG);}}}return decorations;}var PR_TAG_LEXER=PR_createSimpleLexer([[PR_ATTRIB_VALUE,/^\'[^\']*(?:\'|$)/,null,"'"],[PR_ATTRIB_VALUE,/^"[^"]*(?:"|$)/,null,'"'],[PR_PUNCTUATION,/^[<>\/=]+/,null,'<>/=']],[[PR_TAG,/^[\w-]+/,/^</],[PR_ATTRIB_VALUE,/^[\w-]+/,/^=/],[PR_ATTRIB_NAME,/^[\w-]+/,null],[PR_PLAIN,/^\s+/,null,' \r\n']]);function PR_splitTagAttributes(source,decorations){for(var i=0;i<decorations.length;i+=2){var style=decorations[i+1];if(style===PR_TAG){var start=decorations[i];var end=i+2<decorations.length?decorations[i+2]:source.length;var chunk=source.substring(start,end);var subDecorations=PR_TAG_LEXER(chunk,start);PR_spliceArrayInto(subDecorations,decorations,i,2);i+=subDecorations.length-2;}}return decorations;}function PR_splitSourceNodes(source,decorations){for(var i=0;i<decorations.length;i+=2){var style=decorations[i+1];if(style==PR_SOURCE){var start=decorations[i];var end=i+2<decorations.length?decorations[i+2]:source.length;var subDecorations=PR_decorateSource(source.substring(start,end));for(var j=0,m=subDecorations.length;j<m;j+=2){subDecorations[j]+=start;}PR_spliceArrayInto(subDecorations,decorations,i,2);i+=subDecorations.length-2;}}return decorations;}function PR_splitSourceAttributes(source,decorations){var nextValueIsSource=false;for(var i=0;i<decorations.length;i+=2){var style=decorations[i+1];if(style===PR_ATTRIB_NAME){var start=decorations[i];var end=i+2<decorations.length?decorations[i+2]:source.length;nextValueIsSource=/^on|^style$/i.test(source.substring(start,end));}else if(style==PR_ATTRIB_VALUE){if(nextValueIsSource){var start=decorations[i];var end=i+2<decorations.length?decorations[i+2]:source.length;var attribValue=source.substring(start,end);var attribLen=attribValue.length;var quoted=(attribLen>=2&&/^["\']/.test(attribValue)&&attribValue.charAt(0)===attribValue.charAt(attribLen-1));var attribSource;var attribSourceStart;var attribSourceEnd;if(quoted){attribSourceStart=start+1;attribSourceEnd=end-1;attribSource=attribValue;}else{attribSourceStart=start+1;attribSourceEnd=end-1;attribSource=attribValue.substring(1,attribValue.length-1);}var attribSourceDecorations=PR_decorateSource(attribSource);for(var j=0,m=attribSourceDecorations.length;j<m;j+=2){attribSourceDecorations[j]+=attribSourceStart;}if(quoted){attribSourceDecorations.push(attribSourceEnd,PR_ATTRIB_VALUE);PR_spliceArrayInto(attribSourceDecorations,decorations,i+2,0);}else{PR_spliceArrayInto(attribSourceDecorations,decorations,i,2);}}nextValueIsSource=false;}}return decorations;}function PR_decorateSource(sourceCode){var decorations=PR_splitStringAndCommentTokens(sourceCode);decorations=PR_splitNonStringNonCommentTokens(sourceCode,decorations);return decorations;}function PR_decorateMarkup(sourceCode){var decorations=PR_tokenizeMarkup(sourceCode);decorations=PR_splitTagAttributes(sourceCode,decorations);decorations=PR_splitSourceNodes(sourceCode,decorations);decorations=PR_splitSourceAttributes(sourceCode,decorations);return decorations;}function PR_recombineTagsAndDecorations(sourceText,extractedTags,decorations){var html=[];var outputIdx=0;var openDecoration=null;var currentDecoration=null;var tagPos=0;var decPos=0;var tabExpander=PR_tabExpander(PR_TAB_WIDTH);function emitTextUpTo(sourceIdx){if(sourceIdx>outputIdx){if(openDecoration&&openDecoration!==currentDecoration){html.push('</span>');openDecoration=null;}if(!openDecoration&&currentDecoration){openDecoration=currentDecoration;html.push('<span class="',openDecoration,'">');}var htmlChunk=PR_textToHtml(tabExpander(sourceText.substring(outputIdx,sourceIdx))).replace(/(\r\n?|\n| ) /g,'$1&nbsp;').replace(/\r\n?|\n/g,'&nbsp;<br>');html.push(htmlChunk);outputIdx=sourceIdx;}}while(true){var outputTag;if(tagPos<extractedTags.length){if(decPos<decorations.length){outputTag=extractedTags[tagPos]<=decorations[decPos];}else{outputTag=true;}}else{outputTag=false;}if(outputTag){emitTextUpTo(extractedTags[tagPos]);if(openDecoration){html.push('</span>');openDecoration=null;}html.push(extractedTags[tagPos+1]);tagPos+=2;}else if(decPos<decorations.length){emitTextUpTo(decorations[decPos]);currentDecoration=decorations[decPos+1];decPos+=2;}else{break;}}emitTextUpTo(sourceText.length);if(openDecoration){html.push('</span>');}return html.join('');}function prettyPrintOne(sourceCodeHtml){try{var sourceAndExtractedTags=PR_extractTags(sourceCodeHtml);var source=sourceAndExtractedTags.source;var extractedTags=sourceAndExtractedTags.tags;var isMarkup=/^\s*</.test(source)&&/>\s*$/.test(source);var decorations=isMarkup?PR_decorateMarkup(source):PR_decorateSource(source);return PR_recombineTagsAndDecorations(source,extractedTags,decorations);}catch(e){if('console'in window){console.log(e);console.trace();}return sourceCodeHtml;}}var PR_SHOULD_USE_CONTINUATION=true;function prettyPrint(opt_whenDone){var codeSegments=[document.getElementsByTagName('pre'),document.getElementsByTagName('code'),document.getElementsByTagName('xmp')];var elements=[];for(var i=0;i<codeSegments.length;++i){for(var j=0;j<codeSegments[i].length;++j){elements.push(codeSegments[i][j]);}}codeSegments=null;var k=0;function doWork(){var endTime=(PR_SHOULD_USE_CONTINUATION?new Date().getTime()+250:Infinity);for(;k<elements.length&&new Date().getTime()<endTime;k++){var cs=elements[k];if(cs.className&&cs.className.indexOf('prettyprint')>=0){var nested=false;for(var p=cs.parentNode;p!=null;p=p.parentNode){if((p.tagName=='pre'||p.tagName=='code'||p.tagName=='xmp')&&p.className&&p.className.indexOf('prettyprint')>=0){nested=true;break;}}if(!nested){var content=PR_getInnerHtml(cs);content=content.replace(/(?:\r\n?|\n)$/,'');var newContent=prettyPrintOne(content);if(!PR_isRawContent(cs)){cs.innerHTML=newContent;}else{var pre=document.createElement('PRE');for(var i=0;i<cs.attributes.length;++i){var a=cs.attributes[i];if(a.specified){pre.setAttribute(a.name,a.value);}}pre.innerHTML=newContent;cs.parentNode.replaceChild(pre,cs);}}}}if(k<elements.length){setTimeout(doWork,250);}else if(opt_whenDone){opt_whenDone();}}doWork();}</script><script type='text/javascript'>prettyPrint();</script></BODY>
</HTML>