/*
 * 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.
 */

This is the (draft) of the 2.4.0 change log so far. It's not in the Manual yet, as merging in XDocBook XML
changes from the 2.3 branch would be rather difficult.

Non-backward compatible (all are unlikely to affect real world applications):
- Removed command-line tools (main methods in a library, often classified as CWE-489 "Leftover Debug Code"):
  - freemarker.core.CommandLine (jar main-class). This has only printed the current version and copyright.
  - freemarker.ext.dom.Transform. This was used to transform an XML file to output file via a template file.
    Surpassed by FMPP long ago. (If there will be demand for it, it can be still reintroduced in a separate jar.)
  - freemarker.template.utility.ToCanonical class: Converted a template to its canonical form. As the canonical
    form was heavily broken before 2.3.21, and is still not perfect, yet nobody has complained, it's assumed
    that canonicalization isn't used, hence nor the CLI to it.
  - freemarker.ext.jdom.NodeListModel.main() method: Was used to transform an XML given on stdin with the specified
    template file and write the output to stdout. The data model used for this transformation (JDOM NodeListModel) was
    deprecated long ago.
- Removed TemplateObject.getTemplate(), added getUnboundTemplate() instead. TemplateObject is not to be confused with
  Template, and is only exploited by very few for some deeper tricks. Although TemplateObject is technically
  (historically) public, it was marked as internal API and was excluded from the JavaDoc for a while.
- When TemplateCache2 will be merged in: In 2.3.x, a cached error was thrown as a plain IOException with the original
  (cached) exception as its cause exception.
  This is not possible starting from 2.4.x, because to prevent memory leaks, the cache doesn't hold reference to the
  cached exception any more, instead it only stores a String description of it (class name, message, and the same for
  each its cause exceptions). The cached error will be throw as a CachedTemplateLoadingException (an IOException
  subclass), which contains the string description of the original exception in its getMessage() value.
- Removed deprecated *package visible* method:
  Template#Template(String name, TemplateElement root, Configuration cfg)
- freemarker.core.FMParser API changes. These were marked as internal and deprecated for a while,
  and are very unlikely to be used. They could be exploited for tools that try to tokenize String-s as FTL or such.
  - freemarker.core.FMParser constructors were removed or has become non-public
  - freemarker.core.FMParser.createExpressionParser war removed

New features:
- There are no separate org.freemarker:freemarker-gae and org.freemarker:freemarker artifacts any more.
  There's only org.freemarker:freemarker, which is GAE compatible.
- TemplateLoader.getLastModified(Object templateSource) can now throw GetLastModifiedException to indicate an
  error instead of returning -1 (which doesn't count as an error).
- Custom attributes now keep the order of adding them
- Bug fixed: When the same template was both #include-d and #import-ed, the macros from the #import-ed template has
  ran in the namespace of the #import-ed template.

Notes on internal changes (some of this need not be in Version History):
- The main change is splitting Template to Template and UnboundTemplate. With an analogy, if UnboundTemplate is
  the class of the template, then Template is the instance of the template. The content of UnboundTemplate only
  depends on the content of the actual template file, the ParserSettings, and on its *source* path, while Template
  contains all the settings defined in by the Configurable class and the name with which the template was requested.
  This splitting allows more efficient caching when due to the template lookup mechanism, multiple Template-s
  share the same actual template file.
