Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

This is a sample class using Rhino (1.7R4). I need it because in the context of JSON Schema, regexes should be ECMA 262. One requirement is that it is thread safe, and it is.

But I'm not sure I actually use it correctly. Can you comment?

public final class RhinoHelper
{
    /**
     * JavaScript scriptlet defining functions {@link #regexIsValid}
     * and {@link #regMatch}
     */
    private static final String jsAsString
        = "function regexIsValid(re)"
        + '{'
        + "    try {"
        + "         new RegExp(re);"
        + "         return true;"
        + "    } catch (e) {"
        + "        return false;"
        + "    }"
        + '}'
        + ""
        + "function regMatch(re, input)"
        + '{'
        + "    return new RegExp(re).test(input);"
        + '}';

    /**
     * Script context to use
     */
    private static final Context ctx;

    /**
     * Script scope
     */
    private static final Scriptable sharedScope;

    /**
     * Reference to Javascript function for regex validation
     */
    private static final Function regexIsValid;

    /**
     * Reference to Javascript function for regex matching
     */
    private static final Function regMatch;

    private RhinoHelper()
    {
    }

    static {
        ctx = Context.enter();
        sharedScope = ctx.initStandardObjects();
        ctx.evaluateString(sharedScope, jsAsString, "re", 1, null);
        regexIsValid = (Function) sharedScope.get("regexIsValid", sharedScope);
        regMatch = (Function) sharedScope.get("regMatch", sharedScope);
        ctx.seal(null);
    }

    /**
     * Validate that a regex is correct
     *
     * @param regex the regex to validate
     * @return true if the regex is valid
     */
    public static boolean regexIsValid(final String regex)
    {
        final Context context = Context.enter();
        try {
            final Scriptable scope = context.newObject(sharedScope);
            scope.setPrototype(sharedScope);
            scope.setParentScope(null);
            return (Boolean) regexIsValid.call(context, scope, scope,
                new Object[]{ regex });
        } finally {
            Context.exit();
        }
    }

    /**
     * <p>Matches an input against a given regex, in the <b>real</b> sense
     * of matching, that is, the regex can match anywhere in the input. Java's
     * {@link java.util.regex} makes the unfortunate mistake to make people
     * believe that matching is done on the whole input... Which is not true.
     * </p>
     *
     * <p>Also note that the regex MUST have been validated at this point
     * (using {@link #regexIsValid(String)}).</p>
     *
     * @param regex the regex to use
     * @param input the input to match against (and again, see description)
     * @return true if the regex matches the input
     */
    public static boolean regMatch(final String regex, final String input)
    {
        final Context context = Context.enter();
        try {
            final Scriptable scope = context.newObject(sharedScope);
            scope.setPrototype(sharedScope);
            scope.setParentScope(null);
            return (Boolean) regMatch.call(context, scope, scope,
                new Object[]{ regex, input });
        } finally {
            Context.exit();
        }

    }
}
share|improve this question

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.