Commits

Anonymous committed 2e78be8

Reworked validator configuration loading:

o Use the default validator class for validators not configured in the validators.xml file
o Read all *-validators.xml
o Allow extending default.xml validations rather than overwritting them

NOTE: New configuration loader workflow:

1) parse com/opensymphony/xwork2/validator/validators/default.xml
-> prepare the default set of validators

2) parse validators.xml (should be backwards compliant)
-> extend the default validators with custom validator implementations
-> override existing default validators with a custom implementation

3) optional: parse all custom XXX-validators.xml files from the root classpath (should work with jars as well)
-> extend the default validators with custom validator implementations
-> override existing default validators with a custom implementation

Issue Number: XW-317, XW-466, XW-504

git-svn-id: http://svn.opensymphony.com/svn/xwork/branches/2.0@1457e221344d-f017-0410-9bd5-d282ab1896d7

  • Participants
  • Parent commits 2d6d9dc
  • Branches 2.0, xwork_2_0_7

Comments (0)

Files changed (4)

src/java/com/opensymphony/xwork2/validator/ValidatorFactory.java

 import org.apache.commons.logging.LogFactory;
 
 import java.io.InputStream;
+import java.io.File;
+import java.io.FilenameFilter;
 import java.util.HashMap;
 import java.util.Map;
+import java.net.URL;
+import java.net.URISyntaxException;
 
 
 /**
             LOG.debug("Loading validator definitions.");
         }
 
-        String resourceName = "validators.xml";
-        InputStream is = ClassLoaderUtil.getResourceAsStream(resourceName, ValidatorFactory.class);
-        if (is == null) {
-            resourceName = "com/opensymphony/xwork2/validator/validators/default.xml";
-            is = ClassLoaderUtil.getResourceAsStream(resourceName, ValidatorFactory.class);
+        // Get custom validator configurations via the classpath
+        URL u = ClassLoaderUtil.getResource("", ValidatorFactory.class);
+        File[] files = null;
+        try {
+            File f = new File(u.toURI());
+            FilenameFilter filter = new FilenameFilter() {
+                public boolean accept(File file, String fileName) {
+                    return fileName.contains("-validators.xml");
+                }
+            };
+            files = f.listFiles(filter);
+        } catch (URISyntaxException e) {
+            // swallow
+        }
+
+        // Parse default validator configurations
+        String resourceName = "com/opensymphony/xwork2/validator/validators/default.xml";
+        retrieveValidatorConfiguration(resourceName);
+
+        // Overwrite and extend defaults with application specific validator configurations
+        resourceName = "validators.xml";
+        retrieveValidatorConfiguration(resourceName);
+
+        // Add custom (plugin) specific validator configurations
+        if ( files != null && files.length > 0 ) {
+            for (File file : files) {
+                retrieveValidatorConfiguration(file.getName());
+            }
         }
+    }
 
+    private static void retrieveValidatorConfiguration(String resourceName) {
+        InputStream is = ClassLoaderUtil.getResourceAsStream(resourceName, ValidatorFactory.class);
         if (is != null) {
             ValidatorFileParser.parseValidatorDefinitions(is, resourceName);
         }

src/test/com/opensymphony/xwork2/validator/ValidatorFactoryTest.java

+package com.opensymphony.xwork2.validator;
+
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.config.providers.MockConfigurationProvider;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Constructor;
+import java.util.Map;
+
+/**
+ * <code>ValidatorFactoryTest</code>
+ *
+ * @author <a href="mailto:hermanns@aixcept.de">Rainer Hermanns</a>
+ * @version $Id: $
+ */
+public class ValidatorFactoryTest extends XWorkTestCase {
+
+    public void testParseValidators() {
+        try {
+            Class c = Class.forName("com.opensymphony.xwork2.validator.ValidatorFactory");
+            Constructor constructor = c.getDeclaredConstructors()[0];
+            constructor.setAccessible(true);
+            
+            assertNotNull(c);
+            Field field = c.getDeclaredField("validators");
+            field.setAccessible(true);
+            Map validators = (Map) field.get(null);
+            assertNotNull(validators);
+            assertNotNull(validators.get("requiredAdditional"));
+            assertNotNull(validators.get("requiredAnother"));
+            assertNotNull(validators.get("regex"));
+
+            // There should be 15 validators at all: 
+            // 13 from default.xml overwritten by validators.xml
+            //  1 from my-Validators.xml
+            //  1 from myOther-validators.xml
+            assertEquals(15, validators.size());
+        } catch (Exception e) {
+            fail("We shouldn't get here...");
+        }
+    }
+
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        configurationManager.clearConfigurationProviders();
+        configurationManager.addConfigurationProvider(new MockConfigurationProvider());
+        configurationManager.reload();
+    }
+
+}

src/test/my-validators.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE validators PUBLIC
+        "-//OpenSymphony Group//XWork Validator Config 1.0//EN"
+        "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd">
+<validators>
+    <validator name="requiredAdditional" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
+</validators>

src/test/myOther-validators.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE validators PUBLIC
+        "-//OpenSymphony Group//XWork Validator Config 1.0//EN"
+        "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd">
+<validators>
+    <validator name="requiredAnother" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
+</validators>