Author: rdonkin
Date: Wed Apr 16 13:19:59 2008
New Revision: 648831

URL: http://svn.apache.org/viewvc?rev=648831&view=rev
Log:
Addressed JSIEVE-8 (https://issues.apache.org/jira/browse/JSIEVE-8). I think 
that the raiser of the issue is right that throwing an exception during parsing 
is more specification compliant. If anyone disagrees with this reading please 
jump in.

Added:
    
james/jsieve/trunk/src/main/java/org/apache/jsieve/SieveValidationVisitor.java
    
james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/RequireMissingTest.java
Modified:
    james/jsieve/trunk/src/main/java/org/apache/jsieve/Command.java
    james/jsieve/trunk/src/main/java/org/apache/jsieve/SieveFactory.java
    james/jsieve/trunk/src/main/java/org/apache/jsieve/Test.java
    james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/RequireTest.java
    
james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/utils/JUnitUtils.java

Modified: james/jsieve/trunk/src/main/java/org/apache/jsieve/Command.java
URL: 
http://svn.apache.org/viewvc/james/jsieve/trunk/src/main/java/org/apache/jsieve/Command.java?rev=648831&r1=648830&r2=648831&view=diff
==============================================================================
--- james/jsieve/trunk/src/main/java/org/apache/jsieve/Command.java (original)
+++ james/jsieve/trunk/src/main/java/org/apache/jsieve/Command.java Wed Apr 16 
13:19:59 2008
@@ -20,6 +20,7 @@
 package org.apache.jsieve;
 
 import org.apache.commons.logging.Log;
+import org.apache.jsieve.exception.LookupException;
 import org.apache.jsieve.exception.SieveException;
 import org.apache.jsieve.mail.MailAdapter;
 
@@ -31,30 +32,24 @@
  * <code>command = identifier arguments ( ";" / block )</code>
  */
 public class Command implements Executable {
+
     /**
-     * @see org.apache.jsieve.Executable#execute(MailAdapter)
+     * Looks up an executable command with the given name.
+     * @param name not null
+     * @return <code>ExecutableCommand</code>, not null
+     * @throws LookupException if the command is not available
      */
-    public Object execute(MailAdapter mail) throws SieveException {
-        Log log = Logger.getLog();
-        if (log.isDebugEnabled()) {
-            log.debug(toString());
-            coordinate.debugDiagnostics(log);
-        }
-        // commands are executed after the parsing phase
-        // recursively from the top level block
-        // so need to use the coordinate recorded from the parse
-        context.setCoordinate(coordinate);
-        return CommandManager.getInstance().newInstance(getName()).execute(
-                mail, getArguments(), getBlock(), context);
+    public static ExecutableCommand lookup(final String name) throws 
LookupException {
+        return CommandManager.getInstance().newInstance(name);
     }
-
-    // The name of this Command
+    
+    /** The name of this Command */
     private String fieldName;
 
-    // The Arguments for this Command
+    /** The Arguments for this Command */
     private Arguments fieldArguments;
 
-    // The Block for this Command
+    /** The Block for this Command */
     private Block fieldBlock;
 
     private SieveContext context;
@@ -158,5 +153,28 @@
     protected void setBlock(Block block) {
         fieldBlock = block;
     }
+    
+    /**
+     * @see org.apache.jsieve.Executable#execute(MailAdapter)
+     */
+    public Object execute(MailAdapter mail) throws SieveException {
+        Log log = Logger.getLog();
+        if (log.isDebugEnabled()) {
+            log.debug(toString());
+            coordinate.debugDiagnostics(log);
+        }
+        // commands are executed after the parsing phase
+        // recursively from the top level block
+        // so need to use the coordinate recorded from the parse
+        context.setCoordinate(coordinate);
+        final ExecutableCommand executable = getExecutable();
+        final Object result = executable.execute(
+                        mail, getArguments(), getBlock(), context);
+        return result;
+    }
 
+    private ExecutableCommand getExecutable() throws LookupException {
+        final String name = getName();
+        return lookup(name);
+    }
 }

Modified: james/jsieve/trunk/src/main/java/org/apache/jsieve/SieveFactory.java
URL: 
http://svn.apache.org/viewvc/james/jsieve/trunk/src/main/java/org/apache/jsieve/SieveFactory.java?rev=648831&r1=648830&r2=648831&view=diff
==============================================================================
--- james/jsieve/trunk/src/main/java/org/apache/jsieve/SieveFactory.java 
(original)
+++ james/jsieve/trunk/src/main/java/org/apache/jsieve/SieveFactory.java Wed 
Apr 16 13:19:59 2008
@@ -30,6 +30,7 @@
 import org.apache.jsieve.parser.generated.ParseException;
 import org.apache.jsieve.parser.generated.SieveParser;
 import org.apache.jsieve.parser.generated.SieveParserVisitor;
+import org.apache.jsieve.parser.generated.SimpleNode;
 
 /**
  * <p>
@@ -83,7 +84,10 @@
      */
     public Node parse(InputStream inputStream) throws ParseException {
         try {
-            return new SieveParser(inputStream, "UTF-8").start();
+            final SimpleNode node = new SieveParser(inputStream, 
"UTF-8").start();
+            SieveValidationVisitor visitor = new SieveValidationVisitor();
+            node.jjtAccept(visitor, null);
+            return node;
         } catch (ParseException ex) {
             Log log = Logger.getLog();
             if (log.isErrorEnabled())
@@ -91,6 +95,13 @@
             if (log.isDebugEnabled())
                 log.debug("Parse failed.", ex);
             throw ex;
+        } catch (SieveException ex) {
+            Log log = Logger.getLog();
+            if (log.isErrorEnabled())
+                log.error("Parse failed. Reason: " + ex.getMessage());
+            if (log.isDebugEnabled())
+                log.debug("Parse failed.", ex);
+            throw new ParseException(ex);
         }
     }
 

Added: 
james/jsieve/trunk/src/main/java/org/apache/jsieve/SieveValidationVisitor.java
URL: 
http://svn.apache.org/viewvc/james/jsieve/trunk/src/main/java/org/apache/jsieve/SieveValidationVisitor.java?rev=648831&view=auto
==============================================================================
--- 
james/jsieve/trunk/src/main/java/org/apache/jsieve/SieveValidationVisitor.java 
(added)
+++ 
james/jsieve/trunk/src/main/java/org/apache/jsieve/SieveValidationVisitor.java 
Wed Apr 16 13:19:59 2008
@@ -0,0 +1,107 @@
+package org.apache.jsieve;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jsieve.exception.LookupException;
+import org.apache.jsieve.exception.SieveException;
+import org.apache.jsieve.parser.generated.ASTargument;
+import org.apache.jsieve.parser.generated.ASTarguments;
+import org.apache.jsieve.parser.generated.ASTblock;
+import org.apache.jsieve.parser.generated.ASTcommand;
+import org.apache.jsieve.parser.generated.ASTcommands;
+import org.apache.jsieve.parser.generated.ASTstart;
+import org.apache.jsieve.parser.generated.ASTstring;
+import org.apache.jsieve.parser.generated.ASTstring_list;
+import org.apache.jsieve.parser.generated.ASTtest;
+import org.apache.jsieve.parser.generated.ASTtest_list;
+import org.apache.jsieve.parser.generated.SieveParserVisitor;
+import org.apache.jsieve.parser.generated.SimpleNode;
+
+/**
+ * Validates nodes visited.
+ * Some checks are more conveniently carried out what then 
+ * tree has already been constructed.
+ */
+public class SieveValidationVisitor implements SieveParserVisitor {
+    
+    private boolean requireAllowed = true;
+    private boolean isInRequire = false;
+
+    public Object visit(SimpleNode node, Object data) throws SieveException {
+        return visitNode(node, data);
+    }
+
+    private Object visitNode(SimpleNode node, Object data) throws 
SieveException {
+        List children = new ArrayList(node.jjtGetNumChildren());
+        node.childrenAccept(this, children);
+        return data;
+    }
+
+    public Object visit(ASTstart node, Object data) throws SieveException {
+        return visitNode(node, data);
+    }
+
+    public Object visit(ASTcommands node, Object data) throws SieveException {
+        return visitNode(node, data);
+    }
+
+    public Object visit(ASTcommand node, Object data) throws SieveException {
+        final String name = node.getName();
+        Command.lookup(name);
+        if ("require".equalsIgnoreCase(name)) {
+            if (requireAllowed) {
+                isInRequire = true;
+            } else {
+                throw new SieveException("'require' is only allowed before 
other commands");
+            }
+        } else {
+            requireAllowed = false;
+            isInRequire = false;
+        }
+        return visitNode(node, data);
+    }
+
+    public Object visit(ASTblock node, Object data) throws SieveException {
+        return visitNode(node, data);
+    }
+
+    public Object visit(ASTarguments node, Object data) throws SieveException {
+
+        return visitNode(node, data);
+    }
+
+    public Object visit(ASTargument node, Object data) throws SieveException {
+        return visitNode(node, data);
+    }
+
+    public Object visit(ASTtest node, Object data) throws SieveException {
+        return visitNode(node, data);
+    }
+
+    public Object visit(ASTtest_list node, Object data) throws SieveException {
+        return visitNode(node, data);
+    }
+
+    public Object visit(ASTstring node, Object data) throws SieveException {
+        if (isInRequire) {
+            final Object value = node.getValue();
+            if (value != null && value instanceof String) {
+                final String quotedName = (String) value;
+                final String name = quotedName.substring(1, 
quotedName.length()-1);
+                try {
+                    Command.lookup(name);
+                } catch (LookupException e) {
+                    //TODO: catching is inefficient, should just check
+                    Test.lookup(name);
+                }
+            }
+        }
+        return visitNode(node, data);
+    }
+
+    public Object visit(ASTstring_list node, Object data) throws 
SieveException {
+        return visitNode(node, data);
+    }
+
+}

Modified: james/jsieve/trunk/src/main/java/org/apache/jsieve/Test.java
URL: 
http://svn.apache.org/viewvc/james/jsieve/trunk/src/main/java/org/apache/jsieve/Test.java?rev=648831&r1=648830&r2=648831&view=diff
==============================================================================
--- james/jsieve/trunk/src/main/java/org/apache/jsieve/Test.java (original)
+++ james/jsieve/trunk/src/main/java/org/apache/jsieve/Test.java Wed Apr 16 
13:19:59 2008
@@ -21,8 +21,10 @@
 
 import org.apache.commons.logging.Log;
 
+import org.apache.jsieve.exception.LookupException;
 import org.apache.jsieve.exception.SieveException;
 import org.apache.jsieve.mail.*;
+import org.apache.jsieve.tests.ExecutableTest;
 
 /**
  * <p>
@@ -32,12 +34,17 @@
  * <code>test = identifier arguments</code>
  */
 public class Test implements Executable {
+    
+    public static ExecutableTest lookup(final String name) throws 
LookupException {
+        return TestManager.getInstance().newInstance(name);
+    }
+    
     private SieveContext context;
 
-    // The name of this Test
+    /** The name of this Test */
     private String fieldName;
 
-    // The arguments for this Test
+    /** The arguments for this Test */
     private Arguments fieldArguments;
 
     /**
@@ -48,8 +55,10 @@
         if (log.isDebugEnabled()) {
             log.debug(toString());
         }
-        return new Boolean(TestManager.getInstance().newInstance(getName())
-                .execute(mail, getArguments(), context));
+        final String name = getName();
+        final ExecutableTest test = lookup(name);
+        final boolean result = test.execute(mail, getArguments(), context);
+        return new Boolean(result);
     }
 
     /**

Added: 
james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/RequireMissingTest.java
URL: 
http://svn.apache.org/viewvc/james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/RequireMissingTest.java?rev=648831&view=auto
==============================================================================
--- 
james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/RequireMissingTest.java
 (added)
+++ 
james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/RequireMissingTest.java
 Wed Apr 16 13:19:59 2008
@@ -0,0 +1,116 @@
+/****************************************************************
+ * 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.apache.jsieve.junit;
+
+import junit.framework.TestCase;
+
+import org.apache.jsieve.CommandManager;
+import org.apache.jsieve.TestManager;
+import org.apache.jsieve.junit.utils.JUnitUtils;
+import org.apache.jsieve.parser.generated.ParseException;
+
+/**
+ * Class AddressTest
+ */
+public class RequireMissingTest extends TestCase {
+
+
+    /**
+     * @see TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        super.setUp();
+        CommandManager.resetInstance();
+        TestManager.resetInstance();
+    }
+
+    /**
+     * @see TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+    
+    /**
+     * Tests that unsupported requires are caught before script execution. 
+     */
+    public void testUnsupportedRequireNoBrackets() throws Exception {
+        String script = "require \"whatever\"; if address :contains [\"To\", 
\"From\"] \"Fish!\"{ fileinto \"aFolder\"; }";
+        try {
+            JUnitUtils.parse(script);
+            fail("Expect exception to be throw during parse since command is 
unsupported");
+        } catch (ParseException e) {
+//          expected
+        }
+    }
+    
+    /**
+     * Tests that unsupported requires are caught before script execution. 
+     */
+    public void testUnsupportedRequireMultiple() throws Exception {
+        String script = "require [\"fileinto\",\"whatever\"]; if address 
:contains [\"To\", \"From\"] \"Fish!\"{ fileinto \"aFolder\"; }";
+        try {
+            JUnitUtils.parse(script);
+            fail("Expect exception to be throw during parse since command is 
unsupported");
+        } catch (ParseException e) {
+//          expected
+        }
+    }
+    
+    /**
+     * Tests that unsupported requires are caught before script execution. 
+     */
+    public void testUnsupportedRequire() throws Exception {
+        String script = "require [\"whatever\"]; if address :contains [\"To\", 
\"From\"] \"Fish!\"{ fileinto \"aFolder\"; }";
+        try {
+            JUnitUtils.parse(script);
+            fail("Expect exception to be throw during parse since command is 
unsupported");
+        } catch (ParseException e) {
+//          expected
+        }
+    }
+
+    /**
+     * Tests 2.10.5 Extensions and Optional Features: If an extension is not 
enabled with "required" 
+     * they must treat it as if they do not support it at all. 
+     */
+    public void testMissingRequire() throws Exception {
+        String script = "if address :contains [\"To\", \"From\"] \"Fish!\"{ 
bogus \"aFolder\"; }";
+        try {
+            JUnitUtils.parse(script);
+            fail("Expect exception to be throw during parse since command is 
missing");
+        } catch (ParseException e) {
+//          expected
+        }
+    }
+
+    /**
+     * Tests 3.2 Control Structure Require: Require MUST NOT be used after any 
other command.
+     */
+    public void testRequireAfterOtherCommand() throws Exception {
+        String script = "if address :contains [\"To\", \"From\"] \"Fish!\"{ 
fileinto \"aFolder\"; } require [\"whatever\"]; ";
+        try {
+            JUnitUtils.parse(script);
+            fail("Expect exception to be throw during parse");
+        } catch (ParseException e) {
+            //expected
+        }
+    }
+}

Modified: 
james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/RequireTest.java
URL: 
http://svn.apache.org/viewvc/james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/RequireTest.java?rev=648831&r1=648830&r2=648831&view=diff
==============================================================================
--- james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/RequireTest.java 
(original)
+++ james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/RequireTest.java 
Wed Apr 16 13:19:59 2008
@@ -83,64 +83,38 @@
     /**
      * Test for Command 'require' with a single test that is present
      */
-    public void testSingleTestSatisfied() {
-        boolean isTestPassed = false;
+    public void testSingleTestSatisfied() throws Exception {
         String script = "require \"true\";";
-
-        try {
-            JUnitUtils.interpret(JUnitUtils.createMail(), script);
-            isTestPassed = true;
-        } catch (ParseException e) {
-        } catch (SieveException e) {
-        }
-        assertTrue(isTestPassed);
+        JUnitUtils.interpret(JUnitUtils.createMail(), script);
     }
 
     /**
      * Test for Command 'require' with multiple commands that are present
      */
-    public void testMultipleCommandSatisfied() {
-        boolean isTestPassed = false;
+    public void testMultipleCommandSatisfied()  throws Exception {
         String script = "require [\"if\", \"elsif\", \"else\"];";
-
-        try {
-            JUnitUtils.interpret(JUnitUtils.createMail(), script);
-            isTestPassed = true;
-        } catch (ParseException e) {
-        } catch (SieveException e) {
-        }
-        assertTrue(isTestPassed);
+        JUnitUtils.interpret(JUnitUtils.createMail(), script);
     }
 
     /**
      * Test for Command 'require' with multiple tests that are present
      */
-    public void testMultipleTestSatisfied() {
-        boolean isTestPassed = false;
+    public void testMultipleTestSatisfied() throws Exception {
         String script = "require [\"true\", \"false\", \"not\"];";
-
-        try {
-            JUnitUtils.interpret(JUnitUtils.createMail(), script);
-            isTestPassed = true;
-        } catch (ParseException e) {
-        } catch (SieveException e) {
-        }
-        assertTrue(isTestPassed);
+        JUnitUtils.interpret(JUnitUtils.createMail(), script);
     }
 
     /**
      * Test for Command 'require' with a single command that is absent
      */
-    public void testSingleCommandUnsatisfied() {
+    public void testSingleCommandUnsatisfied() throws Exception {
         boolean isTestPassed = false;
         String script = "require \"absent\";";
 
         try {
             JUnitUtils.interpret(JUnitUtils.createMail(), script);
-        } catch (FeatureException e) {
-            isTestPassed = true;
         } catch (ParseException e) {
-        } catch (SieveException e) {
+            isTestPassed = true;
         }
         assertTrue(isTestPassed);
     }
@@ -148,16 +122,14 @@
     /**
      * Test for Command 'require' with a single test that is absent
      */
-    public void testSingleTestUnsatisfied() {
+    public void testSingleTestUnsatisfied() throws Exception {
         boolean isTestPassed = false;
         String script = "require \"absent\";";
 
         try {
             JUnitUtils.interpret(JUnitUtils.createMail(), script);
-        } catch (FeatureException e) {
-            isTestPassed = true;
         } catch (ParseException e) {
-        } catch (SieveException e) {
+            isTestPassed = true;
         }
         assertTrue(isTestPassed);
     }
@@ -165,7 +137,7 @@
     /**
      * Test for Command 'require' for missing argument
      */
-    public void testMissingArgument() {
+    public void testMissingArgument() throws Exception {
         boolean isTestPassed = false;
         String script = "require;";
 
@@ -173,16 +145,14 @@
             JUnitUtils.interpret(JUnitUtils.createMail(), script);
         } catch (SyntaxException e) {
             isTestPassed = true;
-        } catch (ParseException e) {
-        } catch (SieveException e) {
-        }
+        } 
         assertTrue(isTestPassed);
     }
 
     /**
      * Test for Command 'require' for extra argument
      */
-    public void testExtraArgument() {
+    public void testExtraArgument() throws Exception {
         boolean isTestPassed = false;
         String script = "require \"if\" 1;";
 
@@ -190,8 +160,6 @@
             JUnitUtils.interpret(JUnitUtils.createMail(), script);
         } catch (SyntaxException e) {
             isTestPassed = true;
-        } catch (ParseException e) {
-        } catch (SieveException e) {
         }
         assertTrue(isTestPassed);
     }
@@ -199,7 +167,7 @@
     /**
      * Test for Command 'require' rejecting Blocks
      */
-    public void testRejectBlock() {
+    public void testRejectBlock()  throws Exception {
         boolean isTestPassed = false;
         String script = "require \"if\" {stop;}";
 
@@ -207,25 +175,21 @@
             JUnitUtils.interpret(JUnitUtils.createMail(), script);
         } catch (SyntaxException e) {
             isTestPassed = true;
-        } catch (ParseException e) {
-        } catch (SieveException e) {
-        }
+        } 
         assertTrue(isTestPassed);
     }
 
     /**
      * Test for Command 'require' after a Command
      */
-    public void testInterveningCommand() {
+    public void testInterveningCommand() throws Exception {
         boolean isTestPassed = false;
         String script = "fileinto \"someplace\"; require \"fileinto\";";
 
         try {
             JUnitUtils.interpret(JUnitUtils.createMail(), script);
-        } catch (CommandException e) {
-            isTestPassed = true;
         } catch (ParseException e) {
-        } catch (SieveException e) {
+            isTestPassed = true;
         }
         assertTrue(isTestPassed);
     }
@@ -233,7 +197,7 @@
     /**
      * Test for Command 'require' rejecting invalid arguments
      */
-    public void testRejectInvalidArgument() {
+    public void testRejectInvalidArgument() throws Exception {
         boolean isTestPassed = false;
         String script = "require 1 ;";
 
@@ -241,8 +205,6 @@
             JUnitUtils.interpret(JUnitUtils.createMail(), script);
         } catch (SyntaxException e) {
             isTestPassed = true;
-        } catch (ParseException e) {
-        } catch (SieveException e) {
         }
         assertTrue(isTestPassed);
     }
@@ -251,16 +213,14 @@
      * Test for Command 'require' with a multiple commands of which one is
      * absent
      */
-    public void testMultipleCommandsUnsatisfied() {
+    public void testMultipleCommandsUnsatisfied()  throws Exception {
         boolean isTestPassed = false;
         String script = "require [\"if\", \"elsif\", \"absent\"];";
 
         try {
             JUnitUtils.interpret(JUnitUtils.createMail(), script);
-        } catch (FeatureException e) {
-            isTestPassed = true;
         } catch (ParseException e) {
-        } catch (SieveException e) {
+            isTestPassed = true;
         }
         assertTrue(isTestPassed);
     }
@@ -268,17 +228,15 @@
     /**
      * Test for Command 'require' with a multiple tests of which one is absent
      */
-    public void testMultipleTestsUnsatisfied() {
+    public void testMultipleTestsUnsatisfied()  throws Exception {
         boolean isTestPassed = false;
         String script = "require [\"true\", \"false\", \"absent\"];";
 
         try {
             JUnitUtils.interpret(JUnitUtils.createMail(), script);
-        } catch (FeatureException e) {
-            isTestPassed = true;
         } catch (ParseException e) {
-        } catch (SieveException e) {
-        }
+            isTestPassed = true;
+        } 
         assertTrue(isTestPassed);
     }
 

Modified: 
james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/utils/JUnitUtils.java
URL: 
http://svn.apache.org/viewvc/james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/utils/JUnitUtils.java?rev=648831&r1=648830&r2=648831&view=diff
==============================================================================
--- 
james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/utils/JUnitUtils.java 
(original)
+++ 
james/jsieve/trunk/src/test/java/org/apache/jsieve/junit/utils/JUnitUtils.java 
Wed Apr 16 13:19:59 2008
@@ -50,6 +50,20 @@
             mail,
             new ByteArrayInputStream(script.getBytes()));
     }
+        
+    /**
+     * Method interpret parses a script and evaluates it against a MailAdapter.
+     * @param mail
+     * @param script
+     * @throws SieveException
+     * @throws ParseException
+     */
+    static public void parse(String script)
+        throws SieveException, ParseException
+    {
+        SieveFactory.getInstance().parse(
+            new ByteArrayInputStream(script.getBytes()));
+    }
     
 
     /**



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to