/* * Copyright 2002-2005 the original author or authors. * * Licensed 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.springmodules.validation.valang.javascript.taglib; import java.io.IOException; import java.io.Reader; import java.io.Writer; import javax.servlet.ServletException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import org.springframework.util.Assert; import org.springframework.web.servlet.tags.RequestContextAwareTag; import org.springmodules.validation.valang.javascript.ValangJavaScriptTranslator; /** * Generates the JavaScript codebase that is necessary for the use of the JavaScript validation produced by * {@link ValangValidateTag}. * <p/> * <p> * The generated codebase is an exact copy of the code from the file "valang_codebase.js" located in * org.springmodules.validation.valang.javascript. You can therefor avoid having to use this tag by simply placing this * file on your web server and linking to it using a the following HTML: * * <pre> * <script type="text/javascript" src="/somepath/valang_codebase.js"></script> * </pre> * <p/> * <p> * When using this tag or the HTML above you must make sure that the codebase is included before any * {@link ValangValidateTag}s in you JSP file. * * @author Oliver Hutchison */ public class ValangCodebaseTag extends RequestContextAwareTag { private boolean includeScriptTags; private String logId; private String globalErrorsId; private String fieldErrorIdSuffix; /** * Sets the HTML ID of the log parent node. */ public void setLogId(String logId) { this.logId = logId; } /** * Sets whether or not the generated code should be wrapped in HTML <script> tags. This is useful if you wont * to include the codebase directly in a HTML page. */ public void setIncludeScriptTags(String includeScriptTags) { this.includeScriptTags = "true".equalsIgnoreCase(includeScriptTags); } /** * Sets the id of the element that will hold the global error. If not set, this tag will look for an element with id * "global_errors". * * @param globalErrorsId * The id of the element that should hold the global errors. */ public void setGlobalErrorsId(String globalErrorsId) { this.globalErrorsId = globalErrorsId; } /** * Sets the id suffix of the element that should hold the error of a specific field. For example, if the validated * field is "firstName" and the suffix is set to "_err" then this tag will put the validation errors for the * firstName field in an element with id "firstName_err". If this suffix is not set, it is set by default to * "_error". * * @param fieldErrorsIdSuffix * The id suffix of the element that should hold the error of a specific field. */ public void setFieldErrorsIdSuffix(String fieldErrorIdSuffix) { this.fieldErrorIdSuffix = fieldErrorIdSuffix; } protected int doStartTagInternal() throws ServletException, JspException { return SKIP_BODY; } public int doEndTag() throws JspException { try { JspWriter out = pageContext.getOut(); if (includeScriptTags) { out.write("<script type=\"text/javascript\">\n"); } copy(ValangJavaScriptTranslator.getCodebaseReader(), out); if (globalErrorsId != null) { out.write("ValangValidator.prototype.globalErrorsId = '" + globalErrorsId + "';\n"); } if (fieldErrorIdSuffix != null) { out.write("ValangValidator.prototype.fieldErrorIdSuffix = '" + fieldErrorIdSuffix + "';\n"); } if (logId != null) { out.write("ValangValidator.Logger.logId = '" + logId + "';\n"); } if (includeScriptTags) { out.write("\n</script>"); } return EVAL_PAGE; } catch (IOException e) { throw new JspException("Could not write validation codebase", e); } } /** * Copies the chars from in to out and then closes in but leaves out open. */ private void copy(Reader in, Writer out) throws IOException { Assert.notNull(in, "No Reader specified"); Assert.notNull(out, "No Writer specified"); try { char[] buffer = new char[1024]; int bytesRead; while ((bytesRead = in.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); } out.flush(); } finally { try { in.close(); } catch (IOException ex) { logger.warn("Could not close Reader", ex); } } } public void doFinally() { super.doFinally(); includeScriptTags = false; } }