Author: nbelaevski
Date: 2007-04-02 20:27:24 -0400 (Mon, 02 Apr 2007)
New Revision: 49
Added:
trunk/test/src/main/java/org/ajax4jsf/tests/MockFacesResourceContext.java
trunk/test/src/main/java/org/ajax4jsf/tests/org/
trunk/test/src/main/java/org/ajax4jsf/tests/org/apache/
trunk/test/src/main/java/org/ajax4jsf/tests/org/apache/shale/
trunk/test/src/main/java/org/ajax4jsf/tests/org/apache/shale/test/
trunk/test/src/main/java/org/ajax4jsf/tests/org/apache/shale/test/config/
trunk/test/src/main/java/org/ajax4jsf/tests/org/apache/shale/test/config/ConfigParser.java
Modified:
trunk/test/
trunk/test/src/main/java/org/ajax4jsf/tests/AbstractAjax4JsfTestCase.java
Log:
Initial faces artefacts configuration through ConfigParser added to
AbstractAjax4JsfTestCase
Resources handling through ResourceBuilder added
Property changes on: trunk/test
___________________________________________________________________
Name: svn:ignore
- target
+ target
.settings
.clover
.classpath
.project
Modified: trunk/test/src/main/java/org/ajax4jsf/tests/AbstractAjax4JsfTestCase.java
===================================================================
--- trunk/test/src/main/java/org/ajax4jsf/tests/AbstractAjax4JsfTestCase.java 2007-04-02
19:52:02 UTC (rev 48)
+++ trunk/test/src/main/java/org/ajax4jsf/tests/AbstractAjax4JsfTestCase.java 2007-04-03
00:27:24 UTC (rev 49)
@@ -26,9 +26,15 @@
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Random;
+import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -40,24 +46,36 @@
import javax.faces.render.RenderKitFactory;
import javax.faces.render.Renderer;
import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
import org.ajax4jsf.framework.ajax.AjaxContext;
import org.ajax4jsf.framework.ajax.AjaxViewHandler;
import org.ajax4jsf.framework.ajax.AjaxViewRoot;
import org.ajax4jsf.framework.renderer.AjaxViewRootRenderer;
import org.ajax4jsf.framework.renderer.ChameleonRenderKitImpl;
+import org.ajax4jsf.framework.resource.FacesResourceContext;
+import org.ajax4jsf.framework.resource.InternetResource;
import org.ajax4jsf.framework.resource.InternetResourceBuilder;
import org.ajax4jsf.framework.skin.SkinBean;
import org.ajax4jsf.framework.skin.SkinFactory;
import org.ajax4jsf.framework.skin.VersionBean;
+import org.ajax4jsf.framework.util.config.WebXml;
+import org.ajax4jsf.tests.org.apache.shale.test.config.ConfigParser;
+import org.apache.commons.httpclient.Header;
import org.apache.shale.test.base.AbstractJsfTestCase;
+import org.apache.shale.test.mock.MockHttpServletResponse;
import org.apache.shale.test.mock.MockPrintWriter;
import org.apache.shale.test.mock.MockResponseWriter;
import org.apache.shale.test.mock.MockServletOutputStream;
+import com.gargoylesoftware.htmlunit.KeyValuePair;
import com.gargoylesoftware.htmlunit.MockWebConnection;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.WebRequestSettings;
+import com.gargoylesoftware.htmlunit.WebResponse;
+import com.gargoylesoftware.htmlunit.WebResponseData;
+import com.gargoylesoftware.htmlunit.WebResponseImpl;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
/**
@@ -72,6 +90,8 @@
*/
public class AbstractAjax4JsfTestCase extends AbstractJsfTestCase {
+ protected final static String SLASHED_RESOURCE_URI_PREFIX = "/" +
WebXml.RESOURCE_URI_PREFIX;
+
private File tmpRoot = null;
/**
@@ -159,6 +179,14 @@
InternetResourceBuilder.setInstance(null);
}
// setupWebClient();
+
+ ConfigParser parser = new ConfigParser();
+ parser.parse(parser.getPlatformURLs());
+
+ Enumeration resources =
getClass().getClassLoader().getResources("META-INF/faces-config.xml");
+ while (resources.hasMoreElements()) {
+ parser.parse((URL) resources.nextElement());
+ }
}
/**
@@ -168,7 +196,36 @@
ajaxContext = null;
// setup webClient for got response content.
webClient = new WebClient();
- webConnection = new MockWebConnection(webClient);
+ webConnection = new MockWebConnection(webClient) {
+ public WebResponse getResponse(WebRequestSettings settings)
+ throws IOException {
+ if
(settings.getURL().getFile().startsWith(AbstractAjax4JsfTestCase.SLASHED_RESOURCE_URI_PREFIX))
{
+ InternetResource resource = InternetResourceBuilder.getInstance().getResource(
+ settings.getURL().getFile().substring(AbstractAjax4JsfTestCase.SLASHED_RESOURCE_URI_PREFIX.length()));
+
+ final MockFacesResourceContext resourceContext = new
MockFacesResourceContext(facesContext);
+ resource.sendHeaders(resourceContext);
+
+ return new WebResponseImpl(
+ new WebResponseData(
+ resource.getResourceAsStream(resourceContext),
+ HttpServletResponse.SC_OK,
+ "OK",
+ resourceContext.getHeaders()),
+ settings.getURL(),
+ settings.getSubmitMethod(),
+ 0) {
+
+ public String getContentType() {
+ return resourceContext.getContentType();
+ }
+ };
+
+ } else {
+ return super.getResponse(settings);
+ }
+ }
+ };
webClient.setWebConnection(webConnection);
webConnection.setDefaultResponse("<html><body>not
found</body></html>",404,"NOT FOUND","text/html");
webClient.setThrowExceptionOnFailingStatusCode(false);
Added: trunk/test/src/main/java/org/ajax4jsf/tests/MockFacesResourceContext.java
===================================================================
--- trunk/test/src/main/java/org/ajax4jsf/tests/MockFacesResourceContext.java
(rev 0)
+++ trunk/test/src/main/java/org/ajax4jsf/tests/MockFacesResourceContext.java 2007-04-03
00:27:24 UTC (rev 49)
@@ -0,0 +1,90 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package org.ajax4jsf.tests;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.faces.context.FacesContext;
+
+import org.ajax4jsf.framework.resource.FacesResourceContext;
+import org.apache.shale.test.mock.MockHttpServletResponse;
+
+import com.gargoylesoftware.htmlunit.KeyValuePair;
+
+/**
+ * @author Nick - mailto:nbelaevski@exadel.com
+ * created 03.04.2007
+ *
+ */
+public class MockFacesResourceContext extends FacesResourceContext {
+
+ private String contentType;
+ //used to encode headers properly
+ private MockHttpServletResponse mockResponse = new MockHttpServletResponse();
+ private Set headerSet = new LinkedHashSet();
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public void setDateHeader(String name, long value) {
+ headerSet.add(name);
+ mockResponse.setDateHeader(name, value);
+ }
+
+ public void setHeader(String name, String value) {
+ headerSet.add(name);
+ mockResponse.setHeader(name, value);
+ }
+
+ public void setIntHeader(String name, int value) {
+ headerSet.add(name);
+ mockResponse.setIntHeader(name, value);
+ }
+
+ public List getHeaders() {
+ List headers = new ArrayList();
+ for (Iterator iterator = headerSet.iterator(); iterator
+ .hasNext();) {
+ String headerName = (String) iterator.next();
+
+ String headerValue = mockResponse.getHeader(headerName);
+ if (headerValue != null) {
+ headers.add(new KeyValuePair(headerName, headerValue));
+ }
+ }
+
+ return headers;
+ }
+
+ public MockFacesResourceContext(FacesContext facesContext) {
+ super(facesContext);
+ }
+
+}
Added:
trunk/test/src/main/java/org/ajax4jsf/tests/org/apache/shale/test/config/ConfigParser.java
===================================================================
---
trunk/test/src/main/java/org/ajax4jsf/tests/org/apache/shale/test/config/ConfigParser.java
(rev 0)
+++
trunk/test/src/main/java/org/ajax4jsf/tests/org/apache/shale/test/config/ConfigParser.java 2007-04-03
00:27:24 UTC (rev 49)
@@ -0,0 +1,502 @@
+/**
+ * License Agreement.
+ *
+ * Ajax4jsf 1.1 - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * 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.ajax4jsf.tests.org.apache.shale.test.config;
+
+import java.io.IOException;
+import java.net.URL;
+import javax.faces.FactoryFinder;
+import javax.faces.application.Application;
+import javax.faces.application.ApplicationFactory;
+import javax.faces.render.RenderKit;
+import javax.faces.render.RenderKitFactory;
+import javax.faces.render.Renderer;
+import org.apache.commons.digester.Digester;
+import org.apache.commons.digester.Rule;
+import org.apache.shale.test.mock.MockRenderKit;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>Utility class to parse JavaServer Faces configuration resources, and
+ * register JSF artifacts with the mock object hierarchy.</p>
+ *
+ * <p>The following artifacts are registered:</p>
+ * <ul>
+ * <li><code>Converter</code> (by-id and by-class)</li>
+ * <li><code>RenderKit</code> and
<code>Renderer</code></li>
+ * <li><code>UIComponent</code></li>
+ * <li><code>Validator</code></li>
+ * </ul>
+ *
+ * <p>Note that any declared <em>factory</em> instances are explicitly
+ * <strong>NOT</strong> registered, allowing the mock object hierarchy
+ * of the Shale Test Framework to manage these APIs.</p>
+ *
+ * <p><strong>USAGE NOTE</strong> - If you are using an instance of
this
+ * class within a subclass of <code>AbstractJsfTestCase</code> or
+ * <code>AbstractJmockJsfTestCase</code>, be sure you have completed the
+ * <code>setUp()</code> processing in this base class before calling one
+ * of the <code>parse()</code> methods.</p>
+ *
+ * @since 1.1
+ */
+public final class ConfigParser {
+
+
+ // ------------------------------------------------------------ Constructors
+
+
+ /** Creates a new instance of ConfigParser */
+ public ConfigParser() {
+ }
+
+
+ // ------------------------------------------------------ Manifest Constants
+
+
+ /**
+ * <p>Configuration resource URLs for the JSF RI.</p>
+ */
+ private static final String[] JSFRI_RESOURCES =
+ { "/com/sun/faces/jsf-ri-runtime.xml",
+ };
+
+
+ /**
+ * <p>Configuration resource URLs for Apache MyFaces.</p>
+ */
+ private static final String[] MYFACES_RESOURCES =
+ { "/org/apache/myfaces/resource/standard-faces-config.xml",
+ };
+
+
+ // ------------------------------------------------------ Instance Variables
+
+
+ /**
+ * <p>The <code>Digester</code> instance we will use for
parsing.</p>
+ */
+ private Digester digester = null;
+
+
+ // ------------------------------------------------------- Public Properties
+
+
+ /**
+ * <p>Return the URLs of the platform configuration resources for this
+ * application. The following platforms are currently supported:</p>
+ * <ul>
+ * <li>JavaServer Faces Reference Implementation (version 1.0 -
1.2)</li>
+ * <li>MyFaces (version 1.1)</li>
+ * </ul>
+ *
+ * <p>If MyFaces (version 1.2), currently under development, does not change
+ * the name of the configuration resource, it will be supported as well.</p>
+ */
+ public URL[] getPlatformURLs() {
+
+ URL[] urls = translate(JSFRI_RESOURCES);
+ if (urls[0] == null) {
+ urls = translate(MYFACES_RESOURCES);
+ }
+ return urls;
+
+ }
+
+
+ // ---------------------------------------------------------- Public Methods
+
+
+ /**
+ * <p>Parse the specified JavaServer Faces configuration resource, causing
+ * the appropriate JSF artifacts to be registered with the mock object
+ * hierarchy.</p>
+ *
+ * @param url <code>URL</code> of the configuration resource to parse
+ *
+ * @exception IOException if an input/output error occurs
+ * @exception SAXException if a parsing error occurs
+ */
+ public void parse(URL url) throws IOException, SAXException {
+
+ // Acquire and configure the Digester instance we will use
+ Digester digester = digester();
+ ApplicationFactory factory = (ApplicationFactory)
+ FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
+ Application application = factory.getApplication();
+ digester.push(application);
+
+ // Perform the required parsing
+ try {
+ digester.parse(new InputSource(url.openStream()));
+ } finally {
+ digester.clear();
+ }
+
+ }
+
+
+ /**
+ * <p>Parse the specified set of JavaServer Faces configuration resources,
+ * in the listed order, causing the appropriate JSF artifacts to be registered
+ * with the mock object hierarchy.</p>
+ *
+ * @param urls <code>URL</code>s of the configuration resources to parse
+ *
+ * @exception IOException if an input/output error occurs
+ * @exception SAXException if a parsing error occurs
+ */
+ public void parse(URL[] urls) throws IOException, SAXException {
+
+ for (int i = 0; i < urls.length; i++) {
+ parse(urls[i]);
+ }
+
+ }
+
+
+ // --------------------------------------------------------- Private Methods
+
+
+ /**
+ * <p>Return the <code>Digester</code> instance we will use for
parsing,
+ * creating and configuring a new instance if necessary.</p>
+ */
+ private Digester digester() {
+
+ if (this.digester == null) {
+ this.digester = new Digester();
+ digester.addRule("faces-config/component", new ComponentRule());
+ digester.addCallMethod
+ ("faces-config/component/component-type",
"setComponentType", 0);
+ digester.addCallMethod
+ ("faces-config/component/component-class",
"setComponentClass", 0);
+ digester.addRule("faces-config/converter", new ConverterRule());
+ digester.addCallMethod
+ ("faces-config/converter/converter-id",
"setConverterId", 0);
+ digester.addCallMethod
+ ("faces-config/converter/converter-class",
"setConverterClass", 0);
+ digester.addCallMethod
+ ("faces-config/converter/converter-for-class",
"setConverterForClass", 0);
+ digester.addRule("faces-config/render-kit", new RenderKitRule());
+ digester.addRule("faces-config/render-kit/render-kit-id", new
RenderKitIdRule());
+ digester.addRule("faces-config/render-kit/renderer", new
RendererRule());
+ digester.addCallMethod
+ ("faces-config/render-kit/renderer/component-family",
"setComponentFamily", 0);
+ digester.addCallMethod
+ ("faces-config/render-kit/renderer/renderer-class",
"setRendererClass", 0);
+ digester.addCallMethod
+ ("faces-config/render-kit/renderer/renderer-type",
"setRendererType", 0);
+ digester.addRule("faces-config/validator", new ValidatorRule());
+ digester.addCallMethod
+ ("faces-config/validator/validator-id",
"setValidatorId", 0);
+ digester.addCallMethod
+ ("faces-config/validator/validator-class",
"setValidatorClass", 0);
+ }
+ return this.digester;
+
+ }
+
+
+ /**
+ * <p>Translate an array of resource names into an array of resource
URLs.</p>
+ *
+ * @param names Resource names to translate
+ */
+ private URL[] translate(String[] names) {
+
+ URL[] results = new URL[names.length];
+ for (int i = 0; i < names.length; i++) {
+ results[i] = this.getClass().getResource(names[i]);
+ }
+ return results;
+
+ }
+
+
+ // --------------------------------------------------------- Private Classes
+
+
+ /**
+ * <p>Data bean that stores information related to a component.</p>
+ */
+ class ComponentBean {
+
+ private String componentClass;
+ public String getComponentClass() {
+ return this.componentClass;
+ }
+ public void setComponentClass(String componentClass) {
+ this.componentClass = componentClass;
+ }
+
+ private String componentType;
+ public String getComponentType() {
+ return this.componentType;
+ }
+ public void setComponentType(String componentType) {
+ this.componentType = componentType;
+ }
+
+ }
+
+
+ /**
+ * <p>Digester <code>Rule</code> for processing
components.</p>
+ */
+ class ComponentRule extends Rule {
+
+ public void begin(String namespace, String name, Attributes attributes) {
+ getDigester().push(new ComponentBean());
+ }
+
+ public void end(String namespace, String name) {
+ ComponentBean bean = (ComponentBean) getDigester().pop();
+ Application application = (Application) getDigester().peek();
+ application.addComponent(bean.getComponentType(), bean.getComponentClass());
+ }
+
+ }
+
+
+ /**
+ * <p>Data bean that stores information related to a converter.</p>
+ */
+ class ConverterBean {
+
+ private String converterClass;
+ public String getConverterClass() {
+ return this.converterClass;
+ }
+ public void setConverterClass(String converterClass) {
+ this.converterClass = converterClass;
+ }
+
+ private String converterForClass;
+ public String getConverterForClass() {
+ return this.converterForClass;
+ }
+ public void setConverterForClass(String converterForClass) {
+ this.converterForClass = converterForClass;
+ }
+
+ private String converterId;
+ public String getConverterId() {
+ return this.converterId;
+ }
+ public void setConverterId(String converterId) {
+ this.converterId = converterId;
+ }
+
+ }
+
+
+ /**
+ * <p>Digester <code>Rule</code> for processing
converers.</p>
+ */
+ class ConverterRule extends Rule {
+
+ public void begin(String namespace, String name, Attributes attributes) {
+ getDigester().push(new ConverterBean());
+ }
+
+ public void end(String namespace, String name) {
+ ConverterBean bean = (ConverterBean) getDigester().pop();
+ Application application = (Application) getDigester().peek();
+ if (bean.getConverterId() != null) {
+ application.addConverter(bean.getConverterId(),
bean.getConverterClass());
+ } else {
+ Class clazz = null;
+ try {
+ clazz =
this.getClass().getClassLoader().loadClass(bean.getConverterForClass());
+ } catch (ClassNotFoundException e) {
+ throw new
IllegalArgumentException("java.lang.ClassNotFoundException: "
+ + bean.getConverterForClass());
+ }
+ application.addConverter(clazz, bean.getConverterClass());
+ }
+ }
+
+ }
+
+
+ /**
+ * <p>Digester <code>Rule</code> for processing render
kits.</p>
+ */
+ class RenderKitRule extends Rule {
+
+ public void begin(String namespace, String name, Attributes attributes) {
+ RenderKitFactory factory = (RenderKitFactory)
+ FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
+ getDigester().push(factory.getRenderKit(null,
RenderKitFactory.HTML_BASIC_RENDER_KIT));
+ }
+
+ public void end(String namespace, String name) {
+ getDigester().pop();
+ }
+
+ }
+
+
+ /**
+ * <p>Digester <code>Rule</code> for processing render kit
identifiers.</p>
+ */
+ class RenderKitIdRule extends Rule {
+
+ public void body(String namespace, String name, String text) {
+ String renderKitId = text.trim();
+ RenderKitFactory factory = (RenderKitFactory)
+ FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
+ RenderKit renderKit = factory.getRenderKit(null, renderKitId);
+ if (renderKit == null) {
+ renderKit = new MockRenderKit();
+ factory.addRenderKit(renderKitId, renderKit);
+ }
+ digester.pop();
+ digester.push(renderKit);
+ }
+
+ }
+
+
+ /**
+ * <p>Data bean that stores information related to a renderer.</p>
+ */
+ class RendererBean {
+
+ private String componentFamily;
+ public String getComponentFamily() {
+ return this.componentFamily;
+ }
+ public void setComponentFamily(String componentFamily) {
+ this.componentFamily = componentFamily;
+ }
+
+ private String rendererClass;
+ public String getRendererClass() {
+ return this.rendererClass;
+ }
+ public void setRendererClass(String rendererClass) {
+ this.rendererClass = rendererClass;
+ }
+
+ private String rendererType;
+ public String getRendererType() {
+ return this.rendererType;
+ }
+ public void setRendererType(String rendererType) {
+ this.rendererType = rendererType;
+ }
+
+ }
+
+
+ /**
+ * <p>Digester <code>Rule</code> for processing
renderers.</p>
+ */
+ class RendererRule extends Rule {
+
+ public void begin(String namespace, String name, Attributes attributes) {
+ getDigester().push(new RendererBean());
+ }
+
+ public void end(String namespace, String name) {
+ RendererBean bean = (RendererBean) getDigester().pop();
+ RenderKit kit = (RenderKit) getDigester().peek();
+ Renderer renderer = null;
+ Class clazz = null;
+ try {
+ clazz =
this.getClass().getClassLoader().loadClass(bean.getRendererClass());
+ renderer = (Renderer) clazz.newInstance();
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Exception while trying to
instantiate"
+ + " renderer class '" + bean.getRendererClass() +
"' : "
+ + e.getMessage());
+ }
+ kit.addRenderer(bean.getComponentFamily(), bean.getRendererType(),
+ renderer);
+ }
+
+ }
+
+
+ /**
+ * <p>Data bean that stores information related to a validator.</p>
+ */
+ class ValidatorBean {
+
+ private String validatorClass;
+ public String getValidatorClass() {
+ return this.validatorClass;
+ }
+ public void setValidatorClass(String validatorClass) {
+ this.validatorClass = validatorClass;
+ }
+
+ private String validatorId;
+ public String getValidatorId() {
+ return this.validatorId;
+ }
+ public void setValidatorId(String validatorId) {
+ this.validatorId = validatorId;
+ }
+
+ }
+
+
+ /**
+ * <p>Digester <code>Rule</code> for processing
validators.</p>
+ */
+ class ValidatorRule extends Rule {
+
+ public void begin(String namespace, String name, Attributes attributes) {
+ getDigester().push(new ValidatorBean());
+ }
+
+ public void end(String namespace, String name) {
+ ValidatorBean bean = (ValidatorBean) getDigester().pop();
+ Application application = (Application) getDigester().peek();
+ application.addValidator(bean.getValidatorId(), bean.getValidatorClass());
+ }
+
+ }
+
+
+}