001    /*******************************************************************************
002     * Portions created by Sebastian Thomschke are copyright (c) 2005-2013 Sebastian
003     * Thomschke.
004     *
005     * All Rights Reserved. This program and the accompanying materials
006     * are made available under the terms of the Eclipse Public License v1.0
007     * which accompanies this distribution, and is available at
008     * http://www.eclipse.org/legal/epl-v10.html
009     *
010     * Contributors:
011     *     Sebastian Thomschke - initial implementation.
012     *******************************************************************************/
013    package net.sf.oval.expression;
014    
015    import java.util.Map;
016    
017    import net.sf.oval.Validator;
018    import net.sf.oval.exception.ExpressionLanguageNotAvailableException;
019    import net.sf.oval.internal.Log;
020    import net.sf.oval.internal.util.Assert;
021    import net.sf.oval.internal.util.ReflectionUtils;
022    
023    /**
024     * @author Sebastian Thomschke
025     */
026    public class ExpressionLanguageRegistry
027    {
028            private static final Log LOG = Log.getLog(ExpressionLanguageRegistry.class);
029    
030            private final Map<String, ExpressionLanguage> elcache = Validator.getCollectionFactory().createMap(4);
031    
032            private ExpressionLanguage _initializeDefaultEL(final String languageId)
033            {
034                    // JavaScript support
035                    if (("javascript".equals(languageId) || "js".equals(languageId))
036                                    && ReflectionUtils.isClassPresent("org.mozilla.javascript.Context"))
037                            return registerExpressionLanguage("js", registerExpressionLanguage("javascript", new ExpressionLanguageJavaScriptImpl()));
038    
039                    // Groovy support
040                    if ("groovy".equals(languageId) && ReflectionUtils.isClassPresent("groovy.lang.Binding"))
041                            return registerExpressionLanguage("groovy", new ExpressionLanguageGroovyImpl());
042    
043                    // BeanShell support
044                    if (("beanshell".equals(languageId) || "bsh".equals(languageId)) && ReflectionUtils.isClassPresent("bsh.Interpreter"))
045                            return registerExpressionLanguage("beanshell", registerExpressionLanguage("bsh", new ExpressionLanguageBeanShellImpl()));
046    
047                    // OGNL support
048                    if ("ognl".equals(languageId) && ReflectionUtils.isClassPresent("ognl.Ognl"))
049                            return registerExpressionLanguage("ognl", new ExpressionLanguageOGNLImpl());
050    
051                    // MVEL2 support
052                    if ("mvel".equals(languageId) && ReflectionUtils.isClassPresent("org.mvel2.MVEL"))
053                            return registerExpressionLanguage("mvel", new ExpressionLanguageMVELImpl());
054    
055                    // JRuby support
056                    else if (("jruby".equals(languageId) || "ruby".equals(languageId)) && ReflectionUtils.isClassPresent("org.jruby.Ruby"))
057                            return registerExpressionLanguage("jruby", registerExpressionLanguage("ruby", new ExpressionLanguageJRubyImpl()));
058    
059                    // JEXL2 support
060                    if ("jexl".equals(languageId) && ReflectionUtils.isClassPresent("org.apache.commons.jexl2.JexlEngine"))
061                            return registerExpressionLanguage("jexl", new ExpressionLanguageJEXLImpl());
062    
063                    // scripting support via JSR223
064                    if (ReflectionUtils.isClassPresent("javax.script.ScriptEngineManager"))
065                    {
066                            final ExpressionLanguage el = ExpressionLanguageScriptEngineImpl.get(languageId);
067                            if (el != null) return registerExpressionLanguage(languageId, el);
068                    }
069    
070                    return null;
071            }
072    
073            /**
074             *
075             * @param languageId the id of the language, cannot be null
076             *
077             * @throws IllegalArgumentException if <code>languageName == null</code>
078             * @throws ExpressionLanguageNotAvailableException
079             */
080            public ExpressionLanguage getExpressionLanguage(final String languageId) throws IllegalArgumentException,
081                            ExpressionLanguageNotAvailableException
082            {
083                    Assert.argumentNotNull("languageId", languageId);
084    
085                    ExpressionLanguage el = elcache.get(languageId);
086    
087                    if (el == null) el = _initializeDefaultEL(languageId);
088    
089                    if (el == null) throw new ExpressionLanguageNotAvailableException(languageId);
090    
091                    return el;
092            }
093    
094            /**
095             *
096             * @param languageId the expression language identifier
097             * @param impl the expression language implementation
098             * @throws IllegalArgumentException if <code>languageId == null || expressionLanguage == null</code>
099             */
100            public ExpressionLanguage registerExpressionLanguage(final String languageId, final ExpressionLanguage impl)
101                            throws IllegalArgumentException
102            {
103                    Assert.argumentNotNull("languageId", languageId);
104                    Assert.argumentNotNull("impl", impl);
105    
106                    LOG.info("Expression language '{1}' registered: {2}", languageId, impl);
107                    elcache.put(languageId, impl);
108                    return impl;
109            }
110    }