Commits

Anonymous committed 94dafc9

XW-510 (allowing multiple validator definition to be loaded from classpath, overriding each others according to their precedence)

git-svn-id: http://svn.opensymphony.com/svn/xwork/branches/xwork_1-2/src@1691e221344d-f017-0410-9bd5-d282ab1896d7

Comments (0)

Files changed (14)

java/com/opensymphony/xwork/util/ResourceScanner.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Scans for resource that resides within classpath and jar file.
+ * <p/>
+ * Typical usage would be :-
+ * <p/>
+ * To scan for all resources (apple.txt) that lies in the root of a classpath or in the
+ * root of the jar file.
+ * <pre>
+ * <code>
+ *      // to scan for a resource (apple.txt) that lies in the root of a classpath or in
+ *      // the root of the jar file.
+ *      ResourceScanner resourceScanner = new ResourceScanner(
+ *          new String[] { "" },  // an empty string indicate that the scanning should start at the 'root'
+ *          MyMain.class
+ *      );
+ *      List<URL> ourResources = resourceScanner.scanForResources(
+ *           new ResourceScanner.Filter() {
+ *                 public boolean accept(URL resource) {
+ *                     if (resource.getFile().endsWith("apple.txt")) {
+ *                         return true;
+ *                     }
+ *                     return false;
+ *                 }
+ *           });
+ *
+ * </code>
+ * </pre>
+ * To scan for all resources that lies under the '/com/opensymphony/xwork/util' directory in
+ * the classpath, we could do
+ * <pre>
+ * <code>
+ *      List<URL> ourResources = new ResourceScanner(
+ *              new String[] { "com/opensymphony/xwork/util/" }, // Note that it DOES NOT start with a '/' and MUST ends with '/'
+ *              MyMain.class).scanForResources();
+ * </code>
+ * </pre>
+ *
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class ResourceScanner {
+
+    private static final Log LOG = LogFactory.getLog(ResourceScanner.class);
+
+    private String[] roots;
+    private Class callingClass;
+
+    /**
+     * Create an instance of {@link com.opensymphony.xwork.util.ResourceScanner}, taking
+     * in arguments
+     * <ul>
+     *  <li><code>root</code> - An array of String, defining the root we should start scanning
+     *                          for resources.</li>
+     *  <li><code>callingClass</code> - The class invoking methods on
+     *                                  {@link com.opensymphony.xwork.util.ResourceScanner}</li>
+     * </ul>
+     * @param roots An array of String, defining the root we should start scanning for resources.
+     * @param callingClass The class invoking methods on {@link com.opensymphony.xwork.util.ResourceScanner}
+     */
+    public ResourceScanner(String[] roots, Class callingClass) {
+        this.roots = roots;
+        this.callingClass = callingClass;
+    }
+
+    /**
+     * Start scanning for the resources, assuming that all the resources under <code>roots</code>
+     * specified in the constructor is what we need.
+     *
+     * @return {@link java.util.List} of {@link java.net.URL}.
+     * @throws IOException
+     * @throws URISyntaxException
+     */
+    public List scanForResources() throws IOException, URISyntaxException {
+        return scanForResources(
+            new Filter() {
+                public boolean accept(URL resource) {
+                    return true;
+                }
+            });
+    }
+
+    /**
+     * Start scanning for the resources under <code>roots</code> as specified in the constructor
+     * applying <code>filter</code>({@link com.opensymphony.xwork.util.ResourceScanner.Filter})
+     * to the resources that we've found.
+     *
+     * @param filter
+     * @return {@link java.util.List} of {@link java.net.URL}
+     * @throws IOException
+     * @throws URISyntaxException
+     */
+    public List scanForResources(Filter filter) throws IOException, URISyntaxException {
+        List resources = new ArrayList();
+        for (int a=0; a< roots.length; a++) {
+            String root = roots[a].replace('.', '/');
+
+            /*
+             * Special case if root is '', we need to scan all the root directory of
+             * the jar files as well. We can't do thate with
+             *    classLoader.getResources("");
+             * it doesn't work, we'll need to do a bit of hack to get around this.
+             * This only applies when the resource might be located in a jar file. For
+             * non-jar file resources
+             *    classLoader.getResources("");
+             * works fine.
+             */
+            if ("".equals(root)) {
+                URL[] rootResources = getResources("META-INF", ResourceScanner.class);
+                for (int c=0; c<rootResources.length; c++) {
+                    if (rootResources[c].toString().startsWith("jar:file:") &&
+                       (rootResources[c].toString().indexOf("!") > 0)) {
+                        //System.out.println(rootResources[c]);
+                        String jarFilePath = rootResources[c].toString().substring(9,
+                                rootResources[c].toString().indexOf("!"));
+                        resources.addAll(loadRootResourcesFromJarFile(
+                            rootResources[c].toString().substring(0, rootResources[c].toString().indexOf("!")),
+                            new File(URLDecoder.decode(jarFilePath, "UTF-8")), filter, null));
+                    }
+                }
+            }
+
+            /*
+             * Normal case, we just let
+             *    classLoader.getResources(...)
+             * helps us get the resources. This works for resources lying in jar and non-jar, except
+             * for resources in jar file that should be in the root eg. validators.xml that lies in the
+             * root of a jar file. In this case, we deal with it in the above code (special case).
+             */
+            URL[] rootResources = getResources(root, ResourceScanner.class);
+            for (int b=0; b< rootResources.length; b++) {
+                if (rootResources[b].toString().startsWith("file:")) {
+                    //System.out.println(rootResources[b]);
+                    resources.addAll(loadResourcesFromClassPath(new File(rootResources[b].toURI()), filter, null));
+                }
+                else if (rootResources[b].toString().startsWith("jar:file:") &&
+                        (rootResources[b].toString().indexOf("!") > 0)) {
+                    //System.out.println(rootResources[b]);
+                    String jarFilePath = rootResources[b].toString().substring(
+                            9, rootResources[b].toString().indexOf("!"));
+
+                    resources.addAll(loadResourcesFromJarFile(
+                            rootResources[b].toString().substring(0, rootResources[b].toString().indexOf("!")),
+                            root, new File(URLDecoder.decode(jarFilePath, "UTF-8")), filter, null));
+                }
+            }
+        }
+        return resources;
+    }
+
+    /**
+     * Find resources (a {@link java.util.List} of {@link java.net.URL}) from a jar file that lies in the
+     * root of the jar file, applying {@link com.opensymphony.xwork.util.ResourceScanner.Filter} on each
+     * resources found. 
+     *
+     * @param jarFilePath
+     * @param jarFile
+     * @param filter
+     * @param resources
+     * @return {@link java.util.List} of {@link java.net.URL}.
+     * @throws IOException
+     */
+    protected List loadRootResourcesFromJarFile(String jarFilePath, File jarFile, Filter filter, List resources) throws IOException {
+        if (resources == null) {
+            resources = new ArrayList();
+        }
+        JarFile _jarFile = null;
+        try {
+            _jarFile = new JarFile(jarFile);
+            Enumeration jarFileEntries = _jarFile.entries();
+            while(jarFileEntries.hasMoreElements()) {
+                JarEntry jarEntry = (JarEntry) jarFileEntries.nextElement();
+                String fullResourcePath = jarEntry.getName();
+                if (fullResourcePath.indexOf("/") < 0) {
+                    //System.out.println(jarEntry.getName());
+                    //System.out.println(jarFilePath+"!"+fullResourcePath);
+                    //URL _resource = ClassLoaderUtil.getResource(fullResourcePath, ResourceScanner.class);
+                    URL _resource = new URL(jarFilePath+"!/"+fullResourcePath);
+                    if (_resource != null) {
+                        if (filter.accept(_resource)) {
+                            resources.add(_resource);
+                        }
+                    }
+                }
+            }
+        }
+        finally {
+            if (jarFile != null) {
+                _jarFile.close();
+            }
+        }
+        return resources;
+    }
+
+    public List loadResourcesFromJarFile(String jarFilePath, String root, File jarFile, Filter filter, List resources) throws IOException {
+        if (resources == null) {
+            resources = new ArrayList();
+        }
+        JarFile _jarFile = null;
+        try {
+            _jarFile = new JarFile(jarFile);
+            Enumeration jarFileEntries = _jarFile.entries();
+            while(jarFileEntries.hasMoreElements()) {
+                JarEntry jarEntry = (JarEntry) jarFileEntries.nextElement();
+                String fullResourcePath = jarEntry.getName();
+                //String fullResourcePath = root + (root.endsWith("/")?(jarEntry.getName()):("/"+jarEntry.getName()));
+                //System.out.println("** jarEntry.getName()="+jarEntry.getName());
+                //System.out.println("** fullResourePath="+fullResourcePath);
+                if (fullResourcePath.startsWith(root) &&
+                        (fullResourcePath.substring(root.length()).indexOf("/") < 0)) {
+                    // see if this resource really exists
+                    //URL _resource = ClassLoaderUtil.getResource(fullResourcePath, ResourceScanner.class);
+                    URL _resource = new URL(jarFilePath+"!/"+fullResourcePath);
+
+                    if (_resource != null) {
+                        if(filter.accept(_resource)) {
+                            resources.add(_resource);
+                        }
+                    }
+                }
+            }
+        }
+        finally {
+            if (jarFile != null) {
+                _jarFile.close();
+            }
+        }
+        return resources;
+    }
+
+
+    public List loadResourcesFromClassPath(File rootFile, Filter filter, List resources) throws URISyntaxException,
+            MalformedURLException {
+        if (resources == null) {
+            resources = new ArrayList();
+        }
+        if (rootFile.isDirectory()) {
+            File[] children = rootFile.listFiles();
+            for (int a=0; a<children.length; a++) {
+                //System.out.println("** "+children[a]);
+                if (children[a].isFile()) {
+                    if (filter.accept(children[a].toURL())) {
+                        resources.add(children[a].toURL());
+                    }
+                }
+            }
+        }
+        return resources;
+    }
+
+
+    /**
+     * Returns an array of {@link java.net.URL} corresponding to <code>resourceName</code>.
+     * Search for {@link java.net.URL}s using {@link ClassLoader} in the following precedence :-
+     * <ul>
+     *      <li>ThreadLocal's context class loader</li>
+     *      <li>ValidatorFactory's class loader</li>
+     *      <li><code>callingClass</code>'s class loader</li>
+     * </ul>
+     *
+     * @param resourceName
+     * @param callingClass
+     * @return URL[]
+     * @throws java.io.IOException
+     */
+     protected URL[] getResources(String resourceName, Class callingClass) throws IOException {
+        // use ThreadLocal's class loader
+        URL[] urls =  (URL[]) Collections.list(
+                Thread.currentThread().getContextClassLoader().getResources(resourceName)
+        ).toArray(new URL[0]);
+
+        // use ClassLoaderUtil's classloader
+        if (urls.length == 0) {
+            urls = (URL[]) Collections.list(
+                   ResourceScanner.class.getClassLoader().getResources(resourceName)
+            ).toArray(new URL[0]);
+        }
+
+        // use callingClass's classloader
+        if (urls.length == 0) {
+            urls = (URL[]) Collections.list(
+                    callingClass.getClassLoader().getResources(resourceName)
+            ).toArray(new URL[0]);
+        }
+
+        return urls;
+     }
+
+
+    /**
+     * @author tmjee
+     * @version $Date$ $Id$
+     */
+    public static interface Filter {
+        boolean accept(URL resource);
+    }
+}

