http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java b/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java deleted file mode 100644 index 7ec4461..0000000 --- a/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java +++ /dev/null @@ -1,92 +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 freemarker.template; - -import freemarker.ext.util.WrapperTemplateModel; - -/** - * <b>Experimental - subject to change:</b> Adds functionality to {@link ObjectWrapper} that creates a plain Java object - * from a {@link TemplateModel}. This is usually implemented by {@link ObjectWrapper}-s and reverses - * {@link ObjectWrapper#wrap(Object)}. However, an implementation of this interface should make a reasonable effort to - * "unwrap" {@link TemplateModel}-s that wasn't the result of object wrapping (such as those created directly in FTL), - * or which was created by another {@link ObjectWrapper}. The author of an {@link ObjectWrapperAndUnwrapper} should be - * aware of the {@link TemplateModelAdapter} and {@link WrapperTemplateModel} interfaces, which should be used for - * unwrapping if the {@link TemplateModel} implements them. - * - * <p> - * <b>Experimental status warning:</b> This interface is subject to change on non-backward compatible ways, hence, it - * shouldn't be implemented outside FreeMarker yet. - * - * @since 2.3.22 - */ -public interface ObjectWrapperAndUnwrapper extends ObjectWrapper { - - /** - * Indicates that while the unwrapping is <em>maybe</em> possible, the result surely can't be the instance of the - * desired class, nor it can be {@code null}. - * - * @see #tryUnwrapTo(TemplateModel, Class) - * - * @since 2.3.22 - */ - Object CANT_UNWRAP_TO_TARGET_CLASS = new Object(); - - /** - * Unwraps a {@link TemplateModel} to a plain Java object. - * - * @return The plain Java object. Can be {@code null}, if {@code null} is the appropriate Java value to represent - * the template model. {@code null} must not be used to indicate an unwrapping failure. It must NOT be - * {@link #CANT_UNWRAP_TO_TARGET_CLASS}. - * - * @throws TemplateModelException - * If the unwrapping fails from any reason. - * - * @see #tryUnwrapTo(TemplateModel, Class) - * - * @since 2.3.22 - */ - Object unwrap(TemplateModel tm) throws TemplateModelException; - - /** - * Attempts to unwrap a {@link TemplateModel} to a plain Java object that's the instance of the given class (or is - * {@code null}). - * - * @param targetClass - * The class that the return value must be an instance of (except when the return value is {@code null}). - * Can't be {@code null}; if the caller doesn't care, it should either use {#unwrap(TemplateModel)}, or - * {@code Object.class} as the parameter value. - * - * @return The unwrapped value that's either an instance of {@code targetClass}, or is {@code null} (if {@code null} - * is the appropriate Java value to represent the template model), or is - * {@link #CANT_UNWRAP_TO_TARGET_CLASS} if the unwrapping can't satisfy the {@code targetClass} (nor the - * result can be {@code null}). However, {@link #CANT_UNWRAP_TO_TARGET_CLASS} must not be returned if the - * {@code targetClass} parameter was {@code Object.class}. - * - * @throws TemplateModelException - * If the unwrapping fails for a reason than doesn't fit the meaning of the - * {@link #CANT_UNWRAP_TO_TARGET_CLASS} return value. - * - * @see #unwrap(TemplateModel) - * - * @since 2.3.22 - */ - Object tryUnwrapTo(TemplateModel tm, Class<?> targetClass) throws TemplateModelException; - -}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/ResourceBundleLocalizedString.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/ResourceBundleLocalizedString.java b/src/main/java/freemarker/template/ResourceBundleLocalizedString.java deleted file mode 100755 index bc9afda..0000000 --- a/src/main/java/freemarker/template/ResourceBundleLocalizedString.java +++ /dev/null @@ -1,54 +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 freemarker.template; - -import java.util.Locale; -import java.util.MissingResourceException; -import java.util.ResourceBundle; - -/** - * A concrete implementation of {@link LocalizedString} that gets - * a localized string from a {@link java.util.ResourceBundle} - */ - -public class ResourceBundleLocalizedString extends LocalizedString { - - private String resourceKey, resourceBundleLookupKey; - - /** - * @param resourceBundleLookupKey The lookup key for the resource bundle - * @param resourceKey the specific resource (assumed to be a string) to fish out of the resource bundle - */ - - public ResourceBundleLocalizedString(String resourceBundleLookupKey, String resourceKey) { - this.resourceBundleLookupKey = resourceBundleLookupKey; - this.resourceKey = resourceKey; - } - - @Override - public String getLocalizedString(Locale locale) throws TemplateModelException { - try { - ResourceBundle rb = ResourceBundle.getBundle(resourceBundleLookupKey, locale); - return rb.getString(resourceKey); - } catch (MissingResourceException mre) { - throw new TemplateModelException("missing resource", mre); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/SerializableTemplateBooleanModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/SerializableTemplateBooleanModel.java b/src/main/java/freemarker/template/SerializableTemplateBooleanModel.java deleted file mode 100644 index 13b4db9..0000000 --- a/src/main/java/freemarker/template/SerializableTemplateBooleanModel.java +++ /dev/null @@ -1,24 +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 freemarker.template; - -import java.io.Serializable; - -interface SerializableTemplateBooleanModel extends TemplateBooleanModel, Serializable {}; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/SimpleCollection.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/SimpleCollection.java b/src/main/java/freemarker/template/SimpleCollection.java deleted file mode 100644 index 77f9755..0000000 --- a/src/main/java/freemarker/template/SimpleCollection.java +++ /dev/null @@ -1,150 +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 freemarker.template; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Iterator; - -/** - * A simple implementation of {@link TemplateCollectionModel}. - * It's able to wrap <tt>java.util.Iterator</tt>-s and <tt>java.util.Collection</tt>-s. - * If you wrap an <tt>Iterator</tt>, the variable can be <#list>-ed only once! - * - * <p>Consider using {@link SimpleSequence} instead of this class if you want to wrap <tt>Iterator</tt>s. - * <tt>SimpleSequence</tt> will read all elements of the <tt>Iterator</tt>, and store them in a <tt>List</tt> - * (this may cause too high resource consumption in some applications), so you can list the variable - * for unlimited times. Also, if you want to wrap <tt>Collection</tt>s, and then list the resulting - * variable for many times, <tt>SimpleSequence</tt> may gives better performance, as the - * wrapping of non-<tt>TemplateModel</tt> objects happens only once. - * - * <p>This class is thread-safe. The returned {@link TemplateModelIterator}-s - * are <em>not</em> thread-safe. - */ -public class SimpleCollection extends WrappingTemplateModel -implements TemplateCollectionModel, Serializable { - - private boolean iteratorOwned; - private final Iterator iterator; - private final Collection collection; - - /** - * @deprecated Use {@link #SimpleCollection(Iterator, ObjectWrapper)} - */ - @Deprecated - public SimpleCollection(Iterator iterator) { - this.iterator = iterator; - collection = null; - } - - /** - * @deprecated Use {@link #SimpleCollection(Collection, ObjectWrapper)} - */ - @Deprecated - public SimpleCollection(Collection collection) { - this.collection = collection; - iterator = null; - } - - public SimpleCollection(Iterator iterator, ObjectWrapper wrapper) { - super(wrapper); - this.iterator = iterator; - collection = null; - } - - public SimpleCollection(Collection collection, ObjectWrapper wrapper) { - super(wrapper); - this.collection = collection; - iterator = null; - } - - /** - * Retrieves a template model iterator that is used to iterate over the elements in this collection. - * - * <p>When you wrap an <tt>Iterator</tt> and you get <tt>TemplateModelIterator</tt> for multiple times, - * only on of the returned <tt>TemplateModelIterator</tt> instances can be really used. When you have called a - * method of a <tt>TemplateModelIterator</tt> instance, all other instance will throw a - * <tt>TemplateModelException</tt> when you try to call their methods, since the wrapped <tt>Iterator</tt> - * can't return the first element anymore. - */ - public TemplateModelIterator iterator() { - if (iterator != null) { - return new SimpleTemplateModelIterator(iterator, false); - } else { - synchronized (collection) { - return new SimpleTemplateModelIterator(collection.iterator(), true); - } - } - } - - /** - * Wraps an {@link Iterator}; not thread-safe. The encapsulated {@link Iterator} may be accessible from multiple - * threads (as multiple {@link SimpleTemplateModelIterator} instance can wrap the same {@link Iterator} instance), - * but if the {@link Iterator} was marked in the constructor as shared, the first thread which uses the - * {@link Iterator} will monopolize that. - */ - private class SimpleTemplateModelIterator implements TemplateModelIterator { - - private final Iterator iterator; - private boolean iteratorOwnedByMe; - - SimpleTemplateModelIterator(Iterator iterator, boolean iteratorOwnedByMe) { - this.iterator = iterator; - this.iteratorOwnedByMe = iteratorOwnedByMe; - } - - public TemplateModel next() throws TemplateModelException { - if (!iteratorOwnedByMe) { - synchronized (SimpleCollection.this) { - checkIteratorOwned(); - iteratorOwned = true; - iteratorOwnedByMe = true; - } - } - - if (!iterator.hasNext()) { - throw new TemplateModelException("The collection has no more items."); - } - - Object value = iterator.next(); - return value instanceof TemplateModel ? (TemplateModel) value : wrap(value); - } - - public boolean hasNext() throws TemplateModelException { - // Calling hasNext may looks safe, but I have met sync. problems. - if (!iteratorOwnedByMe) { - synchronized (SimpleCollection.this) { - checkIteratorOwned(); - } - } - - return iterator.hasNext(); - } - - private void checkIteratorOwned() throws TemplateModelException { - if (iteratorOwned) { - throw new TemplateModelException( - "This collection value wraps a java.util.Iterator, thus it can be listed only once."); - } - } - - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/SimpleDate.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/SimpleDate.java b/src/main/java/freemarker/template/SimpleDate.java deleted file mode 100644 index 7086f4b..0000000 --- a/src/main/java/freemarker/template/SimpleDate.java +++ /dev/null @@ -1,79 +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 freemarker.template; - -/** - * A simple implementation of the <tt>TemplateDateModel</tt> - * interface. Note that this class is immutable. - * <p>This class is thread-safe. - */ -public class SimpleDate implements TemplateDateModel { - private final java.util.Date date; - private final int type; - - /** - * Creates a new date model wrapping the specified date object and - * having DATE type. - */ - public SimpleDate(java.sql.Date date) { - this(date, DATE); - } - - /** - * Creates a new date model wrapping the specified time object and - * having TIME type. - */ - public SimpleDate(java.sql.Time time) { - this(time, TIME); - } - - /** - * Creates a new date model wrapping the specified time object and - * having DATETIME type. - */ - public SimpleDate(java.sql.Timestamp datetime) { - this(datetime, DATETIME); - } - - /** - * Creates a new date model wrapping the specified date object and - * having the specified type. - */ - public SimpleDate(java.util.Date date, int type) { - if (date == null) { - throw new IllegalArgumentException("date == null"); - } - this.date = date; - this.type = type; - } - - public java.util.Date getAsDate() { - return date; - } - - public int getDateType() { - return type; - } - - @Override - public String toString() { - return date.toString(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/SimpleHash.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/SimpleHash.java b/src/main/java/freemarker/template/SimpleHash.java deleted file mode 100644 index 4b1bf0f..0000000 --- a/src/main/java/freemarker/template/SimpleHash.java +++ /dev/null @@ -1,418 +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 freemarker.template; - -import java.io.Serializable; -import java.util.ConcurrentModificationException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; - -import freemarker.core._DelayedJQuote; -import freemarker.core._TemplateModelException; -import freemarker.ext.beans.BeansWrapper; - -/** - * A simple implementation of the {@link TemplateHashModelEx} interface, using its own underlying {@link Map} or - * {@link SortedMap} for storing the hash entries. If you are wrapping an already existing {@link Map}, you should - * certainly use {@link DefaultMapAdapter} instead (see comparison below). - * - * <p> - * This class is thread-safe if you don't call modifying methods (like {@link #put(String, Object)}, - * {@link #remove(String)}, etc.) after you have made the object available for multiple threads (assuming you have - * published it safely to the other threads; see JSR-133 Java Memory Model). These methods aren't called by FreeMarker, - * so it's usually not a concern. - * - * <p> - * <b>{@link SimpleHash} VS {@link DefaultMapAdapter} - Which to use when?</b> - * - * <p> - * For a {@link Map} that exists regardless of FreeMarker, only you need to access it from templates, - * {@link DefaultMapAdapter} should be the default choice, as it reflects the exact behavior of the underlying - * {@link Map} (no surprises), can be unwrapped to the originally wrapped object (important when passing it to Java - * methods from the template), and has more predictable performance (no spikes). - * - * <p> - * For a hash that's made specifically to be used from templates, creating an empty {@link SimpleHash} then filling it - * with {@link SimpleHash#put(String, Object)} is usually the way to go, as the resulting hash is significantly faster - * to read from templates than a {@link DefaultMapAdapter} (though it's somewhat slower to read from a plain Java method - * to which it had to be passed adapted to a {@link Map}). - * - * <p> - * If regardless of which of the above two cases stand, you just need to (or more convenient to) create the hash from a - * {@link Map} (via {@link SimpleHash#SimpleHash(Map, ObjectWrapper)} or - * {@link SimpleHash#SimpleHash(Map, ObjectWrapper)}), which will be the faster depends on how many times will the - * <em>same</em> {@link Map} entry be read from the template(s) later, on average. If, on average, you read each entry - * for more than 4 times, {@link SimpleHash} will be most certainly faster, but if for 2 times or less (and especially - * if not at all) then {@link DefaultMapAdapter} will be. Before choosing based on performance though, pay attention to - * the behavioral differences; {@link SimpleHash} will shallow-copy the original {@link Map} at construction time, so - * key order will be lost in some cases, and it won't reflect {@link Map} content changes after the {@link SimpleHash} - * construction, also {@link SimpleHash} can't be unwrapped to the original {@link Map} instance. - * - * @see DefaultMapAdapter - * @see TemplateHashModelEx - */ -public class SimpleHash extends WrappingTemplateModel implements TemplateHashModelEx2, Serializable { - - private final Map map; - private boolean putFailed; - private Map unwrappedMap; - - /** - * Constructs an empty hash that uses the default wrapper set in - * {@link WrappingTemplateModel#setDefaultObjectWrapper(ObjectWrapper)}. - * - * @deprecated Use {@link #SimpleHash(ObjectWrapper)} - */ - @Deprecated - public SimpleHash() { - this((ObjectWrapper) null); - } - - /** - * Creates a new simple hash with the copy of the underlying map and the - * default wrapper set in - * {@link WrappingTemplateModel#setDefaultObjectWrapper(ObjectWrapper)}. - * @param map The Map to use for the key/value pairs. It makes a copy for - * internal use. If the map implements the {@link SortedMap} interface, the - * internal copy will be a {@link TreeMap}, otherwise it will be a - * {@link HashMap}. - * - * @deprecated Use {@link #SimpleHash(Map, ObjectWrapper)} - */ - @Deprecated - public SimpleHash(Map map) { - this(map, null); - } - - /** - * Creates an empty simple hash using the specified object wrapper. - * @param wrapper The object wrapper to use to wrap objects into - * {@link TemplateModel} instances. If null, the default wrapper set in - * {@link WrappingTemplateModel#setDefaultObjectWrapper(ObjectWrapper)} is - * used. - */ - public SimpleHash(ObjectWrapper wrapper) { - super(wrapper); - map = new HashMap(); - } - - /** - * Creates a new hash by shallow-coping (possibly cloning) the underlying map; in many applications you should use - * {@link DefaultMapAdapter} instead. - * - * @param map - * The Map to use for the key/value pairs. It makes a copy for internal use. If the map implements the - * {@link SortedMap} interface, the internal copy will be a {@link TreeMap}, otherwise it will be a - * @param wrapper - * The object wrapper to use to wrap contained objects into {@link TemplateModel} instances. Using - * {@code null} is deprecated but allowed, in which case the deprecated default wrapper set in - * {@link WrappingTemplateModel#setDefaultObjectWrapper(ObjectWrapper)} is used. - */ - public SimpleHash(Map map, ObjectWrapper wrapper) { - super(wrapper); - Map mapCopy; - try { - mapCopy = copyMap(map); - } catch (ConcurrentModificationException cme) { - //This will occur extremely rarely. - //If it does, we just wait 5 ms and try again. If - // the ConcurrentModificationException - // is thrown again, we just let it bubble up this time. - // TODO: Maybe we should log here. - try { - Thread.sleep(5); - } catch (InterruptedException ie) { - } - synchronized (map) { - mapCopy = copyMap(map); - } - } - this.map = mapCopy; - } - - protected Map copyMap(Map map) { - if (map instanceof HashMap) { - return (Map) ((HashMap) map).clone(); - } - if (map instanceof SortedMap) { - if (map instanceof TreeMap) { - return (Map) ((TreeMap) map).clone(); - } else { - return new TreeMap((SortedMap) map); - } - } - return new HashMap(map); - } - - /** - * Adds a key-value entry to this hash. - * - * @param key - * The name by which the object is identified in the template. - * @param value - * The value to which the name will be associated. This will only be wrapped to {@link TemplateModel} - * lazily when it's first read. - */ - public void put(String key, Object value) { - map.put(key, value); - unwrappedMap = null; - } - - /** - * Puts a boolean in the map - * - * @param key the name by which the resulting <tt>TemplateModel</tt> - * is identified in the template. - * @param b the boolean to store. - */ - public void put(String key, boolean b) { - put(key, b ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE); - } - - public TemplateModel get(String key) throws TemplateModelException { - Object result; - try { - result = map.get(key); - } catch (ClassCastException e) { - throw new _TemplateModelException(e, - "ClassCastException while getting Map entry with String key ", - new _DelayedJQuote(key)); - } catch (NullPointerException e) { - throw new _TemplateModelException(e, - "NullPointerException while getting Map entry with String key ", - new _DelayedJQuote(key)); - } - // The key to use for putting -- it's the key that already exists in - // the map (either key or charKey below). This way, we'll never put a - // new key in the map, avoiding spurious ConcurrentModificationException - // from another thread iterating over the map, see bug #1939742 in - // SourceForge tracker. - Object putKey = null; - if (result == null) { - // Check for Character key if this is a single-character string. - // In SortedMap-s, however, we can't do that safely, as it can cause ClassCastException. - if (key.length() == 1 && !(map instanceof SortedMap)) { - Character charKey = Character.valueOf(key.charAt(0)); - try { - result = map.get(charKey); - if (result != null || map.containsKey(charKey)) { - putKey = charKey; - } - } catch (ClassCastException e) { - throw new _TemplateModelException(e, - "ClassCastException while getting Map entry with Character key ", - new _DelayedJQuote(key)); - } catch (NullPointerException e) { - throw new _TemplateModelException(e, - "NullPointerException while getting Map entry with Character key ", - new _DelayedJQuote(key)); - } - } - if (putKey == null) { - if (!map.containsKey(key)) { - return null; - } else { - putKey = key; - } - } - } else { - putKey = key; - } - - if (result instanceof TemplateModel) { - return (TemplateModel) result; - } - - TemplateModel tm = wrap(result); - if (!putFailed) { - try { - map.put(putKey, tm); - } catch (Exception e) { - // If it's immutable or something, we just keep going. - putFailed = true; - } - } - return tm; - } - - /** - * Tells if the map contains a key or not, regardless if the associated value is {@code null} or not. - * @since 2.3.20 - */ - public boolean containsKey(String key) { - return map.containsKey(key); - } - - /** - * Removes the given key from the underlying map. - * - * @param key the key to be removed - */ - public void remove(String key) { - map.remove(key); - } - - /** - * Adds all the key/value entries in the map - * @param m the map with the entries to add, the keys are assumed to be strings. - */ - - public void putAll(Map m) { - for (Iterator it = m.entrySet().iterator(); it.hasNext(); ) { - Map.Entry entry = (Map.Entry) it.next(); - this.put((String) entry.getKey(), entry.getValue()); - } - } - - /** - * Note that this method creates and returns a deep-copy of the underlying hash used - * internally. This could be a gotcha for some people - * at some point who want to alter something in the data model, - * but we should maintain our immutability semantics (at least using default SimpleXXX wrappers) - * for the data model. It will recursively unwrap the stuff in the underlying container. - */ - public Map toMap() throws TemplateModelException { - if (unwrappedMap == null) { - Class mapClass = this.map.getClass(); - Map m = null; - try { - m = (Map) mapClass.newInstance(); - } catch (Exception e) { - throw new TemplateModelException("Error instantiating map of type " + mapClass.getName() + "\n" + e.getMessage()); - } - // Create a copy to maintain immutability semantics and - // Do nested unwrapping of elements if necessary. - BeansWrapper bw = BeansWrapper.getDefaultInstance(); - for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) { - Map.Entry entry = (Map.Entry) it.next(); - Object key = entry.getKey(); - Object value = entry.getValue(); - if (value instanceof TemplateModel) { - value = bw.unwrap((TemplateModel) value); - } - m.put(key, value); - } - unwrappedMap = m; - } - return unwrappedMap; - } - - /** - * Returns the {@code toString()} of the underlying {@link Map}. - */ - @Override - public String toString() { - return map.toString(); - } - - public int size() { - return map.size(); - } - - public boolean isEmpty() { - return map == null || map.isEmpty(); - } - - public TemplateCollectionModel keys() { - return new SimpleCollection(map.keySet(), getObjectWrapper()); - } - - public TemplateCollectionModel values() { - return new SimpleCollection(map.values(), getObjectWrapper()); - } - - public KeyValuePairIterator keyValuePairIterator() { - return new MapKeyValuePairIterator(map, getObjectWrapper()); - } - - public SimpleHash synchronizedWrapper() { - return new SynchronizedHash(); - } - - private class SynchronizedHash extends SimpleHash { - - @Override - public boolean isEmpty() { - synchronized (SimpleHash.this) { - return SimpleHash.this.isEmpty(); - } - } - - @Override - public void put(String key, Object obj) { - synchronized (SimpleHash.this) { - SimpleHash.this.put(key, obj); - } - } - - @Override - public TemplateModel get(String key) throws TemplateModelException { - synchronized (SimpleHash.this) { - return SimpleHash.this.get(key); - } - } - - @Override - public void remove(String key) { - synchronized (SimpleHash.this) { - SimpleHash.this.remove(key); - } - } - - @Override - public int size() { - synchronized (SimpleHash.this) { - return SimpleHash.this.size(); - } - } - - @Override - public TemplateCollectionModel keys() { - synchronized (SimpleHash.this) { - return SimpleHash.this.keys(); - } - } - - @Override - public TemplateCollectionModel values() { - synchronized (SimpleHash.this) { - return SimpleHash.this.values(); - } - } - - @Override - public KeyValuePairIterator keyValuePairIterator() { - synchronized (SimpleHash.this) { - return SimpleHash.this.keyValuePairIterator(); - } - } - - @Override - public Map toMap() throws TemplateModelException { - synchronized (SimpleHash.this) { - return SimpleHash.this.toMap(); - } - } - - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/SimpleNumber.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/SimpleNumber.java b/src/main/java/freemarker/template/SimpleNumber.java deleted file mode 100644 index bc6943f..0000000 --- a/src/main/java/freemarker/template/SimpleNumber.java +++ /dev/null @@ -1,74 +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 freemarker.template; - -import java.io.Serializable; - - -/** - * A simple implementation of the <tt>TemplateNumberModel</tt> - * interface. Note that this class is immutable. - * - * <p>This class is thread-safe. - */ -public final class SimpleNumber implements TemplateNumberModel, Serializable { - - /** - * @serial the value of this <tt>SimpleNumber</tt> - */ - private final Number value; - - public SimpleNumber(Number value) { - this.value = value; - } - - public SimpleNumber(byte val) { - this.value = Byte.valueOf(val); - } - - public SimpleNumber(short val) { - this.value = Short.valueOf(val); - } - - public SimpleNumber(int val) { - this.value = Integer.valueOf(val); - } - - public SimpleNumber(long val) { - this.value = Long.valueOf(val); - } - - public SimpleNumber(float val) { - this.value = Float.valueOf(val); - } - - public SimpleNumber(double val) { - this.value = Double.valueOf(val); - } - - public Number getAsNumber() { - return value; - } - - @Override - public String toString() { - return value.toString(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/SimpleObjectWrapper.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/SimpleObjectWrapper.java b/src/main/java/freemarker/template/SimpleObjectWrapper.java deleted file mode 100644 index 3bef7fa..0000000 --- a/src/main/java/freemarker/template/SimpleObjectWrapper.java +++ /dev/null @@ -1,65 +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 freemarker.template; - -import freemarker.ext.beans.BeansWrapper; - -/** - * A restricted object wrapper that will not expose arbitrary object, just those that directly correspond to the - * {@link TemplateModel} sub-interfaces ({@code String}, {@code Map} and such). If it had to wrap other kind of objects, - * it will throw exception. It will also block {@code ?api} calls on the values it wraps. - */ -public class SimpleObjectWrapper extends DefaultObjectWrapper { - - static final SimpleObjectWrapper instance = new SimpleObjectWrapper(); - - /** - * @deprecated Use {@link #SimpleObjectWrapper(Version)} instead. - */ - @Deprecated - public SimpleObjectWrapper() { - super(); - } - - /** - * @param incompatibleImprovements see in {@link BeansWrapper#BeansWrapper(Version)}. - * - * @since 2.3.21 - */ - public SimpleObjectWrapper(Version incompatibleImprovements) { - super(incompatibleImprovements); - } - - /** - * Called if a type other than the simple ones we know about is passed in. - * In this implementation, this just throws an exception. - */ - @Override - protected TemplateModel handleUnknownType(Object obj) throws TemplateModelException { - throw new TemplateModelException("SimpleObjectWrapper deliberately won't wrap this type: " - + obj.getClass().getName()); - } - - @Override - public TemplateHashModel wrapAsAPI(Object obj) throws TemplateModelException { - throw new TemplateModelException("SimpleObjectWrapper deliberately doesn't allow ?api."); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/SimpleScalar.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/SimpleScalar.java b/src/main/java/freemarker/template/SimpleScalar.java deleted file mode 100644 index 0890c18..0000000 --- a/src/main/java/freemarker/template/SimpleScalar.java +++ /dev/null @@ -1,70 +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 freemarker.template; - -import java.io.Serializable; - -/** - * A simple implementation of the <tt>TemplateScalarModel</tt> - * interface, using a <tt>String</tt>. - * As of version 2.0 this object is immutable. - * - * <p>This class is thread-safe. - * - * @see SimpleSequence - * @see SimpleHash - */ -public final class SimpleScalar -implements TemplateScalarModel, Serializable { - - /** - * @serial the value of this <tt>SimpleScalar</tt> if it wraps a - * <tt>String</tt>. - */ - private final String value; - - /** - * Constructs a <tt>SimpleScalar</tt> containing a string value. - * @param value the string value. If this is {@code null}, its value in FTL will be {@code ""}. - */ - public SimpleScalar(String value) { - this.value = value; - } - - public String getAsString() { - return (value == null) ? "" : value; - } - - @Override - public String toString() { - // [2.4] Shouldn't return null - return value; - } - - /** - * Same as calling the constructor, except that for a {@code null} parameter it returns null. - * - * @since 2.3.23 - */ - public static SimpleScalar newInstanceOrNull(String s) { - return s != null ? new SimpleScalar(s) : null; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/SimpleSequence.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/SimpleSequence.java b/src/main/java/freemarker/template/SimpleSequence.java deleted file mode 100644 index e0ea945..0000000 --- a/src/main/java/freemarker/template/SimpleSequence.java +++ /dev/null @@ -1,299 +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 freemarker.template; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import freemarker.ext.beans.BeansWrapper; - -/** - * A simple implementation of the {@link TemplateSequenceModel} interface, using its own underlying {@link List} for - * storing the list items. If you are wrapping an already existing {@link List} or {@code array}, you should certainly - * use {@link DefaultMapAdapter} or {@link DefaultArrayAdapter} (see comparison below). - * - * <p> - * This class is thread-safe if you don't call modifying methods (like {@link #add(Object)}) after you have made the - * object available for multiple threads (assuming you have published it safely to the other threads; see JSR-133 Java - * Memory Model). These methods aren't called by FreeMarker, so it's usually not a concern. - * - * <p> - * <b>{@link SimpleSequence} VS {@link DefaultListAdapter}/{@link DefaultArrayAdapter} - Which to use when?</b> - * </p> - * - * <p> - * For a {@link List} or {@code array} that exists regardless of FreeMarker, only you need to access it from templates, - * {@link DefaultMapAdapter} should be the default choice, as it can be unwrapped to the originally wrapped object - * (important when passing it to Java methods from the template). It also has more predictable performance (no spikes). - * - * <p> - * For a sequence that's made specifically to be used from templates, creating an empty {@link SimpleSequence} then - * filling it with {@link SimpleSequence#add(Object)} is usually the way to go, as the resulting sequence is - * significantly faster to read from templates than a {@link DefaultListAdapter} (though it's somewhat slower to read - * from a plain Java method to which it had to be passed adapted to a {@link List}). - * - * <p> - * If regardless of which of the above two cases stand, you just need to (or more convenient to) create the sequence - * from a {@link List} (via {@link DefaultListAdapter#adapt(List, freemarker.template.utility.RichObjectWrapper)} or - * {@link SimpleSequence#SimpleSequence(Collection)}), which will be the faster depends on how many times will the - * <em>same</em> {@link List} entry be read from the template(s) later, on average. If, on average, you read each entry - * for more than 4 times, {@link SimpleSequence} will be most certainly faster, but if for 2 times or less (and - * especially if not at all) then {@link DefaultMapAdapter} will be. Before choosing based on performance though, pay - * attention to the behavioral differences; {@link SimpleSequence} will shallow-copy the original {@link List} at - * construction time, so it won't reflect {@link List} content changes after the {@link SimpleSequence} construction, - * also {@link SimpleSequence} can't be unwrapped to the original wrapped instance. - * - * @see DefaultListAdapter - * @see DefaultArrayAdapter - * @see TemplateSequenceModel - */ -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 - * and non-{@link TemplateModel} elements. - */ - protected final List list; - - private List unwrappedList; - - /** - * Constructs an empty simple sequence that will use the the default object - * wrapper set in - * {@link WrappingTemplateModel#setDefaultObjectWrapper(ObjectWrapper)}. - * - * @deprecated Use {@link #SimpleSequence(ObjectWrapper)} instead. - */ - @Deprecated - public SimpleSequence() { - this((ObjectWrapper) null); - } - - /** - * Constructs an empty simple sequence with preallocated capacity and using - * the default object wrapper set in - * {@link WrappingTemplateModel#setDefaultObjectWrapper(ObjectWrapper)}. - * - * @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 the the default - * object wrapper set in - * {@link WrappingTemplateModel#setDefaultObjectWrapper(ObjectWrapper)}. - * @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 (set in - * {@link WrappingTemplateModel#setDefaultObjectWrapper(ObjectWrapper)}) to be used. - */ - public SimpleSequence(ObjectWrapper wrapper) { - super(wrapper); - list = new ArrayList(); - } - - /** - * Constructs an empty simple sequence with preallocated capacity. - * - * @param wrapper - * See the similar parameter of {@link SimpleSequence#SimpleSequence(ObjectWrapper)}. - * - * @since 2.3.21 - */ - public SimpleSequence(int capacity, ObjectWrapper wrapper) { - super(wrapper); - list = new ArrayList(capacity); - } - - /** - * Constructs a simple sequence that will contain the elements from the specified {@link Collection}; consider - * using {@link DefaultListAdapter} instead. - * - * @param collection - * The collection containing the initial items of the sequence. A shallow copy of this collection is made - * immediately for internal use (thus, later modification on the parameter collection won't be visible in - * the resulting sequence). The items however, will be only wrapped with the {@link ObjectWrapper} - * lazily, when first needed. - * @param wrapper - * See the similar parameter of {@link SimpleSequence#SimpleSequence(ObjectWrapper)}. - */ - public SimpleSequence(Collection collection, ObjectWrapper wrapper) { - super(wrapper); - list = new ArrayList(collection); - } - - /** - * Adds an arbitrary object to the end of this sequence. If the newly added object does not implement the - * {@link TemplateModel} interface, it will be wrapped into the appropriate {@link TemplateModel} interface when - * it's first read (lazily). - * - * @param obj - * The object to be added. - */ - 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); - } - BeansWrapper bw = BeansWrapper.getDefaultInstance(); - for (int i = 0; i < list.size(); i++) { - Object elem = list.get(i); - if (elem instanceof TemplateModel) { - elem = bw.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. - */ - public TemplateModel get(int index) throws TemplateModelException { - try { - Object value = list.get(index); - if (value instanceof TemplateModel) { - return (TemplateModel) value; - } - TemplateModel tm = wrap(value); - list.set(index, tm); - return tm; - } catch (IndexOutOfBoundsException e) { - return null; - } - } - - public int size() { - 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
