001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.wicket.velocity;
018:
019: import java.io.StringWriter;
020: import java.util.Map;
021:
022: import org.apache.velocity.VelocityContext;
023: import org.apache.velocity.app.Velocity;
024: import org.apache.wicket.Component;
025: import org.apache.wicket.WicketRuntimeException;
026: import org.apache.wicket.behavior.AbstractBehavior;
027: import org.apache.wicket.markup.html.IHeaderContributor;
028: import org.apache.wicket.markup.html.IHeaderResponse;
029: import org.apache.wicket.model.IDetachable;
030: import org.apache.wicket.model.IModel;
031: import org.apache.wicket.util.string.Strings;
032:
033: /**
034: * An IHeaderContributor implementation that renders a velocity template and
035: * writes it to the response. The template is loaded via Velocity's resource
036: * loading mechanism, as defined in your velocity.properties. If you do not have
037: * a velocity.properties for your app, it will default to a directory
038: * "templates" in the root of your app.
039: */
040: public class VelocityContributor extends AbstractBehavior implements
041: IHeaderContributor {
042: private static final long serialVersionUID = 1L;
043:
044: private String encoding = "ISO-8859-1";
045:
046: private final IModel model;
047:
048: private final String templateName;
049:
050: /**
051: * Ctor for VelocityContributor
052: *
053: * The templateName needs to have the full path relative to where the
054: * resource loader starts looking. For example, if there is a template next
055: * to this class in the package called foo.vm, and you have configured the
056: * ClassPathResourceLoader, template name will then be
057: * "wicket/contrib/util/resource/foo.vm". Wicket provides a nice utility
058: * {@link wicket.util.lang.Packages} for this.
059: *
060: *
061: * @param templateName
062: * @param model
063: */
064: public VelocityContributor(String templateName, final IModel model) {
065: this .templateName = templateName;
066: this .model = model;
067: }
068:
069: /**
070: * @see org.apache.wicket.behavior.AbstractBehavior#detach(org.apache.wicket.Component)
071: */
072: public void detach(Component c) {
073: if (model instanceof IDetachable) {
074: ((IDetachable) model).detach();
075: }
076: }
077:
078: /**
079: * @return The encoding
080: */
081: public String getEncoding() {
082: return encoding;
083: }
084:
085: /**
086: * @see org.apache.wicket.behavior.AbstractBehavior#renderHead(org.apache.wicket.markup.html.IHeaderResponse)
087: */
088: public void renderHead(IHeaderResponse response) {
089: CharSequence s = evaluate();
090: if (null != s) {
091: response.renderString(s);
092: }
093: }
094:
095: /**
096: * @param encoding
097: * The encoding
098: */
099: public void setEncoding(String encoding) {
100: this .encoding = encoding;
101: }
102:
103: /**
104: * @return whether to escape HTML characters. The default value is false
105: */
106: protected boolean escapeHtml() {
107: return false;
108: }
109:
110: /**
111: * Evaluate the template.
112: *
113: * @return The avaluated template
114: */
115: protected final CharSequence evaluate() {
116: if (!Velocity.resourceExists(templateName)) {
117: return null;
118: }
119: // create a Velocity context object using the model if set
120: final VelocityContext ctx = new VelocityContext((Map) model
121: .getObject());
122:
123: // create a writer for capturing the Velocity output
124: StringWriter writer = new StringWriter();
125:
126: try {
127: // execute the velocity script and capture the output in writer
128: if (!Velocity.mergeTemplate(templateName, encoding, ctx,
129: writer)) {
130: return null;
131: }
132:
133: // replace the tag's body the Velocity output
134: CharSequence result = writer.getBuffer();
135:
136: if (escapeHtml()) {
137: // encode the result in order to get valid html output that
138: // does not break the rest of the page
139: result = Strings.escapeMarkup(result.toString());
140: }
141: return result;
142: } catch (Exception e) {
143: throw new WicketRuntimeException(e);
144: }
145: }
146: }
|