java/com/opensymphony/xwork/validator/ValidatorFactory.java

 import com.opensymphony.util.ClassLoaderUtil;
 import com.opensymphony.xwork.ObjectFactory;
 import com.opensymphony.xwork.XworkException;
+import com.opensymphony.xwork.util.ResourceScanner;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-import java.io.InputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
-import java.util.Collections;
-import java.net.URL;
 
 
 /**
     private static Log LOG = LogFactory.getLog(ValidatorFactory.class);
 
     static {
-        parseValidators();
+        try {
+            parseValidators();
+        }
+        catch(Exception e) {
+            throw new XworkException(e);
+        }
     }
 
 
 
 
     /**
+     * Removed all registered validators.
+     */
+    public static void reset() {
+        validators.clear();
+    }
+
+    /**
      * Get a Validator that matches the given configuration.
      *
      * @param cfg  the configurator.
      * @param className   the FQ classname of the validator.
      */
     public static void registerValidator(String name, String className) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("Registering validator of class " + className + " with name " + name);
+        if (validators.containsKey(name)) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Validator with name ["+name+"] with class ["+validators.get(name)+"], replacing it with ["+className+"]");
+            }
+        }
+        else {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Registering validator of class " + className + " with name " + name);
+            }
         }
-
         validators.put(name, className);
     }
 
     }
 
     /**
-     * Returns an array of {@link java.net.URL} corresponding to <code>resourceName</code>.
-     * Search for {@link java.net.URL}s using {@link ClassLoader} in the following precedence :-
+     * Parse all the validators definition, using the following precedence:-
      * <ul>
-     *      <li>ThreadLocal's context class loader</li>
-     *      <li>ValidatorFactory's class loader</li>
-     *      <li><code>callingClass</code>'s class loader</li>
+     *  <li>Defaults from com/opensymphony/xwork/validator/validators/default.xml</li>
+     *  <li>validators.xml that lies in the root of the classpath</li>
+     *  <li>*-validators.xml that lies in the root of the classpath</li>
      * </ul>
-     *
-     * @param resourceName
-     * @param callingClass
-     * @return URL[]
-     * @throws java.io.IOException
      */
