/* * Copyright 2014 Attila Szegedi, Daniel Dekany, Jonathan Revusky * * Licensed 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 freemarker.ext.jsp; import java.util.Iterator; import java.util.LinkedList; import javax.el.ArrayELResolver; import javax.el.BeanELResolver; import javax.el.CompositeELResolver; import javax.el.ELContext; import javax.el.ELContextEvent; import javax.el.ELContextListener; import javax.el.ELResolver; import javax.el.ExpressionFactory; import javax.el.FunctionMapper; import javax.el.ListELResolver; import javax.el.MapELResolver; import javax.el.ResourceBundleELResolver; import javax.el.ValueExpression; import javax.el.VariableMapper; import javax.servlet.jsp.JspApplicationContext; import javax.servlet.jsp.el.ImplicitObjectELResolver; import javax.servlet.jsp.el.ScopedAttributeELResolver; import freemarker.log.Logger; import freemarker.template.utility.ClassUtil; /** */ class FreeMarkerJspApplicationContext implements JspApplicationContext { private static final Logger LOG = Logger.getLogger("freemarker.jsp"); private static final ExpressionFactory expressionFactoryImpl = findExpressionFactoryImplementation(); private final LinkedList listeners = new LinkedList(); private final CompositeELResolver elResolver = new CompositeELResolver(); private final CompositeELResolver additionalResolvers = new CompositeELResolver(); { elResolver.add(new ImplicitObjectELResolver()); elResolver.add(additionalResolvers); elResolver.add(new MapELResolver()); elResolver.add(new ResourceBundleELResolver()); elResolver.add(new ListELResolver()); elResolver.add(new ArrayELResolver()); elResolver.add(new BeanELResolver()); elResolver.add(new ScopedAttributeELResolver()); } public void addELContextListener(ELContextListener listener) { synchronized (listeners) { listeners.addLast(listener); } } private static ExpressionFactory findExpressionFactoryImplementation() { ExpressionFactory ef = tryExpressionFactoryImplementation("com.sun"); if (ef == null) { ef = tryExpressionFactoryImplementation("org.apache"); if (ef == null) { LOG.warn("Could not find any implementation for " + ExpressionFactory.class.getName()); } } return ef; } private static ExpressionFactory tryExpressionFactoryImplementation(String packagePrefix) { String className = packagePrefix + ".el.ExpressionFactoryImpl"; try { Class cl = ClassUtil.forName(className); if (ExpressionFactory.class.isAssignableFrom(cl)) { LOG.info("Using " + className + " as implementation of " + ExpressionFactory.class.getName()); return (ExpressionFactory) cl.newInstance(); } LOG.warn("Class " + className + " does not implement " + ExpressionFactory.class.getName()); } catch (ClassNotFoundException e) { } catch (Exception e) { LOG.error("Failed to instantiate " + className, e); } return null; } public void addELResolver(ELResolver resolver) { additionalResolvers.add(resolver); } public ExpressionFactory getExpressionFactory() { return expressionFactoryImpl; } ELContext createNewELContext(final FreeMarkerPageContext pageCtx) { ELContext ctx = new FreeMarkerELContext(pageCtx); ELContextEvent event = new ELContextEvent(ctx); synchronized (listeners) { for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { ELContextListener l = (ELContextListener) iter.next(); l.contextCreated(event); } } return ctx; } private class FreeMarkerELContext extends ELContext { private final FreeMarkerPageContext pageCtx; FreeMarkerELContext(FreeMarkerPageContext pageCtx) { this.pageCtx = pageCtx; } @Override public ELResolver getELResolver() { return elResolver; } @Override public FunctionMapper getFunctionMapper() { return null; } @Override public VariableMapper getVariableMapper() { return new VariableMapper() { @Override public ValueExpression resolveVariable(String name) { Object obj = pageCtx.findAttribute(name); if (obj == null) { return null; } return expressionFactoryImpl.createValueExpression(obj, obj.getClass()); } @Override public ValueExpression setVariable(String name, ValueExpression value) { ValueExpression prev = resolveVariable(name); pageCtx.setAttribute(name, value.getValue( FreeMarkerELContext.this)); return prev; } }; } } }