Return-Path: X-Original-To: apmail-freemarker-notifications-archive@minotaur.apache.org Delivered-To: apmail-freemarker-notifications-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 65069197F5 for ; Sat, 26 Mar 2016 15:41:23 +0000 (UTC) Received: (qmail 30788 invoked by uid 500); 26 Mar 2016 15:41:23 -0000 Delivered-To: apmail-freemarker-notifications-archive@freemarker.apache.org Received: (qmail 30769 invoked by uid 500); 26 Mar 2016 15:41:23 -0000 Mailing-List: contact notifications-help@freemarker.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@freemarker.incubator.apache.org Delivered-To: mailing list notifications@freemarker.incubator.apache.org Received: (qmail 30760 invoked by uid 99); 26 Mar 2016 15:41:23 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 26 Mar 2016 15:41:23 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id D963D1A06CE for ; Sat, 26 Mar 2016 15:41:22 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -3.221 X-Spam-Level: X-Spam-Status: No, score=-3.221 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001] autolearn=disabled Received: from mx2-lw-us.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id qeFShFeOM7ye for ; Sat, 26 Mar 2016 15:41:18 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx2-lw-us.apache.org (ASF Mail Server at mx2-lw-us.apache.org) with SMTP id 328945F5CD for ; Sat, 26 Mar 2016 15:41:16 +0000 (UTC) Received: (qmail 29774 invoked by uid 99); 26 Mar 2016 15:41:16 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 26 Mar 2016 15:41:16 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 3D8A0E9816; Sat, 26 Mar 2016 15:41:16 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ddekany@apache.org To: notifications@freemarker.incubator.apache.org Date: Sat, 26 Mar 2016 15:41:36 -0000 Message-Id: In-Reply-To: <8c7376f324c743db965a0b1f464bdb3b@git.apache.org> References: <8c7376f324c743db965a0b1f464bdb3b@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [22/32] incubator-freemarker git commit: Manual grammatical/wording improvements, and some minor clarifications. Manual grammatical/wording improvements, and some minor clarifications. Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/12c64ded Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/12c64ded Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/12c64ded Branch: refs/heads/2.3 Commit: 12c64ded99861bbd67b5026e577c6622fcc629f6 Parents: ac7a07e Author: ddekany Authored: Sun Mar 20 12:12:54 2016 +0100 Committer: ddekany Committed: Sun Mar 20 12:12:54 2016 +0100 ---------------------------------------------------------------------- src/manual/en_US/book.xml | 367 ++++++++++++++++++++++------------------- 1 file changed, 197 insertions(+), 170 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/12c64ded/src/manual/en_US/book.xml ---------------------------------------------------------------------- diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml index a037f65..0df042a 100644 --- a/src/manual/en_US/book.xml +++ b/src/manual/en_US/book.xml @@ -5790,7 +5790,9 @@ ${"<h1>"?no_esc + "Foo & bar" + "</h1>"?no_esc} just a shorthand of using the + operator (<#assign s = "Hello" + name + "!">). Thus, ${...}-s - inside string expressions aren't auto-escaped. + inside string expressions aren't auto-escaped, but of course when + the resulting concatenated string is printed later, it will be + possibly auto-escaped. <#-- We assume that we have "HTML" output format by default. --> <#assign name = "Foo & Bar"> @@ -6224,11 +6226,11 @@ That's all. First you have to create a freemarker.template.Configuration instance and - adjust its settings. A Configuration instance is a - central place to store the application level settings of FreeMarker. - Also, it deals with the creation and caching of - pre-parsed templates (i.e., Template - objects). + adjust its settings. A Configuration instance is + the central place to store the application level settings of + FreeMarker. Also, it deals with the creation and + caching of pre-parsed templates (i.e., + Template objects). Normally you will do this only once at the beginning of the application (possibly servlet) life-cycle: @@ -6261,21 +6263,21 @@ cfg.setLogTemplateExceptions(false); Do not needlessly re-create Configuration - instances; it's expensive, among others because you lose the caches. - Configuration instances meant to - application-level singletons. + instances; it's expensive, among others because you lose the + template cache. Configuration instances meant to + be application-level singletons. - When using in multi-threaded applications (like for Web sites), - the settings in the Configuration instance must not - be modified anymore after this point. Then it can be treated as - effectively immutable object, so you can continue with - safe publishing techniques (see JSR 133 and - related literature) to make the instance available for the other - threads. Like, publish the instance through a final or volatile filed, - or through a thread-safe IoC container, but not through a plain field. - (Configuration methods that don't deal with - modifying settings are thread-safe.) + In multi-threaded applications (like Web sites) the settings in + the Configuration instance must not be modified + anymore after this point. Thus it can be treated as effectively + immutable object, so you can continue with safe + publishing techniques (see JSR 133 and related literature) + to make the instance available for other threads. Like, publish the + instance through a final or volatile filed, or through a thread-safe + IoC container (like the one provided by Spring). + Configuration methods that don't deal with + modifying settings are thread-safe.
@@ -6297,7 +6299,7 @@ cfg.setLogTemplateExceptions(false); - Use java.lang.Number descents for + Use java.lang.Number subclasses for numbers. @@ -6307,12 +6309,18 @@ cfg.setLogTemplateExceptions(false); + Use java.util.Date and its subclasses for + date/time values + + + Use java.util.List or Java arrays for sequences. - Use java.util.Map for hashes. + Use java.util.Map with + String keys for hashes. @@ -6426,9 +6434,8 @@ public class Product { Templates are represented by freemarker.template.Template instances. Typically you obtain a Template instance from the - Configuration instance. Whenever you need a - template instance you can get it with its - getTemplate method. Store Configuration instance, using its. + getTemplate method. If you store the example template in the test.ftlh file of the earlier set @@ -6436,16 +6443,18 @@ public class Product { Template temp = cfg.getTemplate("test.ftlh"); - When you call this, it will create a Template - instance corresponds to test.ftlh, by reading + This gives you a Template instance that was + created by reading /where/you/store/templates/test.ftlh - and parsing (compile) it. The Template instance - stores the template in the parsed form, and not as text. + and parsing it. The Template instance stores the + template in parsed form, and not as text. If the template is missing + or syntactically incorrect, getTemplate will throw + exception instead. Configuration caches - Template instances, so when you get - test.ftlh again, it probably won't read and parse - the template file again, just returns the same + Template instances, so when you call + cfg.getTemplate("test.ftlh") next time, it probably + won't read and parse the template file again, just returns the same Template instance as for the first time.
@@ -6462,8 +6471,8 @@ public class Product { merging - As we know, data-model + template = output, and we have a - data-model (root) and a template + As you might already know, data-model + template = output. We + already have a data-model (root) and a template (temp), so to get the output we have to merge them. This is done by the process method of the template. It takes the data-model root and a Writer as @@ -6474,9 +6483,9 @@ public class Product { Writer out = new OutputStreamWriter(System.out); temp.process(root, out); - This will print to your terminal the output what you have seen - in the first example of the - Template Author's Guide. + This will print to your terminal the output you have seen in the + first example of the Template + Author's Guide. Java I/O related notes: Depending on what out is, you may need to ensure that out.close() is @@ -6485,8 +6494,9 @@ temp.process(root, out); other times, like in typical Web applications, you must not close out. FreeMarker calls out.flush() after a successful template - execution (can be disabled in Configuration), so - you don't need to worry about that. + execution (but tis can be disabled in + Configuration), so you don't need to worry about + that. Note that once you have obtained a Template instance, you can merge it with different data-models for unlimited @@ -7850,22 +7860,26 @@ cfg.setObjectWrapper(new MyAppObjectWrapper(cfg.getIncompatibleImprovements())); shared variables). Also, it deals with the creation and caching of Template instances. - An application typically should use only a single shared + An application typically uses only a single shared Configuration instance. More precisely, typically - you should have one Configuration instance per - independently developed components (like projects, modules, etc.) that - internally use FreeMarker, as each should create its own - instance. - - As running templates are influenced by the configuration - settings, each Template instance has a - Configuration instance associated with it, via the - corresponding Template constructor parameter. - Usually you obtain Template instances with - Configuration.getTemplate (not by directly calling - the Template constructor), in which case the - associated Configuration instance will be the one - whose getTemplate method has been called. + you have one Configuration instance per + independently developed component that internally uses FreeMarker, so + they can be configured independently of each other. For example, your + e-mail sender component and your report generator component (service) + probably want to use their own Configuration-s, as + their needs differ. + + As the behavior of templates depends on the configuration + settings, each Template instance has an associated + Configuration instance. If you obtain the + Template instances with + Configuration.getTemplate, the associated + Configuration instance will be the one whose + getTemplate method was called. If you create the + Template instances directly with the + Template constructor, the + Configuration should be specified as constructor + parameter.
@@ -7967,17 +7981,17 @@ cfg.setSharedVariable("company", "Foo Inc."); API documentation of Configuration.setSetting(...). - Settings stored in Configuration instance can - be overridden in a Template instance. For example - you set "en_US" for the locale - setting in the configuration, then the locale in - all templates that use this configuration will be - "en_US", except in templates where the locale was - explicitly specified differently (see localization). Thus, - values in a Configuration serve as defaults that - can be overridden in a per template manner. The value comes from - Configuration instance or + The settings coming from the Configuration + can be overridden in a Template instance. For + example, if you set the locale setting to + "en_US" in the configuration, then the + locale in all templates that use this configuration + will be "en_US", except in templates where the + locale was explicitly specified differently (see + localization). + Thus, the setting values in the Configuration serve + as defaults that can be overridden in a per template manner. The value + coming from the Configuration instance or Template instance can be further overridden for a single Template.process call. For each such call a freemarker.core.Environment object is created @@ -7985,7 +7999,8 @@ cfg.setSharedVariable("company", "Foo Inc."); processing, including the setting values that were overridden on that level. The values stored there can even be changed during the template processing, so a template can set settings itself, like switching - locale at the middle of the output. + locale at the middle of the ongoing + processing. This can be imagined as 3 layers (Configuration, Template, @@ -8084,22 +8099,22 @@ cfg.setSharedVariable("company", "Foo Inc."); myCfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); myCfg.setDefaultEncoding("UTF-8"); - You do it before you start to actually use the + You do this before you start to actually use the Configuration object (typically, when you initialize the application); you should treat the object as read-only after that. - In practice, in most Web application frameworks you have to - specify the settings in a framework-specific configuration file - that require specifying setting as String + In practice, in most frameworks you have to specify the + settings in some kind of framework-specific configuration file + that require specifying settings as String name-value pairs (like in a .properties file). In that case the authors of the frameworks most probably use the - setSetting(String name, String value) method of - Configuration; see available setting names and - the format of the values in the Confguration.setSetting(String name, String + value) method; see available setting names and the + format of the values in the API - doc of setSetting. Example for Spring - Framework: + documentation of setSetting. Example for + Spring Framework: <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> @@ -8113,9 +8128,9 @@ myCfg.setDefaultEncoding("UTF-8"); </bean> Note that this kind of configuring - (String key-value pairs) is unfortunately - limited compared to directly using the API of - Configuration. + (String key-value pairs) is somewhat limited + compared to directly using Java API, so in some cases you have to + find a way to do this in Java. @@ -8145,14 +8160,14 @@ myCfg.setDefaultEncoding("UTF-8"); tag_syntax, whitespace_stripping, etc.), as these are not inherited from the top-level template, instead each template - always uses its own, no mater how it was invoked. + always uses its own values, no mater how it was invoked. If you are going to use template layer settings, you should set the incompatible_improvements setting to - 2.3.22 or higher, to avoid confusing legacy bugs. + 2.3.22 or higher, to avoid soe confusing legacy bugs. @@ -8163,14 +8178,13 @@ myCfg.setDefaultEncoding("UTF-8"); With Java API: Use the setter methods of the - Environment object. Certainly you want to - do that just before the processing of the template is started, - and then you run into the problem that when you call - myTemplate.process(...) it creates the - Environment object internally and the - immediately processes the template, so you had no chance. The - solution is that this two steps can be separated like - this: + Environment object. You may run into the + API problem that myTemplate.process(...) + both creates the Environment object + internally and processes the template, so you have no + opportunity to adjust the Environment in + between. The solution is that those two steps can be separated + like this: Environment env = myTemplate.createProcessingEnvironment(root, out); env.setLocale(java.util.Locale.ITALY); @@ -8252,80 +8266,93 @@ env.process(); // process the template Template loaders are objects that load raw textual data based on abstract template paths like "index.ftl" or - "products/catalog.ftl". It is up to the concrete - template loader object what source does it use to fetch the - requested data (files in a directory, data base, etc.). When you - call cfg.getTemplate (where - cfg is a Configuration - instance), FreeMarker ask the template loader you have set up for - the cfg to return the text for the given template - path, and then FreeMarker parses that text as template. + "products/catalog.ftl". It's up to the concrete + template loader if from where and how the template + files are loaded. They could be real files inside a + specified directory, or values in a data base table, or + String-s in a Java Map, etc. When you call + cfg.getTemplate (where cfg is + a Configuration instance), FreeMarker asks the + template loader (cfg.getTemplateLoader) to return + the text for the given template path, and then FreeMarker parses + that text as template. It doesn't care or even know if the template + is a real file or not, and where it is physically; those details are + only known by the template loader.
Built-in template loaders - You can set up three template loading methods in the - Configuration using the following convenience - methods. (Each method will create a template loader object - internally and set up the Configuration - instance to use that.) - - void setDirectoryForTemplateLoading(File dir); - - or - - void setClassForTemplateLoading(Class cl, String prefix); - - or - - void setServletContextForTemplateLoading(Object servletContext, String path); - - The first method above sets an explicit directory on the - file system from which to load templates. Needless to say perhaps, - the File parameter must be an existing - directory. Otherwise, an exception will be thrown. - - The second call takes a Class as a - parameter and a prefix. This is for when you want to load - templates via the same mechanism that a java - ClassLoader uses to load classes. This means - that the class you pass in will be used to call - Class.getResource() to find the templates. The - prefix parameter is prepended to the name of - the template. The classloading mechanism will very likely be the - preferred means of loading templates for production code, since - loading from the classpath mechanism is usually more foolproof - than specifying an explicit directory location on the file system. - It is also nicer in a final application to keep everything in a - .jar file that the user can simply execute - directly and have all the icons and text and everything else - inside the .jar file. - - The third call takes the context of your web application, - and a base path, which is interpreted relative to the web - application root directory (that's the parent of the - WEB-INF directory). This loader will load the - templates from the web application directory. Note that we refer - to "directory" here although this loading method works even for - unpacked .war files since it uses - ServletContext.getResource() to access the - templates. If you omit the second parameter (or use - ""), you can simply store the static files - (.html, .jpg, etc.) mixed - with the .ftl files, just - .ftl files will be sent to the client - processed. Of course, you must set up a Servlet for the - *.ftl uri-pattern in - WEB-INF/web.xml for this, otherwise the client - will get the templates as is, and thus may see confidential - content! You should not use empty path if this is a problem for - your site, rather you should store the templates somewhere inside - the WEB-INF directory, so the raw templates are - never served accidentally. This mechanism will very likely be the - preferred means of loading templates for servlet applications, - since the templates can be updated without restarting the web - application, while this often doesn't work with the class-loader - mechanism. + You can set up the three most common template loading + mechanism in the Configuration using the + following convenience methods: + + + + void setDirectoryForTemplateLoading(File + dir): Sets a directory on the file system from which + to load templates. Template names (template paths) will be + interpreted relatively to this physical directory. It won't + let you load files outside this directory. + + + + void setClassForTemplateLoading(Class cl, + String basePackagePath) and void + setClassLoaderForTemplateLoading(ClassLoader classLoader, + String basePackagePath): These are for when you want + to load templates via the same mechanism with which Java loads + classes (from the class-path, as they used to say vaguely). + This is very likely be the preferred means of loading + templates for production code, as it allows you to keep + everything inside the deployment jar files. + The first parameter decides which Java + ClassLoader will be used. The second + parameter specifies the package that contains the templates, + in /-separated format. Note that if you + don't start it with /, it will be + interpreted relatively to the package of the + Class parameter. + + + + void setServletContextForTemplateLoading(Object + servletContext, String path): Takes the context of + your Servlet-based web application, and a base path, which is + interpreted relative to the web application root directory + (that's the parent of the WEB-INF + directory). Note that we refer to "directory" here although + this loading method works even for unpacked + .war files, since it uses + ServletContext.getResource() to access the + templates. If you omit the second parameter (or use + ""), you can simply store the static files + (.html, .jpg, etc.) + mixed with the .ftl files. Of course, you + must set up a Servlet for the *.ftl, + *.ftlh, *.ftlx + uri-patterns in WEB-INF/web.xml for this, + otherwise the client will get the raw templates as is! To + avoid a such accident, many prefers storing the templates + somewhere inside the WEB-INF directory, + which is never visitable directly. This mechanism will very + likely be the preferred means of loading templates for servlet + applications, since the templates can be updated without + restarting the web application, while this often doesn't work + with the class-loader mechanism. + + + + If you want to use a custom + TemplateLoader implementation, or need to set + up some extra settings of a built-in template loader, you need to + instantiate the TemplateLoader object yourself, + and then call + Configuration.setTemplateLoader(TemplateLoader): + + WebappTemplateLoader templateLoader = new WebappTemplateLoader(servletContext, "WEB-INF/templates"); +templateLoader.setURLConnectionUsesCaches(false); +templateLoader.setAttemptFileAccess(false); +cfg.setTemplateLoader(templateLoader);
@@ -8333,12 +8360,12 @@ env.process(); // process the template If you need to load templates from multiple locations, you have to instantiate the template loader objects for every - location, wrap them into a special template loader named - MultiTemplateLoader and finally pass that - loader to the setTemplateLoader(TemplateLoader - loader) method of Configuration. - Here's an example for loading templates from two distinct - directories and with the class-loader: + location, wrap them into a MultiTemplateLoader, + and finally pass that loader to the + setTemplateLoader(TemplateLoader loader) method + of Configuration. Here's an example for loading + templates from two distinct directories and with the + class-loader: import freemarker.cache.*; // template loaders live in this package @@ -8346,9 +8373,9 @@ env.process(); // process the template FileTemplateLoader ftl1 = new FileTemplateLoader(new File("/tmp/templates")); FileTemplateLoader ftl2 = new FileTemplateLoader(new File("/usr/data/templates")); -ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), ""); -TemplateLoader[] loaders = new TemplateLoader[] { ftl1, ftl2, ctl }; -MultiTemplateLoader mtl = new MultiTemplateLoader(loaders); +ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), "/com/example/templates"); + +MultiTemplateLoader mtl = new MultiTemplateLoader(new TemplateLoader[] { ftl1, ftl2, ctl }); cfg.setTemplateLoader(mtl); @@ -8356,15 +8383,15 @@ cfg.setTemplateLoader(mtl); /tmp/templates directory, and if it does not find the requested template there, it will try to load that from /usr/data/templates, and if it still does not - find the requested template, then it tries to load that with the - class-loader. + find the requested template, then it tries to load it from the + com.example.templates Java package.
Loading templates from other sources - If none of the built-in class loaders are good for you, you - will have to write your own class that implements the + If none of the built-in class loaders fit your needs, you + can write your own class that implements the freemarker.cache.TemplateLoader interface and pass it to the setTemplateLoader(TemplateLoader loader) method of Configuration.