Repository: incubator-freemarker Updated Branches: refs/heads/3 83b4b77ca -> b4dfe5d24
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/model/impl/SimpleSequence.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/SimpleSequence.java b/src/main/java/org/apache/freemarker/core/model/impl/SimpleSequence.java index b16069c..17cd03a 100644 --- a/src/main/java/org/apache/freemarker/core/model/impl/SimpleSequence.java +++ b/src/main/java/org/apache/freemarker/core/model/impl/SimpleSequence.java @@ -26,7 +26,6 @@ import java.util.List; import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.RichObjectWrapper; -import org.apache.freemarker.core.model.TemplateBooleanModel; import org.apache.freemarker.core.model.TemplateCollectionModel; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; @@ -77,70 +76,17 @@ import org.apache.freemarker.core.model.WrappingTemplateModel; public class SimpleSequence extends WrappingTemplateModel implements TemplateSequenceModel, Serializable { /** - * The {@link List} that stored the elements of this sequence. It migth contains both {@link TemplateModel} elements + * The {@link List} that stored the elements of this sequence. It might contains both {@link TemplateModel} elements * and non-{@link TemplateModel} elements. */ protected final List list; - - private List unwrappedList; - - /** - * Constructs an empty simple sequence that will use - * {@link _StaticObjectWrappers#DEFAULT_OBJECT_WRAPPER}. - * - * @deprecated Use {@link #SimpleSequence(ObjectWrapper)} instead. - */ - @Deprecated - public SimpleSequence() { - this((ObjectWrapper) null); - } - - /** - * Constructs an empty simple sequence with preallocated capacity and using - * {@link _StaticObjectWrappers#DEFAULT_OBJECT_WRAPPER}. - * - * @deprecated Use {@link #SimpleSequence(Collection, ObjectWrapper)}. - */ - @Deprecated - public SimpleSequence(int capacity) { - list = new ArrayList(capacity); - } - - /** - * Constructs a simple sequence that will contain the elements - * from the specified {@link Collection} and will use {@link _StaticObjectWrappers#DEFAULT_OBJECT_WRAPPER}. - * @param collection the collection containing initial values. Note that a - * copy of the collection is made for internal use. - * - * @deprecated Use {@link #SimpleSequence(Collection, ObjectWrapper)}. - */ - @Deprecated - public SimpleSequence(Collection collection) { - this(collection, null); - } - - /** - * Constructs a simple sequence from the passed collection model, which shouldn't be added to later. The internal - * list will be build immediately (not lazily). The resulting sequence shouldn't be extended with - * {@link #add(Object)}, because the appropriate {@link ObjectWrapper} won't be available; use - * {@link #SimpleSequence(Collection, ObjectWrapper)} instead, if you need that. - */ - public SimpleSequence(TemplateCollectionModel tcm) throws TemplateModelException { - ArrayList alist = new ArrayList(); - for (TemplateModelIterator it = tcm.iterator(); it.hasNext(); ) { - alist.add(it.next()); - } - alist.trimToSize(); - list = alist; - } /** * Constructs an empty sequence using the specified object wrapper. * * @param wrapper - * The object wrapper to use to wrap the list items into {@link TemplateModel} instances. {@code null} is - * allowed, but deprecated, and will cause the deprecated default object wrapper - * {@link _StaticObjectWrappers#DEFAULT_OBJECT_WRAPPER} to be used. + * The object wrapper to use to wrap the list items into {@link TemplateModel} instances. Not + * {@code null}. */ public SimpleSequence(ObjectWrapper wrapper) { super(wrapper); @@ -187,55 +133,9 @@ public class SimpleSequence extends WrappingTemplateModel implements TemplateSeq */ public void add(Object obj) { list.add(obj); - unwrappedList = null; } /** - * Adds a boolean value to the end of this sequence. The newly added boolean will be immediately converted into - * {@link TemplateBooleanModel#TRUE} or {@link TemplateBooleanModel#FALSE}, without using the {@link ObjectWrapper}. - * - * @param b - * The boolean value to be added. - * - * @deprecated Use {@link #add(Object)} instead, as this bypasses the {@link ObjectWrapper}. - */ - @Deprecated - public void add(boolean b) { - add(b ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE); - } - - /** - * Builds a deep-copy of the underlying list, unwrapping any values that were already converted to - * {@link TemplateModel}-s. When called for the second time (or later), it just reuses the first result, unless the - * sequence was modified since then. - * - * @deprecated No replacement exists; not a reliable way of getting back the original list elemnts. - */ - @Deprecated - public List toList() throws TemplateModelException { - if (unwrappedList == null) { - Class listClass = list.getClass(); - List result = null; - try { - result = (List) listClass.newInstance(); - } catch (Exception e) { - throw new TemplateModelException("Error instantiating an object of type " + listClass.getName(), - e); - } - DefaultObjectWrapper ow = _StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER; - for (int i = 0; i < list.size(); i++) { - Object elem = list.get(i); - if (elem instanceof TemplateModel) { - elem = ow.unwrap((TemplateModel) elem); - } - result.add(elem); - } - unwrappedList = result; - } - return unwrappedList; - } - - /** * Returns the item at the specified index of the list. If the item isn't yet an {@link TemplateModel}, it will wrap * it to one now, and writes it back into the backing list. */ @@ -259,47 +159,9 @@ public class SimpleSequence extends WrappingTemplateModel implements TemplateSeq return list.size(); } - /** - * @return a synchronized wrapper for list. - */ - public SimpleSequence synchronizedWrapper() { - return new SynchronizedSequence(); - } - @Override public String toString() { return list.toString(); } - private class SynchronizedSequence extends SimpleSequence { - - @Override - public void add(Object obj) { - synchronized (SimpleSequence.this) { - SimpleSequence.this.add(obj); - } - } - - @Override - public TemplateModel get(int i) throws TemplateModelException { - synchronized (SimpleSequence.this) { - return SimpleSequence.this.get(i); - } - } - - @Override - public int size() { - synchronized (SimpleSequence.this) { - return SimpleSequence.this.size(); - } - } - - @Override - public List toList() throws TemplateModelException { - synchronized (SimpleSequence.this) { - return SimpleSequence.this.toList(); - } - } - } - } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/core/model/impl/_StaticObjectWrappers.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/_StaticObjectWrappers.java b/src/main/java/org/apache/freemarker/core/model/impl/_StaticObjectWrappers.java deleted file mode 100644 index 3be2da5..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/_StaticObjectWrappers.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.freemarker.core.model.impl; - -import org.apache.freemarker.core.Configuration; - -/** - * For internal use only; don't depend on this, there's no backward compatibility guarantee at all! - */ -// [FM3] This was added temporary until we get to cleaning up the parts that depend on a static ObjectWrapper. The -// ObjectWrapper should always come from the Configuration, not from the statics here. -public final class _StaticObjectWrappers { - - private _StaticObjectWrappers() { - // - } - - public static final DefaultObjectWrapper DEFAULT_OBJECT_WRAPPER - = new DefaultObjectWrapperBuilder(Configuration.VERSION_3_0_0).build(); - - public static final RestrictedObjectWrapper RESTRICTED_OBJECT_WRAPPER - = new RestrictedObjectWrapper(Configuration.VERSION_3_0_0); - { - RESTRICTED_OBJECT_WRAPPER.writeProtect(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java b/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java index 0d4bd78..cd0724a 100644 --- a/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java +++ b/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java @@ -41,7 +41,6 @@ import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; import org.apache.freemarker.core.model.TemplateNumberModel; import org.apache.freemarker.core.model.TemplateScalarModel; -import org.apache.freemarker.core.model.impl._StaticObjectWrappers; import org.apache.freemarker.core.util.UndeclaredThrowableException; import org.jaxen.BaseXPath; import org.jaxen.Function; @@ -92,8 +91,7 @@ class JaxenXPathSupport implements XPathSupport { } List result = xpath.selectNodes(context != null ? context : EMPTY_ARRAYLIST); if (result.size() == 1) { - // [2.4] Use the proper object wrapper (argument in 2.4) - return _StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER.wrap(result.get(0)); + return NodeQueryResultItemObjectWrapper.INSTANCE.wrap(result.get(0)); } NodeListModel nlm = new NodeListModel(result, null); nlm.xpathSupport = this; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/dom/NodeListModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/dom/NodeListModel.java b/src/main/java/org/apache/freemarker/dom/NodeListModel.java index d119339..75b9e13 100644 --- a/src/main/java/org/apache/freemarker/dom/NodeListModel.java +++ b/src/main/java/org/apache/freemarker/dom/NodeListModel.java @@ -25,7 +25,6 @@ import java.util.List; import org.apache.freemarker.core.Configuration; import org.apache.freemarker.core.Environment; import org.apache.freemarker.core._UnexpectedTypeErrorExplainerTemplateModel; -import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.TemplateBooleanModel; import org.apache.freemarker.core.model.TemplateDateModel; import org.apache.freemarker.core.model.TemplateHashModel; @@ -56,27 +55,17 @@ class NodeListModel extends SimpleSequence implements TemplateHashModel, _Unexpe NodeModel contextNode; XPathSupport xpathSupport; - private static ObjectWrapper nodeWrapper = new ObjectWrapper() { - @Override - public TemplateModel wrap(Object obj) { - if (obj instanceof NodeModel) { - return (NodeModel) obj; - } - return NodeModel.wrap((Node) obj); - } - }; - NodeListModel(Node contextNode) { this(NodeModel.wrap(contextNode)); } NodeListModel(NodeModel contextNode) { - super(nodeWrapper); + super(NodeQueryResultItemObjectWrapper.INSTANCE); this.contextNode = contextNode; } NodeListModel(NodeList nodeList, NodeModel contextNode) { - super(nodeWrapper); + super(NodeQueryResultItemObjectWrapper.INSTANCE); for (int i = 0; i < nodeList.getLength(); i++) { list.add(nodeList.item(i)); } @@ -84,7 +73,7 @@ class NodeListModel extends SimpleSequence implements TemplateHashModel, _Unexpe } NodeListModel(NamedNodeMap nodeList, NodeModel contextNode) { - super(nodeWrapper); + super(NodeQueryResultItemObjectWrapper.INSTANCE); for (int i = 0; i < nodeList.getLength(); i++) { list.add(nodeList.item(i)); } @@ -92,7 +81,7 @@ class NodeListModel extends SimpleSequence implements TemplateHashModel, _Unexpe } NodeListModel(List list, NodeModel contextNode) { - super(list, nodeWrapper); + super(list, NodeQueryResultItemObjectWrapper.INSTANCE); this.contextNode = contextNode; } @@ -227,5 +216,5 @@ class NodeListModel extends SimpleSequence implements TemplateHashModel, _Unexpe : "multiple matches." }; } - + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/dom/NodeQueryResultItemObjectWrapper.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/dom/NodeQueryResultItemObjectWrapper.java b/src/main/java/org/apache/freemarker/dom/NodeQueryResultItemObjectWrapper.java new file mode 100644 index 0000000..e84e977 --- /dev/null +++ b/src/main/java/org/apache/freemarker/dom/NodeQueryResultItemObjectWrapper.java @@ -0,0 +1,92 @@ +/* + * 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.freemarker.dom; + +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.model.ObjectWrapper; +import org.apache.freemarker.core.model.TemplateBooleanModel; +import org.apache.freemarker.core.model.TemplateDateModel; +import org.apache.freemarker.core.model.TemplateModel; +import org.apache.freemarker.core.model.TemplateModelAdapter; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.model.WrappingTemplateModel; +import org.apache.freemarker.core.model.impl.SimpleDate; +import org.apache.freemarker.core.model.impl.SimpleNumber; +import org.apache.freemarker.core.model.impl.SimpleScalar; +import org.w3c.dom.Node; + +/** + * Used for wrapping query result items (such as XPath query result items). Because {@link NodeModel} and such aren't + * {@link WrappingTemplateModel}-s, we can't use the actual {@link ObjectWrapper} from the {@link Environment}, also, + * even if we could, it might not be the right thing to do, because that {@link ObjectWrapper} might not even wrap + * {@link Node}-s via {@link NodeModel}. + */ +class NodeQueryResultItemObjectWrapper implements ObjectWrapper { + + static final NodeQueryResultItemObjectWrapper INSTANCE = new NodeQueryResultItemObjectWrapper(); + + private NodeQueryResultItemObjectWrapper() { + // + } + + @Override + public TemplateModel wrap(Object obj) throws TemplateModelException { + if (obj instanceof NodeModel) { + return (NodeModel) obj; + } + if (obj instanceof Node) { + return NodeModel.wrap((Node) obj); + } else { + if (obj == null) { + return null; + } + if (obj instanceof TemplateModel) { + return (TemplateModel) obj; + } + if (obj instanceof TemplateModelAdapter) { + return ((TemplateModelAdapter) obj).getTemplateModel(); + } + + if (obj instanceof String) { + return new SimpleScalar((String) obj); + } + if (obj instanceof Number) { + return new SimpleNumber((Number) obj); + } + if (obj instanceof Boolean) { + return obj.equals(Boolean.TRUE) ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; + } + if (obj instanceof java.util.Date) { + if (obj instanceof java.sql.Date) { + return new SimpleDate((java.sql.Date) obj); + } + if (obj instanceof java.sql.Time) { + return new SimpleDate((java.sql.Time) obj); + } + if (obj instanceof java.sql.Timestamp) { + return new SimpleDate((java.sql.Timestamp) obj); + } + return new SimpleDate((java.util.Date) obj, TemplateDateModel.UNKNOWN); + } + throw new TemplateModelException("Don't know how to wrap a W3C DOM query result item of this type: " + + obj.getClass().getName()); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java b/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java index 9dbc701..95b139e 100644 --- a/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java +++ b/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java @@ -49,11 +49,14 @@ import org.apache.freemarker.core.Template; import org.apache.freemarker.core.TemplateException; import org.apache.freemarker.core.TemplateExceptionHandler; import org.apache.freemarker.core.TemplateNotFoundException; +import org.apache.freemarker.core.Version; import org.apache.freemarker.core._CoreLogs; import org.apache.freemarker.core.model.ObjectWrapper; +import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; -import org.apache.freemarker.core.model.impl._StaticObjectWrappers; +import org.apache.freemarker.core.model.impl.RestrictedObjectWrapper; +import org.apache.freemarker.core.model.impl.SimpleHash; import org.apache.freemarker.core.outputformat.OutputFormat; import org.apache.freemarker.core.outputformat.impl.UndefinedOutputFormat; import org.apache.freemarker.core.templateresolver.TemplateLoader; @@ -521,7 +524,7 @@ public class FreemarkerServlet extends HttpServlet { @SuppressFBWarnings(value="SE_BAD_FIELD", justification="Not investing into making this Servlet serializable") private Configuration config; @SuppressFBWarnings(value="SE_BAD_FIELD", justification="Not investing into making this Servlet serializable") - private ObjectWrapper wrapper; + private ObjectWrapperAndUnwrapper wrapper; private ContentType contentType; private OverrideResponseContentType overrideResponseContentType = initParamValueToEnum( getDefaultOverrideResponseContentType(), OverrideResponseContentType.values()); @@ -1004,7 +1007,7 @@ public class FreemarkerServlet extends HttpServlet { return config.getLocale(); } - protected TemplateModel createModel(ObjectWrapper objectWrapper, + protected TemplateModel createModel(ObjectWrapperAndUnwrapper objectWrapper, ServletContext servletContext, final HttpServletRequest request, final HttpServletResponse response) throws TemplateModelException { @@ -1289,7 +1292,7 @@ public class FreemarkerServlet extends HttpServlet { * @return The {@link ObjectWrapper} that will be used for adapting request, session, and servlet context attributes * to {@link TemplateModel}-s, and also as the object wrapper setting of {@link Configuration}. */ - protected ObjectWrapper createObjectWrapper() { + protected ObjectWrapperAndUnwrapper createObjectWrapper() { String wrapper = getServletConfig().getInitParameter(DEPR_INITPARAM_OBJECT_WRAPPER); if (wrapper != null) { // BC if (getInitParameter(Configurable.OBJECT_WRAPPER_KEY) != null) { @@ -1298,7 +1301,7 @@ public class FreemarkerServlet extends HttpServlet { + DEPR_INITPARAM_OBJECT_WRAPPER); } if (DEPR_INITPARAM_WRAPPER_RESTRICTED.equals(wrapper)) { - return _StaticObjectWrappers.RESTRICTED_OBJECT_WRAPPER; + return new RestrictedObjectWrapper(Configuration.VERSION_3_0_0); } return createDefaultObjectWrapper(); } else { @@ -1307,7 +1310,7 @@ public class FreemarkerServlet extends HttpServlet { if (!config.isObjectWrapperExplicitlySet()) { return createDefaultObjectWrapper(); } else { - return config.getObjectWrapper(); + return asObjectWrapperAndUnwrapper(config.getObjectWrapper()); } } else { try { @@ -1315,11 +1318,20 @@ public class FreemarkerServlet extends HttpServlet { } catch (ConfigurationException e) { throw new RuntimeException("Failed to set " + Configurable.OBJECT_WRAPPER_KEY, e); } - return config.getObjectWrapper(); + return asObjectWrapperAndUnwrapper(config.getObjectWrapper()); } } } + private ObjectWrapperAndUnwrapper asObjectWrapperAndUnwrapper(ObjectWrapper objectWrapper) { + if (!(objectWrapper instanceof ObjectWrapperAndUnwrapper)) { + throw new RuntimeException(FreemarkerServlet.class.getSimpleName() + " requires an ObjectWrapper that " + + "implements " + ObjectWrapperAndUnwrapper.class.getName() + ", but this class doesn't do that: " + + objectWrapper.getClass().getName()); + } + return (ObjectWrapperAndUnwrapper) objectWrapper; + } + /** * Override this to specify what the default {@link ObjectWrapper} will be when the * {@code object_wrapper} Servlet init-param wasn't specified. Note that this is called by @@ -1328,13 +1340,13 @@ public class FreemarkerServlet extends HttpServlet { * won't be called, since then that has already specified the default. * * <p> - * The default implementation calls {@link Configuration#getDefaultObjectWrapper(org.apache.freemarker.core.Version)}. You + * The default implementation calls {@link Configuration#getDefaultObjectWrapper(Version)}. You * should also pass in the version paramter when creating an {@link ObjectWrapper} that supports that. You can get * the version by calling {@link #getConfiguration()} and then {@link Configuration#getIncompatibleImprovements()}. * * @since 2.3.22 */ - protected ObjectWrapper createDefaultObjectWrapper() { + protected ObjectWrapperAndUnwrapper createDefaultObjectWrapper() { return Configuration.getDefaultObjectWrapper(config.getIncompatibleImprovements()); } @@ -1358,7 +1370,7 @@ public class FreemarkerServlet extends HttpServlet { } protected HttpRequestParametersHashModel createRequestParametersHashModel(HttpServletRequest request) { - return new HttpRequestParametersHashModel(request); + return new HttpRequestParametersHashModel(request, getObjectWrapper()); } /** @@ -1407,13 +1419,11 @@ public class FreemarkerServlet extends HttpServlet { * The template that will get executed * @param model * The data model that will be passed to the template. By default this will be an - * {@link AllHttpScopesHashModel} (which is a {@link org.apache.freemarker.core.model.impl.SimpleHash} subclass). Thus, you - * can add new variables to the data-model with the - * {@link org.apache.freemarker.core.model.impl.SimpleHash#put(String, Object)} subclass) method. However, to adjust the - * data-model, overriding - * {@link #createModel(ObjectWrapper, ServletContext, HttpServletRequest, HttpServletResponse)} is - * probably a more appropriate place. - * + * {@link AllHttpScopesHashModel} (which is a {@link SimpleHash} subclass). Thus, you can add new + * variables to the data-model with the {@link SimpleHash#put(String, Object)} subclass) method. However, + * to adjust the data-model, overriding {@link #createModel(ObjectWrapperAndUnwrapper, ServletContext, + * HttpServletRequest, HttpServletResponse)} is probably a more appropriate place. + * * @return true to process the template, false to suppress template processing. */ protected boolean preTemplateProcess( http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/servlet/HttpRequestHashModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/servlet/HttpRequestHashModel.java b/src/main/java/org/apache/freemarker/servlet/HttpRequestHashModel.java index 5124e01..a14bbc2 100644 --- a/src/main/java/org/apache/freemarker/servlet/HttpRequestHashModel.java +++ b/src/main/java/org/apache/freemarker/servlet/HttpRequestHashModel.java @@ -39,21 +39,18 @@ import org.apache.freemarker.core.model.impl.SimpleCollection; public final class HttpRequestHashModel implements TemplateHashModelEx { private final HttpServletRequest request; private final HttpServletResponse response; - private final ObjectWrapper wrapper; + private final ObjectWrapperAndUnwrapper wrapper; /** * @param wrapper * Should be an {@link ObjectWrapperAndUnwrapper}, or else some features might won't work properly. (It's * declared as {@link ObjectWrapper} only for backward compatibility.) */ - public HttpRequestHashModel( - HttpServletRequest request, ObjectWrapper wrapper) { + public HttpRequestHashModel(HttpServletRequest request, ObjectWrapperAndUnwrapper wrapper) { this(request, null, wrapper); } - public HttpRequestHashModel( - HttpServletRequest request, HttpServletResponse response, - ObjectWrapper wrapper) { + public HttpRequestHashModel(HttpServletRequest request, HttpServletResponse response, ObjectWrapperAndUnwrapper wrapper) { this.request = request; this.response = response; this.wrapper = wrapper; @@ -85,7 +82,7 @@ public final class HttpRequestHashModel implements TemplateHashModelEx { for (Enumeration enumeration = request.getAttributeNames(); enumeration.hasMoreElements(); ) { keys.add(enumeration.nextElement()); } - return new SimpleCollection(keys.iterator()); + return new SimpleCollection(keys.iterator(), wrapper); } @Override @@ -105,7 +102,7 @@ public final class HttpRequestHashModel implements TemplateHashModelEx { return response; } - public ObjectWrapper getObjectWrapper() { + public ObjectWrapperAndUnwrapper getObjectWrapper() { return wrapper; } } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/servlet/HttpRequestParametersHashModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/servlet/HttpRequestParametersHashModel.java b/src/main/java/org/apache/freemarker/servlet/HttpRequestParametersHashModel.java index b1aca6f..33e5817 100644 --- a/src/main/java/org/apache/freemarker/servlet/HttpRequestParametersHashModel.java +++ b/src/main/java/org/apache/freemarker/servlet/HttpRequestParametersHashModel.java @@ -26,6 +26,7 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; +import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.TemplateCollectionModel; import org.apache.freemarker.core.model.TemplateHashModelEx; import org.apache.freemarker.core.model.TemplateModel; @@ -36,14 +37,14 @@ import org.apache.freemarker.core.model.impl.SimpleScalar; * TemplateHashModel wrapper for a HttpServletRequest parameters. */ -public class HttpRequestParametersHashModel - implements - TemplateHashModelEx { +public class HttpRequestParametersHashModel implements TemplateHashModelEx { private final HttpServletRequest request; + private final ObjectWrapper objectWrapper; private List keys; - public HttpRequestParametersHashModel(HttpServletRequest request) { + public HttpRequestParametersHashModel(HttpServletRequest request, ObjectWrapper objectWrapper) { this.request = request; + this.objectWrapper = objectWrapper; } @Override @@ -64,7 +65,7 @@ public class HttpRequestParametersHashModel @Override public TemplateCollectionModel keys() { - return new SimpleCollection(getKeys().iterator()); + return new SimpleCollection(getKeys().iterator(), objectWrapper); } @Override @@ -78,13 +79,13 @@ public class HttpRequestParametersHashModel } @Override public Object next() { - return request.getParameter((String) iter.next()); + return request.getParameter((String) iter.next()); } @Override public void remove() { throw new UnsupportedOperationException(); } - }); + }, objectWrapper); } protected String transcode(String string) { http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/servlet/jsp/FreeMarkerPageContext.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/servlet/jsp/FreeMarkerPageContext.java b/src/main/java/org/apache/freemarker/servlet/jsp/FreeMarkerPageContext.java index 2b8b8eb..7d35203 100644 --- a/src/main/java/org/apache/freemarker/servlet/jsp/FreeMarkerPageContext.java +++ b/src/main/java/org/apache/freemarker/servlet/jsp/FreeMarkerPageContext.java @@ -46,18 +46,13 @@ import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.BodyContent; import org.apache.freemarker.core.Environment; -import org.apache.freemarker.core.model.AdapterTemplateModel; import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper; -import org.apache.freemarker.core.model.TemplateBooleanModel; -import org.apache.freemarker.core.model.TemplateDateModel; import org.apache.freemarker.core.model.TemplateHashModelEx; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; import org.apache.freemarker.core.model.TemplateModelIterator; -import org.apache.freemarker.core.model.TemplateNumberModel; import org.apache.freemarker.core.model.TemplateScalarModel; -import org.apache.freemarker.core.model.WrapperTemplateModel; import org.apache.freemarker.core.util.UndeclaredThrowableException; import org.apache.freemarker.servlet.FreemarkerServlet; import org.apache.freemarker.servlet.HttpRequestHashModel; @@ -75,8 +70,7 @@ abstract class FreeMarkerPageContext extends PageContext implements TemplateMode private HttpSession session; private final HttpServletRequest request; private final HttpServletResponse response; - private final ObjectWrapper wrapper; - private final ObjectWrapperAndUnwrapper unwrapper; + private final ObjectWrapperAndUnwrapper wrapper; private JspWriter jspOut; protected FreeMarkerPageContext() throws TemplateModelException { @@ -109,9 +103,8 @@ abstract class FreeMarkerPageContext extends PageContext implements TemplateMode request = reqHash.getRequest(); session = request.getSession(false); response = reqHash.getResponse(); - wrapper = reqHash.getObjectWrapper(); - unwrapper = wrapper instanceof ObjectWrapperAndUnwrapper - ? (ObjectWrapperAndUnwrapper) wrapper : null; + ObjectWrapperAndUnwrapper ow = reqHash.getObjectWrapper(); + wrapper = (ObjectWrapperAndUnwrapper) ow; } else { throw new TemplateModelException("Could not find an instance of " + HttpRequestHashModel.class.getName() + @@ -131,7 +124,7 @@ abstract class FreeMarkerPageContext extends PageContext implements TemplateMode setAttribute(APPLICATION, servlet.getServletContext()); } - ObjectWrapper getObjectWrapper() { + ObjectWrapperAndUnwrapper getObjectWrapper() { return wrapper; } @@ -191,32 +184,9 @@ abstract class FreeMarkerPageContext extends PageContext implements TemplateMode switch (scope) { case PAGE_SCOPE: { try { - final TemplateModel tm = environment.getGlobalNamespace().get(name); - if (unwrapper != null) { - return unwrapper.unwrap(tm); - } else { // [FM3] Such unwrapping logic rather belongs to some core util - if (tm instanceof AdapterTemplateModel) { - return ((AdapterTemplateModel) tm).getAdaptedObject(OBJECT_CLASS); - } - if (tm instanceof WrapperTemplateModel) { - return ((WrapperTemplateModel) tm).getWrappedObject(); - } - if (tm instanceof TemplateScalarModel) { - return ((TemplateScalarModel) tm).getAsString(); - } - if (tm instanceof TemplateNumberModel) { - return ((TemplateNumberModel) tm).getAsNumber(); - } - if (tm instanceof TemplateBooleanModel) { - return Boolean.valueOf(((TemplateBooleanModel) tm).getAsBoolean()); - } - if (tm instanceof TemplateDateModel) { - return ((TemplateDateModel) tm).getAsDate(); - } - return tm; - } + return wrapper.unwrap(environment.getGlobalNamespace().get(name)); } catch (TemplateModelException e) { - throw new UndeclaredThrowableException("Failed to unwrapp FTL global variable", e); + throw new UndeclaredThrowableException("Failed to unwrap FTL global variable", e); } } case REQUEST_SCOPE: { http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/servlet/jsp/JspContextModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/servlet/jsp/JspContextModel.java b/src/main/java/org/apache/freemarker/servlet/jsp/JspContextModel.java deleted file mode 100644 index 1d02be6..0000000 --- a/src/main/java/org/apache/freemarker/servlet/jsp/JspContextModel.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.freemarker.servlet.jsp; - -import javax.servlet.jsp.PageContext; - -import org.apache.freemarker.core.model.TemplateHashModel; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateModelException; -import org.apache.freemarker.core.model.impl._StaticObjectWrappers; - -class JspContextModel -implements - TemplateHashModel { - public static final int ANY_SCOPE = -1; - public static final int PAGE_SCOPE = PageContext.PAGE_SCOPE; - public static final int REQUEST_SCOPE = PageContext.REQUEST_SCOPE; - public static final int SESSION_SCOPE = PageContext.SESSION_SCOPE; - public static final int APPLICATION_SCOPE = PageContext.APPLICATION_SCOPE; - - private final PageContext pageContext; - private final int scope; - - public JspContextModel(PageContext pageContext, int scope) { - this.pageContext = pageContext; - this.scope = scope; - } - - @Override - public TemplateModel get(String key) throws TemplateModelException { - Object bean = scope == ANY_SCOPE ? pageContext.findAttribute(key) : pageContext.getAttribute(key, scope); - return _StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER.wrap(bean); - } - - @Override - public boolean isEmpty() { - return false; - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/main/java/org/apache/freemarker/servlet/jsp/JspTagModelBase.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/servlet/jsp/JspTagModelBase.java b/src/main/java/org/apache/freemarker/servlet/jsp/JspTagModelBase.java index 7f297dd..8c6fd3a 100644 --- a/src/main/java/org/apache/freemarker/servlet/jsp/JspTagModelBase.java +++ b/src/main/java/org/apache/freemarker/servlet/jsp/JspTagModelBase.java @@ -35,11 +35,9 @@ import org.apache.freemarker.core._DelayedJQuote; import org.apache.freemarker.core._DelayedShortClassName; import org.apache.freemarker.core._ErrorDescriptionBuilder; import org.apache.freemarker.core._TemplateModelException; -import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; -import org.apache.freemarker.core.model.impl._StaticObjectWrappers; import org.apache.freemarker.core.model.impl.DefaultObjectWrapper; import org.apache.freemarker.core.util._StringUtil; import org.apache.freemarker.servlet.jsp.SimpleTagDirectiveModel.TemplateExceptionWrapperJspException; @@ -77,18 +75,15 @@ class JspTagModelBase { return tagClass.newInstance(); } - void setupTag(Object tag, Map args, ObjectWrapper wrapper) + void setupTag(Object tag, Map args, ObjectWrapperAndUnwrapper wrapper) throws TemplateModelException, InvocationTargetException, IllegalAccessException { if (args != null && !args.isEmpty()) { - ObjectWrapperAndUnwrapper unwrapper = - wrapper instanceof ObjectWrapperAndUnwrapper ? (ObjectWrapperAndUnwrapper) wrapper - : _StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER; // [2.4] Throw exception in this case final Object[] argArray = new Object[1]; for (Iterator iter = args.entrySet().iterator(); iter.hasNext(); ) { final Map.Entry entry = (Map.Entry) iter.next(); - final Object arg = unwrapper.unwrap((TemplateModel) entry.getValue()); + final Object arg = wrapper.unwrap((TemplateModel) entry.getValue()); argArray[0] = arg; final Object paramName = entry.getKey(); Method setterMethod = (Method) propertySetters.get(paramName); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/manual/en_US/FM3-CHANGE-LOG.txt ---------------------------------------------------------------------- diff --git a/src/manual/en_US/FM3-CHANGE-LOG.txt b/src/manual/en_US/FM3-CHANGE-LOG.txt index bb16fb8..3c66826 100644 --- a/src/manual/en_US/FM3-CHANGE-LOG.txt +++ b/src/manual/en_US/FM3-CHANGE-LOG.txt @@ -126,4 +126,16 @@ the FreeMarer 3 changelog here: obj.m(1), you could write obj.m[1]. This strange feature has led to some tricky cases, while almost nobody has utilized it. - SimpleObjectWrapper was renamed to RestrictedObjectWrapper, also the "simple" setting value was rename to - "restricted". \ No newline at end of file + "restricted". +- Removed the global static final ObjectWrapper-s. It had a "few" consequences: + - Standard TemplateModel implementations that can have an ObjectWrapper contrucor parameter don't allow null there anymore. + Also, any constructor overloads where you cold omit the ObjectWrapper were removed (these were deprecated in FM2 too). + In FM2, such overloads has used the global static default DefaltObjectWrapper, but that was removed. + - If the ObjectWrapper is not a DefaultObjectWrapper (or a subclass of it), `className?new(args)` will only accept 0 arguments. + (Earlier we have fallen back to using the global static default DefaultObjectWrapper instance to handle argument unwrapping + and overloaded constructors.) Note that ?new is only used to instantiate TemplateModel-s, typically, tempalte language + functions/directives implemented in Java, and so they hardly ever has an argument. + - FreemarkerServlet now requires that the ObjectWrapper it uses implements ObjectWrapperAndUnwrapper. (Thus, the return type + of FreemarerServlet.createDefaultObjectWrapper() has changed to ObjectWrapperAndUnwrapper.) The unwrapping functionality is + required when calling JSP custom tags/functions, and in FreeMarker 2 this was worked around with using the + global static default DefaultObjectWrapper when the ObjectWrapper wasn't an ObjectWrapperAndUnwrapper. http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/core/ConfigurationTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/ConfigurationTest.java b/src/test/java/org/apache/freemarker/core/ConfigurationTest.java index 6889f8c..c1650ec 100644 --- a/src/test/java/org/apache/freemarker/core/ConfigurationTest.java +++ b/src/test/java/org/apache/freemarker/core/ConfigurationTest.java @@ -41,8 +41,8 @@ import org.apache.freemarker.core.model.TemplateModelException; import org.apache.freemarker.core.model.TemplateScalarModel; import org.apache.freemarker.core.model.impl.DefaultObjectWrapper; import org.apache.freemarker.core.model.impl.DefaultObjectWrapperBuilder; +import org.apache.freemarker.core.model.impl.RestrictedObjectWrapper; import org.apache.freemarker.core.model.impl.SimpleScalar; -import org.apache.freemarker.core.model.impl._StaticObjectWrappers; import org.apache.freemarker.core.outputformat.MarkupOutputFormat; import org.apache.freemarker.core.outputformat.OutputFormat; import org.apache.freemarker.core.outputformat.UnregisteredOutputFormatException; @@ -107,16 +107,17 @@ public class ConfigurationTest extends TestCase { } assertFalse(cfg.isObjectWrapperExplicitlySet()); - assertSame(_StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER, cfg.getObjectWrapper()); + assertSame(Configuration.getDefaultObjectWrapper(Configuration.VERSION_3_0_0), cfg.getObjectWrapper()); // - cfg.setObjectWrapper(_StaticObjectWrappers.RESTRICTED_OBJECT_WRAPPER); + RestrictedObjectWrapper ow = new RestrictedObjectWrapper(Configuration.VERSION_3_0_0); + cfg.setObjectWrapper(ow); assertTrue(cfg.isObjectWrapperExplicitlySet()); - assertSame(_StaticObjectWrappers.RESTRICTED_OBJECT_WRAPPER, cfg.getObjectWrapper()); + assertSame(ow, cfg.getObjectWrapper()); // for (int i = 0; i < 2; i++) { cfg.unsetObjectWrapper(); assertFalse(cfg.isObjectWrapperExplicitlySet()); - assertSame(_StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER, cfg.getObjectWrapper()); + assertSame(Configuration.getDefaultObjectWrapper(Configuration.VERSION_3_0_0), cfg.getObjectWrapper()); } assertFalse(cfg.isTemplateExceptionHandlerExplicitlySet()); @@ -200,10 +201,6 @@ public class ConfigurationTest extends TestCase { } } - private void assertUsesLegacyObjectWrapper(Configuration cfg) { - assertSame(_StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER, cfg.getObjectWrapper()); - } - private void assertUsesNewObjectWrapper(Configuration cfg) { assertEquals( Configuration.VERSION_3_0_0, @@ -641,14 +638,14 @@ public class ConfigurationTest extends TestCase { { cfg.setSetting(Configurable.OBJECT_WRAPPER_KEY, "defAult"); - assertSame(_StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER, cfg.getObjectWrapper()); + assertSame(Configuration.getDefaultObjectWrapper(Configuration.VERSION_3_0_0), cfg.getObjectWrapper()); DefaultObjectWrapper dow = (DefaultObjectWrapper) cfg.getObjectWrapper(); assertEquals(Configuration.VERSION_3_0_0, dow.getIncompatibleImprovements()); } { cfg.setSetting(Configurable.OBJECT_WRAPPER_KEY, "restricted"); - assertSame(_StaticObjectWrappers.RESTRICTED_OBJECT_WRAPPER, cfg.getObjectWrapper()); + assertThat(cfg.getObjectWrapper(), instanceOf(RestrictedObjectWrapper.class)); } } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/core/NewBiObjectWrapperRestrictionTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/NewBiObjectWrapperRestrictionTest.java b/src/test/java/org/apache/freemarker/core/NewBiObjectWrapperRestrictionTest.java new file mode 100644 index 0000000..40dfe13 --- /dev/null +++ b/src/test/java/org/apache/freemarker/core/NewBiObjectWrapperRestrictionTest.java @@ -0,0 +1,51 @@ +/* + * 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.freemarker.core; + +import java.io.IOException; + +import org.apache.freemarker.test.TemplateTest; +import org.apache.freemarker.test.util.FullyCustomObjectWrapper; +import org.junit.Test; + +public class NewBiObjectWrapperRestrictionTest extends TemplateTest { + + @Override + protected Configuration createConfiguration() throws Exception { + Configuration cfg = super.createConfiguration(); + cfg.setObjectWrapper(new FullyCustomObjectWrapper()); + return cfg; + } + + @Test + public void testPositive() throws IOException, TemplateException { + assertOutput( + "${'org.apache.freemarker.test.templatesuite.models.NewTestModel'?new()}", + "default constructor"); + } + + @Test + public void testNegative() { + assertErrorContains( + "${'org.apache.freemarker.test.templatesuite.models.NewTestModel'?new('s')}", + "only supports 0 argument"); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java b/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java index 2405a38..deefd32 100644 --- a/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java +++ b/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java @@ -491,18 +491,6 @@ public class DefaultObjectWrapperTest { assertFalse(coll.isEmpty()); assertCollectionTMEquals(coll, "a", "b", "c"); - assertTrue(coll.contains(OW.wrap("a"))); - assertTrue(coll.contains(OW.wrap("b"))); - assertTrue(coll.contains(OW.wrap("c"))); - assertTrue(coll.contains(OW.wrap("c"))); - assertFalse(coll.contains(OW.wrap("d"))); - try { - assertFalse(coll.contains(OW.wrap(1))); - fail(); - } catch (TemplateModelException e) { - assertThat(e.getMessage(), containsString("Integer")); - } - assertRoundtrip(OW, set, DefaultNonListCollectionAdapter.class, TreeSet.class, "[a, b, c]"); assertSizeThroughAPIModel(3, coll); @@ -523,13 +511,6 @@ public class DefaultObjectWrapperTest { assertTrue(obj1 != null && obj1.equals(list) || obj2 != null && obj2.equals(list)); assertTrue(tm1 instanceof DefaultListAdapter || tm2 instanceof DefaultListAdapter); - List similarList = new ArrayList(); - similarList.add("b"); - assertTrue(coll.contains(OW.wrap(similarList))); - assertTrue(coll.contains(OW.wrap(null))); - assertFalse(coll.contains(OW.wrap("a"))); - assertFalse(coll.contains(OW.wrap(1))); - assertRoundtrip(OW, set, DefaultNonListCollectionAdapter.class, HashSet.class, "[" + obj1 + ", " + obj2 + "]"); } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/servlet/jsp/RealServletContainertTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/servlet/jsp/RealServletContainertTest.java b/src/test/java/org/apache/freemarker/servlet/jsp/RealServletContainertTest.java index d3c1a14..4f87e2c 100644 --- a/src/test/java/org/apache/freemarker/servlet/jsp/RealServletContainertTest.java +++ b/src/test/java/org/apache/freemarker/servlet/jsp/RealServletContainertTest.java @@ -40,6 +40,7 @@ import javax.servlet.http.HttpServletResponse; import org.apache.freemarker.core.Configuration; import org.apache.freemarker.core.TemplateExceptionHandler; import org.apache.freemarker.core.model.ObjectWrapper; +import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper; import org.apache.freemarker.core.model.impl.DefaultObjectWrapper; import org.apache.freemarker.core.model.impl.DefaultObjectWrapperBuilder; import org.apache.freemarker.core.model.impl.RestrictedObjectWrapper; @@ -451,7 +452,7 @@ public class RealServletContainertTest extends WebAppTestCase { } @Override - protected ObjectWrapper createDefaultObjectWrapper() { + protected ObjectWrapperAndUnwrapper createDefaultObjectWrapper() { DefaultObjectWrapperBuilder bwb = new DefaultObjectWrapperBuilder(Configuration.VERSION_3_0_0); bwb.setUseModelCache(true); assertEquals(Configuration.VERSION_3_0_0, bwb.getIncompatibleImprovements()); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/test/templatesuite/TemplateTestCase.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/test/templatesuite/TemplateTestCase.java b/src/test/java/org/apache/freemarker/test/templatesuite/TemplateTestCase.java index 0511490..347ae06 100644 --- a/src/test/java/org/apache/freemarker/test/templatesuite/TemplateTestCase.java +++ b/src/test/java/org/apache/freemarker/test/templatesuite/TemplateTestCase.java @@ -61,7 +61,6 @@ import org.apache.freemarker.core.model.impl.ResourceBundleModel; import org.apache.freemarker.core.model.impl.SimpleCollection; import org.apache.freemarker.core.model.impl.SimpleDate; import org.apache.freemarker.core.model.impl.SimpleNumber; -import org.apache.freemarker.core.model.impl._StaticObjectWrappers; import org.apache.freemarker.core.templateresolver.impl.FileTemplateLoader; import org.apache.freemarker.core.util._NullArgumentException; import org.apache.freemarker.core.util._NullWriter; @@ -210,8 +209,7 @@ public class TemplateTestCase extends FileTestCase { dataModel.put("obj", new org.apache.freemarker.test.templatesuite.models.BeanTestClass()); dataModel.put("resourceBundle", new ResourceBundleModel(ResourceBundle.getBundle( - "org.apache.freemarker.test.templatesuite.models.BeansTestResources"), - _StaticObjectWrappers.DEFAULT_OBJECT_WRAPPER)); + "org.apache.freemarker.test.templatesuite.models.BeansTestResources"), dow)); dataModel.put("date", new GregorianCalendar(1974, 10, 14).getTime()); dataModel.put("statics", dow.getStaticModels()); dataModel.put("enums", dow.getEnumModels()); @@ -222,8 +220,8 @@ public class TemplateTestCase extends FileTestCase { dataModel.put( "boolean4", TemplateBooleanModel.TRUE); dataModel.put( "boolean5", TemplateBooleanModel.FALSE); - dataModel.put( "list1", new BooleanList1() ); - dataModel.put( "list2", new BooleanList2() ); + dataModel.put( "list1", new BooleanList1(dow) ); + dataModel.put( "list2", new BooleanList2(dow) ); dataModel.put( "hash1", new BooleanHash1() ); dataModel.put( "hash2", new BooleanHash2() ); @@ -291,8 +289,8 @@ public class TemplateTestCase extends FileTestCase { } else if (simpleTestName.startsWith("type-builtins")) { dataModel.put("testmethod", new TestMethod()); dataModel.put("testnode", new TestNode()); - dataModel.put("testcollection", new SimpleCollection(new ArrayList<>())); - dataModel.put("testcollectionEx", DefaultNonListCollectionAdapter.adapt(new HashSet<>(), null)); + dataModel.put("testcollection", new SimpleCollection(new ArrayList<>(), dow)); + dataModel.put("testcollectionEx", DefaultNonListCollectionAdapter.adapt(new HashSet<>(), dow)); dataModel.put("bean", new TestBean()); } else if (simpleTestName.equals("date-type-builtins")) { GregorianCalendar cal = new GregorianCalendar(2003, 4 - 1, 5, 6, 7, 8); @@ -353,7 +351,7 @@ public class TemplateTestCase extends FileTestCase { listWithNull.add(null); dataModel.put("listWithNullsOnly", listWithNullsOnly); - dataModel.put("abcCollection", new SimpleCollection(abcSet)); + dataModel.put("abcCollection", new SimpleCollection(abcSet, dow)); Set<String> set = new HashSet<>(); set.add("a"); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/test/templatesuite/models/BooleanList1.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/test/templatesuite/models/BooleanList1.java b/src/test/java/org/apache/freemarker/test/templatesuite/models/BooleanList1.java index 7c33c1e..3e0a69c 100644 --- a/src/test/java/org/apache/freemarker/test/templatesuite/models/BooleanList1.java +++ b/src/test/java/org/apache/freemarker/test/templatesuite/models/BooleanList1.java @@ -19,10 +19,12 @@ package org.apache.freemarker.test.templatesuite.models; +import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.TemplateBooleanModel; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; import org.apache.freemarker.core.model.TemplateSequenceModel; +import org.apache.freemarker.core.model.impl.SimpleSequence; /** * Model for testing the impact of isEmpty() on template list models. Every @@ -30,11 +32,11 @@ import org.apache.freemarker.core.model.TemplateSequenceModel; */ public class BooleanList1 implements TemplateSequenceModel { - private LegacyList cList; + private SimpleSequence cList; /** Creates new BooleanList1 */ - public BooleanList1() { - cList = new LegacyList(); + public BooleanList1(ObjectWrapper ow) { + cList = new SimpleSequence(ow); cList.add( "false" ); cList.add( "0" ); cList.add(TemplateBooleanModel.FALSE); @@ -45,27 +47,6 @@ public class BooleanList1 implements TemplateSequenceModel { } /** - * @return true if there is a next element. - */ - public boolean hasNext() { - return cList.hasNext(); - } - - /** - * @return the next element in the list. - */ - public TemplateModel next() throws TemplateModelException { - return cList.next(); - } - - /** - * @return true if the cursor is at the beginning of the list. - */ - public boolean isRewound() { - return cList.isRewound(); - } - - /** * @return the specified index in the list */ @Override @@ -73,13 +54,6 @@ public class BooleanList1 implements TemplateSequenceModel { return cList.get(i); } - /** - * Resets the cursor to the beginning of the list. - */ - public void rewind() { - cList.rewind(); - } - @Override public int size() { return cList.size(); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/test/templatesuite/models/BooleanList2.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/test/templatesuite/models/BooleanList2.java b/src/test/java/org/apache/freemarker/test/templatesuite/models/BooleanList2.java index 4f4f3cb..939fb5f 100644 --- a/src/test/java/org/apache/freemarker/test/templatesuite/models/BooleanList2.java +++ b/src/test/java/org/apache/freemarker/test/templatesuite/models/BooleanList2.java @@ -19,9 +19,11 @@ package org.apache.freemarker.test.templatesuite.models; +import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; import org.apache.freemarker.core.model.TemplateSequenceModel; +import org.apache.freemarker.core.model.impl.SimpleSequence; /** * Model for testing list models. Every @@ -29,11 +31,11 @@ import org.apache.freemarker.core.model.TemplateSequenceModel; */ public class BooleanList2 implements TemplateSequenceModel { - private LegacyList cList; + private SimpleSequence cList; /** Creates new BooleanList2 */ - public BooleanList2() { - cList = new LegacyList(); + public BooleanList2(ObjectWrapper ow) { + cList = new SimpleSequence(ow); } /** http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/test/templatesuite/models/LegacyList.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/test/templatesuite/models/LegacyList.java b/src/test/java/org/apache/freemarker/test/templatesuite/models/LegacyList.java deleted file mode 100644 index b369cfc..0000000 --- a/src/test/java/org/apache/freemarker/test/templatesuite/models/LegacyList.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.freemarker.test.templatesuite.models; - -import java.util.Iterator; - -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateModelException; -import org.apache.freemarker.core.model.impl.SimpleSequence; - -/** - * A little bridge class that subclasses the new SimpleList - * and still implements the deprecated TemplateListModel - */ -public class LegacyList extends SimpleSequence { - - private Iterator iterator; - - /** - * Resets the cursor to the beginning of the list. - */ - public synchronized void rewind() { - iterator = null; - } - - /** - * @return true if the cursor is at the beginning of the list. - */ - public synchronized boolean isRewound() { - return (iterator == null); - } - - /** - * @return true if there is a next element. - */ - public synchronized boolean hasNext() { - if (iterator == null) { - iterator = list.listIterator(); - } - return iterator.hasNext(); - } - - /** - * @return the next element in the list. - */ - public synchronized TemplateModel next() throws TemplateModelException { - if (iterator == null) { - iterator = list.listIterator(); - } - if (iterator.hasNext()) { - return (TemplateModel) iterator.next(); - } else { - throw new TemplateModelException("No more elements."); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel1.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel1.java b/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel1.java index 35eea63..3c1adfb 100644 --- a/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel1.java +++ b/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel1.java @@ -19,11 +19,14 @@ package org.apache.freemarker.test.templatesuite.models; +import org.apache.freemarker.core.Configuration; +import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.TemplateHashModel; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; import org.apache.freemarker.core.model.TemplateScalarModel; import org.apache.freemarker.core.model.TemplateSequenceModel; +import org.apache.freemarker.core.model.impl.DefaultObjectWrapperBuilder; import org.apache.freemarker.core.model.impl.SimpleHash; import org.apache.freemarker.core.model.impl.SimpleScalar; import org.apache.freemarker.core.model.impl.SimpleSequence; @@ -34,11 +37,13 @@ import org.apache.freemarker.core.model.impl.SimpleSequence; public class MultiModel1 implements TemplateHashModel, TemplateSequenceModel, TemplateScalarModel { + private ObjectWrapper ow = new DefaultObjectWrapperBuilder(Configuration.VERSION_3_0_0).build(); + private TemplateModel m_cSubModel = new MultiModel2(); - private TemplateModel m_cListHashModel1 = new MultiModel4(); - private TemplateModel m_cListHashModel2 = new MultiModel5(); - private TemplateSequenceModel m_cListModel = new SimpleSequence(); - private TemplateHashModel m_cHashModel = new SimpleHash(); + private TemplateModel m_cListHashModel1 = new MultiModel4(ow); + private TemplateModel m_cListHashModel2 = new MultiModel5(ow); + private TemplateSequenceModel m_cListModel = new SimpleSequence(ow); + private TemplateHashModel m_cHashModel = new SimpleHash(ow); /** Creates new MultiModel1 */ public MultiModel1() { http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel4.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel4.java b/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel4.java index 60a4a29..bdd11fc 100644 --- a/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel4.java +++ b/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel4.java @@ -19,18 +19,24 @@ package org.apache.freemarker.test.templatesuite.models; +import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.TemplateHashModel; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; import org.apache.freemarker.core.model.TemplateSequenceModel; import org.apache.freemarker.core.model.impl.SimpleScalar; +import org.apache.freemarker.core.model.impl.SimpleSequence; /** * Testcase to see how FreeMarker deals with multiple Template models. */ public class MultiModel4 implements TemplateSequenceModel, TemplateHashModel { - private LegacyList m_cList = new LegacyList(); + private final SimpleSequence m_cList; + + public MultiModel4(ObjectWrapper ow) { + this.m_cList = new SimpleSequence(ow); + } /** * @return the specified index in the list http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel5.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel5.java b/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel5.java index d6b2b35..01f7a3e 100644 --- a/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel5.java +++ b/src/test/java/org/apache/freemarker/test/templatesuite/models/MultiModel5.java @@ -19,21 +19,24 @@ package org.apache.freemarker.test.templatesuite.models; +import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.TemplateHashModel; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; import org.apache.freemarker.core.model.TemplateSequenceModel; import org.apache.freemarker.core.model.impl.SimpleScalar; +import org.apache.freemarker.core.model.impl.SimpleSequence; /** * Testcase to see how FreeMarker deals with multiple Template models. */ public class MultiModel5 implements TemplateSequenceModel, TemplateHashModel { - private LegacyList m_cList = new LegacyList(); + private final SimpleSequence m_cList; /** Creates new MultiModel5 */ - public MultiModel5() { + public MultiModel5(ObjectWrapper ow) { + this.m_cList = new SimpleSequence(ow); m_cList.add( new SimpleScalar( "Dummy to make list non-empty" )); } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformHashWrapper.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformHashWrapper.java b/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformHashWrapper.java index c4f9212..cfdbe12 100644 --- a/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformHashWrapper.java +++ b/src/test/java/org/apache/freemarker/test/templatesuite/models/TransformHashWrapper.java @@ -19,10 +19,13 @@ package org.apache.freemarker.test.templatesuite.models; +import org.apache.freemarker.core.Configuration; +import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.TemplateHashModel; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; import org.apache.freemarker.core.model.TemplateScalarModel; +import org.apache.freemarker.core.model.impl.DefaultObjectWrapperBuilder; import org.apache.freemarker.core.model.impl.SimpleHash; import org.apache.freemarker.core.util.HtmlEscape; import org.apache.freemarker.core.util.StandardCompress; @@ -33,7 +36,8 @@ import org.apache.freemarker.core.util.StandardCompress; public class TransformHashWrapper implements TemplateHashModel, TemplateScalarModel { - private SimpleHash m_cHashModel = new SimpleHash(); + private ObjectWrapper ow = new DefaultObjectWrapperBuilder(Configuration.VERSION_3_0_0).build(); + private SimpleHash m_cHashModel = new SimpleHash(ow); /** Creates new TransformHashWrapper */ public TransformHashWrapper() { http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b4dfe5d2/src/test/java/org/apache/freemarker/test/util/FullyCustomObjectWrapper.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/test/util/FullyCustomObjectWrapper.java b/src/test/java/org/apache/freemarker/test/util/FullyCustomObjectWrapper.java new file mode 100644 index 0000000..31a1110 --- /dev/null +++ b/src/test/java/org/apache/freemarker/test/util/FullyCustomObjectWrapper.java @@ -0,0 +1,91 @@ +/* + * 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.freemarker.test.util; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; + +import org.apache.freemarker.core.model.ObjectWrapper; +import org.apache.freemarker.core.model.TemplateBooleanModel; +import org.apache.freemarker.core.model.TemplateDateModel; +import org.apache.freemarker.core.model.TemplateModel; +import org.apache.freemarker.core.model.TemplateModelAdapter; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.model.impl.DefaultObjectWrapper; +import org.apache.freemarker.core.model.impl.SimpleDate; +import org.apache.freemarker.core.model.impl.SimpleHash; +import org.apache.freemarker.core.model.impl.SimpleNumber; +import org.apache.freemarker.core.model.impl.SimpleScalar; +import org.apache.freemarker.core.model.impl.SimpleSequence; + +/** + * An object wrapper that doesn't extend {@link DefaultObjectWrapper}. + */ +public class FullyCustomObjectWrapper implements ObjectWrapper { + + @Override + public TemplateModel wrap(Object obj) throws TemplateModelException { + if (obj == null) { + return null; + } + + if (obj instanceof TemplateModel) { + return (TemplateModel) obj; + } + if (obj instanceof TemplateModelAdapter) { + return ((TemplateModelAdapter) obj).getTemplateModel(); + } + + if (obj instanceof String) { + return new SimpleScalar((String) obj); + } + if (obj instanceof Number) { + return new SimpleNumber((Number) obj); + } + if (obj instanceof Boolean) { + return obj.equals(Boolean.TRUE) ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; + } + if (obj instanceof java.util.Date) { + if (obj instanceof java.sql.Date) { + return new SimpleDate((java.sql.Date) obj); + } + if (obj instanceof java.sql.Time) { + return new SimpleDate((java.sql.Time) obj); + } + if (obj instanceof java.sql.Timestamp) { + return new SimpleDate((java.sql.Timestamp) obj); + } + return new SimpleDate((java.util.Date) obj, TemplateDateModel.UNKNOWN); + } + + if (obj.getClass().isArray()) { + obj = Arrays.asList((Object[]) obj); + } + if (obj instanceof Collection) { + return new SimpleSequence((Collection<?>) obj, this); + } + if (obj instanceof Map) { + return new SimpleHash((Map<?, ?>) obj, this); + } + + return null; + } +}