-     public static URL[] getResources(String resourceName, Class callingClass) throws IOException {
-        // use ThreadLocal's class loader
-        URL[] urls =  (URL[]) Collections.list(
-                Thread.currentThread().getContextClassLoader().getResources(resourceName)
-        ).toArray(new URL[0]);
-
-        // use ClassLoaderUtil's classloader
-        if (urls.length == 0) {
-            urls = (URL[]) Collections.list(
-                   ValidatorFactory.class.getClassLoader().getResources(resourceName)
-            ).toArray(new URL[0]);
+    public static void parseValidators() throws IOException, URISyntaxException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Loading validator definitions.");
         }
 
-        // use callingClass's classloader
-        if (urls.length == 0) {
-            urls = (URL[]) Collections.list(
-                    callingClass.getClassLoader().getResources(resourceName)
-            ).toArray(new URL[0]);
+        // Try loading com/opensymphony/xwork/validator/validators/default.xml
+        {
+            String resourceName = "com/opensymphony/xwork/validator/validators/default.xml";
+            loadValidators(ClassLoaderUtil.getResourceAsStream(resourceName, ValidatorFactory.class), resourceName);
         }
 
-        return urls;
-     }
-
 
-    private static void parseValidators() {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("Loading validator definitions.");
+        // Try loading from validators.xml
+        {
+            String resourceName = "validators.xml";
+            loadValidators(ClassLoaderUtil.getResourceAsStream(resourceName, ValidatorFactory.class), resourceName);
         }
 
-        String resourceName = "validators.xml";
-        InputStream is = ClassLoaderUtil.getResourceAsStream(resourceName, ValidatorFactory.class);
-        if (is == null) {
-            resourceName = "com/opensymphony/xwork/validator/validators/default.xml";
-            is = ClassLoaderUtil.getResourceAsStream(resourceName, ValidatorFactory.class);
-        }
 
-        if (is != null) {
-            ValidatorFileParser.parseValidatorDefinitions(is, resourceName);
+        // Try loading from *-validators.xml
+        {
+            ResourceScanner resourceScanner = new ResourceScanner(
+                    new String[] { "" }, ValidatorFactory.class
+            );
+            List validatorDefs = resourceScanner.scanForResources(new ResourceScanner.Filter() {
+                public boolean accept(URL resource) {
+                    // eg. file:/C:/j2sdk1.5.12/jre/lib/javaws.jar!/COPYRIGHT
+                    if (resource.getFile().endsWith("-validators.xml")) {
+                        return true;
+                    }
+                    return false;
+                }
+            });
+            for (Iterator i = validatorDefs.iterator(); i.hasNext(); ) {
+                URL validatorDefUrl = (URL) i.next();
+                loadValidators(validatorDefUrl.openStream(),
+                        validatorDefUrl.getFile().substring(validatorDefUrl.getFile().lastIndexOf("/")+1));
+            }
         }
     }
+
+
+    private static void loadValidators(InputStream is, String resourceName) {
+         if (is != null) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("loading validators definition from "+resourceName);
+            }
+            try {
+                ValidatorFileParser.parseValidatorDefinitions(is, resourceName);
+            }
+            finally {
+                try { is.close(); } catch(IOException e) { };
+            }
+         }
+    }
 }

