http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/PrimtiveArrayBackedReadOnlyList.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/PrimtiveArrayBackedReadOnlyList.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/PrimtiveArrayBackedReadOnlyList.java deleted file mode 100644 index 2e8850d..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/PrimtiveArrayBackedReadOnlyList.java +++ /dev/null @@ -1,47 +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.beans; - -import java.lang.reflect.Array; -import java.util.AbstractList; - -/** - * Similar to {@link NonPrimitiveArrayBackedReadOnlyList}, but uses reflection so that it works with primitive arrays - * too. - */ -class PrimtiveArrayBackedReadOnlyList extends AbstractList { - - private final Object array; - - PrimtiveArrayBackedReadOnlyList(Object array) { - this.array = array; - } - - @Override - public Object get(int index) { - return Array.get(array, index); - } - - @Override - public int size() { - return Array.getLength(array); - } - -} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/ReflectionCallableMemberDescriptor.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/ReflectionCallableMemberDescriptor.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/ReflectionCallableMemberDescriptor.java deleted file mode 100644 index 5cf0676..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/ReflectionCallableMemberDescriptor.java +++ /dev/null @@ -1,95 +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.beans; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateModelException; - -/** - * The most commonly used {@link CallableMemberDescriptor} implementation. - */ -final class ReflectionCallableMemberDescriptor extends CallableMemberDescriptor { - - private final Member/*Method|Constructor*/ member; - - /** - * Don't modify this array! - */ - final Class[] paramTypes; - - ReflectionCallableMemberDescriptor(Method member, Class[] paramTypes) { - this.member = member; - this.paramTypes = paramTypes; - } - - ReflectionCallableMemberDescriptor(Constructor member, Class[] paramTypes) { - this.member = member; - this.paramTypes = paramTypes; - } - - @Override - TemplateModel invokeMethod(BeansWrapper bw, Object obj, Object[] args) - throws TemplateModelException, InvocationTargetException, IllegalAccessException { - return bw.invokeMethod(obj, (Method) member, args); - } - - @Override - Object invokeConstructor(BeansWrapper bw, Object[] args) - throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { - return ((Constructor) member).newInstance(args); - } - - @Override - String getDeclaration() { - return _MethodUtil.toString(member); - } - - @Override - boolean isConstructor() { - return member instanceof Constructor; - } - - @Override - boolean isStatic() { - return (member.getModifiers() & Modifier.STATIC) != 0; - } - - @Override - boolean isVarargs() { - return _MethodUtil.isVarargs(member); - } - - @Override - Class[] getParamTypes() { - return paramTypes; - } - - @Override - String getName() { - return member.getName(); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/ResourceBundleModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/ResourceBundleModel.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/ResourceBundleModel.java deleted file mode 100644 index a79e786..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/ResourceBundleModel.java +++ /dev/null @@ -1,190 +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.beans; - -import java.text.MessageFormat; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.MissingResourceException; -import java.util.ResourceBundle; -import java.util.Set; - -import org.apache.freemarker.core._DelayedJQuote; -import org.apache.freemarker.core._TemplateModelException; -import org.apache.freemarker.core.model.ObjectWrapper; -import org.apache.freemarker.core.model.TemplateMethodModelEx; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateModelException; - -/** - * <p>A hash model that wraps a resource bundle. Makes it convenient to store - * localized content in the data model. It also acts as a method model that will - * take a resource key and arbitrary number of arguments and will apply - * {@link MessageFormat} with arguments on the string represented by the key.</p> - * - * <p>Typical usages:</p> - * <ul> - * <li><tt>bundle.resourceKey</tt> will retrieve the object from resource bundle - * with key <tt>resourceKey</tt></li> - * <li><tt>bundle("patternKey", arg1, arg2, arg3)</tt> will retrieve the string - * from resource bundle with key <tt>patternKey</tt>, and will use it as a pattern - * for MessageFormat with arguments arg1, arg2 and arg3</li> - * </ul> - */ -public class ResourceBundleModel - extends - BeanModel - implements - TemplateMethodModelEx { - static final ModelFactory FACTORY = - new ModelFactory() - { - @Override - public TemplateModel create(Object object, ObjectWrapper wrapper) { - return new ResourceBundleModel((ResourceBundle) object, (BeansWrapper) wrapper); - } - }; - - private Hashtable formats = null; - - public ResourceBundleModel(ResourceBundle bundle, BeansWrapper wrapper) { - super(bundle, wrapper); - } - - /** - * Overridden to invoke the getObject method of the resource bundle. - */ - @Override - protected TemplateModel invokeGenericGet(Map keyMap, Class clazz, String key) - throws TemplateModelException { - try { - return wrap(((ResourceBundle) object).getObject(key)); - } catch (MissingResourceException e) { - throw new _TemplateModelException(e, - "No ", new _DelayedJQuote(key), " key in the ResourceBundle. " - + "Note that conforming to the ResourceBundle Java API, this is an error and not just " - + "a missing sub-variable (a null)."); - } - } - - /** - * Returns true if this bundle contains no objects. - */ - @Override - public boolean isEmpty() { - return !((ResourceBundle) object).getKeys().hasMoreElements() && - super.isEmpty(); - } - - @Override - public int size() { - return keySet().size(); - } - - @Override - protected Set keySet() { - Set set = super.keySet(); - Enumeration e = ((ResourceBundle) object).getKeys(); - while (e.hasMoreElements()) { - set.add(e.nextElement()); - } - return set; - } - - /** - * Takes first argument as a resource key, looks up a string in resource bundle - * with this key, then applies a MessageFormat.format on the string with the - * rest of the arguments. The created MessageFormats are cached for later reuse. - */ - @Override - public Object exec(List arguments) - throws TemplateModelException { - // Must have at least one argument - the key - if (arguments.size() < 1) - throw new TemplateModelException("No message key was specified"); - // Read it - Iterator it = arguments.iterator(); - String key = unwrap((TemplateModel) it.next()).toString(); - try { - if (!it.hasNext()) { - return wrap(((ResourceBundle) object).getObject(key)); - } - - // Copy remaining arguments into an Object[] - int args = arguments.size() - 1; - Object[] params = new Object[args]; - for (int i = 0; i < args; ++i) - params[i] = unwrap((TemplateModel) it.next()); - - // Invoke format - return new StringModel(format(key, params), wrapper); - } catch (MissingResourceException e) { - throw new TemplateModelException("No such key: " + key); - } catch (Exception e) { - throw new TemplateModelException(e.getMessage()); - } - } - - /** - * Provides direct access to caching format engine from code (instead of from script). - */ - public String format(String key, Object[] params) - throws MissingResourceException { - // Check to see if we already have a cache for message formats - // and construct it if we don't - // NOTE: this block statement should be synchronized. However - // concurrent creation of two caches will have no harmful - // consequences, and we avoid a performance hit. - /* synchronized(this) */ - { - if (formats == null) - formats = new Hashtable(); - } - - MessageFormat format = null; - // Check to see if we already have a requested MessageFormat cached - // and construct it if we don't - // NOTE: this block statement should be synchronized. However - // concurrent creation of two formats will have no harmful - // consequences, and we avoid a performance hit. - /* synchronized(formats) */ - { - format = (MessageFormat) formats.get(key); - if (format == null) { - format = new MessageFormat(((ResourceBundle) object).getString(key)); - format.setLocale(getBundle().getLocale()); - formats.put(key, format); - } - } - - // Perform the formatting. We synchronize on it in case it - // contains date formatting, which is not thread-safe. - synchronized (format) { - return format.format(params); - } - } - - public ResourceBundle getBundle() { - return (ResourceBundle) object; - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/SequenceAdapter.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/SequenceAdapter.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/SequenceAdapter.java deleted file mode 100644 index 7f66cf9..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/SequenceAdapter.java +++ /dev/null @@ -1,68 +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.beans; - -import java.util.AbstractList; - -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.TemplateSequenceModel; -import org.apache.freemarker.core.util.UndeclaredThrowableException; - -/** - */ -class SequenceAdapter extends AbstractList implements TemplateModelAdapter { - private final BeansWrapper wrapper; - private final TemplateSequenceModel model; - - SequenceAdapter(TemplateSequenceModel model, BeansWrapper wrapper) { - this.model = model; - this.wrapper = wrapper; - } - - @Override - public TemplateModel getTemplateModel() { - return model; - } - - @Override - public int size() { - try { - return model.size(); - } catch (TemplateModelException e) { - throw new UndeclaredThrowableException(e); - } - } - - @Override - public Object get(int index) { - try { - return wrapper.unwrap(model.get(index)); - } catch (TemplateModelException e) { - throw new UndeclaredThrowableException(e); - } - } - - public TemplateSequenceModel getTemplateSequenceModel() { - return model; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/SetAdapter.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/SetAdapter.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/SetAdapter.java deleted file mode 100644 index 2d65efa..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/SetAdapter.java +++ /dev/null @@ -1,32 +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.beans; - -import java.util.Set; - -import org.apache.freemarker.core.model.TemplateCollectionModel; - -/** - */ -class SetAdapter extends CollectionAdapter implements Set { - SetAdapter(TemplateCollectionModel model, BeansWrapper wrapper) { - super(model, wrapper); - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/SimpleMapModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/SimpleMapModel.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/SimpleMapModel.java deleted file mode 100644 index 80e04f7..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/SimpleMapModel.java +++ /dev/null @@ -1,132 +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.beans; - -import java.util.List; -import java.util.Map; - -import org.apache.freemarker.core.model.AdapterTemplateModel; -import org.apache.freemarker.core.model.ObjectWrapper; -import org.apache.freemarker.core.model.RichObjectWrapper; -import org.apache.freemarker.core.model.TemplateCollectionModel; -import org.apache.freemarker.core.model.TemplateHashModelEx2; -import org.apache.freemarker.core.model.TemplateMethodModelEx; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateModelException; -import org.apache.freemarker.core.model.TemplateModelWithAPISupport; -import org.apache.freemarker.core.model.WrapperTemplateModel; -import org.apache.freemarker.core.model.WrappingTemplateModel; -import org.apache.freemarker.core.model.impl.CollectionAndSequence; -import org.apache.freemarker.core.model.impl.MapKeyValuePairIterator; -import org.apache.freemarker.core.model.impl.SimpleSequence; - -/** - * Model used by {@link BeansWrapper} when <tt>simpleMapWrapper</tt> - * mode is enabled. Provides a simple hash model interface to the - * underlying map (does not copy like {@link org.apache.freemarker.core.model.impl.SimpleHash}), - * and a method interface to non-string keys. - */ -public class SimpleMapModel extends WrappingTemplateModel -implements TemplateHashModelEx2, TemplateMethodModelEx, AdapterTemplateModel, -WrapperTemplateModel, TemplateModelWithAPISupport { - static final ModelFactory FACTORY = - new ModelFactory() - { - @Override - public TemplateModel create(Object object, ObjectWrapper wrapper) { - return new SimpleMapModel((Map) object, (BeansWrapper) wrapper); - } - }; - - private final Map map; - - public SimpleMapModel(Map map, BeansWrapper wrapper) { - super(wrapper); - this.map = map; - } - - @Override - public TemplateModel get(String key) throws TemplateModelException { - Object val = map.get(key); - if (val == null) { - if (key.length() == 1) { - // just check for Character key if this is a single-character string - Character charKey = Character.valueOf(key.charAt(0)); - val = map.get(charKey); - if (val == null && !(map.containsKey(key) || map.containsKey(charKey))) { - return null; - } - } else if (!map.containsKey(key)) { - return null; - } - } - return wrap(val); - } - - @Override - public Object exec(List args) throws TemplateModelException { - Object key = ((BeansWrapper) getObjectWrapper()).unwrap((TemplateModel) args.get(0)); - Object value = map.get(key); - if (value == null && !map.containsKey(key)) { - return null; - } - return wrap(value); - } - - @Override - public boolean isEmpty() { - return map.isEmpty(); - } - - @Override - public int size() { - return map.size(); - } - - @Override - public TemplateCollectionModel keys() { - return new CollectionAndSequence(new SimpleSequence(map.keySet(), getObjectWrapper())); - } - - @Override - public TemplateCollectionModel values() { - return new CollectionAndSequence(new SimpleSequence(map.values(), getObjectWrapper())); - } - - @Override - public KeyValuePairIterator keyValuePairIterator() { - return new MapKeyValuePairIterator(map, getObjectWrapper()); - } - - @Override - public Object getAdaptedObject(Class hint) { - return map; - } - - @Override - public Object getWrappedObject() { - return map; - } - - @Override - public TemplateModel getAPI() throws TemplateModelException { - return ((RichObjectWrapper) getObjectWrapper()).wrapAsAPI(map); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/SimpleMethod.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/SimpleMethod.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/SimpleMethod.java deleted file mode 100644 index f863486..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/SimpleMethod.java +++ /dev/null @@ -1,174 +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.beans; - -import java.lang.reflect.Array; -import java.lang.reflect.Member; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.apache.freemarker.core._DelayedFTLTypeDescription; -import org.apache.freemarker.core._DelayedOrdinal; -import org.apache.freemarker.core._ErrorDescriptionBuilder; -import org.apache.freemarker.core._TemplateModelException; -import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper; -import org.apache.freemarker.core.model.TemplateMarkupOutputModel; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateModelException; -import org.apache.freemarker.core.util._ClassUtil; - -/** - * This class is used for as a base for non-overloaded method models and for constructors. - * (For overloaded methods and constructors see {@link OverloadedMethods}.) - */ -class SimpleMethod { - - static final String MARKUP_OUTPUT_TO_STRING_TIP - = "A markup output value can be converted to markup string like value?markup_string. " - + "But consider if the Java method whose argument it will be can handle markup strings properly."; - - private final Member member; - private final Class[] argTypes; - - protected SimpleMethod(Member member, Class[] argTypes) { - this.member = member; - this.argTypes = argTypes; - } - - Object[] unwrapArguments(List arguments, BeansWrapper wrapper) throws TemplateModelException { - if (arguments == null) { - arguments = Collections.EMPTY_LIST; - } - boolean isVarArg = _MethodUtil.isVarargs(member); - int typesLen = argTypes.length; - if (isVarArg) { - if (typesLen - 1 > arguments.size()) { - throw new _TemplateModelException( - _MethodUtil.invocationErrorMessageStart(member), - " takes at least ", Integer.valueOf(typesLen - 1), - typesLen - 1 == 1 ? " argument" : " arguments", ", but ", - Integer.valueOf(arguments.size()), " was given."); - } - } else if (typesLen != arguments.size()) { - throw new _TemplateModelException( - _MethodUtil.invocationErrorMessageStart(member), - " takes ", Integer.valueOf(typesLen), typesLen == 1 ? " argument" : " arguments", ", but ", - Integer.valueOf(arguments.size()), " was given."); - } - - return unwrapArguments(arguments, argTypes, isVarArg, wrapper); - } - - private Object[] unwrapArguments(List args, Class[] argTypes, boolean isVarargs, - BeansWrapper w) - throws TemplateModelException { - if (args == null) return null; - - int typesLen = argTypes.length; - int argsLen = args.size(); - - Object[] unwrappedArgs = new Object[typesLen]; - - // Unwrap arguments: - Iterator it = args.iterator(); - int normalArgCnt = isVarargs ? typesLen - 1 : typesLen; - int argIdx = 0; - while (argIdx < normalArgCnt) { - Class argType = argTypes[argIdx]; - TemplateModel argVal = (TemplateModel) it.next(); - Object unwrappedArgVal = w.tryUnwrapTo(argVal, argType); - if (unwrappedArgVal == ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS) { - throw createArgumentTypeMismarchException(argIdx, argVal, argType); - } - if (unwrappedArgVal == null && argType.isPrimitive()) { - throw createNullToPrimitiveArgumentException(argIdx, argType); - } - - unwrappedArgs[argIdx++] = unwrappedArgVal; - } - if (isVarargs) { - // The last argType, which is the vararg type, wasn't processed yet. - - Class varargType = argTypes[typesLen - 1]; - Class varargItemType = varargType.getComponentType(); - if (!it.hasNext()) { - unwrappedArgs[argIdx++] = Array.newInstance(varargItemType, 0); - } else { - TemplateModel argVal = (TemplateModel) it.next(); - - Object unwrappedArgVal; - // We first try to treat the last argument as a vararg *array*. - // This is consistent to what OverloadedVarArgMethod does. - if (argsLen - argIdx == 1 - && (unwrappedArgVal = w.tryUnwrapTo(argVal, varargType)) - != ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS) { - // It was a vararg array. - unwrappedArgs[argIdx++] = unwrappedArgVal; - } else { - // It wasn't a vararg array, so we assume it's a vararg - // array *item*, possibly followed by further ones. - int varargArrayLen = argsLen - argIdx; - Object varargArray = Array.newInstance(varargItemType, varargArrayLen); - for (int varargIdx = 0; varargIdx < varargArrayLen; varargIdx++) { - TemplateModel varargVal = (TemplateModel) (varargIdx == 0 ? argVal : it.next()); - Object unwrappedVarargVal = w.tryUnwrapTo(varargVal, varargItemType); - if (unwrappedVarargVal == ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS) { - throw createArgumentTypeMismarchException( - argIdx + varargIdx, varargVal, varargItemType); - } - - if (unwrappedVarargVal == null && varargItemType.isPrimitive()) { - throw createNullToPrimitiveArgumentException(argIdx + varargIdx, varargItemType); - } - Array.set(varargArray, varargIdx, unwrappedVarargVal); - } - unwrappedArgs[argIdx++] = varargArray; - } - } - } - - return unwrappedArgs; - } - - private TemplateModelException createArgumentTypeMismarchException( - int argIdx, TemplateModel argVal, Class targetType) { - _ErrorDescriptionBuilder desc = new _ErrorDescriptionBuilder( - _MethodUtil.invocationErrorMessageStart(member), " couldn't be called: Can't convert the ", - new _DelayedOrdinal(Integer.valueOf(argIdx + 1)), - " argument's value to the target Java type, ", _ClassUtil.getShortClassName(targetType), - ". The type of the actual value was: ", new _DelayedFTLTypeDescription(argVal)); - if (argVal instanceof TemplateMarkupOutputModel && (targetType.isAssignableFrom(String.class))) { - desc.tip(MARKUP_OUTPUT_TO_STRING_TIP); - } - return new _TemplateModelException(desc); - } - - private TemplateModelException createNullToPrimitiveArgumentException(int argIdx, Class targetType) { - return new _TemplateModelException( - _MethodUtil.invocationErrorMessageStart(member), " couldn't be called: The value of the ", - new _DelayedOrdinal(Integer.valueOf(argIdx + 1)), - " argument was null, but the target Java parameter type (", _ClassUtil.getShortClassName(targetType), - ") is primitive and so can't store null."); - } - - protected Member getMember() { - return member; - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/SimpleMethodModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/SimpleMethodModel.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/SimpleMethodModel.java deleted file mode 100644 index 32c2bc2..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/SimpleMethodModel.java +++ /dev/null @@ -1,134 +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.beans; - -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.List; - -import org.apache.freemarker.core._UnexpectedTypeErrorExplainerTemplateModel; -import org.apache.freemarker.core.model.TemplateMethodModelEx; -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.SimpleNumber; -import org.apache.freemarker.core.util.FTLUtil; - -/** - * A class that will wrap a reflected method call into a - * {@link org.apache.freemarker.core.model.TemplateMethodModel} interface. - * It is used by {@link BeanModel} to wrap reflected method calls - * for non-overloaded methods. - */ -public final class SimpleMethodModel extends SimpleMethod - implements - TemplateMethodModelEx, - TemplateSequenceModel, - _UnexpectedTypeErrorExplainerTemplateModel { - private final Object object; - private final BeansWrapper wrapper; - - /** - * Creates a model for a specific method on a specific object. - * @param object the object to call the method on, or {@code null} for a static method. - * @param method the method that will be invoked. - * @param argTypes Either pass in {@code Method#getParameterTypes() method.getParameterTypes()} here, - * or reuse an earlier result of that call (for speed). Not {@code null}. - */ - SimpleMethodModel(Object object, Method method, Class[] argTypes, - BeansWrapper wrapper) { - super(method, argTypes); - this.object = object; - this.wrapper = wrapper; - } - - /** - * Invokes the method, passing it the arguments from the list. - */ - @Override - public Object exec(List arguments) - throws TemplateModelException { - try { - return wrapper.invokeMethod(object, (Method) getMember(), - unwrapArguments(arguments, wrapper)); - } catch (TemplateModelException e) { - throw e; - } catch (Exception e) { - throw _MethodUtil.newInvocationTemplateModelException(object, getMember(), e); - } - } - - @Override - public TemplateModel get(int index) throws TemplateModelException { - return (TemplateModel) exec(Collections.singletonList( - new SimpleNumber(Integer.valueOf(index)))); - } - - @Override - public int size() throws TemplateModelException { - throw new TemplateModelException( - "Getting the number of items or enumerating the items is not supported on this " - + FTLUtil.getTypeDescription(this) + " value.\n" - + "(" - + "Hint 1: Maybe you wanted to call this method first and then do something with its return value. " - + "Hint 2: Getting items by intex possibly works, hence it's a \"+sequence\"." - + ")"); - } - - @Override - public String toString() { - return getMember().toString(); - } - - /** - * Implementation of experimental interface; don't use it, no backward compatibility guarantee! - */ - @Override - public Object[] explainTypeError(Class[] expectedClasses) { - final Member member = getMember(); - if (!(member instanceof Method)) { - return null; // This shouldn't occur - } - Method m = (Method) member; - - final Class returnType = m.getReturnType(); - if (returnType == null || returnType == void.class || returnType == Void.class) { - return null; // Calling it won't help - } - - String mName = m.getName(); - if (mName.startsWith("get") && mName.length() > 3 && Character.isUpperCase(mName.charAt(3)) - && (m.getParameterTypes().length == 0)) { - return new Object[] { - "Maybe using obj.something instead of obj.getSomething will yield the desired value." }; - } else if (mName.startsWith("is") && mName.length() > 2 && Character.isUpperCase(mName.charAt(2)) - && (m.getParameterTypes().length == 0)) { - return new Object[] { - "Maybe using obj.something instead of obj.isSomething will yield the desired value." }; - } else { - return new Object[] { - "Maybe using obj.something(", - (m.getParameterTypes().length != 0 ? "params" : ""), - ") instead of obj.something will yield the desired value" }; - } - } - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/SingletonCustomizer.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/SingletonCustomizer.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/SingletonCustomizer.java deleted file mode 100644 index df2a6c3..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/SingletonCustomizer.java +++ /dev/null @@ -1,51 +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.beans; - -import org.apache.freemarker.core.model.ObjectWrapper; - -/** - * Marker interface useful when used together with {@link MethodAppearanceFineTuner} and such customizer objects, to - * indicate that it <b>doesn't contain reference to the {@link ObjectWrapper}</b> (so beware with non-static inner - * classes) and can be and should be used in call introspection cache keys. This also implies that you won't - * create many instances of the class, rather just reuse the same (or same few) instances over and over. Furthermore, - * the instances must be thread-safe. The typical pattern in which this instance should be used is like this: - * - * <pre>static class MyMethodAppearanceFineTuner implements MethodAppearanceFineTuner, SingletonCustomizer { - * - * // This is the singleton: - * static final MyMethodAppearanceFineTuner INSTANCE = new MyMethodAppearanceFineTuner(); - * - * // Private, so it can't be constructed from outside this class. - * private MyMethodAppearanceFineTuner() { } - * - * @Override - * public void fineTuneMethodAppearance(...) { - * // Do something here, only using the parameters and maybe some other singletons. - * ... - * } - * - * }</pre> - * - * @since 2.3.21 - */ -public interface SingletonCustomizer { - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/StaticModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/StaticModel.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/StaticModel.java deleted file mode 100644 index a302d8b..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/StaticModel.java +++ /dev/null @@ -1,177 +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.beans; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import org.apache.freemarker.core._CoreLogs; -import org.apache.freemarker.core.model.TemplateCollectionModel; -import org.apache.freemarker.core.model.TemplateHashModelEx; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateModelException; -import org.slf4j.Logger; - -/** - * Wraps the static fields and methods of a class in a - * {@link org.apache.freemarker.core.model.TemplateHashModel}. - * Fields are wrapped using {@link BeansWrapper#wrap(Object)}, and - * methods are wrapped into an appropriate {@link org.apache.freemarker.core.model.TemplateMethodModelEx} instance. - * Unfortunately, there is currently no support for bean property-style - * calls of static methods, similar to that in {@link BeanModel}. - */ -final class StaticModel implements TemplateHashModelEx { - - private static final Logger LOG = _CoreLogs.BEANS_WRAPPER; - - private final Class clazz; - private final BeansWrapper wrapper; - private final Map map = new HashMap(); - - StaticModel(Class clazz, BeansWrapper wrapper) throws TemplateModelException { - this.clazz = clazz; - this.wrapper = wrapper; - populate(); - } - - /** - * Returns the field or method named by the <tt>key</tt> - * parameter. - */ - @Override - public TemplateModel get(String key) throws TemplateModelException { - Object model = map.get(key); - // Simple method, overloaded method or final field -- these have cached - // template models - if (model instanceof TemplateModel) - return (TemplateModel) model; - // Non-final field; this must be evaluated on each call. - if (model instanceof Field) { - try { - return wrapper.getOuterIdentity().wrap(((Field) model).get(null)); - } catch (IllegalAccessException e) { - throw new TemplateModelException( - "Illegal access for field " + key + " of class " + clazz.getName()); - } - } - - throw new TemplateModelException( - "No such key: " + key + " in class " + clazz.getName()); - } - - /** - * Returns true if there is at least one public static - * field or method in the underlying class. - */ - @Override - public boolean isEmpty() { - return map.isEmpty(); - } - - @Override - public int size() { - return map.size(); - } - - @Override - public TemplateCollectionModel keys() throws TemplateModelException { - return (TemplateCollectionModel) wrapper.getOuterIdentity().wrap(map.keySet()); - } - - @Override - public TemplateCollectionModel values() throws TemplateModelException { - return (TemplateCollectionModel) wrapper.getOuterIdentity().wrap(map.values()); - } - - private void populate() throws TemplateModelException { - if (!Modifier.isPublic(clazz.getModifiers())) { - throw new TemplateModelException( - "Can't wrap the non-public class " + clazz.getName()); - } - - if (wrapper.getExposureLevel() == BeansWrapper.EXPOSE_NOTHING) { - return; - } - - Field[] fields = clazz.getFields(); - for (Field field : fields) { - int mod = field.getModifiers(); - if (Modifier.isPublic(mod) && Modifier.isStatic(mod)) { - if (Modifier.isFinal(mod)) - try { - // public static final fields are evaluated once and - // stored in the map - map.put(field.getName(), wrapper.getOuterIdentity().wrap(field.get(null))); - } catch (IllegalAccessException e) { - // Intentionally ignored - } - else - // This is a special flagging value: Field in the map means - // that this is a non-final field, and it must be evaluated - // on each get() call. - map.put(field.getName(), field); - } - } - if (wrapper.getExposureLevel() < BeansWrapper.EXPOSE_PROPERTIES_ONLY) { - Method[] methods = clazz.getMethods(); - for (Method method : methods) { - int mod = method.getModifiers(); - if (Modifier.isPublic(mod) && Modifier.isStatic(mod) - && wrapper.getClassIntrospector().isAllowedToExpose(method)) { - String name = method.getName(); - Object obj = map.get(name); - if (obj instanceof Method) { - OverloadedMethods overloadedMethods = new OverloadedMethods(); - overloadedMethods.addMethod((Method) obj); - overloadedMethods.addMethod(method); - map.put(name, overloadedMethods); - } else if (obj instanceof OverloadedMethods) { - OverloadedMethods overloadedMethods = (OverloadedMethods) obj; - overloadedMethods.addMethod(method); - } else { - if (obj != null) { - if (LOG.isInfoEnabled()) { - LOG.info("Overwriting value [" + obj + "] for " + - " key '" + name + "' with [" + method + - "] in static model for " + clazz.getName()); - } - } - map.put(name, method); - } - } - } - for (Iterator entries = map.entrySet().iterator(); entries.hasNext(); ) { - Map.Entry entry = (Map.Entry) entries.next(); - Object value = entry.getValue(); - if (value instanceof Method) { - Method method = (Method) value; - entry.setValue(new SimpleMethodModel(null, method, - method.getParameterTypes(), wrapper)); - } else if (value instanceof OverloadedMethods) { - entry.setValue(new OverloadedMethodsModel(null, (OverloadedMethods) value, wrapper)); - } - } - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/StaticModels.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/StaticModels.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/StaticModels.java deleted file mode 100644 index f89fda8..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/StaticModels.java +++ /dev/null @@ -1,43 +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.beans; - -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateModelException; - -/** - * Utility class for instantiating {@link StaticModel} instances from - * templates. If your template's data model contains an instance of - * StaticModels (named, say <tt>StaticModels</tt>), then you can - * instantiate an arbitrary StaticModel using get syntax (i.e. - * <tt>StaticModels["java.lang.System"].currentTimeMillis()</tt>). - */ -class StaticModels extends ClassBasedModelFactory { - - StaticModels(BeansWrapper wrapper) { - super(wrapper); - } - - @Override - protected TemplateModel createModel(Class clazz) - throws TemplateModelException { - return new StaticModel(clazz, getWrapper()); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/StringModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/StringModel.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/StringModel.java deleted file mode 100644 index 0591f6e..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/StringModel.java +++ /dev/null @@ -1,63 +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.beans; - -import org.apache.freemarker.core.model.ObjectWrapper; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateScalarModel; - -/** - * Subclass of {@link BeanModel} that exposes the return value of the {@link - * java.lang.Object#toString()} method through the {@link TemplateScalarModel} - * interface. - */ -public class StringModel extends BeanModel -implements TemplateScalarModel { - static final ModelFactory FACTORY = - new ModelFactory() - { - @Override - public TemplateModel create(Object object, ObjectWrapper wrapper) { - return new StringModel(object, (BeansWrapper) wrapper); - } - }; - - /** - * Creates a new model that wraps the specified object with BeanModel + scalar - * functionality. - * @param object the object to wrap into a model. - * @param wrapper the {@link BeansWrapper} associated with this model. - * Every model has to have an associated {@link BeansWrapper} instance. The - * model gains many attributes from its wrapper, including the caching - * behavior, method exposure level, method-over-item shadowing policy etc. - */ - public StringModel(Object object, BeansWrapper wrapper) { - super(object, wrapper); - } - - /** - * Returns the result of calling {@link Object#toString()} on the wrapped - * object. - */ - @Override - public String getAsString() { - return object.toString(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/TypeFlags.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/TypeFlags.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/TypeFlags.java deleted file mode 100644 index e836e47..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/TypeFlags.java +++ /dev/null @@ -1,130 +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.beans; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Flag values and masks for "type flags". "Type flags" is a set of bits that store information about the possible - * destination types at a parameter position of overloaded methods. - */ -class TypeFlags { - - /** - * Indicates that the unwrapping hint will not be a specific numerical type; it must not be set if there's no - * numerical type at the given parameter index. - */ - static final int WIDENED_NUMERICAL_UNWRAPPING_HINT = 1; - - static final int BYTE = 4; - static final int SHORT = 8; - static final int INTEGER = 16; - static final int LONG = 32; - static final int FLOAT = 64; - static final int DOUBLE = 128; - static final int BIG_INTEGER = 256; - static final int BIG_DECIMAL = 512; - static final int UNKNOWN_NUMERICAL_TYPE = 1024; - - static final int ACCEPTS_NUMBER = 0x800; - static final int ACCEPTS_DATE = 0x1000; - static final int ACCEPTS_STRING = 0x2000; - static final int ACCEPTS_BOOLEAN = 0x4000; - static final int ACCEPTS_MAP = 0x8000; - static final int ACCEPTS_LIST = 0x10000; - static final int ACCEPTS_SET = 0x20000; - static final int ACCEPTS_ARRAY = 0x40000; - - /** - * Indicates the presence of the char or Character type - */ - static final int CHARACTER = 0x80000; - - static final int ACCEPTS_ANY_OBJECT = ACCEPTS_NUMBER | ACCEPTS_DATE | ACCEPTS_STRING | ACCEPTS_BOOLEAN - | ACCEPTS_MAP | ACCEPTS_LIST | ACCEPTS_SET | ACCEPTS_ARRAY; - - static final int MASK_KNOWN_INTEGERS = BYTE | SHORT | INTEGER | LONG | BIG_INTEGER; - static final int MASK_KNOWN_NONINTEGERS = FLOAT | DOUBLE | BIG_DECIMAL; - static final int MASK_ALL_KNOWN_NUMERICALS = MASK_KNOWN_INTEGERS | MASK_KNOWN_NONINTEGERS; - static final int MASK_ALL_NUMERICALS = MASK_ALL_KNOWN_NUMERICALS | UNKNOWN_NUMERICAL_TYPE; - - static int classToTypeFlags(Class pClass) { - // We start with the most frequent cases - if (pClass == Object.class) { - return ACCEPTS_ANY_OBJECT; - } else if (pClass == String.class) { - return ACCEPTS_STRING; - } else if (pClass.isPrimitive()) { - if (pClass == Integer.TYPE) return INTEGER | ACCEPTS_NUMBER; - else if (pClass == Long.TYPE) return LONG | ACCEPTS_NUMBER; - else if (pClass == Double.TYPE) return DOUBLE | ACCEPTS_NUMBER; - else if (pClass == Float.TYPE) return FLOAT | ACCEPTS_NUMBER; - else if (pClass == Byte.TYPE) return BYTE | ACCEPTS_NUMBER; - else if (pClass == Short.TYPE) return SHORT | ACCEPTS_NUMBER; - else if (pClass == Character.TYPE) return CHARACTER; - else if (pClass == Boolean.TYPE) return ACCEPTS_BOOLEAN; - else return 0; - } else if (Number.class.isAssignableFrom(pClass)) { - if (pClass == Integer.class) return INTEGER | ACCEPTS_NUMBER; - else if (pClass == Long.class) return LONG | ACCEPTS_NUMBER; - else if (pClass == Double.class) return DOUBLE | ACCEPTS_NUMBER; - else if (pClass == Float.class) return FLOAT | ACCEPTS_NUMBER; - else if (pClass == Byte.class) return BYTE | ACCEPTS_NUMBER; - else if (pClass == Short.class) return SHORT | ACCEPTS_NUMBER; - else if (BigDecimal.class.isAssignableFrom(pClass)) return BIG_DECIMAL | ACCEPTS_NUMBER; - else if (BigInteger.class.isAssignableFrom(pClass)) return BIG_INTEGER | ACCEPTS_NUMBER; - else return UNKNOWN_NUMERICAL_TYPE | ACCEPTS_NUMBER; - } else if (pClass.isArray()) { - return ACCEPTS_ARRAY; - } else { - int flags = 0; - if (pClass.isAssignableFrom(String.class)) { - flags |= ACCEPTS_STRING; - } - if (pClass.isAssignableFrom(Date.class)) { - flags |= ACCEPTS_DATE; - } - if (pClass.isAssignableFrom(Boolean.class)) { - flags |= ACCEPTS_BOOLEAN; - } - if (pClass.isAssignableFrom(Map.class)) { - flags |= ACCEPTS_MAP; - } - if (pClass.isAssignableFrom(List.class)) { - flags |= ACCEPTS_LIST; - } - if (pClass.isAssignableFrom(Set.class)) { - flags |= ACCEPTS_SET; - } - - if (pClass == Character.class) { - flags |= CHARACTER; - } - - return flags; - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/UnsafeMethods.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/UnsafeMethods.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/UnsafeMethods.java deleted file mode 100644 index 93b7f3c..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/UnsafeMethods.java +++ /dev/null @@ -1,112 +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.beans; - -import java.io.InputStream; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.StringTokenizer; - -import org.apache.freemarker.core._CoreLogs; -import org.apache.freemarker.core.util._ClassUtil; -import org.slf4j.Logger; - -class UnsafeMethods { - - private static final Logger LOG = _CoreLogs.BEANS_WRAPPER; - private static final String UNSAFE_METHODS_PROPERTIES = "unsafeMethods.properties"; - private static final Set UNSAFE_METHODS = createUnsafeMethodsSet(); - - private UnsafeMethods() { } - - static boolean isUnsafeMethod(Method method) { - return UNSAFE_METHODS.contains(method); - } - - private static Set createUnsafeMethodsSet() { - Properties props = new Properties(); - InputStream in = BeansWrapper.class.getResourceAsStream(UNSAFE_METHODS_PROPERTIES); - if (in == null) { - throw new IllegalStateException("Class loader resource not found: " - + BeansWrapper.class.getPackage().getName() + UNSAFE_METHODS_PROPERTIES); - } - String methodSpec = null; - try { - try { - props.load(in); - } finally { - in.close(); - } - Set set = new HashSet(props.size() * 4 / 3, 1f); - Map primClasses = createPrimitiveClassesMap(); - for (Iterator iterator = props.keySet().iterator(); iterator.hasNext(); ) { - methodSpec = (String) iterator.next(); - try { - set.add(parseMethodSpec(methodSpec, primClasses)); - } catch (ClassNotFoundException | NoSuchMethodException e) { - LOG.debug("Failed to get unsafe method", e); - } - } - return set; - } catch (Exception e) { - throw new RuntimeException("Could not load unsafe method " + methodSpec + " " + e.getClass().getName() + " " + e.getMessage()); - } - } - - private static Method parseMethodSpec(String methodSpec, Map primClasses) - throws ClassNotFoundException, - NoSuchMethodException { - int brace = methodSpec.indexOf('('); - int dot = methodSpec.lastIndexOf('.', brace); - Class clazz = _ClassUtil.forName(methodSpec.substring(0, dot)); - String methodName = methodSpec.substring(dot + 1, brace); - String argSpec = methodSpec.substring(brace + 1, methodSpec.length() - 1); - StringTokenizer tok = new StringTokenizer(argSpec, ","); - int argcount = tok.countTokens(); - Class[] argTypes = new Class[argcount]; - for (int i = 0; i < argcount; i++) { - String argClassName = tok.nextToken(); - argTypes[i] = (Class) primClasses.get(argClassName); - if (argTypes[i] == null) { - argTypes[i] = _ClassUtil.forName(argClassName); - } - } - return clazz.getMethod(methodName, argTypes); - } - - private static Map createPrimitiveClassesMap() { - Map map = new HashMap(); - map.put("boolean", Boolean.TYPE); - map.put("byte", Byte.TYPE); - map.put("char", Character.TYPE); - map.put("short", Short.TYPE); - map.put("int", Integer.TYPE); - map.put("long", Long.TYPE); - map.put("float", Float.TYPE); - map.put("double", Double.TYPE); - return map; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/_BeansAPI.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/_BeansAPI.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/_BeansAPI.java deleted file mode 100644 index cac3ba7..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/_BeansAPI.java +++ /dev/null @@ -1,220 +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.beans; - -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.lang.reflect.Array; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.freemarker.core.model.TemplateModelException; -import org.apache.freemarker.core.model.impl.DefaultObjectWrapper; -import org.apache.freemarker.core.util.BugException; -import org.apache.freemarker.core.util._CollectionUtil; - -/** - * For internal use only; don't depend on this, there's no backward compatibility guarantee at all! - * This class is to work around the lack of module system in Java, i.e., so that other FreeMarker packages can - * access things inside this package that users shouldn't. - */ -public class _BeansAPI { - - private _BeansAPI() { } - - public static Object newInstance(Class<?> pClass, Object[] args, BeansWrapper bw) - throws NoSuchMethodException, IllegalArgumentException, InstantiationException, - IllegalAccessException, InvocationTargetException, TemplateModelException { - return newInstance(getConstructorDescriptor(pClass, args), args, bw); - } - - /** - * Gets the constructor that matches the types of the arguments the best. So this is more - * than what the Java reflection API provides in that it can handle overloaded constructors. This re-uses the - * overloaded method selection logic of {@link BeansWrapper}. - */ - private static CallableMemberDescriptor getConstructorDescriptor(Class<?> pClass, Object[] args) - throws NoSuchMethodException { - if (args == null) args = _CollectionUtil.EMPTY_OBJECT_ARRAY; - - final ArgumentTypes argTypes = new ArgumentTypes(args); - final List<ReflectionCallableMemberDescriptor> fixedArgMemberDescs - = new ArrayList<>(); - final List<ReflectionCallableMemberDescriptor> varArgsMemberDescs - = new ArrayList<>(); - for (Constructor<?> constr : pClass.getConstructors()) { - ReflectionCallableMemberDescriptor memberDesc = new ReflectionCallableMemberDescriptor(constr, constr.getParameterTypes()); - if (!_MethodUtil.isVarargs(constr)) { - fixedArgMemberDescs.add(memberDesc); - } else { - varArgsMemberDescs.add(memberDesc); - } - } - - MaybeEmptyCallableMemberDescriptor contrDesc = argTypes.getMostSpecific(fixedArgMemberDescs, false); - if (contrDesc == EmptyCallableMemberDescriptor.NO_SUCH_METHOD) { - contrDesc = argTypes.getMostSpecific(varArgsMemberDescs, true); - } - - if (contrDesc instanceof EmptyCallableMemberDescriptor) { - if (contrDesc == EmptyCallableMemberDescriptor.NO_SUCH_METHOD) { - throw new NoSuchMethodException( - "There's no public " + pClass.getName() - + " constructor with compatible parameter list."); - } else if (contrDesc == EmptyCallableMemberDescriptor.AMBIGUOUS_METHOD) { - throw new NoSuchMethodException( - "There are multiple public " + pClass.getName() - + " constructors that match the compatible parameter list with the same preferability."); - } else { - throw new NoSuchMethodException(); - } - } else { - return (CallableMemberDescriptor) contrDesc; - } - } - - private static Object newInstance(CallableMemberDescriptor constrDesc, Object[] args, BeansWrapper bw) - throws InstantiationException, IllegalAccessException, InvocationTargetException, IllegalArgumentException, - TemplateModelException { - if (args == null) args = _CollectionUtil.EMPTY_OBJECT_ARRAY; - - final Object[] packedArgs; - if (constrDesc.isVarargs()) { - // We have to put all the varargs arguments into a single array argument. - - final Class<?>[] paramTypes = constrDesc.getParamTypes(); - final int fixedArgCnt = paramTypes.length - 1; - - packedArgs = new Object[fixedArgCnt + 1]; - for (int i = 0; i < fixedArgCnt; i++) { - packedArgs[i] = args[i]; - } - - final Class<?> compType = paramTypes[fixedArgCnt].getComponentType(); - final int varArgCnt = args.length - fixedArgCnt; - final Object varArgsArray = Array.newInstance(compType, varArgCnt); - for (int i = 0; i < varArgCnt; i++) { - Array.set(varArgsArray, i, args[fixedArgCnt + i]); - } - packedArgs[fixedArgCnt] = varArgsArray; - } else { - packedArgs = args; - } - - return constrDesc.invokeConstructor(bw, packedArgs); - } - - /** - * Contains the common parts of the singleton management for {@link BeansWrapper} and {@link DefaultObjectWrapper}. - * - * @param beansWrapperSubclassFactory Creates a <em>new</em> read-only object wrapper of the desired - * {@link BeansWrapper} subclass. - */ - public static <BW extends BeansWrapper, BWC extends BeansWrapperConfiguration> BW getBeansWrapperSubclassSingleton( - BWC settings, - Map<ClassLoader, Map<BWC, WeakReference<BW>>> instanceCache, - ReferenceQueue<BW> instanceCacheRefQue, - _BeansWrapperSubclassFactory<BW, BWC> beansWrapperSubclassFactory) { - // BeansWrapper can't be cached across different Thread Context Class Loaders (TCCL), because the result of - // a class name (String) to Class mappings depends on it, and the staticModels and enumModels need that. - // (The ClassIntrospector doesn't have to consider the TCCL, as it only works with Class-es, not class - // names.) - ClassLoader tccl = Thread.currentThread().getContextClassLoader(); - - Reference<BW> instanceRef; - Map<BWC, WeakReference<BW>> tcclScopedCache; - synchronized (instanceCache) { - tcclScopedCache = instanceCache.get(tccl); - if (tcclScopedCache == null) { - tcclScopedCache = new HashMap<>(); - instanceCache.put(tccl, tcclScopedCache); - instanceRef = null; - } else { - instanceRef = tcclScopedCache.get(settings); - } - } - - BW instance = instanceRef != null ? instanceRef.get() : null; - if (instance != null) { // cache hit - return instance; - } - // cache miss - - settings = clone(settings); // prevent any aliasing issues - instance = beansWrapperSubclassFactory.create(settings); - if (!instance.isWriteProtected()) { - throw new BugException(); - } - - synchronized (instanceCache) { - instanceRef = tcclScopedCache.get(settings); - BW concurrentInstance = instanceRef != null ? instanceRef.get() : null; - if (concurrentInstance == null) { - tcclScopedCache.put(settings, new WeakReference<>(instance, instanceCacheRefQue)); - } else { - instance = concurrentInstance; - } - } - - removeClearedReferencesFromCache(instanceCache, instanceCacheRefQue); - - return instance; - } - - @SuppressWarnings("unchecked") - private static <BWC extends BeansWrapperConfiguration> BWC clone(BWC settings) { - return (BWC) settings.clone(true); - } - - private static <BW extends BeansWrapper, BWC extends BeansWrapperConfiguration> - void removeClearedReferencesFromCache( - Map<ClassLoader, Map<BWC, WeakReference<BW>>> instanceCache, - ReferenceQueue<BW> instanceCacheRefQue) { - Reference<? extends BW> clearedRef; - while ((clearedRef = instanceCacheRefQue.poll()) != null) { - synchronized (instanceCache) { - findClearedRef: for (Map<BWC, WeakReference<BW>> tcclScopedCache : instanceCache.values()) { - for (Iterator<WeakReference<BW>> it2 = tcclScopedCache.values().iterator(); it2.hasNext(); ) { - if (it2.next() == clearedRef) { - it2.remove(); - break findClearedRef; - } - } - } - } // sync - } // while poll - } - - /** - * For internal use only; don't depend on this, there's no backward compatibility guarantee at all! - */ - public interface _BeansWrapperSubclassFactory<BW extends BeansWrapper, BWC extends BeansWrapperConfiguration> { - - /** Creates a new read-only {@link BeansWrapper}; used for {@link BeansWrapperBuilder} and such. */ - BW create(BWC sa); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/051a0822/src/main/java/org/apache/freemarker/core/model/impl/beans/_EnumModels.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/model/impl/beans/_EnumModels.java b/src/main/java/org/apache/freemarker/core/model/impl/beans/_EnumModels.java deleted file mode 100644 index 573757b..0000000 --- a/src/main/java/org/apache/freemarker/core/model/impl/beans/_EnumModels.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 org.apache.freemarker.core.model.impl.beans; - -import java.util.LinkedHashMap; -import java.util.Map; - -import org.apache.freemarker.core.model.TemplateModel; - -/** - * Don't use this class; it's only public to work around Google App Engine Java - * compliance issues. FreeMarker developers only: treat this class as package-visible. - */ -public class _EnumModels extends ClassBasedModelFactory { - - public _EnumModels(BeansWrapper wrapper) { - super(wrapper); - } - - @Override - protected TemplateModel createModel(Class clazz) { - Object[] obj = clazz.getEnumConstants(); - if (obj == null) { - // Return null - it'll manifest itself as undefined in the template. - // We're doing this rather than throw an exception as this way - // people can use someEnumModel?default({}) to gracefully fall back - // to an empty hash if they want to. - return null; - } - Map map = new LinkedHashMap(); - for (Object anObj : obj) { - Enum value = (Enum) anObj; - map.put(value.name(), value); - } - return new SimpleMapModel(map, getWrapper()); - } -}
