http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/IteratorBlock.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/IteratorBlock.java b/src/main/java/freemarker/core/IteratorBlock.java deleted file mode 100644 index 0ae8d1d..0000000 --- a/src/main/java/freemarker/core/IteratorBlock.java +++ /dev/null @@ -1,475 +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.core; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; - -import freemarker.template.SimpleNumber; -import freemarker.template.TemplateBooleanModel; -import freemarker.template.TemplateCollectionModel; -import freemarker.template.TemplateException; -import freemarker.template.TemplateHashModelEx; -import freemarker.template.TemplateHashModelEx2; -import freemarker.template.TemplateHashModelEx2.KeyValuePair; -import freemarker.template.TemplateHashModelEx2.KeyValuePairIterator; -import freemarker.template.TemplateModel; -import freemarker.template.TemplateModelException; -import freemarker.template.TemplateModelIterator; -import freemarker.template.TemplateScalarModel; -import freemarker.template.TemplateSequenceModel; - -/** - * A #list (or #foreach) element, or pre-#else section of it inside a {@link ListElseContainer}. - */ -final class IteratorBlock extends TemplateElement { - - private final Expression listedExp; - private final String loopVarName; - private final String loopVar2Name; - private final boolean hashListing; - private final boolean forEach; - - /** - * @param listedExp - * a variable referring to a sequence or collection or extended hash to list - * @param loopVarName - * The name of the variable that will hold the value of the current item when looping through listed value, - * or {@code null} if we have a nested {@code #items}. If this is a hash listing then this variable will holds the value - * of the hash key. - * @param loopVar2Name - * The name of the variable that will hold the value of the current item when looping through the list, - * or {@code null} if we have a nested {@code #items}. If this is a hash listing then it variable will hold the value - * from the key-value pair. - * @param childrenBeforeElse - * The nested content to execute if the listed value wasn't empty; can't be {@code null}. If the loop variable - * was specified in the start tag, this is also what we will iterate over. - * @param hashListing - * Whether this is a key-value pair listing, or a usual listing. This is properly set even if we have - * a nested {@code #items}. - * @param forEach - * Whether this is {@code #foreach} or a {@code #list}. - */ - IteratorBlock(Expression listedExp, - String loopVarName, - String loopVar2Name, - TemplateElements childrenBeforeElse, - boolean hashListing, - boolean forEach) { - this.listedExp = listedExp; - this.loopVarName = loopVarName; - this.loopVar2Name = loopVar2Name; - setChildren(childrenBeforeElse); - this.hashListing = hashListing; - this.forEach = forEach; - } - - boolean isHashListing() { - return hashListing; - } - - @Override - TemplateElement[] accept(Environment env) throws TemplateException, IOException { - acceptWithResult(env); - return null; - } - - boolean acceptWithResult(Environment env) throws TemplateException, IOException { - TemplateModel listedValue = listedExp.eval(env); - if (listedValue == null) { - listedExp.assertNonNull(null, env); - } - - return env.visitIteratorBlock(new IterationContext(listedValue, loopVarName, loopVar2Name)); - } - - /** - * @param loopVariableName - * Then name of the loop variable whose context we are looking for, or {@code null} if we simply look for - * the innermost context. - * @return The matching context or {@code null} if no such context exists. - */ - static IterationContext findEnclosingIterationContext(Environment env, String loopVariableName) - throws _MiscTemplateException { - LocalContextStack ctxStack = env.getLocalContextStack(); - if (ctxStack != null) { - for (int i = ctxStack.size() - 1; i >= 0; i--) { - Object ctx = ctxStack.get(i); - if (ctx instanceof IterationContext - && (loopVariableName == null - || loopVariableName.equals(((IterationContext) ctx).getLoopVariableName()) - || loopVariableName.equals(((IterationContext) ctx).getLoopVariable2Name()) - )) { - return (IterationContext) ctx; - } - } - } - return null; - } - - @Override - protected String dump(boolean canonical) { - StringBuilder buf = new StringBuilder(); - if (canonical) buf.append('<'); - buf.append(getNodeTypeSymbol()); - buf.append(' '); - if (forEach) { - buf.append(_CoreStringUtils.toFTLTopLevelIdentifierReference(loopVarName)); - buf.append(" in "); - buf.append(listedExp.getCanonicalForm()); - } else { - buf.append(listedExp.getCanonicalForm()); - if (loopVarName != null) { - buf.append(" as "); - buf.append(_CoreStringUtils.toFTLTopLevelIdentifierReference(loopVarName)); - if (loopVar2Name != null) { - buf.append(", "); - buf.append(_CoreStringUtils.toFTLTopLevelIdentifierReference(loopVar2Name)); - } - } - } - if (canonical) { - buf.append(">"); - buf.append(getChildrenCanonicalForm()); - if (!(getParentElement() instanceof ListElseContainer)) { - buf.append("</"); - buf.append(getNodeTypeSymbol()); - buf.append('>'); - } - } - return buf.toString(); - } - - @Override - int getParameterCount() { - return 1 + (loopVarName != null ? 1 : 0) + (loopVar2Name != null ? 1 : 0); - } - - @Override - Object getParameterValue(int idx) { - switch (idx) { - case 0: - return listedExp; - case 1: - if (loopVarName == null) throw new IndexOutOfBoundsException(); - return loopVarName; - case 2: - if (loopVar2Name == null) throw new IndexOutOfBoundsException(); - return loopVar2Name; - default: throw new IndexOutOfBoundsException(); - } - } - - @Override - ParameterRole getParameterRole(int idx) { - switch (idx) { - case 0: - return ParameterRole.LIST_SOURCE; - case 1: - if (loopVarName == null) throw new IndexOutOfBoundsException(); - return ParameterRole.TARGET_LOOP_VARIABLE; - case 2: - if (loopVar2Name == null) throw new IndexOutOfBoundsException(); - return ParameterRole.TARGET_LOOP_VARIABLE; - default: throw new IndexOutOfBoundsException(); - } - } - - @Override - String getNodeTypeSymbol() { - return forEach ? "#foreach" : "#list"; - } - - @Override - boolean isNestedBlockRepeater() { - return loopVarName != null; - } - - /** - * Holds the context of a #list (or #forEach) directive. - */ - class IterationContext implements LocalContext { - - private static final String LOOP_STATE_HAS_NEXT = "_has_next"; // lenght: 9 - private static final String LOOP_STATE_INDEX = "_index"; // length 6 - - private Object openedIterator; - private boolean hasNext; - private TemplateModel loopVar; - private TemplateModel loopVar2; - private int index; - private boolean alreadyEntered; - private Collection localVarNames = null; - - /** If the {@code #list} has nested {@code #items}, it's {@code null} outside the {@code #items}. */ - private String loopVarName; - /** Used if we list key-value pairs */ - private String loopVar2Name; - - private final TemplateModel listedValue; - - public IterationContext(TemplateModel listedValue, String loopVarName, String loopVar2Name) { - this.listedValue = listedValue; - this.loopVarName = loopVarName; - this.loopVar2Name = loopVar2Name; - } - - boolean accept(Environment env) throws TemplateException, IOException { - return executeNestedContent(env, getChildBuffer()); - } - - void loopForItemsElement(Environment env, TemplateElement[] childBuffer, String loopVarName, String loopVar2Name) - throws NonSequenceOrCollectionException, TemplateModelException, InvalidReferenceException, - TemplateException, IOException { - try { - if (alreadyEntered) { - throw new _MiscTemplateException(env, - "The #items directive was already entered earlier for this listing."); - } - alreadyEntered = true; - this.loopVarName = loopVarName; - this.loopVar2Name = loopVar2Name; - executeNestedContent(env, childBuffer); - } finally { - this.loopVarName = null; - this.loopVar2Name = null; - } - } - - /** - * Executes the given block for the {@link #listedValue}: if {@link #loopVarName} is non-{@code null}, then for - * each list item once, otherwise once if {@link #listedValue} isn't empty. - */ - private boolean executeNestedContent(Environment env, TemplateElement[] childBuffer) - throws TemplateModelException, TemplateException, IOException, NonSequenceOrCollectionException, - InvalidReferenceException { - return !hashListing - ? executedNestedContentForCollOrSeqListing(env, childBuffer) - : executedNestedContentForHashListing(env, childBuffer); - } - - private boolean executedNestedContentForCollOrSeqListing(Environment env, TemplateElement[] childBuffer) - throws TemplateModelException, IOException, TemplateException, - NonSequenceOrCollectionException, InvalidReferenceException { - final boolean listNotEmpty; - if (listedValue instanceof TemplateCollectionModel) { - final TemplateCollectionModel collModel = (TemplateCollectionModel) listedValue; - final TemplateModelIterator iterModel - = openedIterator == null ? collModel.iterator() - : ((TemplateModelIterator) openedIterator); - listNotEmpty = iterModel.hasNext(); - if (listNotEmpty) { - if (loopVarName != null) { - try { - do { - loopVar = iterModel.next(); - hasNext = iterModel.hasNext(); - env.visit(childBuffer); - index++; - } while (hasNext); - } catch (BreakInstruction.Break br) { - // Silently exit loop - } - openedIterator = null; - } else { - // We must reuse this later, because TemplateCollectionModel-s that wrap an Iterator only - // allow one iterator() call. - openedIterator = iterModel; - env.visit(childBuffer); - } - } - } else if (listedValue instanceof TemplateSequenceModel) { - final TemplateSequenceModel seqModel = (TemplateSequenceModel) listedValue; - final int size = seqModel.size(); - listNotEmpty = size != 0; - if (listNotEmpty) { - if (loopVarName != null) { - try { - for (index = 0; index < size; index++) { - loopVar = seqModel.get(index); - hasNext = (size > index + 1); - env.visit(childBuffer); - } - } catch (BreakInstruction.Break br) { - // Silently exit loop - } - } else { - env.visit(childBuffer); - } - } - } else if (listedValue instanceof TemplateHashModelEx - && !NonSequenceOrCollectionException.isWrappedIterable(listedValue)) { - throw new NonSequenceOrCollectionException(env, - new _ErrorDescriptionBuilder("The value you try to list is ", - new _DelayedAOrAn(new _DelayedFTLTypeDescription(listedValue)), - ", thus you must specify two loop variables after the \"as\"; one for the key, and " - + "another for the value, like ", "<#... as k, v>", ")." - )); - } else { - throw new NonSequenceOrCollectionException( - listedExp, listedValue, env); - } - return listNotEmpty; - } - - private boolean executedNestedContentForHashListing(Environment env, TemplateElement[] childBuffer) - throws TemplateModelException, IOException, TemplateException { - final boolean hashNotEmpty; - if (listedValue instanceof TemplateHashModelEx) { - TemplateHashModelEx listedHash = (TemplateHashModelEx) listedValue; - if (listedHash instanceof TemplateHashModelEx2) { - KeyValuePairIterator kvpIter - = openedIterator == null ? ((TemplateHashModelEx2) listedHash).keyValuePairIterator() - : (KeyValuePairIterator) openedIterator; - hashNotEmpty = kvpIter.hasNext(); - if (hashNotEmpty) { - if (loopVarName != null) { - try { - do { - KeyValuePair kvp = kvpIter.next(); - loopVar = kvp.getKey(); - loopVar2 = kvp.getValue(); - hasNext = kvpIter.hasNext(); - env.visit(childBuffer); - index++; - } while (hasNext); - } catch (BreakInstruction.Break br) { - // Silently exit loop - } - openedIterator = null; - } else { - // We will reuse this at the #iterms - openedIterator = kvpIter; - env.visit(childBuffer); - } - } - } else { // not a TemplateHashModelEx2, but still a TemplateHashModelEx - TemplateModelIterator keysIter = listedHash.keys().iterator(); - hashNotEmpty = keysIter.hasNext(); - if (hashNotEmpty) { - if (loopVarName != null) { - try { - do { - loopVar = keysIter.next(); - if (!(loopVar instanceof TemplateScalarModel)) { - throw new NonStringException(env, - new _ErrorDescriptionBuilder( - "When listing key-value pairs of traditional hash " - + "implementations, all keys must be strings, but one of them " - + "was ", - new _DelayedAOrAn(new _DelayedFTLTypeDescription(loopVar)), "." - ).tip("The listed value's TemplateModel class was ", - new _DelayedShortClassName(listedValue.getClass()), - ", which doesn't implement ", - new _DelayedShortClassName(TemplateHashModelEx2.class), - ", which leads to this restriction.")); - } - loopVar2 = listedHash.get(((TemplateScalarModel) loopVar).getAsString()); - hasNext = keysIter.hasNext(); - env.visit(childBuffer); - index++; - } while (hasNext); - } catch (BreakInstruction.Break br) { - // Silently exit loop - } - } else { - env.visit(childBuffer); - } - } - } - } else if (listedValue instanceof TemplateCollectionModel - || listedValue instanceof TemplateSequenceModel) { - throw new NonSequenceOrCollectionException(env, - new _ErrorDescriptionBuilder("The value you try to list is ", - new _DelayedAOrAn(new _DelayedFTLTypeDescription(listedValue)), - ", thus you must specify only one loop variable after the \"as\" (there's no separate " - + "key and value)." - )); - } else { - throw new NonExtendedHashException( - listedExp, listedValue, env); - } - return hashNotEmpty; - } - - String getLoopVariableName() { - return this.loopVarName; - } - - String getLoopVariable2Name() { - return this.loopVar2Name; - } - - @Override - public TemplateModel getLocalVariable(String name) { - String loopVariableName = this.loopVarName; - if (loopVariableName != null && name.startsWith(loopVariableName)) { - switch(name.length() - loopVariableName.length()) { - case 0: - return loopVar; - case 6: - if (name.endsWith(LOOP_STATE_INDEX)) { - return new SimpleNumber(index); - } - break; - case 9: - if (name.endsWith(LOOP_STATE_HAS_NEXT)) { - return hasNext ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; - } - break; - } - } - - if (name.equals(loopVar2Name)) { - return loopVar2; - } - - return null; - } - - @Override - public Collection getLocalVariableNames() { - String loopVariableName = this.loopVarName; - if (loopVariableName != null) { - if (localVarNames == null) { - localVarNames = new ArrayList(3); - localVarNames.add(loopVariableName); - localVarNames.add(loopVariableName + LOOP_STATE_INDEX); - localVarNames.add(loopVariableName + LOOP_STATE_HAS_NEXT); - } - return localVarNames; - } else { - return Collections.EMPTY_LIST; - } - } - - boolean hasNext() { - return hasNext; - } - - int getIndex() { - return index; - } - - } - -}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/JSONOutputFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/JSONOutputFormat.java b/src/main/java/freemarker/core/JSONOutputFormat.java deleted file mode 100644 index 8577198..0000000 --- a/src/main/java/freemarker/core/JSONOutputFormat.java +++ /dev/null @@ -1,52 +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.core; - -/** - * Represents the JSON output format (MIME type "application/json", name "JSON"). This format doesn't support escaping. - * - * @since 2.3.24 - */ -public class JSONOutputFormat extends OutputFormat { - - /** - * The only instance (singleton) of this {@link OutputFormat}. - */ - public static final JSONOutputFormat INSTANCE = new JSONOutputFormat(); - - private JSONOutputFormat() { - // Only to decrease visibility - } - - @Override - public String getName() { - return "JSON"; - } - - @Override - public String getMimeType() { - return "application/json"; - } - - @Override - public boolean isOutputFormatMixingAllowed() { - return false; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/JavaScriptOutputFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/JavaScriptOutputFormat.java b/src/main/java/freemarker/core/JavaScriptOutputFormat.java deleted file mode 100644 index c766af9..0000000 --- a/src/main/java/freemarker/core/JavaScriptOutputFormat.java +++ /dev/null @@ -1,53 +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.core; - -/** - * Represents the JavaScript output format (MIME type "application/javascript", name "JavaScript"). This format doesn't - * support escaping. - * - * @since 2.3.24 - */ -public class JavaScriptOutputFormat extends OutputFormat { - - /** - * The only instance (singleton) of this {@link OutputFormat}. - */ - public static final JavaScriptOutputFormat INSTANCE = new JavaScriptOutputFormat(); - - private JavaScriptOutputFormat() { - // Only to decrease visibility - } - - @Override - public String getName() { - return "JavaScript"; - } - - @Override - public String getMimeType() { - return "application/javascript"; - } - - @Override - public boolean isOutputFormatMixingAllowed() { - return false; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/JavaTemplateDateFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/JavaTemplateDateFormat.java b/src/main/java/freemarker/core/JavaTemplateDateFormat.java deleted file mode 100644 index 1b630ae..0000000 --- a/src/main/java/freemarker/core/JavaTemplateDateFormat.java +++ /dev/null @@ -1,72 +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.core; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import freemarker.template.TemplateDateModel; -import freemarker.template.TemplateModelException; - -/** - * Java {@link DateFormat}-based format. - */ -class JavaTemplateDateFormat extends TemplateDateFormat { - - private final DateFormat javaDateFormat; - - public JavaTemplateDateFormat(DateFormat javaDateFormat) { - this.javaDateFormat = javaDateFormat; - } - - @Override - public String formatToPlainText(TemplateDateModel dateModel) throws TemplateModelException { - return javaDateFormat.format(TemplateFormatUtil.getNonNullDate(dateModel)); - } - - @Override - public Date parse(String s, int dateType) throws UnparsableValueException { - try { - return javaDateFormat.parse(s); - } catch (ParseException e) { - throw new UnparsableValueException(e.getMessage(), e); - } - } - - @Override - public String getDescription() { - return javaDateFormat instanceof SimpleDateFormat - ? ((SimpleDateFormat) javaDateFormat).toPattern() - : javaDateFormat.toString(); - } - - @Override - public boolean isLocaleBound() { - return true; - } - - @Override - public boolean isTimeZoneBound() { - return true; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/JavaTemplateDateFormatFactory.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/JavaTemplateDateFormatFactory.java b/src/main/java/freemarker/core/JavaTemplateDateFormatFactory.java deleted file mode 100644 index c8d851f..0000000 --- a/src/main/java/freemarker/core/JavaTemplateDateFormatFactory.java +++ /dev/null @@ -1,175 +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.core; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Locale; -import java.util.StringTokenizer; -import java.util.TimeZone; -import java.util.concurrent.ConcurrentHashMap; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import freemarker.template.TemplateDateModel; - -class JavaTemplateDateFormatFactory extends TemplateDateFormatFactory { - - static final JavaTemplateDateFormatFactory INSTANCE = new JavaTemplateDateFormatFactory(); - - private static final Logger LOG = LoggerFactory.getLogger("freemarker.runtime"); - - private static final ConcurrentHashMap<CacheKey, DateFormat> GLOBAL_FORMAT_CACHE - = new ConcurrentHashMap<CacheKey, DateFormat>(); - private static final int LEAK_ALERT_NUMBER_FORMAT_CACHE_SIZE = 1024; - - private JavaTemplateDateFormatFactory() { - // Can't be instantiated - } - - /** - * @param zonelessInput - * Has no effect in this implementation. - */ - @Override - public TemplateDateFormat get(String params, int dateType, Locale locale, TimeZone timeZone, boolean zonelessInput, - Environment env) throws UnknownDateTypeFormattingUnsupportedException, InvalidFormatParametersException { - return new JavaTemplateDateFormat(getJavaDateFormat(dateType, params, locale, timeZone)); - } - - /** - * Returns a "private" copy (not in the global cache) for the given format. - */ - private DateFormat getJavaDateFormat(int dateType, String nameOrPattern, Locale locale, TimeZone timeZone) - throws UnknownDateTypeFormattingUnsupportedException, InvalidFormatParametersException { - - // Get DateFormat from global cache: - CacheKey cacheKey = new CacheKey(dateType, nameOrPattern, locale, timeZone); - DateFormat jFormat; - - jFormat = GLOBAL_FORMAT_CACHE.get(cacheKey); - if (jFormat == null) { - // Add format to global format cache. - StringTokenizer tok = new StringTokenizer(nameOrPattern, "_"); - int tok1Style = tok.hasMoreTokens() ? parseDateStyleToken(tok.nextToken()) : DateFormat.DEFAULT; - if (tok1Style != -1) { - switch (dateType) { - case TemplateDateModel.UNKNOWN: { - throw new UnknownDateTypeFormattingUnsupportedException(); - } - case TemplateDateModel.TIME: { - jFormat = DateFormat.getTimeInstance(tok1Style, cacheKey.locale); - break; - } - case TemplateDateModel.DATE: { - jFormat = DateFormat.getDateInstance(tok1Style, cacheKey.locale); - break; - } - case TemplateDateModel.DATETIME: { - int tok2Style = tok.hasMoreTokens() ? parseDateStyleToken(tok.nextToken()) : tok1Style; - if (tok2Style != -1) { - jFormat = DateFormat.getDateTimeInstance(tok1Style, tok2Style, cacheKey.locale); - } - break; - } - } - } - if (jFormat == null) { - try { - jFormat = new SimpleDateFormat(nameOrPattern, cacheKey.locale); - } catch (IllegalArgumentException e) { - final String msg = e.getMessage(); - throw new InvalidFormatParametersException( - msg != null ? msg : "Invalid SimpleDateFormat pattern", e); - } - } - jFormat.setTimeZone(cacheKey.timeZone); - - if (GLOBAL_FORMAT_CACHE.size() >= LEAK_ALERT_NUMBER_FORMAT_CACHE_SIZE) { - boolean triggered = false; - synchronized (JavaTemplateNumberFormatFactory.class) { - if (GLOBAL_FORMAT_CACHE.size() >= LEAK_ALERT_NUMBER_FORMAT_CACHE_SIZE) { - triggered = true; - GLOBAL_FORMAT_CACHE.clear(); - } - } - if (triggered) { - LOG.warn("Global Java DateFormat cache has exceeded {} entries => cache flushed. " - + "Typical cause: Some template generates high variety of format pattern strings.", - LEAK_ALERT_NUMBER_FORMAT_CACHE_SIZE); - } - } - - DateFormat prevJFormat = GLOBAL_FORMAT_CACHE.putIfAbsent(cacheKey, jFormat); - if (prevJFormat != null) { - jFormat = prevJFormat; - } - } // if cache miss - - return (DateFormat) jFormat.clone(); // For thread safety - } - - private static final class CacheKey { - private final int dateType; - private final String pattern; - private final Locale locale; - private final TimeZone timeZone; - - CacheKey(int dateType, String pattern, Locale locale, TimeZone timeZone) { - this.dateType = dateType; - this.pattern = pattern; - this.locale = locale; - this.timeZone = timeZone; - } - - @Override - public boolean equals(Object o) { - if (o instanceof CacheKey) { - CacheKey fk = (CacheKey) o; - return dateType == fk.dateType && fk.pattern.equals(pattern) && fk.locale.equals(locale) - && fk.timeZone.equals(timeZone); - } - return false; - } - - @Override - public int hashCode() { - return dateType ^ pattern.hashCode() ^ locale.hashCode() ^ timeZone.hashCode(); - } - } - - private int parseDateStyleToken(String token) { - if ("short".equals(token)) { - return DateFormat.SHORT; - } - if ("medium".equals(token)) { - return DateFormat.MEDIUM; - } - if ("long".equals(token)) { - return DateFormat.LONG; - } - if ("full".equals(token)) { - return DateFormat.FULL; - } - return -1; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/JavaTemplateNumberFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/JavaTemplateNumberFormat.java b/src/main/java/freemarker/core/JavaTemplateNumberFormat.java deleted file mode 100644 index 27b85e2..0000000 --- a/src/main/java/freemarker/core/JavaTemplateNumberFormat.java +++ /dev/null @@ -1,66 +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.core; - -import java.text.NumberFormat; - -import freemarker.template.TemplateModelException; -import freemarker.template.TemplateNumberModel; - -final class JavaTemplateNumberFormat extends BackwardCompatibleTemplateNumberFormat { - - private final String formatString; - private final NumberFormat javaNumberFormat; - - public JavaTemplateNumberFormat(NumberFormat javaNumberFormat, String formatString) { - this.formatString = formatString; - this.javaNumberFormat = javaNumberFormat; - } - - @Override - public String formatToPlainText(TemplateNumberModel numberModel) throws UnformattableValueException, TemplateModelException { - Number number = TemplateFormatUtil.getNonNullNumber(numberModel); - return format(number); - } - - @Override - public boolean isLocaleBound() { - return true; - } - - @Override - String format(Number number) throws UnformattableValueException { - try { - return javaNumberFormat.format(number); - } catch (ArithmeticException e) { - throw new UnformattableValueException( - "This format can't format the " + number + " number. Reason: " + e.getMessage(), e); - } - } - - public NumberFormat getJavaNumberFormat() { - return javaNumberFormat; - } - - @Override - public String getDescription() { - return formatString; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/JavaTemplateNumberFormatFactory.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/JavaTemplateNumberFormatFactory.java b/src/main/java/freemarker/core/JavaTemplateNumberFormatFactory.java deleted file mode 100644 index ec8db4b..0000000 --- a/src/main/java/freemarker/core/JavaTemplateNumberFormatFactory.java +++ /dev/null @@ -1,121 +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.core; - -import java.text.NumberFormat; -import java.text.ParseException; -import java.util.Locale; -import java.util.concurrent.ConcurrentHashMap; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Deals with {@link TemplateNumberFormat}-s that just wrap a Java {@link NumberFormat}. - */ -class JavaTemplateNumberFormatFactory extends TemplateNumberFormatFactory { - - static final JavaTemplateNumberFormatFactory INSTANCE = new JavaTemplateNumberFormatFactory(); - - private static final Logger LOG = LoggerFactory.getLogger("freemarker.runtime"); - - private static final ConcurrentHashMap<CacheKey, NumberFormat> GLOBAL_FORMAT_CACHE - = new ConcurrentHashMap<CacheKey, NumberFormat>(); - private static final int LEAK_ALERT_NUMBER_FORMAT_CACHE_SIZE = 1024; - - private JavaTemplateNumberFormatFactory() { - // Not meant to be instantiated - } - - @Override - public TemplateNumberFormat get(String params, Locale locale, Environment env) - throws InvalidFormatParametersException { - CacheKey cacheKey = new CacheKey(params, locale); - NumberFormat jFormat = GLOBAL_FORMAT_CACHE.get(cacheKey); - if (jFormat == null) { - if ("number".equals(params)) { - jFormat = NumberFormat.getNumberInstance(locale); - } else if ("currency".equals(params)) { - jFormat = NumberFormat.getCurrencyInstance(locale); - } else if ("percent".equals(params)) { - jFormat = NumberFormat.getPercentInstance(locale); - } else if ("computer".equals(params)) { - jFormat = env.getCNumberFormat(); - } else { - try { - jFormat = ExtendedDecimalFormatParser.parse(params, locale); - } catch (ParseException e) { - String msg = e.getMessage(); - throw new InvalidFormatParametersException( - msg != null ? msg : "Invalid DecimalFormat pattern", e); - } - } - - if (GLOBAL_FORMAT_CACHE.size() >= LEAK_ALERT_NUMBER_FORMAT_CACHE_SIZE) { - boolean triggered = false; - synchronized (JavaTemplateNumberFormatFactory.class) { - if (GLOBAL_FORMAT_CACHE.size() >= LEAK_ALERT_NUMBER_FORMAT_CACHE_SIZE) { - triggered = true; - GLOBAL_FORMAT_CACHE.clear(); - } - } - if (triggered) { - LOG.warn("Global Java NumberFormat cache has exceeded {} entries => cache flushed. " - + "Typical cause: Some template generates high variety of format pattern strings.", - LEAK_ALERT_NUMBER_FORMAT_CACHE_SIZE); - } - } - - NumberFormat prevJFormat = GLOBAL_FORMAT_CACHE.putIfAbsent(cacheKey, jFormat); - if (prevJFormat != null) { - jFormat = prevJFormat; - } - } // if cache miss - - // JFormat-s aren't thread-safe; must clone it - jFormat = (NumberFormat) jFormat.clone(); - - return new JavaTemplateNumberFormat(jFormat, params); - } - - private static final class CacheKey { - private final String pattern; - private final Locale locale; - - CacheKey(String pattern, Locale locale) { - this.pattern = pattern; - this.locale = locale; - } - - @Override - public boolean equals(Object o) { - if (o instanceof CacheKey) { - CacheKey fk = (CacheKey) o; - return fk.pattern.equals(pattern) && fk.locale.equals(locale); - } - return false; - } - - @Override - public int hashCode() { - return pattern.hashCode() ^ locale.hashCode(); - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/LibraryLoad.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/LibraryLoad.java b/src/main/java/freemarker/core/LibraryLoad.java deleted file mode 100644 index 8d71b6a..0000000 --- a/src/main/java/freemarker/core/LibraryLoad.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 freemarker.core; - -import java.io.IOException; - -import freemarker.template.MalformedTemplateNameException; -import freemarker.template.Template; -import freemarker.template.TemplateException; - -/** - * <b>Internal API - subject to change:</b> Represents an import via {@code #import}. - * - * @deprecated This is an internal FreeMarker API with no backward compatibility guarantees, so you shouldn't depend on - * it. - */ -@Deprecated -public final class LibraryLoad extends TemplateElement { - - private Expression importedTemplateNameExp; - private String targetNsVarName; - - /** - * @param template the template that this <tt>Include</tt> is a part of. - * @param templateName the name of the template to be included. - * @param targetNsVarName the name of the variable to assign this library's namespace to - */ - LibraryLoad(Template template, - Expression templateName, - String targetNsVarName) { - this.targetNsVarName = targetNsVarName; - this.importedTemplateNameExp = templateName; - } - - @Override - TemplateElement[] accept(Environment env) throws TemplateException, IOException { - final String importedTemplateName = importedTemplateNameExp.evalAndCoerceToPlainText(env); - final String fullImportedTemplateName; - try { - fullImportedTemplateName = env.toFullTemplateName(getTemplate().getName(), importedTemplateName); - } catch (MalformedTemplateNameException e) { - throw new _MiscTemplateException(e, env, - "Malformed template name ", new _DelayedJQuote(e.getTemplateName()), ":\n", - e.getMalformednessDescription()); - } - - try { - env.importLib(fullImportedTemplateName, targetNsVarName); - } catch (IOException e) { - throw new _MiscTemplateException(e, env, - "Template importing failed (for parameter value ", - new _DelayedJQuote(importedTemplateName), - "):\n", new _DelayedGetMessage(e)); - } - return null; - } - - @Override - protected String dump(boolean canonical) { - StringBuilder buf = new StringBuilder(); - if (canonical) buf.append('<'); - buf.append(getNodeTypeSymbol()); - buf.append(' '); - buf.append(importedTemplateNameExp.getCanonicalForm()); - buf.append(" as "); - buf.append(_CoreStringUtils.toFTLTopLevelTragetIdentifier(targetNsVarName)); - if (canonical) buf.append("/>"); - return buf.toString(); - } - - @Override - String getNodeTypeSymbol() { - return "#import"; - } - - @Override - int getParameterCount() { - return 2; - } - - @Override - Object getParameterValue(int idx) { - switch (idx) { - case 0: return importedTemplateNameExp; - case 1: return targetNsVarName; - default: throw new IndexOutOfBoundsException(); - } - } - - @Override - ParameterRole getParameterRole(int idx) { - switch (idx) { - case 0: return ParameterRole.TEMPLATE_NAME; - case 1: return ParameterRole.NAMESPACE; - default: throw new IndexOutOfBoundsException(); - } - } - - public String getTemplateName() { - return importedTemplateNameExp.toString(); - } - - @Override - boolean isNestedBlockRepeater() { - return false; - } - - @Override - boolean isShownInStackTrace() { - return true; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/ListElseContainer.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/ListElseContainer.java b/src/main/java/freemarker/core/ListElseContainer.java deleted file mode 100644 index 1065e9e..0000000 --- a/src/main/java/freemarker/core/ListElseContainer.java +++ /dev/null @@ -1,87 +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.core; - -import java.io.IOException; - -import freemarker.template.TemplateException; - -class ListElseContainer extends TemplateElement { - - private final IteratorBlock listPart; - private final ElseOfList elsePart; - - public ListElseContainer(IteratorBlock listPart, ElseOfList elsePart) { - setChildBufferCapacity(2); - addChild(listPart); - addChild(elsePart); - this.listPart = listPart; - this.elsePart = elsePart; - } - - @Override - TemplateElement[] accept(Environment env) throws TemplateException, IOException { - if (!listPart.acceptWithResult(env)) { - return elsePart.accept(env); - } - return null; - } - - @Override - boolean isNestedBlockRepeater() { - return false; - } - - @Override - protected String dump(boolean canonical) { - if (canonical) { - StringBuilder buf = new StringBuilder(); - int ln = getChildCount(); - for (int i = 0; i < ln; i++) { - TemplateElement element = getChild(i); - buf.append(element.dump(canonical)); - } - buf.append("</#list>"); - return buf.toString(); - } else { - return getNodeTypeSymbol(); - } - } - - @Override - String getNodeTypeSymbol() { - return "#list-#else-container"; - } - - @Override - int getParameterCount() { - return 0; - } - - @Override - Object getParameterValue(int idx) { - throw new IndexOutOfBoundsException(); - } - - @Override - ParameterRole getParameterRole(int idx) { - throw new IndexOutOfBoundsException(); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/ListLiteral.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/ListLiteral.java b/src/main/java/freemarker/core/ListLiteral.java deleted file mode 100644 index 92eba2e..0000000 --- a/src/main/java/freemarker/core/ListLiteral.java +++ /dev/null @@ -1,196 +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.core; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -import freemarker.template.SimpleSequence; -import freemarker.template.TemplateException; -import freemarker.template.TemplateMethodModel; -import freemarker.template.TemplateMethodModelEx; -import freemarker.template.TemplateModel; -import freemarker.template.TemplateSequenceModel; - -final class ListLiteral extends Expression { - - final ArrayList/*<Expression>*/ items; - - ListLiteral(ArrayList items) { - this.items = items; - items.trimToSize(); - } - - @Override - TemplateModel _eval(Environment env) throws TemplateException { - SimpleSequence list = new SimpleSequence(items.size()); - for (Iterator it = items.iterator(); it.hasNext(); ) { - Expression exp = (Expression) it.next(); - TemplateModel tm = exp.eval(env); - exp.assertNonNull(tm, env); - list.add(tm); - } - return list; - } - - /** - * For {@link TemplateMethodModel} calls, but not for {@link TemplateMethodModelEx}-es, returns the list of - * arguments as {@link String}-s. - */ - List/*<String>*/ getValueList(Environment env) throws TemplateException { - int size = items.size(); - switch(size) { - case 0: { - return Collections.EMPTY_LIST; - } - case 1: { - return Collections.singletonList(((Expression) items.get(0)).evalAndCoerceToPlainText(env)); - } - default: { - List result = new ArrayList(items.size()); - for (ListIterator iterator = items.listIterator(); iterator.hasNext(); ) { - Expression exp = (Expression) iterator.next(); - result.add(exp.evalAndCoerceToPlainText(env)); - } - return result; - } - } - } - - /** - * For {@link TemplateMethodModelEx} calls, returns the list of arguments as {@link TemplateModel}-s. - */ - List/*<TemplateModel>*/ getModelList(Environment env) throws TemplateException { - int size = items.size(); - switch(size) { - case 0: { - return Collections.EMPTY_LIST; - } - case 1: { - return Collections.singletonList(((Expression) items.get(0)).eval(env)); - } - default: { - List result = new ArrayList(items.size()); - for (ListIterator iterator = items.listIterator(); iterator.hasNext(); ) { - Expression exp = (Expression) iterator.next(); - result.add(exp.eval(env)); - } - return result; - } - } - } - - @Override - public String getCanonicalForm() { - StringBuilder buf = new StringBuilder("["); - int size = items.size(); - for (int i = 0; i < size; i++) { - Expression value = (Expression) items.get(i); - buf.append(value.getCanonicalForm()); - if (i != size - 1) { - buf.append(", "); - } - } - buf.append("]"); - return buf.toString(); - } - - @Override - String getNodeTypeSymbol() { - return "[...]"; - } - - @Override - boolean isLiteral() { - if (constantValue != null) { - return true; - } - for (int i = 0; i < items.size(); i++) { - Expression exp = (Expression) items.get(i); - if (!exp.isLiteral()) { - return false; - } - } - return true; - } - - // A hacky routine used by VisitNode and RecurseNode - - TemplateSequenceModel evaluateStringsToNamespaces(Environment env) throws TemplateException { - TemplateSequenceModel val = (TemplateSequenceModel) eval(env); - SimpleSequence result = new SimpleSequence(val.size()); - for (int i = 0; i < items.size(); i++) { - Object itemExpr = items.get(i); - if (itemExpr instanceof StringLiteral) { - String s = ((StringLiteral) itemExpr).getAsString(); - try { - Environment.Namespace ns = env.importLib(s, null); - result.add(ns); - } catch (IOException ioe) { - throw new _MiscTemplateException(((StringLiteral) itemExpr), - "Couldn't import library ", new _DelayedJQuote(s), ": ", - new _DelayedGetMessage(ioe)); - } - } else { - result.add(val.get(i)); - } - } - return result; - } - - @Override - protected Expression deepCloneWithIdentifierReplaced_inner( - String replacedIdentifier, Expression replacement, ReplacemenetState replacementState) { - ArrayList clonedValues = (ArrayList) items.clone(); - for (ListIterator iter = clonedValues.listIterator(); iter.hasNext(); ) { - iter.set(((Expression) iter.next()).deepCloneWithIdentifierReplaced( - replacedIdentifier, replacement, replacementState)); - } - return new ListLiteral(clonedValues); - } - - @Override - int getParameterCount() { - return items != null ? items.size() : 0; - } - - @Override - Object getParameterValue(int idx) { - checkIndex(idx); - return items.get(idx); - } - - @Override - ParameterRole getParameterRole(int idx) { - checkIndex(idx); - return ParameterRole.ITEM_VALUE; - } - - private void checkIndex(int idx) { - if (items == null || idx >= items.size()) { - throw new IndexOutOfBoundsException(); - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/ListableRightUnboundedRangeModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/ListableRightUnboundedRangeModel.java b/src/main/java/freemarker/core/ListableRightUnboundedRangeModel.java deleted file mode 100644 index 2cf979c..0000000 --- a/src/main/java/freemarker/core/ListableRightUnboundedRangeModel.java +++ /dev/null @@ -1,93 +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.core; - -import java.math.BigInteger; - -import freemarker.template.SimpleNumber; -import freemarker.template.TemplateCollectionModel; -import freemarker.template.TemplateModel; -import freemarker.template.TemplateModelException; -import freemarker.template.TemplateModelIterator; - -/** - * This is the model used for right-unbounded ranges since Incompatible Improvements 2.3.21. - * - * @since 2.3.21 - */ -final class ListableRightUnboundedRangeModel extends RightUnboundedRangeModel implements TemplateCollectionModel { - - ListableRightUnboundedRangeModel(int begin) { - super(begin); - } - - public int size() throws TemplateModelException { - return Integer.MAX_VALUE; - } - - public TemplateModelIterator iterator() throws TemplateModelException { - return new TemplateModelIterator() { - boolean needInc; - int nextType = 1; - int nextInt = getBegining(); - long nextLong; - BigInteger nextBigInteger; - - public TemplateModel next() throws TemplateModelException { - if (needInc) { - switch (nextType) { - case 1: - if (nextInt < Integer.MAX_VALUE) { - nextInt++; - } else { - nextType = 2; - nextLong = nextInt + 1L; - } - break; - - case 2: - if (nextLong < Long.MAX_VALUE) { - nextLong++; - } else { - nextType = 3; - nextBigInteger = BigInteger.valueOf(nextLong); - nextBigInteger = nextBigInteger.add(BigInteger.ONE); - } - break; - - default: // 3 - nextBigInteger = nextBigInteger.add(BigInteger.ONE); - } - } - needInc = true; - return nextType == 1 ? new SimpleNumber(nextInt) - : (nextType == 2 ? new SimpleNumber(nextLong) - : new SimpleNumber(nextBigInteger)); - } - - public boolean hasNext() throws TemplateModelException { - return true; - } - - }; - - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/LocalContext.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/LocalContext.java b/src/main/java/freemarker/core/LocalContext.java deleted file mode 100644 index 95f7ce0..0000000 --- a/src/main/java/freemarker/core/LocalContext.java +++ /dev/null @@ -1,38 +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.core; - -import java.util.Collection; - -import freemarker.template.TemplateModel; -import freemarker.template.TemplateModelException; - -/** - * An interface that represents a local context. This is used as the abstraction for - * the context of a Macro invocation, a loop, or the nested block call from within - * a macro. - * <a href="mailto:[email protected]">Jonathan Revusky</a> - */ - -public interface LocalContext { - TemplateModel getLocalVariable(String name) throws TemplateModelException; - Collection getLocalVariableNames() throws TemplateModelException; - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/LocalContextStack.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/LocalContextStack.java b/src/main/java/freemarker/core/LocalContextStack.java deleted file mode 100644 index c22a09f..0000000 --- a/src/main/java/freemarker/core/LocalContextStack.java +++ /dev/null @@ -1,57 +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.core; - -/** - * Class that's a little bit more efficient than using an {@code ArrayList<LocalContext>}. - * - * @since 2.3.24 - */ -final class LocalContextStack { - - private LocalContext[] buffer = new LocalContext[8]; - private int size; - - void push(LocalContext localContext) { - final int newSize = ++size; - LocalContext[] buffer = this.buffer; - if (buffer.length < newSize) { - final LocalContext[] newBuffer = new LocalContext[newSize * 2]; - for (int i = 0; i < buffer.length; i++) { - newBuffer[i] = buffer[i]; - } - buffer = newBuffer; - this.buffer = newBuffer; - } - buffer[newSize - 1] = localContext; - } - - void pop() { - buffer[--size] = null; - } - - public LocalContext get(int index) { - return buffer[index]; - } - - public int size() { - return size; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/Macro.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/Macro.java b/src/main/java/freemarker/core/Macro.java deleted file mode 100644 index 16f2c53..0000000 --- a/src/main/java/freemarker/core/Macro.java +++ /dev/null @@ -1,329 +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.core; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; - -import freemarker.template.TemplateException; -import freemarker.template.TemplateModel; -import freemarker.template.TemplateModelException; -import freemarker.template.TemplateModelIterator; - -/** - * An element representing a macro declaration. - * - * @deprecated Subject to be changed or renamed any time; no "stable" replacement exists yet. - */ -@Deprecated -public final class Macro extends TemplateElement implements TemplateModel { - - static final Macro DO_NOTHING_MACRO = new Macro(".pass", - Collections.EMPTY_LIST, - Collections.EMPTY_MAP, - null, false, - TemplateElements.EMPTY); - - final static int TYPE_MACRO = 0; - final static int TYPE_FUNCTION = 1; - - private final String name; - private final String[] paramNames; - private final Map paramDefaults; - private final String catchAllParamName; - private final boolean function; - - Macro(String name, List argumentNames, Map args, - String catchAllParamName, boolean function, - TemplateElements children) { - this.name = name; - this.paramNames = (String[]) argumentNames.toArray( - new String[argumentNames.size()]); - this.paramDefaults = args; - - this.function = function; - this.catchAllParamName = catchAllParamName; - - this.setChildren(children); - } - - public String getCatchAll() { - return catchAllParamName; - } - - public String[] getArgumentNames() { - return paramNames.clone(); - } - - String[] getArgumentNamesInternal() { - return paramNames; - } - - boolean hasArgNamed(String name) { - return paramDefaults.containsKey(name); - } - - public String getName() { - return name; - } - - @Override - TemplateElement[] accept(Environment env) { - env.visitMacroDef(this); - return null; - } - - @Override - protected String dump(boolean canonical) { - StringBuilder sb = new StringBuilder(); - if (canonical) sb.append('<'); - sb.append(getNodeTypeSymbol()); - sb.append(' '); - sb.append(_CoreStringUtils.toFTLTopLevelTragetIdentifier(name)); - if (function) sb.append('('); - int argCnt = paramNames.length; - for (int i = 0; i < argCnt; i++) { - if (function) { - if (i != 0) { - sb.append(", "); - } - } else { - sb.append(' '); - } - String argName = paramNames[i]; - sb.append(_CoreStringUtils.toFTLTopLevelIdentifierReference(argName)); - if (paramDefaults != null && paramDefaults.get(argName) != null) { - sb.append('='); - Expression defaultExpr = (Expression) paramDefaults.get(argName); - if (function) { - sb.append(defaultExpr.getCanonicalForm()); - } else { - MessageUtil.appendExpressionAsUntearable(sb, defaultExpr); - } - } - } - if (catchAllParamName != null) { - if (function) { - if (argCnt != 0) { - sb.append(", "); - } - } else { - sb.append(' '); - } - sb.append(catchAllParamName); - sb.append("..."); - } - if (function) sb.append(')'); - if (canonical) { - sb.append('>'); - sb.append(getChildrenCanonicalForm()); - sb.append("</").append(getNodeTypeSymbol()).append('>'); - } - return sb.toString(); - } - - @Override - String getNodeTypeSymbol() { - return function ? "#function" : "#macro"; - } - - public boolean isFunction() { - return function; - } - - class Context implements LocalContext { - final Environment.Namespace localVars; - final TemplateElement[] nestedContentBuffer; - final Environment.Namespace nestedContentNamespace; - final List nestedContentParameterNames; - final LocalContextStack prevLocalContextStack; - final Context prevMacroContext; - - Context(Environment env, - TemplateElement[] nestedContentBuffer, - List nestedContentParameterNames) { - this.localVars = env.new Namespace(); - this.nestedContentBuffer = nestedContentBuffer; - this.nestedContentNamespace = env.getCurrentNamespace(); - this.nestedContentParameterNames = nestedContentParameterNames; - this.prevLocalContextStack = env.getLocalContextStack(); - this.prevMacroContext = env.getCurrentMacroContext(); - } - - - Macro getMacro() { - return Macro.this; - } - - // Set default parameters, check if all the required parameters are defined. - void sanityCheck(Environment env) throws TemplateException { - boolean resolvedAnArg, hasUnresolvedArg; - Expression firstUnresolvedExpression; - InvalidReferenceException firstReferenceException; - do { - firstUnresolvedExpression = null; - firstReferenceException = null; - resolvedAnArg = hasUnresolvedArg = false; - for (int i = 0; i < paramNames.length; ++i) { - String argName = paramNames[i]; - if (localVars.get(argName) == null) { - Expression valueExp = (Expression) paramDefaults.get(argName); - if (valueExp != null) { - try { - TemplateModel tm = valueExp.eval(env); - if (tm == null) { - if (!hasUnresolvedArg) { - firstUnresolvedExpression = valueExp; - hasUnresolvedArg = true; - } - } else { - localVars.put(argName, tm); - resolvedAnArg = true; - } - } catch (InvalidReferenceException e) { - if (!hasUnresolvedArg) { - hasUnresolvedArg = true; - firstReferenceException = e; - } - } - } else { - boolean argWasSpecified = localVars.containsKey(argName); - throw new _MiscTemplateException(env, - new _ErrorDescriptionBuilder( - "When calling macro ", new _DelayedJQuote(name), - ", required parameter ", new _DelayedJQuote(argName), - " (parameter #", Integer.valueOf(i + 1), ") was ", - (argWasSpecified - ? "specified, but had null/missing value." - : "not specified.") - ).tip(argWasSpecified - ? new Object[] { - "If the parameter value expression on the caller side is known to " - + "be legally null/missing, you may want to specify a default " - + "value for it with the \"!\" operator, like " - + "paramValue!defaultValue." } - : new Object[] { - "If the omission was deliberate, you may consider making the " - + "parameter optional in the macro by specifying a default value " - + "for it, like ", "<#macro macroName paramName=defaultExpr>", ")" } - )); - } - } - } - } while (resolvedAnArg && hasUnresolvedArg); - if (hasUnresolvedArg) { - if (firstReferenceException != null) { - throw firstReferenceException; - } else { - throw InvalidReferenceException.getInstance(firstUnresolvedExpression, env); - } - } - } - - /** - * @return the local variable of the given name - * or null if it doesn't exist. - */ - @Override - public TemplateModel getLocalVariable(String name) throws TemplateModelException { - return localVars.get(name); - } - - Environment.Namespace getLocals() { - return localVars; - } - - /** - * Set a local variable in this macro - */ - void setLocalVar(String name, TemplateModel var) { - localVars.put(name, var); - } - - @Override - public Collection getLocalVariableNames() throws TemplateModelException { - HashSet result = new HashSet(); - for (TemplateModelIterator it = localVars.keys().iterator(); it.hasNext(); ) { - result.add(it.next().toString()); - } - return result; - } - } - - @Override - int getParameterCount() { - return 1/*name*/ + paramNames.length * 2/*name=default*/ + 1/*catchAll*/ + 1/*type*/; - } - - @Override - Object getParameterValue(int idx) { - if (idx == 0) { - return name; - } else { - final int argDescsEnd = paramNames.length * 2 + 1; - if (idx < argDescsEnd) { - String paramName = paramNames[(idx - 1) / 2]; - if (idx % 2 != 0) { - return paramName; - } else { - return paramDefaults.get(paramName); - } - } else if (idx == argDescsEnd) { - return catchAllParamName; - } else if (idx == argDescsEnd + 1) { - return Integer.valueOf(function ? TYPE_FUNCTION : TYPE_MACRO); - } else { - throw new IndexOutOfBoundsException(); - } - } - } - - @Override - ParameterRole getParameterRole(int idx) { - if (idx == 0) { - return ParameterRole.ASSIGNMENT_TARGET; - } else { - final int argDescsEnd = paramNames.length * 2 + 1; - if (idx < argDescsEnd) { - if (idx % 2 != 0) { - return ParameterRole.PARAMETER_NAME; - } else { - return ParameterRole.PARAMETER_DEFAULT; - } - } else if (idx == argDescsEnd) { - return ParameterRole.CATCH_ALL_PARAMETER_NAME; - } else if (idx == argDescsEnd + 1) { - return ParameterRole.AST_NODE_SUBTYPE; - } else { - throw new IndexOutOfBoundsException(); - } - } - } - - @Override - boolean isNestedBlockRepeater() { - // Because of recursive calls - return true; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/core/MarkReleaserTemplateSpecifiedEncodingHandler.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/MarkReleaserTemplateSpecifiedEncodingHandler.java b/src/main/java/freemarker/core/MarkReleaserTemplateSpecifiedEncodingHandler.java deleted file mode 100644 index 9fb8050..0000000 --- a/src/main/java/freemarker/core/MarkReleaserTemplateSpecifiedEncodingHandler.java +++ /dev/null @@ -1,55 +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.core; - -import java.io.InputStream; - -import freemarker.template.Template.WrongEncodingException; - -/** - * A {@link TemplateSpecifiedEncodingHandler} that discards the mark of the specified {@link InputStream} when - * the template parsing gets to a point where it's known that we can't receive a template specified encoding anymore. - * This allows freeing up the mark buffer early during parsing. - * - * @since 2.3.16 - */ -public class MarkReleaserTemplateSpecifiedEncodingHandler implements TemplateSpecifiedEncodingHandler { - - private final InputStream markedInputStream; - - /** - * @param markedInputStream Input stream with marked template content start position - */ - public MarkReleaserTemplateSpecifiedEncodingHandler(InputStream markedInputStream) { - this.markedInputStream = markedInputStream; - } - - public void handle(String templateSpecificEncoding, String constructorSpecifiedEncoding) - throws WrongEncodingException { - TemplateSpecifiedEncodingHandler.DEFAULT.handle(templateSpecificEncoding, constructorSpecifiedEncoding); - - // There was no WrongEncodingException exception, release mark buffer: - markedInputStream.mark(0); // - } - - public InputStream getMarkedInputStream() { - return markedInputStream; - } - -}
