You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by sa...@apache.org on 2010/11/21 12:14:27 UTC

svn commit: r1037417 - in /click/trunk/click/framework/src/org/apache/click: ActionResult.java Behavior.java Stateful.java ajax/AjaxBehavior.java ajax/DefaultAjaxBehavior.java

Author: sabob
Date: Sun Nov 21 11:14:27 2010
New Revision: 1037417

URL: http://svn.apache.org/viewvc?rev=1037417&view=rev
Log:
checkstyle

Modified:
    click/trunk/click/framework/src/org/apache/click/ActionResult.java
    click/trunk/click/framework/src/org/apache/click/Behavior.java
    click/trunk/click/framework/src/org/apache/click/Stateful.java
    click/trunk/click/framework/src/org/apache/click/ajax/AjaxBehavior.java
    click/trunk/click/framework/src/org/apache/click/ajax/DefaultAjaxBehavior.java

Modified: click/trunk/click/framework/src/org/apache/click/ActionResult.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/ActionResult.java?rev=1037417&r1=1037416&r2=1037417&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/ActionResult.java (original)
+++ click/trunk/click/framework/src/org/apache/click/ActionResult.java Sun Nov 21 11:14:27 2010
@@ -1,579 +1,579 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 org.apache.click;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.Writer;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import javax.servlet.http.HttpServletResponse;
-import org.apache.click.util.ClickUtils;
-
-/**
- * Provides an ActionResult that is returned by Page Actions and AjaxBehaviors.
- * ActionResults are often used to return a partial response to the browser
- * instead of the full page content.
- * <p/>
- * An ActionResult can consist of a String (HTML, JSON, XML, plain text) or a byte
- * array (jpg, gif, png, pdf or excel documents). The ActionResult {@link #contentType}
- * must be set appropriately in order for the browser to recognize the action result.
- * <p/>
- * ActionResults are returned by {@link org.apache.click.ajax.AjaxBehavior Ajax Behaviors}
- * and <tt>Page Action</tt> methods.
- *
- * <h3>Ajax Behavior</h3>
- *
- * Ajax requests are handled by adding an {@link org.apache.click.ajax.AjaxBehavior Ajax Behavior}
- * to a control. The AjaxBehavior {@link org.apache.click.ajax.AjaxBehavior#onAction(org.apache.click.Control) onAction}
- * method will handle the request and return a ActionResult instance that contains
- * the response, thus bypassing the rendering of the Page template. For example:
- *
- * <pre class="prettyprint">
- * private ActionLink link = new ActionLink("link");
- *
- * public void onInit() {
- *     addControl(link);
- *
- *     link.addBehavior(new AjaxBehavior() {
- *
- *         // The onAction method must return a ActionResult
- *         public ActionResult onAction(Control source) {
- *             // Create a new action result containing an HTML snippet and HTML content type
- *             ActionResult actionResult = new ActionResult("&lt;span&gt;Hello World&lt;/span&gt;", ActionResult.HTML);
- *             return actionResult;
- *         }
- *     });
- * } </pre>
- *
- * <h3>Page Action</h3>
- *
- * A <tt>Page Action</tt> is a method on a Page that can be invoked directly
- * from the browser. The Page Action method returns an ActionResult instance that
- * is rendered to the browser, thus bypassing the rendering of the Page template.
- *
- * <pre class="prettyprint">
- * private ActionLink link = new ActionLink("link");
- *
- * public void onInit() {
- *     link.addControl(link);
- *
- *     // A "pageAction" is set as a parameter on the link. The "pageAction"
- *     // value is set to the Page method: "renderHelloWorld"
- *     link.setParameter(PAGE_ACTION, "renderHelloWorld");
- * }
- *
- * &#47;**
- *  * This is a "pageAction" method that will render an HTML response.
- *  *
- *  * Note the signature of the pageAction: a public, no-argument method
- *  * returning a ActionResult instance.
- *  *&#47;
- * public ActionResult renderHelloWorld() {
- *     ActionResult actionResult = new ActionResult("&lt;span&gt;Hello World&lt;/span&gt;", ActionResult.HTML);
- *     return actionResult;
- * } </pre>
- *
- * <h3>Content Type</h3>
- *
- * The {@link #contentType} of the ActionResult must be set to the appropriate type
- * in order for the client to recognize the response. ActionResult provides constants
- * for some of the common <tt>content types</tt>, including: {@link #XML text/xml},
- * {@link #HTML text/html}, {@link #JSON application/json}, {@link #TEXT text/plain}.
- * <p/>
- * For example:
- * <pre class="prettyprint">
- * ActionResult actionResult = new ActionResult("alert('hello world');", ActionResult.JAVASCRIPT);
- *
- * ...
- *
- * // content type can also be set through the setContentType method
- * actionResult.setContentType(ActionResult.JAVASCRIPT);
- *
- * ...
- * </pre>
- *
- * More content types can be retrieved through {@link org.apache.click.util.ClickUtils#getMimeType(java.lang.String)}:
- * <pre class="prettyprint">
- * // lookup content type for PNG
- * String contentType = ClickUtils.getMimeType("png");
- * actionResult.setContentType(contentType); </pre>
- */
-public class ActionResult {
-
-    // Constants --------------------------------------------------------------
-
-    /** The plain text content type constant: <tt>text/plain</tt>. */
-    public static final String TEXT = "text/plain";
-
-    /** The html content type constant: <tt>text/html</tt>. */
-    public static final String HTML = "text/html";
-
-    /** The The xhtml content type constant: <tt>application/xhtml+xml</tt>. */
-    public static final String XHTML = "application/xhtml+xml";
-
-    /** The json content type constant: <tt>text/json</tt>. */
-    public static final String JSON = "application/json";
-
-    /** The javascript content type constant: <tt>text/javascript</tt>. */
-    public static final String JAVASCRIPT = "text/javascript";
-
-    /** The xml content type constant: <tt>text/xml</tt>. */
-    public static final String XML = "text/xml";
-
-    /** The ActionResult writer buffer size. */
-    private static final int WRITER_BUFFER_SIZE = 256; // For text, set a small response size
-
-    /** The ActionResult output buffer size. */
-    private static final int OUTPUT_BUFFER_SIZE = 4 * 1024; // For binary, set a a large response size
-
-    // Variables --------------------------------------------------------------
-
-    /** The content to render. */
-    private String content;
-
-    /** The content as a byte array. */
-    private byte[] bytes;
-
-    /** The servlet response reader. */
-    private Reader reader;
-
-    /** The servlet response input stream. */
-    private InputStream inputStream;
-
-    /** The response content type. */
-    private String contentType;
-
-    /** The response character encoding. */
-    private String characterEncoding;
-
-    /** Indicates whether the ActionResult should be cached by browser. */
-    private boolean cacheActionResult = false;
-
-    /** The path of the actionResult template to render. */
-    private String template;
-
-    /** The model for the ActionResult {@link #template}. */
-    private Map<String, Object> model;
-
-    // Constructors -----------------------------------------------------------
-
-    /**
-     * Construct the ActionResult for the given template and model.
-     * <p/>
-     * When the ActionResult is rendered the template and model will be merged and
-     * the result will be streamed back to the client.
-     * <p/>
-     * For example:
-     * <pre class="prettyprint">
-     * public class MyPage extends Page {
-     *     public void onInit() {
-     *
-     *         Behavior behavior = new DefaultAjaxBehavior() {
-     *
-     *             public ActionResult onAction() {
-     *
-     *                 Map model = new HashMap();
-     *                 model.put("id", "link");
-     *
-     *                 // Note: we set XML as the content type
-     *                 ActionResult actionResult = new ActionResult("/js/actionResult.xml", model, ActionResult.XML);
-     *
-     *                 return actionResult;
-     *             }
-     *         }
-     *     }
-     * } </pre>
-     *
-     * @param template the template to render and stream back to the client
-     * @param model the template data model
-     * @param contentType the response content type
-     */
-    public ActionResult(String template, Map<String, Object> model, String contentType) {
-        this.template = template;
-        this.model = model;
-        this.contentType = contentType;
-    }
-
-    /**
-     * Construct the ActionResult for the given reader and content type.
-     *
-     * @param reader the reader which characters must be streamed back to the
-     * client
-     * @param contentType the response content type
-     */
-    public ActionResult(Reader reader, String contentType) {
-        this.reader = reader;
-        this.contentType = contentType;
-    }
-
-    /**
-     * Construct the ActionResult for the given inputStream and content type.
-     *
-     * @param inputStream the input stream to stream back to the client
-     * @param contentType the response content type
-     */
-    public ActionResult(InputStream inputStream, String contentType) {
-        this.inputStream = inputStream;
-        this.contentType = contentType;
-    }
-
-    /**
-     * Construct the ActionResult for the given String content and content type.
-     *
-     * @param content the String content to stream back to the client
-     * @param contentType the response content type
-     */
-    public ActionResult(String content, String contentType) {
-        this.content = content;
-        this.contentType = contentType;
-    }
-
-    /**
-     * Construct the ActionResult for the given byte array and content type.
-     *
-     * @param bytes the byte array to stream back to the client
-     * @param contentType the response content type
-     */
-    public ActionResult(byte[] bytes, String contentType) {
-        this.bytes = bytes;
-        this.contentType = contentType;
-    }
-
-    /**
-     * Construct the ActionResult for the given content. The
-     * <tt>{@link javax.servlet.http.HttpServletResponse#setContentType(java.lang.String) response content type}</tt>
-     * will default to {@link #TEXT}, unless overridden.
-     *
-     * @param content the content to stream back to the client
-     */
-    public ActionResult(String content) {
-        this.content = content;
-    }
-
-    /**
-     * Construct a new empty ActionResult. The
-     * <tt>{@link javax.servlet.http.HttpServletResponse#setContentType(java.lang.String) response content type}</tt>
-     * will default to {@link #TEXT}, unless overridden.
-     */
-    public ActionResult() {
-    }
-
-    // Public Methods ---------------------------------------------------------
-
-    /**
-     * Set whether the action result should be cached by the client browser or
-     * not.
-     * <p/>
-     * If false, Click will set the following headers to prevent browsers
-     * from caching the result:
-     * <pre class="prettyprint">
-     * response.setHeader("Pragma", "no-cache");
-     * response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
-     * response.setDateHeader("Expires", new Date(1L).getTime()); </pre>
-     *
-     * @param cacheActionResult indicates whether the action result should be cached
-     * by the client browser or not
-     */
-    public void setCacheActionResult(boolean cacheActionResult) {
-        this.cacheActionResult = cacheActionResult;
-    }
-
-    /**
-     * Return true if the action result should be cached by the client browser,
-     * defaults to false. It is highly unlikely that you would turn action result
-     * caching on.
-     *
-     * @return true if the action result should be cached by the client browser,
-     * false otherwise
-     */
-    public boolean isCacheActionRestul() {
-        return cacheActionResult;
-    }
-
-    /**
-     * Return the action result character encoding. If no character encoding is specified
-     * the request character encoding will be used.
-     *
-     * @return the action result character encoding
-     */
-    public String getCharacterEncoding() {
-        return characterEncoding;
-    }
-
-    /**
-     * Set the action result character encoding. If no character encoding is set the
-     * request character encoding will be used.
-     *
-     * @param characterEncoding the action result character encoding
-     */
-    public void setCharacterEncoding(String characterEncoding) {
-        this.characterEncoding = characterEncoding;
-    }
-
-    /**
-     * Set the action result response content type. If no content type is set it will
-     * default to {@value #TEXT}.
-     *
-     * @param contentType the action result response content type
-     */
-    public void setContentType(String contentType) {
-        this.contentType = contentType;
-    }
-
-    /**
-     * Return the action result content type, default is {@value #TEXT}.
-     *
-     * @return the response content type
-     */
-    public String getContentType() {
-        if (contentType == null) {
-            contentType = TEXT;
-        }
-        return contentType;
-    }
-
-    /**
-     * Set the content String to stream back to the client.
-     *
-     * @param content the content String to stream back to the client
-     */
-    public void setContent(String content) {
-        this.content = content;
-    }
-
-    /**
-     * Return the content String to stream back to the client.
-     *
-     * @return the content String to stream back to the client
-     */
-    public String getContent() {
-        return content;
-    }
-
-    /**
-     * Set the byte array to stream back to the client.
-     *
-     * @param bytes the byte array to stream back to the client
-     */
-    public void setBytes(byte[] bytes, String contentType) {
-        this.bytes = bytes;
-        this.contentType = contentType;
-    }
-
-    /**
-     * Return the byte array to stream back to the client.
-     *
-     * @return the byte array to stream back to the client
-     */
-    public byte[] getBytes() {
-        return bytes;
-    }
-
-    /**
-     * Set the content to stream back to the client.
-     *
-     * @param inputStream the inputStream to stream back to the client
-     */
-    public void setInputStream(InputStream inputStream) {
-        this.inputStream = inputStream;
-    }
-
-    /**
-     * Return the inputStream to stream back to the client.
-     *
-     * @return the inputStream to stream back to the client
-     */
-    public InputStream getInputStream() {
-        return inputStream;
-    }
-
-    /**
-     * Set the reader which characters are streamed back to the client.
-     *
-     * @param reader the reader which characters are streamed back to the client.
-     */
-    public void setReader(Reader reader) {
-        this.reader = reader;
-    }
-
-    /**
-     * Return the reader which characters are streamed back to the client.
-     *
-     * @return the reader which characters are streamed back to the client.
-     */
-    public Reader getReader() {
-        return reader;
-    }
-
-    /**
-     * Return the data model for the ActionResult {@link #template}.
-     *
-     * @return the data model for the ActionResult template
-     */
-    public Map<String, Object> getModel() {
-        if (model == null) {
-            model = new HashMap<String, Object>();
-        }
-        return model;
-    }
-
-    /**
-     * Set the model of the ActionResult template to render.
-     * <p/>
-     * If the {@link #template} property is set, the template and {@link #model}
-     * will be merged and the result will be streamed back to the client.
-     *
-     * @param model the model of the template to render
-     */
-    public void setModel(Map<String, Object> model) {
-        this.model = model;
-    }
-
-    /**
-     * Return the template to render for this ActionResult.
-     *
-     * @return the template to render for this ActionResult
-     */
-    public String getTemplate() {
-        return template;
-    }
-
-    /**
-     * Set the template to render for this ActionResult.
-     *
-     * @param template the template to render for this ActionResult
-     */
-    public void setTemplate(String template) {
-        this.template = template;
-    }
-
-    /**
-     * Render the ActionResult to the client.
-     *
-     * @param context the request context
-     */
-    public final void render(Context context) {
-        prepare(context);
-        renderActionResult(context);
-    }
-
-    // Protected Methods ------------------------------------------------------
-
-    /**
-     * Render the ActionResult to the client. This method can be overridden
-     * by subclasses if custom rendering or direct access to the
-     * HttpServletResponse is required.
-     *
-     * @param context the request context
-     */
-    protected void renderActionResult(Context context) {
-
-        HttpServletResponse response = context.getResponse();
-
-        Reader localReader = getReader();
-        InputStream localInputStream = getInputStream();
-
-        try {
-            String localContent = getContent();
-            byte[] localBytes = getBytes();
-
-            String localTemplate = getTemplate();
-            if (localTemplate != null) {
-                Map<String, Object> templateModel = getModel();
-                if (templateModel == null) {
-                    templateModel = new HashMap<String, Object>();
-                }
-                String result = context.renderTemplate(localTemplate, templateModel);
-                localReader = new StringReader(result);
-
-            } else if (localContent != null) {
-                localReader = new StringReader(localContent);
-            } else if (localBytes != null) {
-                localInputStream = new ByteArrayInputStream(localBytes);
-            }
-
-            if (localReader != null) {
-                Writer writer = response.getWriter();
-                char[] buffer = new char[WRITER_BUFFER_SIZE];
-                int len = 0;
-                while (-1 != (len = localReader.read(buffer))) {
-                    writer.write(buffer, 0, len);
-                }
-                writer.flush();
-                writer.close();
-
-            } else if (localInputStream != null) {
-                byte[] buffer = new byte[OUTPUT_BUFFER_SIZE];
-                int len = 0;
-                OutputStream outputStream = response.getOutputStream();
-                while (-1 != (len = localInputStream.read(buffer))) {
-                    outputStream.write(buffer, 0, len);
-                }
-                outputStream.flush();
-                outputStream.close();
-            }
-
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-
-        } finally {
-            ClickUtils.close(localInputStream);
-            ClickUtils.close(localReader);
-        }
-    }
-
-    // Private Methods --------------------------------------------------------
-
-    /**
-     * Prepare the ActionResult for rendering.
-     *
-     * @param context the request context
-     */
-    private void prepare(Context context) {
-        HttpServletResponse response = context.getResponse();
-
-        if (!isCacheActionRestul()) {
-            // Set headers to disable cache
-            response.setHeader("Pragma", "no-cache");
-            response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
-            response.setDateHeader("Expires", new Date(1L).getTime());
-        }
-
-        String localContentType = getContentType();
-
-        if (getCharacterEncoding() == null) {
-
-            // Fallback to request character encoding
-            if (context.getRequest().getCharacterEncoding() != null) {
-                response.setContentType(localContentType + "; charset="
-                    + context.getRequest().getCharacterEncoding());
-            } else {
-                response.setContentType(localContentType);
-            }
-
-        } else {
-            response.setContentType(localContentType + "; charset=" + getCharacterEncoding());
-        }
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.click;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.click.util.ClickUtils;
+
+/**
+ * Provides an ActionResult that is returned by Page Actions and AjaxBehaviors.
+ * ActionResults are often used to return a partial response to the browser
+ * instead of the full page content.
+ * <p/>
+ * An ActionResult can consist of a String (HTML, JSON, XML, plain text) or a byte
+ * array (jpg, gif, png, pdf or excel documents). The ActionResult {@link #contentType}
+ * must be set appropriately in order for the browser to recognize the action result.
+ * <p/>
+ * ActionResults are returned by {@link org.apache.click.ajax.AjaxBehavior Ajax Behaviors}
+ * and <tt>Page Action</tt> methods.
+ *
+ * <h3>Ajax Behavior</h3>
+ *
+ * Ajax requests are handled by adding an {@link org.apache.click.ajax.AjaxBehavior Ajax Behavior}
+ * to a control. The AjaxBehavior {@link org.apache.click.ajax.AjaxBehavior#onAction(org.apache.click.Control) onAction}
+ * method will handle the request and return a ActionResult instance that contains
+ * the response, thus bypassing the rendering of the Page template. For example:
+ *
+ * <pre class="prettyprint">
+ * private ActionLink link = new ActionLink("link");
+ *
+ * public void onInit() {
+ *     addControl(link);
+ *
+ *     link.addBehavior(new AjaxBehavior() {
+ *
+ *         // The onAction method must return a ActionResult
+ *         public ActionResult onAction(Control source) {
+ *             // Create a new action result containing an HTML snippet and HTML content type
+ *             ActionResult actionResult = new ActionResult("&lt;span&gt;Hello World&lt;/span&gt;", ActionResult.HTML);
+ *             return actionResult;
+ *         }
+ *     });
+ * } </pre>
+ *
+ * <h3>Page Action</h3>
+ *
+ * A <tt>Page Action</tt> is a method on a Page that can be invoked directly
+ * from the browser. The Page Action method returns an ActionResult instance that
+ * is rendered to the browser, thus bypassing the rendering of the Page template.
+ *
+ * <pre class="prettyprint">
+ * private ActionLink link = new ActionLink("link");
+ *
+ * public void onInit() {
+ *     link.addControl(link);
+ *
+ *     // A "pageAction" is set as a parameter on the link. The "pageAction"
+ *     // value is set to the Page method: "renderHelloWorld"
+ *     link.setParameter(PAGE_ACTION, "renderHelloWorld");
+ * }
+ *
+ * &#47;**
+ *  * This is a "pageAction" method that will render an HTML response.
+ *  *
+ *  * Note the signature of the pageAction: a public, no-argument method
+ *  * returning a ActionResult instance.
+ *  *&#47;
+ * public ActionResult renderHelloWorld() {
+ *     ActionResult actionResult = new ActionResult("&lt;span&gt;Hello World&lt;/span&gt;", ActionResult.HTML);
+ *     return actionResult;
+ * } </pre>
+ *
+ * <h3>Content Type</h3>
+ *
+ * The {@link #contentType} of the ActionResult must be set to the appropriate type
+ * in order for the client to recognize the response. ActionResult provides constants
+ * for some of the common <tt>content types</tt>, including: {@link #XML text/xml},
+ * {@link #HTML text/html}, {@link #JSON application/json}, {@link #TEXT text/plain}.
+ * <p/>
+ * For example:
+ * <pre class="prettyprint">
+ * ActionResult actionResult = new ActionResult("alert('hello world');", ActionResult.JAVASCRIPT);
+ *
+ * ...
+ *
+ * // content type can also be set through the setContentType method
+ * actionResult.setContentType(ActionResult.JAVASCRIPT);
+ *
+ * ...
+ * </pre>
+ *
+ * More content types can be retrieved through {@link org.apache.click.util.ClickUtils#getMimeType(java.lang.String)}:
+ * <pre class="prettyprint">
+ * // lookup content type for PNG
+ * String contentType = ClickUtils.getMimeType("png");
+ * actionResult.setContentType(contentType); </pre>
+ */
+public class ActionResult {
+
+    // Constants --------------------------------------------------------------
+
+    /** The plain text content type constant: <tt>text/plain</tt>. */
+    public static final String TEXT = "text/plain";
+
+    /** The html content type constant: <tt>text/html</tt>. */
+    public static final String HTML = "text/html";
+
+    /** The The xhtml content type constant: <tt>application/xhtml+xml</tt>. */
+    public static final String XHTML = "application/xhtml+xml";
+
+    /** The json content type constant: <tt>text/json</tt>. */
+    public static final String JSON = "application/json";
+
+    /** The javascript content type constant: <tt>text/javascript</tt>. */
+    public static final String JAVASCRIPT = "text/javascript";
+
+    /** The xml content type constant: <tt>text/xml</tt>. */
+    public static final String XML = "text/xml";
+
+    /** The ActionResult writer buffer size. */
+    private static final int WRITER_BUFFER_SIZE = 256; // For text, set a small response size
+
+    /** The ActionResult output buffer size. */
+    private static final int OUTPUT_BUFFER_SIZE = 4 * 1024; // For binary, set a a large response size
+
+    // Variables --------------------------------------------------------------
+
+    /** The content to render. */
+    private String content;
+
+    /** The content as a byte array. */
+    private byte[] bytes;
+
+    /** The servlet response reader. */
+    private Reader reader;
+
+    /** The servlet response input stream. */
+    private InputStream inputStream;
+
+    /** The response content type. */
+    private String contentType;
+
+    /** The response character encoding. */
+    private String characterEncoding;
+
+    /** Indicates whether the ActionResult should be cached by browser. */
+    private boolean cacheActionResult = false;
+
+    /** The path of the actionResult template to render. */
+    private String template;
+
+    /** The model for the ActionResult {@link #template}. */
+    private Map<String, Object> model;
+
+    // Constructors -----------------------------------------------------------
+
+    /**
+     * Construct the ActionResult for the given template and model.
+     * <p/>
+     * When the ActionResult is rendered the template and model will be merged and
+     * the result will be streamed back to the client.
+     * <p/>
+     * For example:
+     * <pre class="prettyprint">
+     * public class MyPage extends Page {
+     *     public void onInit() {
+     *
+     *         Behavior behavior = new DefaultAjaxBehavior() {
+     *
+     *             public ActionResult onAction() {
+     *
+     *                 Map model = new HashMap();
+     *                 model.put("id", "link");
+     *
+     *                 // Note: we set XML as the content type
+     *                 ActionResult actionResult = new ActionResult("/js/actionResult.xml", model, ActionResult.XML);
+     *
+     *                 return actionResult;
+     *             }
+     *         }
+     *     }
+     * } </pre>
+     *
+     * @param template the template to render and stream back to the client
+     * @param model the template data model
+     * @param contentType the response content type
+     */
+    public ActionResult(String template, Map<String, Object> model, String contentType) {
+        this.template = template;
+        this.model = model;
+        this.contentType = contentType;
+    }
+
+    /**
+     * Construct the ActionResult for the given reader and content type.
+     *
+     * @param reader the reader which characters must be streamed back to the
+     * client
+     * @param contentType the response content type
+     */
+    public ActionResult(Reader reader, String contentType) {
+        this.reader = reader;
+        this.contentType = contentType;
+    }
+
+    /**
+     * Construct the ActionResult for the given inputStream and content type.
+     *
+     * @param inputStream the input stream to stream back to the client
+     * @param contentType the response content type
+     */
+    public ActionResult(InputStream inputStream, String contentType) {
+        this.inputStream = inputStream;
+        this.contentType = contentType;
+    }
+
+    /**
+     * Construct the ActionResult for the given String content and content type.
+     *
+     * @param content the String content to stream back to the client
+     * @param contentType the response content type
+     */
+    public ActionResult(String content, String contentType) {
+        this.content = content;
+        this.contentType = contentType;
+    }
+
+    /**
+     * Construct the ActionResult for the given byte array and content type.
+     *
+     * @param bytes the byte array to stream back to the client
+     * @param contentType the response content type
+     */
+    public ActionResult(byte[] bytes, String contentType) {
+        this.bytes = bytes;
+        this.contentType = contentType;
+    }
+
+    /**
+     * Construct the ActionResult for the given content. The
+     * <tt>{@link javax.servlet.http.HttpServletResponse#setContentType(java.lang.String) response content type}</tt>
+     * will default to {@link #TEXT}, unless overridden.
+     *
+     * @param content the content to stream back to the client
+     */
+    public ActionResult(String content) {
+        this.content = content;
+    }
+
+    /**
+     * Construct a new empty ActionResult. The
+     * <tt>{@link javax.servlet.http.HttpServletResponse#setContentType(java.lang.String) response content type}</tt>
+     * will default to {@link #TEXT}, unless overridden.
+     */
+    public ActionResult() {
+    }
+
+    // Public Methods ---------------------------------------------------------
+
+    /**
+     * Set whether the action result should be cached by the client browser or
+     * not.
+     * <p/>
+     * If false, Click will set the following headers to prevent browsers
+     * from caching the result:
+     * <pre class="prettyprint">
+     * response.setHeader("Pragma", "no-cache");
+     * response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
+     * response.setDateHeader("Expires", new Date(1L).getTime()); </pre>
+     *
+     * @param cacheActionResult indicates whether the action result should be cached
+     * by the client browser or not
+     */
+    public void setCacheActionResult(boolean cacheActionResult) {
+        this.cacheActionResult = cacheActionResult;
+    }
+
+    /**
+     * Return true if the action result should be cached by the client browser,
+     * defaults to false. It is highly unlikely that you would turn action result
+     * caching on.
+     *
+     * @return true if the action result should be cached by the client browser,
+     * false otherwise
+     */
+    public boolean isCacheActionRestul() {
+        return cacheActionResult;
+    }
+
+    /**
+     * Return the action result character encoding. If no character encoding is specified
+     * the request character encoding will be used.
+     *
+     * @return the action result character encoding
+     */
+    public String getCharacterEncoding() {
+        return characterEncoding;
+    }
+
+    /**
+     * Set the action result character encoding. If no character encoding is set the
+     * request character encoding will be used.
+     *
+     * @param characterEncoding the action result character encoding
+     */
+    public void setCharacterEncoding(String characterEncoding) {
+        this.characterEncoding = characterEncoding;
+    }
+
+    /**
+     * Set the action result response content type. If no content type is set it will
+     * default to {@value #TEXT}.
+     *
+     * @param contentType the action result response content type
+     */
+    public void setContentType(String contentType) {
+        this.contentType = contentType;
+    }
+
+    /**
+     * Return the action result content type, default is {@value #TEXT}.
+     *
+     * @return the response content type
+     */
+    public String getContentType() {
+        if (contentType == null) {
+            contentType = TEXT;
+        }
+        return contentType;
+    }
+
+    /**
+     * Set the content String to stream back to the client.
+     *
+     * @param content the content String to stream back to the client
+     */
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    /**
+     * Return the content String to stream back to the client.
+     *
+     * @return the content String to stream back to the client
+     */
+    public String getContent() {
+        return content;
+    }
+
+    /**
+     * Set the byte array to stream back to the client.
+     *
+     * @param bytes the byte array to stream back to the client
+     */
+    public void setBytes(byte[] bytes, String contentType) {
+        this.bytes = bytes;
+        this.contentType = contentType;
+    }
+
+    /**
+     * Return the byte array to stream back to the client.
+     *
+     * @return the byte array to stream back to the client
+     */
+    public byte[] getBytes() {
+        return bytes;
+    }
+
+    /**
+     * Set the content to stream back to the client.
+     *
+     * @param inputStream the inputStream to stream back to the client
+     */
+    public void setInputStream(InputStream inputStream) {
+        this.inputStream = inputStream;
+    }
+
+    /**
+     * Return the inputStream to stream back to the client.
+     *
+     * @return the inputStream to stream back to the client
+     */
+    public InputStream getInputStream() {
+        return inputStream;
+    }
+
+    /**
+     * Set the reader which characters are streamed back to the client.
+     *
+     * @param reader the reader which characters are streamed back to the client.
+     */
+    public void setReader(Reader reader) {
+        this.reader = reader;
+    }
+
+    /**
+     * Return the reader which characters are streamed back to the client.
+     *
+     * @return the reader which characters are streamed back to the client.
+     */
+    public Reader getReader() {
+        return reader;
+    }
+
+    /**
+     * Return the data model for the ActionResult {@link #template}.
+     *
+     * @return the data model for the ActionResult template
+     */
+    public Map<String, Object> getModel() {
+        if (model == null) {
+            model = new HashMap<String, Object>();
+        }
+        return model;
+    }
+
+    /**
+     * Set the model of the ActionResult template to render.
+     * <p/>
+     * If the {@link #template} property is set, the template and {@link #model}
+     * will be merged and the result will be streamed back to the client.
+     *
+     * @param model the model of the template to render
+     */
+    public void setModel(Map<String, Object> model) {
+        this.model = model;
+    }
+
+    /**
+     * Return the template to render for this ActionResult.
+     *
+     * @return the template to render for this ActionResult
+     */
+    public String getTemplate() {
+        return template;
+    }
+
+    /**
+     * Set the template to render for this ActionResult.
+     *
+     * @param template the template to render for this ActionResult
+     */
+    public void setTemplate(String template) {
+        this.template = template;
+    }
+
+    /**
+     * Render the ActionResult to the client.
+     *
+     * @param context the request context
+     */
+    public final void render(Context context) {
+        prepare(context);
+        renderActionResult(context);
+    }
+
+    // Protected Methods ------------------------------------------------------
+
+    /**
+     * Render the ActionResult to the client. This method can be overridden
+     * by subclasses if custom rendering or direct access to the
+     * HttpServletResponse is required.
+     *
+     * @param context the request context
+     */
+    protected void renderActionResult(Context context) {
+
+        HttpServletResponse response = context.getResponse();
+
+        Reader localReader = getReader();
+        InputStream localInputStream = getInputStream();
+
+        try {
+            String localContent = getContent();
+            byte[] localBytes = getBytes();
+
+            String localTemplate = getTemplate();
+            if (localTemplate != null) {
+                Map<String, Object> templateModel = getModel();
+                if (templateModel == null) {
+                    templateModel = new HashMap<String, Object>();
+                }
+                String result = context.renderTemplate(localTemplate, templateModel);
+                localReader = new StringReader(result);
+
+            } else if (localContent != null) {
+                localReader = new StringReader(localContent);
+            } else if (localBytes != null) {
+                localInputStream = new ByteArrayInputStream(localBytes);
+            }
+
+            if (localReader != null) {
+                Writer writer = response.getWriter();
+                char[] buffer = new char[WRITER_BUFFER_SIZE];
+                int len = 0;
+                while (-1 != (len = localReader.read(buffer))) {
+                    writer.write(buffer, 0, len);
+                }
+                writer.flush();
+                writer.close();
+
+            } else if (localInputStream != null) {
+                byte[] buffer = new byte[OUTPUT_BUFFER_SIZE];
+                int len = 0;
+                OutputStream outputStream = response.getOutputStream();
+                while (-1 != (len = localInputStream.read(buffer))) {
+                    outputStream.write(buffer, 0, len);
+                }
+                outputStream.flush();
+                outputStream.close();
+            }
+
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+
+        } finally {
+            ClickUtils.close(localInputStream);
+            ClickUtils.close(localReader);
+        }
+    }
+
+    // Private Methods --------------------------------------------------------
+
+    /**
+     * Prepare the ActionResult for rendering.
+     *
+     * @param context the request context
+     */
+    private void prepare(Context context) {
+        HttpServletResponse response = context.getResponse();
+
+        if (!isCacheActionRestul()) {
+            // Set headers to disable cache
+            response.setHeader("Pragma", "no-cache");
+            response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
+            response.setDateHeader("Expires", new Date(1L).getTime());
+        }
+
+        String localContentType = getContentType();
+
+        if (getCharacterEncoding() == null) {
+
+            // Fallback to request character encoding
+            if (context.getRequest().getCharacterEncoding() != null) {
+                response.setContentType(localContentType + "; charset="
+                    + context.getRequest().getCharacterEncoding());
+            } else {
+                response.setContentType(localContentType);
+            }
+
+        } else {
+            response.setContentType(localContentType + "; charset=" + getCharacterEncoding());
+        }
+    }
+}

Modified: click/trunk/click/framework/src/org/apache/click/Behavior.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/Behavior.java?rev=1037417&r1=1037416&r2=1037417&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/Behavior.java (original)
+++ click/trunk/click/framework/src/org/apache/click/Behavior.java Sun Nov 21 11:14:27 2010
@@ -1,74 +1,74 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 org.apache.click;
-
-/**
- * Behaviors provide a mechanism for changing how Controls behave at runtime.
- * Behaviors are added to a Control and provides interceptor methods to decorate
- * and enhance the source Control.
- * <p/>
- * Behaviors provide interceptor methods for specific Control life cycle events.
- * These interceptor methods can be implemented to further process and decorate
- * the control or its children.
- * <p/>
- * The following interceptor methods are defined:
- *
- * <ul>
- * <li>preResponse - occurs before the control markup is written to the response</li>
- * <li>preRenderHeadElements - occurs after <tt>preResponse</tt> but before the control
- * {@link Control#getHeadElements() HEAD elements} are written to the response</li>
- * <li>preDestroy - occurs before the Control {@link Control#onDestroy() onDestroy}
- * event handler.</li>
- * </ul>
- *
- * These interceptor methods allow the Behavior to <tt>decorate</tt> a control,
- * for example:
- *
- * <ul>
- * <li>add or remove Control HEAD elements such as JavaScript and CSS dependencies
- * and setup scripts</li>
- * <li>add or remove Control attributes such as <tt>"class"</tt>, <tt>"style"</tt> etc.</li>
- * </ul>
- */
-public interface Behavior {
-
-    /**
-     * This event occurs before the markup is written to the HttpServletResponse.
-     *
-     * @param source the control the behavior is registered with
-     */
-    public void preResponse(Control source);
-
-    /**
-     * This event occurs after {@link #preResponse(org.apache.click.Control)},
-     * but before the Control's {@link Control#getHeadElements()} is called.
-     *
-     * @param source the control the behavior is registered with
-     */
-    public void preRenderHeadElements(Control source);
-
-    /**
-     * This event occurs before the Control {@link Control#onDestroy() onDestroy}
-     * event handler. This event allows the behavior to cleanup or store Control
-     * state in the Session.
-     *
-     * @param source the control the behavior is registered with
-     */
-    public void preDestroy(Control source);
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.click;
+
+/**
+ * Behaviors provide a mechanism for changing how Controls behave at runtime.
+ * Behaviors are added to a Control and provides interceptor methods to decorate
+ * and enhance the source Control.
+ * <p/>
+ * Behaviors provide interceptor methods for specific Control life cycle events.
+ * These interceptor methods can be implemented to further process and decorate
+ * the control or its children.
+ * <p/>
+ * The following interceptor methods are defined:
+ *
+ * <ul>
+ * <li>preResponse - occurs before the control markup is written to the response</li>
+ * <li>preRenderHeadElements - occurs after <tt>preResponse</tt> but before the control
+ * {@link Control#getHeadElements() HEAD elements} are written to the response</li>
+ * <li>preDestroy - occurs before the Control {@link Control#onDestroy() onDestroy}
+ * event handler.</li>
+ * </ul>
+ *
+ * These interceptor methods allow the Behavior to <tt>decorate</tt> a control,
+ * for example:
+ *
+ * <ul>
+ * <li>add or remove Control HEAD elements such as JavaScript and CSS dependencies
+ * and setup scripts</li>
+ * <li>add or remove Control attributes such as <tt>"class"</tt>, <tt>"style"</tt> etc.</li>
+ * </ul>
+ */
+public interface Behavior {
+
+    /**
+     * This event occurs before the markup is written to the HttpServletResponse.
+     *
+     * @param source the control the behavior is registered with
+     */
+    public void preResponse(Control source);
+
+    /**
+     * This event occurs after {@link #preResponse(org.apache.click.Control)},
+     * but before the Control's {@link Control#getHeadElements()} is called.
+     *
+     * @param source the control the behavior is registered with
+     */
+    public void preRenderHeadElements(Control source);
+
+    /**
+     * This event occurs before the Control {@link Control#onDestroy() onDestroy}
+     * event handler. This event allows the behavior to cleanup or store Control
+     * state in the Session.
+     *
+     * @param source the control the behavior is registered with
+     */
+    public void preDestroy(Control source);
+}

Modified: click/trunk/click/framework/src/org/apache/click/Stateful.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/Stateful.java?rev=1037417&r1=1037416&r2=1037417&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/Stateful.java (original)
+++ click/trunk/click/framework/src/org/apache/click/Stateful.java Sun Nov 21 11:14:27 2010
@@ -1,142 +1,142 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 org.apache.click;
-
-/**
- * Provides an interface that controls can implement that need to preserve
- * state across multiple requests.
- * <p/>
- * <b>Please note:</b> Control state is not saved and restored automatically by
- * Click. Instead, state saving and restoring is under full control of the
- * developer through a public API.
- * <p/>
- * Controls implementing this interface are expected to {@link #getState() save}
- * and {@link #setState(java.lang.Object) restore} their internal state, as well
- * as the state of their child controls. Controls can further expose a public
- * API for saving and restoring their state.
- * <p/>
- * An example implementation is shown below:
- *
- * <pre class="prettyprint">
- * public class MyControl extends AbstractControl implements Stateful {
- *
- *     private String value;
- *
- *     ...
- *
- *     // Return the Control internal state
- *     public Object getState() {
- *         return getValue();
- *     }
- *
- *     // Set the Control internal state
- *     public void setState(Object state) {
- *         String fieldState = (String) state;
- *         setValue(fieldState);
- *     }
- *
- *    // A save state helper method
- *     public void saveState(Context context) {
- *         // Save the control state in the session
- *         ClickUtils.saveState(this, getName(), context);
- *     }
- *    // A restore state helper method
- *     public void restoreState(Context context) {
- *         // Load the control state from the session
-           ClickUtils.restoreState(this, getName(), context);
- *     }
- *
- *    // A remove state helper method
- *     public void removeState(Context context) {
- *         // Remove the control state from the session
-*          ClickUtils.removeState(this, getName(), context);
- *     }
- *
- * } </pre>
- *
- * Saving and restoring Control state is controlled by the developer.
- * <p/>
- * For example:
- *
- * <pre class="prettyprint">
- * public class MyPage extends Page {
- *
- *    private MyControl control = new MyControl("mycontrol");
- *
- *     public MyPage() {
- *         // Load the control state from the session
- *         control.loadState(getContext());
- *     }
- *
- *     public void onPost() {
- *
- *         Context context = getContext();
- *
- *         String id = context.getParameter("id");
- *         control.setValue(id);
- *
- *         // Save control state to the session
- *         control.saveState(context);
- *     }
- * }
- * </pre>
- */
-public interface Stateful {
-
-    /**
-     * Return the Control internal state. State will generally be stored in the
-     * Session, so it is recommended to ensure the state is
-     * {@link java.io.Serializable serializable}.
-     * <p/>
-     * Example implementation below:
-     * <pre class="prettyprint">
-     * public Object getState() {
-     *     Object stateArray[] = new Object[3];
-     *     stateArray[0] = getValue();
-     *     stateArray[1] = Number.valueOf(getNumber());
-     *     stateArray[2] = Boolean.valueOf(getBoolean());
-     *     return stateArray;
-     * } </pre>
-     *
-     * @return the control internal state
-     */
-    public Object getState();
-
-    /**
-     * Restore the Control internal state from the given state object.
-     * <p/>
-     * Example below:
-     * <pre class="prettyprint">
-     * public void setState(Object state) {
-     *
-     *     Object[] stateArray = (Object[]) state;
-     *     String storedValue = stateArray[0];
-     *     setValue(storedValue);
-     *
-     *     int storedNumber = ((Integer) stateArray[1]).intValue();
-     *     setNumber(storedNumber);
-     *
-     *     boolean storedBoolen = ((Boolean) stateArray[2]).booleanValue();
-     *     setBoolean(storedBoolean);
-     * } </pre>
-     *
-     * @param state the control state to restore
-     */
-    public void setState(Object state);
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.click;
+
+/**
+ * Provides an interface that controls can implement that need to preserve
+ * state across multiple requests.
+ * <p/>
+ * <b>Please note:</b> Control state is not saved and restored automatically by
+ * Click. Instead, state saving and restoring is under full control of the
+ * developer through a public API.
+ * <p/>
+ * Controls implementing this interface are expected to {@link #getState() save}
+ * and {@link #setState(java.lang.Object) restore} their internal state, as well
+ * as the state of their child controls. Controls can further expose a public
+ * API for saving and restoring their state.
+ * <p/>
+ * An example implementation is shown below:
+ *
+ * <pre class="prettyprint">
+ * public class MyControl extends AbstractControl implements Stateful {
+ *
+ *     private String value;
+ *
+ *     ...
+ *
+ *     // Return the Control internal state
+ *     public Object getState() {
+ *         return getValue();
+ *     }
+ *
+ *     // Set the Control internal state
+ *     public void setState(Object state) {
+ *         String fieldState = (String) state;
+ *         setValue(fieldState);
+ *     }
+ *
+ *    // A save state helper method
+ *     public void saveState(Context context) {
+ *         // Save the control state in the session
+ *         ClickUtils.saveState(this, getName(), context);
+ *     }
+ *    // A restore state helper method
+ *     public void restoreState(Context context) {
+ *         // Load the control state from the session
+           ClickUtils.restoreState(this, getName(), context);
+ *     }
+ *
+ *    // A remove state helper method
+ *     public void removeState(Context context) {
+ *         // Remove the control state from the session
+*          ClickUtils.removeState(this, getName(), context);
+ *     }
+ *
+ * } </pre>
+ *
+ * Saving and restoring Control state is controlled by the developer.
+ * <p/>
+ * For example:
+ *
+ * <pre class="prettyprint">
+ * public class MyPage extends Page {
+ *
+ *    private MyControl control = new MyControl("mycontrol");
+ *
+ *     public MyPage() {
+ *         // Load the control state from the session
+ *         control.loadState(getContext());
+ *     }
+ *
+ *     public void onPost() {
+ *
+ *         Context context = getContext();
+ *
+ *         String id = context.getParameter("id");
+ *         control.setValue(id);
+ *
+ *         // Save control state to the session
+ *         control.saveState(context);
+ *     }
+ * }
+ * </pre>
+ */
+public interface Stateful {
+
+    /**
+     * Return the Control internal state. State will generally be stored in the
+     * Session, so it is recommended to ensure the state is
+     * {@link java.io.Serializable serializable}.
+     * <p/>
+     * Example implementation below:
+     * <pre class="prettyprint">
+     * public Object getState() {
+     *     Object stateArray[] = new Object[3];
+     *     stateArray[0] = getValue();
+     *     stateArray[1] = Number.valueOf(getNumber());
+     *     stateArray[2] = Boolean.valueOf(getBoolean());
+     *     return stateArray;
+     * } </pre>
+     *
+     * @return the control internal state
+     */
+    public Object getState();
+
+    /**
+     * Restore the Control internal state from the given state object.
+     * <p/>
+     * Example below:
+     * <pre class="prettyprint">
+     * public void setState(Object state) {
+     *
+     *     Object[] stateArray = (Object[]) state;
+     *     String storedValue = stateArray[0];
+     *     setValue(storedValue);
+     *
+     *     int storedNumber = ((Integer) stateArray[1]).intValue();
+     *     setNumber(storedNumber);
+     *
+     *     boolean storedBoolen = ((Boolean) stateArray[2]).booleanValue();
+     *     setBoolean(storedBoolean);
+     * } </pre>
+     *
+     * @param state the control state to restore
+     */
+    public void setState(Object state);
+}

Modified: click/trunk/click/framework/src/org/apache/click/ajax/AjaxBehavior.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/ajax/AjaxBehavior.java?rev=1037417&r1=1037416&r2=1037417&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/ajax/AjaxBehavior.java (original)
+++ click/trunk/click/framework/src/org/apache/click/ajax/AjaxBehavior.java Sun Nov 21 11:14:27 2010
@@ -1,106 +1,106 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 org.apache.click.ajax;
-
-import org.apache.click.ActionResult;
-import org.apache.click.Behavior;
-import org.apache.click.Context;
-import org.apache.click.Control;
-
-/**
- * AjaxBehavior extends the basic Behavior functionality to allow Controls to
- * handle and process incoming Ajax requests.
- * <p/>
- * To handle an Ajax request, AjaxBehavior exposes the listener method:
- * {@link #onAction(org.apache.click.Control) onAction}.
- * The <tt>onAction</tt> method returns an ActionResult that is rendered back
- * to the browser.
- * <p/>
- * Before Click invokes the <tt>onAction</tt> method it checks whether the request
- * is targeted at the AjaxBehavior by invoking the method
- * {@link #isAjaxTarget(org.apache.click.Context) Behavior.isAjaxTarget()}.
- * Click will only invoke <tt>onAction</tt> if <tt>isAjaxTarget</tt> returns true.
- */
-public interface AjaxBehavior extends Behavior {
-
-    /**
-     * This method can be implemented to handle and respond to an Ajax request.
-     * For example:
-     *
-     * <pre class="prettyprint">
-     * public void onInit() {
-     *     ActionLink link = new ActionLink("link");
-     *     link.addBehaior(new DefaultAjaxBehavior() {
-     *
-     *         public ActionResult onAction(Control source) {
-     *             ActionResult result = new ActionResult("&lt;h1&gt;Hello world&lt;/h1&gt;", ActionResult.HTML);
-     *             return result;
-     *         }
-     *     });
-     * } </pre>
-     *
-     * @param source the control the behavior is attached to
-     * @return the action result instance
-     */
-    public ActionResult onAction(Control source);
-
-    /**
-     * Return true if the behavior is the request target, false otherwise.
-     * <p/>
-     * This method is queried by Click to determine if the behavior's
-     * {@link #onAction(org.apache.click.Control)} method should be called in
-     * response to a request.
-     * <p/>
-     * By exposing this method through the Behavior interface it provides
-     * implementers with fine grained control over whether the Behavior's
-     * {@link #onAction(org.apache.click.Control)} method should be invoked or not.
-     * <p/>
-     * Below is an example implementation:
-     *
-     * <pre class="prettyprint">
-     * public CustomBehavior implements Behavior {
-     *
-     *     private String eventType;
-     *
-     *     public CustomBehavior(String eventType) {
-     *         // The event type of the behavior
-     *         super(eventType);
-     *     }
-     *
-     *     public boolean isAjaxTarget(Context context) {
-     *         // Retrieve the eventType parameter from the incoming request
-     *         String eventType = context.getRequestParameter("type");
-     *
-     *         // Check if this Behavior's eventType matches the request
-     *         // "type" parameter
-     *         return StringUtils.equalsIgnoreCase(this.eventType, eventType);
-     *     }
-     *
-     *     public ActionResult onAction(Control source) {
-     *         // If isAjaxTarget returned true, the onAction method will be
-     *         // invoked
-     *         ...
-     *     }
-     * } </pre>
-     *
-     * @param context the request context
-     * @return true if the behavior is the request target, false otherwise
-     */
-    public boolean isAjaxTarget(Context context);
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.click.ajax;
+
+import org.apache.click.ActionResult;
+import org.apache.click.Behavior;
+import org.apache.click.Context;
+import org.apache.click.Control;
+
+/**
+ * AjaxBehavior extends the basic Behavior functionality to allow Controls to
+ * handle and process incoming Ajax requests.
+ * <p/>
+ * To handle an Ajax request, AjaxBehavior exposes the listener method:
+ * {@link #onAction(org.apache.click.Control) onAction}.
+ * The <tt>onAction</tt> method returns an ActionResult that is rendered back
+ * to the browser.
+ * <p/>
+ * Before Click invokes the <tt>onAction</tt> method it checks whether the request
+ * is targeted at the AjaxBehavior by invoking the method
+ * {@link #isAjaxTarget(org.apache.click.Context) Behavior.isAjaxTarget()}.
+ * Click will only invoke <tt>onAction</tt> if <tt>isAjaxTarget</tt> returns true.
+ */
+public interface AjaxBehavior extends Behavior {
+
+    /**
+     * This method can be implemented to handle and respond to an Ajax request.
+     * For example:
+     *
+     * <pre class="prettyprint">
+     * public void onInit() {
+     *     ActionLink link = new ActionLink("link");
+     *     link.addBehaior(new DefaultAjaxBehavior() {
+     *
+     *         public ActionResult onAction(Control source) {
+     *             ActionResult result = new ActionResult("&lt;h1&gt;Hello world&lt;/h1&gt;", ActionResult.HTML);
+     *             return result;
+     *         }
+     *     });
+     * } </pre>
+     *
+     * @param source the control the behavior is attached to
+     * @return the action result instance
+     */
+    public ActionResult onAction(Control source);
+
+    /**
+     * Return true if the behavior is the request target, false otherwise.
+     * <p/>
+     * This method is queried by Click to determine if the behavior's
+     * {@link #onAction(org.apache.click.Control)} method should be called in
+     * response to a request.
+     * <p/>
+     * By exposing this method through the Behavior interface it provides
+     * implementers with fine grained control over whether the Behavior's
+     * {@link #onAction(org.apache.click.Control)} method should be invoked or not.
+     * <p/>
+     * Below is an example implementation:
+     *
+     * <pre class="prettyprint">
+     * public CustomBehavior implements Behavior {
+     *
+     *     private String eventType;
+     *
+     *     public CustomBehavior(String eventType) {
+     *         // The event type of the behavior
+     *         super(eventType);
+     *     }
+     *
+     *     public boolean isAjaxTarget(Context context) {
+     *         // Retrieve the eventType parameter from the incoming request
+     *         String eventType = context.getRequestParameter("type");
+     *
+     *         // Check if this Behavior's eventType matches the request
+     *         // "type" parameter
+     *         return StringUtils.equalsIgnoreCase(this.eventType, eventType);
+     *     }
+     *
+     *     public ActionResult onAction(Control source) {
+     *         // If isAjaxTarget returned true, the onAction method will be
+     *         // invoked
+     *         ...
+     *     }
+     * } </pre>
+     *
+     * @param context the request context
+     * @return true if the behavior is the request target, false otherwise
+     */
+    public boolean isAjaxTarget(Context context);
+}

Modified: click/trunk/click/framework/src/org/apache/click/ajax/DefaultAjaxBehavior.java
URL: http://svn.apache.org/viewvc/click/trunk/click/framework/src/org/apache/click/ajax/DefaultAjaxBehavior.java?rev=1037417&r1=1037416&r2=1037417&view=diff
==============================================================================
--- click/trunk/click/framework/src/org/apache/click/ajax/DefaultAjaxBehavior.java (original)
+++ click/trunk/click/framework/src/org/apache/click/ajax/DefaultAjaxBehavior.java Sun Nov 21 11:14:27 2010
@@ -1,120 +1,120 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 org.apache.click.ajax;
-
-import org.apache.click.Context;
-import org.apache.click.Control;
-import org.apache.click.ActionResult;
-
-/**
- * Provides a default implementation of the AjaxBehavior interface.
- * <p/>
- * This class also provides the method,
- * {@link #addHeadElementsOnce(org.apache.click.Control) addHeadElementsOnce},
- * that subclasses can implement if they need to add HTML HEAD elements only to
- * the <tt>first</tt> Control that this Behavior is registered with.
- * <p/>
- * If this Behavior should add HTML HEAD elements to all the Controls it is
- * registered with, rather implement
- * {@link #preRenderHeadElements(org.apache.click.Control) preRenderHeadElements}.
- */
-public class DefaultAjaxBehavior implements AjaxBehavior {
-
-    // Variables --------------------------------------------------------------
-
-    /** Indicates whether the Behavior HEAD elements have been processed or not. */
-    protected boolean headElementsProcessed = false;
-
-    // Behavior Methods -------------------------------------------------------
-
-    /**
-     * @see org.apache.click.ajax.AjaxBehavior#onAction(org.apache.click.Control)
-     *
-     * @param source the control the behavior is registered with
-     * @return the action result
-     */
-    public ActionResult onAction(Control source) {
-        return null;
-    }
-
-    /**
-     * @see org.apache.click.ajax.AjaxBehavior#isAjaxTarget(org.apache.click.Context)
-     *
-     * @param context the request context
-     * @return true if the behavior is the request target, false otherwise
-     */
-    public boolean isAjaxTarget(Context context) {
-        return true;
-    }
-
-    // Callback Methods -------------------------------------------------------
-
-    /**
-     * @see org.apache.click.Behavior#preResponse(org.apache.click.Control)
-     *
-     * @param source the control the behavior is registered with
-     */
-    public void preResponse(Control source) {
-    }
-
-    /**
-     * @see org.apache.click.Behavior#preRenderHeadElements(org.apache.click.Control)
-     *
-     * @param source the control the behavior is registered with
-     */
-    public void preRenderHeadElements(Control source) {
-        // Guard against adding HEAD elements to more than one control
-        if (headElementsProcessed) {
-            return;
-        }
-
-        addHeadElementsOnce(source);
-
-        headElementsProcessed = true;
-    }
-
-    /**
-     * @see org.apache.click.Behavior#preDestroy(org.apache.click.Control)
-     *
-     * @param source the control the behavior is registered with
-     */
-    public void preDestroy(Control source) {
-        headElementsProcessed = false;
-    }
-
-    // Protected methods ------------------------------------------------------
-
-    /**
-     * Provides a method for adding HTML HEAD elements to the first Control
-     * this Behavior was registered with. This method will only be called once,
-     * passing in the first Control the Behavior was registered with.
-     * <p/>
-     * Subclasses can implement this method instead of
-     * {@link #preRenderHeadElements(org.apache.click.Control)} if HTML HEAD
-     * elements should only be added to one Control, even if the Behavior is
-     * added to multiple Controls.
-     *
-     * @param source the control the behavior is registered with
-     */
-    protected void addHeadElementsOnce(Control source) {
-        // Subclasses can override the default to add head specific elements
-        // NOTE: if this method is ever made public the headElementsProcessed
-        // check should be done here
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.click.ajax;
+
+import org.apache.click.Context;
+import org.apache.click.Control;
+import org.apache.click.ActionResult;
+
+/**
+ * Provides a default implementation of the AjaxBehavior interface.
+ * <p/>
+ * This class also provides the method,
+ * {@link #addHeadElementsOnce(org.apache.click.Control) addHeadElementsOnce},
+ * that subclasses can implement if they need to add HTML HEAD elements only to
+ * the <tt>first</tt> Control that this Behavior is registered with.
+ * <p/>
+ * If this Behavior should add HTML HEAD elements to all the Controls it is
+ * registered with, rather implement
+ * {@link #preRenderHeadElements(org.apache.click.Control) preRenderHeadElements}.
+ */
+public class DefaultAjaxBehavior implements AjaxBehavior {
+
+    // Variables --------------------------------------------------------------
+
+    /** Indicates whether the Behavior HEAD elements have been processed or not. */
+    protected boolean headElementsProcessed = false;
+
+    // Behavior Methods -------------------------------------------------------
+
+    /**
+     * @see org.apache.click.ajax.AjaxBehavior#onAction(org.apache.click.Control)
+     *
+     * @param source the control the behavior is registered with
+     * @return the action result
+     */
+    public ActionResult onAction(Control source) {
+        return null;
+    }
+
+    /**
+     * @see org.apache.click.ajax.AjaxBehavior#isAjaxTarget(org.apache.click.Context)
+     *
+     * @param context the request context
+     * @return true if the behavior is the request target, false otherwise
+     */
+    public boolean isAjaxTarget(Context context) {
+        return true;
+    }
+
+    // Callback Methods -------------------------------------------------------
+
+    /**
+     * @see org.apache.click.Behavior#preResponse(org.apache.click.Control)
+     *
+     * @param source the control the behavior is registered with
+     */
+    public void preResponse(Control source) {
+    }
+
+    /**
+     * @see org.apache.click.Behavior#preRenderHeadElements(org.apache.click.Control)
+     *
+     * @param source the control the behavior is registered with
+     */
+    public void preRenderHeadElements(Control source) {
+        // Guard against adding HEAD elements to more than one control
+        if (headElementsProcessed) {
+            return;
+        }
+
+        addHeadElementsOnce(source);
+
+        headElementsProcessed = true;
+    }
+
+    /**
+     * @see org.apache.click.Behavior#preDestroy(org.apache.click.Control)
+     *
+     * @param source the control the behavior is registered with
+     */
+    public void preDestroy(Control source) {
+        headElementsProcessed = false;
+    }
+
+    // Protected methods ------------------------------------------------------
+
+    /**
+     * Provides a method for adding HTML HEAD elements to the first Control
+     * this Behavior was registered with. This method will only be called once,
+     * passing in the first Control the Behavior was registered with.
+     * <p/>
+     * Subclasses can implement this method instead of
+     * {@link #preRenderHeadElements(org.apache.click.Control)} if HTML HEAD
+     * elements should only be added to one Control, even if the Behavior is
+     * added to multiple Controls.
+     *
+     * @param source the control the behavior is registered with
+     */
+    protected void addHeadElementsOnce(Control source) {
+        // Subclasses can override the default to add head specific elements
+        // NOTE: if this method is ever made public the headElementsProcessed
+        // check should be done here
+    }
+}