Package org.apache.wicket.velocity.markup.html

Source Code of org.apache.wicket.velocity.markup.html.VelocityPanel

/*
* 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.wicket.velocity.markup.html;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Map;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.Markup;
import org.apache.wicket.markup.MarkupParser;
import org.apache.wicket.markup.MarkupResourceStream;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.resource.IStringResourceStream;
import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
import org.apache.wicket.util.resource.StringResourceStream;
import org.apache.wicket.util.string.Strings;

/**
* Panel that displays the result of rendering a <a
* href="http://jakarta.apache.org/velocity">Velocity</a> template. The template itself can be any
* <code><a href="http://wicket.apache.org/wicket/apidocs/org/apache/wicket/util/resource/IStringResourceStream.html">IStringResourceStream</a></code>
* implementation, of which there are a number of convenient implementations in the wicket.util
* package. The model can be any normal
* <code><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Map.html">Map</a></code>,
* which will be used to create the
* <code><a href="http://jakarta.apache.org/velocity/docs/api/org/apache/velocity/VelocityContext.html">VelocityContext</a></code>.
*
* <p>
* <b>Note:</b> Be sure to properly initialize the Velocity engine before using
* <code>VelocityPanel</code>.
* </p>
*/
public abstract class VelocityPanel extends Panel
{
  /**
   * Convenience factory method to create a {@link VelocityPanel} instance with a given
   * {@link IStringResourceStream template resource}.
   *
   * @param id
   *            Component id
   * @param model
   *            optional model for variable substituation.
   * @param templateResource
   *            The template resource
   * @return
   */
  public static VelocityPanel forTemplateResource(String id, IModel model,
      final IStringResourceStream templateResource)
  {
    if (templateResource == null)
    {
      throw new IllegalArgumentException("argument templateResource must be not null");
    }

    return new VelocityPanel(id, model)
    {
      protected IStringResourceStream getTemplateResource()
      {
        return templateResource;
      }
    };
  }

  /**
   * Construct.
   *
   * @param id
   *            Component id
   * @param templateResource
   *            The velocity template as a string resource
   * @param model
   *            Model with variables that can be substituted by Velocity. Must return a
   *            {@link Map}.
   */
  public VelocityPanel(final String id, final IModel/* <Map> */model)
  {
    super(id, model);
  }

  /**
   * Gets a reader for the velocity template.
   *
   * @return reader for the velocity template
   */
  private Reader getTemplateReader()
  {
    final IStringResourceStream resource = getTemplateResource();
    if (resource == null)
    {
      throw new IllegalArgumentException("getTemplateResource must return a resource");
    }

    final String template = resource.asString();
    if (template != null)
    {
      return new StringReader(template);
    }

    return null;
  }

  /**
   * Either print or rethrow the throwable.
   *
   * @param exception
   *            the cause
   * @param markupStream
   *            the markup stream
   * @param openTag
   *            the open tag
   */
  private void onException(final Exception exception, final MarkupStream markupStream,
      final ComponentTag openTag)
  {
    if (!throwVelocityExceptions())
    {
      // print the exception on the panel
      String stackTraceAsString = Strings.toString(exception);
      replaceComponentTagBody(markupStream, openTag, stackTraceAsString);
    }
    else
    {
      // rethrow the exception
      throw new WicketRuntimeException(exception);
    }
  }

  /**
   * Gets whether to escape HTML characters.
   *
   * @return whether to escape HTML characters. The default value is false.
   */
  protected boolean escapeHtml()
  {
    return false;
  }

  /**
   * Returns the template resource passed to the constructor.
   *
   * @return The template resource
   */
  protected abstract IStringResourceStream getTemplateResource();

  /**
   * @see org.apache.wicket.markup.html.panel.Panel#onComponentTagBody(org.apache.wicket.markup.MarkupStream,
   *      org.apache.wicket.markup.ComponentTag)
   */
  protected void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag)
  {
    final Reader templateReader = getTemplateReader();
    if (templateReader != null)
    {
      // Get model as a map
      final Map map = (Map)getModelObject();

      // create a Velocity context object using the model if set
      final VelocityContext ctx = new VelocityContext(map);

      // create a writer for capturing the Velocity output
      StringWriter writer = new StringWriter();

      // string to be used as the template name for log messages in case
      // of error
      final String logTag = getId();
      try
      {
        // execute the velocity script and capture the output in writer
        Velocity.evaluate(ctx, writer, logTag, templateReader);

        // replace the tag's body the Velocity output
        String result = writer.toString();

        if (escapeHtml())
        {
          // encode the result in order to get valid html output that
          // does not break the rest of the page
          result = Strings.escapeMarkup(result).toString();
        }

        if (!parseGeneratedMarkup())
        {
          // now replace the body of the tag with the velocity merge
          // result
          replaceComponentTagBody(markupStream, openTag, result);
        }
        else
        {
          // now parse the velocity merge result
          Markup markup;
          try
          {
            MarkupParser parser = getApplication().getMarkupSettings()
                .getMarkupParserFactory().newMarkupParser(
                    new MarkupResourceStream(new StringResourceStream(result)));
            markup = parser.parse();
          }
          catch (ResourceStreamNotFoundException e)
          {
            throw new RuntimeException("Could not parse resulting markup", e);
          }
          markupStream.skipRawMarkup();
          renderAll(new MarkupStream(markup));
        }
      }
      catch (ParseErrorException e)
      {
        onException(e, markupStream, openTag);
      }
      catch (MethodInvocationException e)
      {
        onException(e, markupStream, openTag);
      }
      catch (ResourceNotFoundException e)
      {
        onException(e, markupStream, openTag);
      }
      catch (IOException e)
      {
        onException(e, markupStream, openTag);
      }
    }
    else
    {
      replaceComponentTagBody(markupStream, openTag, ""); // just empty it
    }
  }

  /**
   * Gets whether to parse the resulting Wicket markup.
   *
   * @return whether to parse the resulting Wicket markup. The default is false.
   */
  protected boolean parseGeneratedMarkup()
  {
    return false;
  }

  /**
   * Whether any velocity exception should be trapped and displayed on the panel (false) or thrown
   * up to be handled by the exception mechanism of Wicket (true). The default is false, which
   * traps and displays any exception without having consequences for the other components on the
   * page.
   * <p>
   * Trapping these exceptions without disturbing the other components is especially usefull in
   * CMS like applications, where 'normal' users are allowed to do basic scripting. On errors, you
   * want them to be able to have them correct them while the rest of the application keeps on
   * working.
   * </p>
   *
   * @return Whether any velocity exceptions should be thrown or trapped. The default is false.
   */
  protected boolean throwVelocityExceptions()
  {
    return false;
  }
}
TOP

Related Classes of org.apache.wicket.velocity.markup.html.VelocityPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.