java/com/opensymphony/xwork/validator/validators/default.xml

     <validator name="regex" class="com.opensymphony.xwork.validator.validators.RegexFieldValidator"/>
     <validator name="collection" class="com.opensymphony.xwork.validator.validators.CollectionFieldValidator" />
 </validators>
+        
 <!--  END SNIPPET: validators-default -->

test/bar-validators.xml

+<!DOCTYPE validators PUBLIC
+  		"-//OpenSymphony Group//XWork Validator Definition 1.0//EN"
+  		"http://www.opensymphony.com/xwork/xwork-validator-definition-1.0.dtd">
+
+<validators>
+    <validator name="bing" class="com.opensymphony.xwork.validator.validators.BingValidator" />
+    <validator name="bang" class="com.opensymphony.xwork.validator.validators.BangValidator" />
+</validators>

test/com/opensymphony/xwork/util/ResourceScannerTest.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.util;
+
+import com.opensymphony.xwork.XWorkTestCase;
+
+import java.net.URL;
+import java.util.List;
+
+/**
+ * Test case for {@link com.opensymphony.xwork.util.ResourceScanner}.
+ *
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class ResourceScannerTest extends XWorkTestCase {
+
+    public void test1() throws Exception {
+        ResourceScanner scanner = new ResourceScanner(
+                new String[] { "com/opensymphony/xwork/util/" }, 
+                ResourceScanner.class
+        );
+        List l = scanner.scanForResources(new ResourceScanner.Filter() {
+            public boolean accept(URL resource) {
+                return true;
+            }
+        });
+        
+        assertTrue(l.size() > 0);
+    }
+
+    public void test2() throws Exception {
+        ResourceScanner scanner = new ResourceScanner(
+                new String[] { "org/apache/commons/logging/" }, 
+                ResourceScanner.class
+        );
+        List l = scanner.scanForResources(new ResourceScanner.Filter() {
+            public boolean accept(URL resource) {
+                return true;
+            }
+        });
+        assertTrue(l.size() > 0);
+    }
+
+    public void test3() throws Exception {
+        ResourceScanner scanner = new ResourceScanner(
+                new String[] {
+                        "com/opensymphony/xwork/util/",
+                        "org/apache/commons/logging/"
+                }, 
+                ResourceScanner.class
+        );
+        List l = scanner.scanForResources(new ResourceScanner.Filter() {
+            public boolean accept(URL resource) {
+                return true;
+            }
+        });
+        
+        assertTrue(l.size() > 0);
+    }
+
+    public void test() throws Exception {
+
+        ResourceScanner scanner = new ResourceScanner(
+                new String[] { "" },
+                ResourceScanner.class
+        );
+        List l = scanner.scanForResources(new ResourceScanner.Filter() {
+            public boolean accept(URL resource) {
+                System.out.println(resource.getFile());
+                if (resource.getFile().endsWith("COPYRIGHT")) {
+                    return true;
+                }
+                return true;
+            }
+        });
+
+        assertTrue(l.size() > 0);
+    }
+}

test/com/opensymphony/xwork/validator/ValidatorFactoryTest.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.validator;
+
+import com.opensymphony.xwork.XWorkTestCase;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class ValidatorFactoryTest extends XWorkTestCase {
+
+    public void test() throws Exception {
+        ValidatorFactory.reset();
+        ValidatorFactory.parseValidators();
+
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("requiredstring"),
+                "com.opensymphony.xwork.validator.validators.RequiredStringValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("required"),
+                "com.opensymphony.xwork.validator.validators.RequiredFieldValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("int"), 
+                "com.opensymphony.xwork.validator.validators.IntRangeFieldValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("double"),
+                "com.opensymphony.xwork.validator.validators.DoubleRangeFieldValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("date"),
+                "com.opensymphony.xwork.validator.validators.DateRangeFieldValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("expression"),
+                "com.opensymphony.xwork.validator.validators.ExpressionValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("fieldexpression"),
+                "com.opensymphony.xwork.validator.validators.FieldExpressionValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("email"),
+                "com.opensymphony.xwork.validator.validators.EmailValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("url"),
+                "com.opensymphony.xwork.validator.validators.URLValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("visitor"),
+                "com.opensymphony.xwork.validator.validators.VisitorFieldValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("conversion"),
+                "com.opensymphony.xwork.validator.validators.ConversionErrorFieldValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("stringlength"),
+                "com.opensymphony.xwork.validator.validators.StringLengthFieldValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("regex"),
+                "com.opensymphony.xwork.validator.validators.RegexFieldValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("foo"),
+                "com.opensymphony.xwork.validator.validators.FooValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("bar"),
+                "com.opensymphony.xwork.validator.validators.BarValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("baz"),
+                "com.opensymphony.xwork.validator.validators.BazValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("boo"),
+                "com.opensymphony.xwork.validator.validators.BooValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("bing"),
+                "com.opensymphony.xwork.validator.validators.BingValidator");
+        assertEquals(
+                ValidatorFactory.lookupRegisteredValidatorType("bang"),
+                "com.opensymphony.xwork.validator.validators.BangValidator");
+    }
+}

test/com/opensymphony/xwork/validator/validators/BangValidator.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.validator.validators;
+
+import com.opensymphony.xwork.validator.validators.ValidatorSupport;
+import com.opensymphony.xwork.validator.ValidationException;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class BangValidator extends ValidatorSupport {
+    public void validate(Object object) throws ValidationException {
+        // do nothing
+    }
+}

test/com/opensymphony/xwork/validator/validators/BarValidator.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.validator.validators;
+
+import com.opensymphony.xwork.validator.validators.ValidatorSupport;
+import com.opensymphony.xwork.validator.ValidationException;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class BarValidator extends ValidatorSupport {
+
+    public void validate(Object object) throws ValidationException {
+        // do nothing
+    }
+}

test/com/opensymphony/xwork/validator/validators/BazValidator.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.validator.validators;
+
+import com.opensymphony.xwork.validator.validators.ValidatorSupport;
+import com.opensymphony.xwork.validator.ValidationException;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class BazValidator extends ValidatorSupport {
+    public void validate(Object object) throws ValidationException {
+        // do nothing
+    }
+}

test/com/opensymphony/xwork/validator/validators/BingValidator.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.validator.validators;
+
+import com.opensymphony.xwork.validator.validators.ValidatorSupport;
+import com.opensymphony.xwork.validator.ValidationException;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class BingValidator extends ValidatorSupport {
+    public void validate(Object object) throws ValidationException {
+        // do nothing
+    }
+}

test/com/opensymphony/xwork/validator/validators/BooValidator.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.validator.validators;
+
+import com.opensymphony.xwork.validator.validators.ValidatorSupport;
+import com.opensymphony.xwork.validator.ValidationException;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class BooValidator extends ValidatorSupport {
+    public void validate(Object object) throws ValidationException {
+        // do nothing
+    }
+}
+

test/com/opensymphony/xwork/validator/validators/FooValidator.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork.validator.validators;
+
+import com.opensymphony.xwork.validator.validators.ValidatorSupport;
+import com.opensymphony.xwork.validator.ValidationException;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class FooValidator extends ValidatorSupport {
+    public void validate(Object object) throws ValidationException {
+        // do nothing        
+    }
+}

test/foo-validators.xml

+<!DOCTYPE validators PUBLIC
+  		"-//OpenSymphony Group//XWork Validator Definition 1.0//EN"
+  		"http://www.opensymphony.com/xwork/xwork-validator-definition-1.0.dtd">
+
+<validators>
+    <validator name="foo" class="com.opensymphony.xwork.validator.validators.FooValidator" />
+    <validator name="bar" class="com.opensymphony.xwork.validator.validators.BarValidator" />
+    <validator name="boo" class="com.opensymphony.xwork.validator.validators.BooValidator" />
+</validators>

test/validators.xml

     <validator name="conversion" class="com.opensymphony.xwork.validator.validators.ConversionErrorFieldValidator"/>
     <validator name="stringlength" class="com.opensymphony.xwork.validator.validators.StringLengthFieldValidator"/>
     <validator name="regex" class="com.opensymphony.xwork.validator.validators.RegexFieldValidator"/>
+
+    <validator name="foo" class="com.opensymphony.xwork.validator.validators.BarValidator" />
+    <validator name="bar" class="com.opensymphony.xwork.validator.validators.FooValidator" />
+    <validator name="baz" class="com.opensymphony.xwork.validator.validators.BazValidator" />
 </validators>
         
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.