diff --git a/CONTRIBUTING.markdown b/CONTRIBUTING.markdown
index c0899e961..72f1345b3 100644
--- a/CONTRIBUTING.markdown
+++ b/CONTRIBUTING.markdown
@@ -1,252 +1,112 @@
-Contributing to Thymeleaf: Terms and Conditions
-===============================================
+# Contributing to Thymeleaf
-------------------------------------------------------------------------------
+Thymeleaf is released under the Apache 2.0 license. If you would like to
+contribute something, or want to hack on the code this document should help you
+get started.
-Do you want to contribute your work to Thymeleaf? Well, then first and most important: **THANK YOU!**
-Now, in order to accept your contribution, there are some terms you must expressly agree with, so please
-read them carefully. They may seem a bit cumbersome but they are there to protect you, your contribution,
-and most importantly, the project's future.
+## Code of Conduct
-**Important**: submitting any contributions to the Thymeleaf project implies your **full acceptance of these terms**,
-including the *"Thymeleaf Individual Contributor License Agreement"* detailed at the end of this document.
+This project adheres to the Contributor Covenant
+[code of conduct][code-of-coduct].
+By participating, you are expected to uphold this code. Please report
+unacceptable behavior to [the project leads][thymeleaf-team].
-Who can contribute?
--------------------
+## Using GitHub Issues
-Anyone, with the unique condition that he/she must be a **private individual**, acting in
-his/her own name, and not being endorsed in their contributed work by any company or government.
+We use GitHub issues to track bugs and enhancements.
+If you have a general usage question please ask on
+[Stack Overflow][stackoverflow].
+The Thymeleaf team and the broader community monitor the
+[`thymeleaf`][stackoverflow-thymeleaf] tag.
-Note that this condition will not only refer to the ownership of the effort invested in contributing
-to the project, but also to the fact that *no private or public company will be mentioned as a part
-of your contribution on the project's website or code*, including but not limited to web/email addresses
-or package names.
+If you are reporting a bug, please help to speed up problem diagnosis by
+providing as much information as possible.
+Ideally, that would include a small sample project that reproduces the problem.
-What is the first step to be taken?
------------------------------------
+## Before submitting a Contribution
-First of all, **talk to the [project members](http://www.thymeleaf.org/team.html)** (an email should do) about
-your ideas: new features, fixes, documentation... whatever you would like to contribute to the project. Let us
-discuss the possibilities with you so that we make sure your contribution goes in the right direction and aligns
-with the project's standards, intentions and roadmap.
+Before submitting a contribution that is not an obvious or trivial fix,
+get in contact with the [the project leads][thymeleaf-team] about your
+ideas (an email should do). Let us discuss the possibilities with you so that
+we make sure your contribution goes in the right direction and aligns with the
+project's standards, intentions and roadmap.
+Please understand that *not all contributions will be accepted and merged into
+the project's repositories*. Talking about your planned contributions with the
+project maintainers before creating pull requests can maximize the possibility
+of your contributions being accepted.
-How will your involvement with the Thymeleaf project work?
-----------------------------------------------------------
-All contributions are submitted in the form of GitHub *pull requests*. Note that contributors do not
-have read+write (or *pull+push*) access to the project repositories, only project *members* do.
-Also, please understand that *not all pull requests will be accepted and merged into the project's
-repositories*. Talk about your planned contributions with the project members before creating pull
-requests so you can maximize the possibility of your contributions being accepted.
+## Signing the Contributor License Agreement
-Once your contribution is approved, you will be listed as a *contributor* on the
-[Thymeleaf Team page](http://www.thymeleaf.org/team.html). You can opt-out of this if you want.
-Also, you will be `@author` for any new Java classes that you write and also co-`@author` of any
-existing classes to which you make significant changes. You can also opt-out of this if you want.
+Before we accept a non-trivial patch or pull request we will need you to
+sign a **Contributor License Agreement**.
+There are two versions of the CLA:
-About the code you contribute
------------------------------
+ * **Individual CLA**: For individuals acting on their own behalf, i.e. not
+ being backed by any company or government, and not making their
+ contributions potentially under the effect of any contracts, agreements or
+ laws that could cause their employeer (or any other entities) claim
+ any rights on their contribution.
+ * **Corporate CLA**: For corporate entities allowing some of their employees
+ to contribute to Thymeleaf on the entity's behalf.
-### General guidelines:
+For more information on the CLA and the (very easy) process involving this
+step, please have a look at the [Thymeleaf CLA repository][cla].
- - Obviously, **your code must both compile and work correctly**. Also, the addition of any new patches to the
- codebase should not render it unstable in any way.
- - All your code should be easy to read and understand by a human.
- - There should be no compilation warnings at all.
-### Detailed Java code quality standards:
- - All your code should compile and run in **Java 6.0**.
- - All comments, names of classes and variables, log messages, etc. must be **in English**.
- - All `.java` files must include the standard Thymeleaf copyright header.
- - All your code should follow the Java Code Conventions regarding variable/method/class naming.
- - Maximum line length is 120 characters.
- - Indentation should be made with 4 spaces, not tabs.
- - Line feeds should be UNIX-like (`\n`).
- - All `.java` source files should be pure ASCII. All `.properties` files should be ISO-8859-1.
- - Number autoboxing and/or autounboxing is forbidden.
- - Every class should define a constructor, even if it is the no-argument constructor, and include a call to `super()`.
- - All method parameters should be declared as `final` so that they cannot be changed or reassigned in the method.
- - All non-nullable parameters in a public method should be first validated with a `Validate.notNull(...)` call.
- This maintains consistency in the behavior of public methods and the error message used.
- - Include a block comment (`/* ... */`) for any non-trivial algorithm you develop. *"Non-trivial"* usually means you
- had to make some design decisions to do things in a certain way. Your comment should explain *why* you wrote the
- code the way you wrote it. Do not write obvious comments that explain what the code does; the code should be clear
- and expressive enough so the *what* and *how* of it is obvious.
- - All public methods and classes directly available to users should have comprehensive JavaDoc comments.
-
-### Detailed HTML/XML code quality standards:
-
- - All tags, CSS styles, file names, etc. must be **in English**.
- - Lower case should be preferred for HTML/XML artifacts. The only exceptions are `DOCTYPE` and `CDATA` clauses.
- - All HTML code should be XML-valid (i.e. all tags should be closed, attributes surrounded by commas, etc.)
- - Maximum line length is 120 characters.
- - Indentation should be made with 4 spaces, not tabs.
- - Line feeds should be UNIX-like (`\n`).
- - All `.html` and `.xml` source files should be pure ASCII, even if _content-type_ is set to a different encoding.
- - All XHTML self-closing (minimized) tags should have a space before `/>` (the XHTML standards say so!).
- - All inline scripts must be enclosed inside a commented `` block.
-
-
-About the documentation/articles you contribute
------------------------------------------------
-
-Note the following only applies to documentation/articles meant to be published at the Thymeleaf website.
-
- - All documentation artifacts, including articles, must be written **in correct English**.
- - Your name and email will be displayed as *"author"* of any documentation artifacts you create.
- - Topic and text structure must be first discussed and agreed upon with the project members.
- - Project members may edit and make small changes to your texts—of which you will be informed—before
- publishing them.
- - Format and visual styles must adhere to the Thymeleaf website standards, of which you will be informed
- by the project members.
-
-
-Pay special attention to this
------------------------------
-
-All Thymeleaf software is distributed under the **Apache License 2.0** open source license; your contributions
-will be licensed in the same way.
-
-If you work for a company which, by the way or place in which your code was written, by your contract terms
-or by the laws in your country, could claim any rights (including but not limited to intellectual or industrial
-property) over your contributed code, you will have to send the project members (either by email from your
-authorised superiors or by signed fax), a statement indicating that your company agrees with the terms
-explained in this page, and that it both authorises your contribution to Thymeleaf and states that it will
-never claim any kind of rights over it.
-
-
-Thymeleaf Individual Contributor License Agreement
---------------------------------------------------
-
-This contributor agreement ("Agreement") documents the rights granted by contributors to the Thymeleaf Project.
-
-This is a legally binding document, so please read it carefully before agreeing to it. The Agreement
-may cover more than one software project managed by Thymeleaf.
-
-
-### 1. Definitions
-
- * _"Thymeleaf"_ means the "Thymeleaf Project organization and members".
- * _"You"_ means the individual who submits a Contribution to Thymeleaf.
- * _"Contribution"_ means any work of authorship that is submitted by you to Thymeleaf in which you own
- or assert ownership of the Copyright.
- * _"Copyright"_ means all rights protecting works of authorship owned or controlled by you,
- including copyright, moral and neighboring rights, as appropriate, for the full term of their
- existence including any extensions by you.
- * _"Material"_ means the work of authorship which is made available by Thymeleaf to third parties. When
- this Agreement covers more than one software project, the Material means the work of authorship
- to which the Contribution was submitted. After you submit the Contribution, it may be included
- in the Material.
- * _"Submit"_ means any form of electronic, verbal, or written communication sent to Thymeleaf or its
- representatives, including but not limited to electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, Thymeleaf for the purpose of discussing
- and improving the Material, but excluding communication that is conspicuously marked or
- otherwise designated in writing by you as _"Not a Contribution."_
- * _"Submission Date"_ means the date on which you submit a Contribution to Thymeleaf.
- * _"Effective Date"_ means the date you execute this agreement or the date You first submit a
- Contribution to Thymeleaf, whichever is earlier.
-
-
-### 2. Grant of Rights
-
-#### 2.1. Copyright License
-
- * (a) You retain ownership of the copyright in your Contribution and have the same rights to use or
- license the Contribution which you would have had without entering into the agreement.
- * (b) To the maximum extent permitted by the relevant law, you grant to Thymeleaf a perpetual, worldwide,
- non-exclusive, transferable, royalty-free, irrevocable license under the copyright covering the
- Contribution, with the right to sublicense such rights through multiple tiers of sublicensees, to
- reproduce, modify, display, perform and distribute the Contribution as part of the Material; provided
- that this license is conditioned upon compliance with Section 2.3.
+## Conventions and Housekeeping
-#### 2.2 Patent License
+### General Guidelines:
-For patent claims including, without limitation, method, process, and apparatus claims which you
-own, control or have the right to grant, now or in the future, you grant to Thymeleaf a perpetual, worldwide,
-non-exclusive, transferable, royalty-free, irrevocable patent license, with the right to sublicense these
-rights to multiple tiers of sublicensees, to make, have made, use, sell, offer for sale, import and
-otherwise transfer the Contribution and the Contribution in combination with the Material (and
-portions of such combination). This license is granted only to the extent that the exercise of the
-licensed rights infringes such patent claims; and provided that this license is conditioned upon
-compliance with Section 2.3.
+ - Obviously, **your code must both compile and work correctly**.
+ - All your code should be easy to read and understand by a human. The same
+ requirement applies to documentation.
+ - Unless for specific artifacts such as documentation translations, all
+ code, comments, documentation, names of classes and variables,
+ log messages, etc. must be **in English**.
+ - All contribured files must include the standard Thymeleaf copyright header.
+ - Maximum recommended line length is 120 characters. This is not strictly
+ enforced.
+ - Indentation should be made with 4 spaces, not tabs. Line feeds should be
+ UNIX-like (`\n`).
+ - All source files should be pure ASCII, except `.properties` files which
+ should be ISO-8859-1.
+ - You shall add yourself as _author_ (e.g. Javadoc `@author`) to any files
+ that you create or modify substantially (more than cosmetic changes).
-#### 2.3 Outbound License
+### Specific Java Code Gudelines:
-As a condition on the grant of rights in Sections 2.1 and 2.2, Thymeleaf agrees to license the Contribution only
-under the terms of the Apache License 2.0 (including any right to adopt any future version of this license if
-permitted).
-
-#### 2.4 Moral Rights
-
-If moral rights apply to the Contribution, to the maximum extent permitted by law, you waive and agree not
-to assert such moral rights against Thymeleaf or its successors in interest, or any of our licensees, either
-direct or indirect.
-
-#### 2.5 Thymeleaf Rights
-
-You acknowledge that Thymeleaf is not obligated to use your Contribution as part of the
-Material and may decide to include any Contributions Thymeleaf considers appropriate.
-
-#### 2.6 Reservation of Rights
-
-Any rights not expressly assigned or licensed under this section are expressly reserved by you.
-
-
-### 3. Agreement
-
-You confirm that:
-
- * (a) You have the legal authority to enter into this Agreement.
- * (b) You own the Copyright and patent claims covering the Contribution which are required to grant
- the rights under Section 2.
- * (c) The grant of rights under Section 2 does not violate any grant of rights which you have made to
- third parties, including your employer. If you are an employee, you have had your employer approve
- this Agreement. If you are less than eighteen years old, please have your parents or guardian
- sign the Agreement.
-
-
-### 4. Disclaimer
-
-EXCEPT FOR THE EXPRESS WARRANTIES IN SECTION 3, THE CONTRIBUTION IS PROVIDED "AS IS". MORE PARTICULARLY,
-ALL EXPRESS OR IMPLIED WARRANTIES INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTY OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY DISCLAIMED BY YOU TO THYMELEAF AND BY
-THYMELEAF TO YOU. TO THE EXTENT THAT ANY SUCH WARRANTIES CANNOT BE DISCLAIMED, SUCH WARRANTY IS LIMITED IN
-DURATION TO THE MINIMUM PERIOD PERMITTED BY LAW.
-
-
-### 5. Consequential Damage Waiver
-
-TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL YOU OR THYMELEAF BE LIABLE FOR ANY LOSS OF
-PROFITS, LOSS OF ANTICIPATED SAVINGS, LOSS OF DATA, INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL AND EXEMPLARY
-DAMAGES ARISING OUT OF THIS AGREEMENT REGARDLESS OF THE LEGAL OR EQUITABLE THEORY (CONTRACT, TORT OR OTHERWISE)
-UPON WHICH THE CLAIM IS BASED.
-
-
-### 6. Miscellaneous
-
- * 6.1 This Agreement will be governed by and construed in accordance with the laws of Spain excluding its
- conflicts of law provisions. Under certain circumstances, the governing law in this section might be
- superseded by the United Nations Convention on Contracts for the International Sale of Goods ("UN
- Convention") and the parties intend to avoid the application of the UN Convention to this Agreement
- and, thus, exclude the application of the UN Convention in its entirety to this Agreement.
- * 6.2 This Agreement sets out the entire agreement between you and Thymeleaf for your Contributions to Thymeleaf
- and overrides all other agreements or understandings.
- * 6.3 If You or Thymeleaf assign the rights or obligations received through this Agreement to a third party, as a
- condition of the assignment, that third party must agree in writing to abide by all the rights and
- obligations in the Agreement.
- * 6.4 The failure of either party to require performance by the other party of any provision of this
- Agreement in one situation shall not affect the right of a party to require such performance at any time
- in the future. A waiver of performance under a provision in one situation shall not be considered a
- waiver of the performance of the provision in the future or a waiver of the provision in its entirety.
- * 6.5 If any provision of this Agreement is found void and unenforceable, such provision will be
- replaced to the extent possible with a provision that comes closest to the meaning of the original
- provision and which is enforceable. The terms and conditions set forth in this Agreement shall apply
- notwithstanding any failure of essential purpose of this Agreement or any limited remedy to the
- maximum extent possible under law.
+ - All your code should compile and run in the current minimum Java version
+ of the project.
+ - All your code should follow the Java Code Conventions regarding
+ variable/method/class naming.
+ - Number autoboxing and/or autounboxing is forbidden.
+ - Every class should define a constructor, even if it is the no-argument
+ constructor, and include a call to `super()`.
+ - All method parameters should be declared as `final` so that they cannot be
+ changed or reassigned in the method.
+ - All non-nullable parameters in public methods should be first validated for
+ non-nullity inside the code.
+ - Existing Javadoc must be maintained along with performed changes. Addition
+ of new Javadoc for public methods or code comments for any non-trivial
+ algorithms is always welcome.
+ - Writing unit tests for new, existing and modified code is always welcome
+ too. For any new algorithms or functionality contributed, or substantial
+ modifications made to existing ones, the team might consider these a
+ requirement.
+
+
+
+
+[cla]: https://github.com/thymeleaf/thymeleaf-org/blob/CLA_CURRENT/CLA/
+[code-of-coduct]: https://github.com/thymeleaf/thymeleaf-org/blob/CoC_CURRENT/CoC/THYMELEAF_CODE_OF_CONDUCT.markdown
+[thymeleaf-team]: https://www.thymeleaf.org/team.html
+[stackoverflow]: https://stackoverflow.com
+[stackoverflow-thymeleaf]: https://stackoverflow.com/tags/thymeleaf
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 041db10c5..06dec4ba8 100755
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,6 +1,48 @@
+3.0.16
+======
+- Updated AttoParser dependency to 2.0.6.RELEASE
+
+
+3.0.15
+======
+- Fixed expression parsing inconsistency provoked by empty literal substitutions.
+- Blocked static and constructor access to certain classes.
+- Block calling methods of blocked classes in expressions.
+
+
+3.0.14
+======
+- Fixed inconsistent restricted variable access check due to caching.
+- Improved detection of restricted expression execution scenarios.
+
+
+3.0.13
+======
+(no relevant changes in core module)
+
+
+3.0.12
+======
+- Fixed #numbers.format*() expression utility methods not producing numbers using the correct digit symbols for
+ locales that use them, in JDK versions where NumberFormat does this (currently >= JDK15).
+- Fixed "package-list" not being produced for JavaDoc since JDK 11 started being used for compiling the project.
+- Added instantiation of new objects and calls to static classes as forbidden operations in restricted mode.
+- Updated OGNL dependency to 3.1.26.
+- Updated jackson-databind to 2.11.3 and jackson-datatype to 2.11.3 (due to vulnerabilities in previous versions).
+
+
+3.0.11
+======
+- Updated jackson-databind dependency to 2.9.7 (due to vulnerabilities in previous jackson version).
+
+
3.0.10
======
- Fixed StackOverflowError when inserting content before first element of model in a model processor.
+- Improved restricted expression evaluation mode to forbid output of textual data from context variables inside
+ JavaScript event handlers in HTML templates.
+- Improved HTML event handler attributes (th:on*) in order to allow processing of their values as fragments
+ of inlined JavaScript (using JAVASCRIPT template mode).
- Improved use of template name abbreviation in logs and exceptions.
- Added "Automatic-Module-Name: thymeleaf" to MANIFEST.MF for Java 9+ JPMS.
- Updated AttoParser dependency to 2.0.5.RELEASE
diff --git a/pom.xml b/pom.xml
index 246eb4791..0bd206b1f 100755
--- a/pom.xml
+++ b/pom.xml
@@ -26,7 +26,7 @@
* Template selectors allow the possibility to process only a part of the specified template, expressing
* this selection in a syntax similar to jQuery, CSS or XPath selectors. Note this is only available for
- * markup template modes (HTML, XML). For more info on template selectors
+ * markup template modes ({@code HTML}, {@code XML}). For more info on template selectors
* syntax, have a look at AttoParser's markup selectors
* documentation.
*
* Template selectors allow the possibility to process only a part of the specified template, expressing
* this selection in a syntax similar to jQuery, CSS or XPath selectors. Note this is only available for
- * markup template modes (HTML, XML). For more info on template selectors
+ * markup template modes ({@code HTML}, {@code XML}). For more info on template selectors
* syntax, have a look at AttoParser's markup selectors
* documentation.
*
* Template selectors allow the possibility to process only a part of the specified template, expressing
* this selection in a syntax similar to jQuery, CSS or XPath selectors. Note this is only available for
- * markup template modes (HTML, XML). For more info on template selectors
+ * markup template modes ({@code HTML}, {@code XML}). For more info on template selectors
* syntax, have a look at AttoParser's markup selectors
* documentation.
*
* Interface defining operations that can regulate the pace at which the template engine will process a
* template (a.k.a. engine throttling). Objects implementing this interface are returned by
- * the processThrottled(...) methods at {@link ITemplateEngine}.
+ * the {@code processThrottled(...)} methods at {@link ITemplateEngine}.
*
* When the processing of a template is throttled the client classes can tell the engine how much output
- * they are prepared to handle by calling any of the process(int,...) methods. As a response to this,
+ * they are prepared to handle by calling any of the {@code process(int,...)} methods. As a response to this,
* the engine will process only the part of the template enough to write at most so many chars
- * or bytes as specified at the processThrottled(...) call. Output will be written to a {@link Writer}
+ * or bytes as specified at the {@code processThrottled(...)} call. Output will be written to a {@link Writer}
* in the form of chars, or to an {@link OutputStream} in the form of bytes.
*
@@ -93,7 +93,7 @@ public interface IThrottledTemplateProcessor {
*
* NOTE Implementations of this method must be thread-safe as, even if executions
- * of the throttled processor (calls to process(...) methods) should never happen concurrently,
+ * of the throttled processor (calls to {@code process(...)} methods) should never happen concurrently,
* determining whether a throttled processor has finished or not can happen concurrently from different
* threads as a way of short-cutting the execution of the processor (and avoid excessive consumption of
* upstream data, for example).
diff --git a/src/main/java/org/thymeleaf/TemplateEngine.java b/src/main/java/org/thymeleaf/TemplateEngine.java
index 00533f69c..09f198ff9 100755
--- a/src/main/java/org/thymeleaf/TemplateEngine.java
+++ b/src/main/java/org/thymeleaf/TemplateEngine.java
@@ -63,7 +63,7 @@
* This is the only implementation of {@link ITemplateEngine} provided out of the box by Thymeleaf.
*
* An instance of this class can be created at any time by calling its constructor:
*
- * Creation and configuration of TemplateEngine instances is expensive, so it is
+ * Creation and configuration of {@code TemplateEngine} instances is expensive, so it is
* recommended to create only one instance of this class (or at least one instance per
* dialect/configuration) and use it to process multiple templates.
*
- * Once created, an instance of TemplateEngine has to be typically configured a
+ * Once created, an instance of {@code TemplateEngine} has to be typically configured a
* mechanism for resolving templates (i.e. obtaining and reading them):
* Creating an instance of TemplateEngine
+ * Creating an instance of {@code TemplateEngine}
* Configuring the TemplateEngine
+ * Configuring the {@code TemplateEngine}
*
@@ -176,7 +176,7 @@
* {@link javax.servlet.ServletContext} objects as constructor arguments:
*
- * final IContext ctx = new WebContext(request, response, servletContext);
+ * final WebContext ctx = new WebContext(request, response, servletContext);
* ctx.setVariable("allItems", items);
*
* @@ -185,9 +185,9 @@ * *
- * In order to execute templates, the different process(...) methods should + * In order to execute templates, the different {@code process(...)} methods should * be used. Those are mostly divided into two blocks: those that return the template processing - * result as a String, and those that receive a {@link Writer} as an argument + * result as a {@code String}, and those that receive a {@link Writer} as an argument * and use it for writing the result instead. *
*@@ -206,7 +206,7 @@ * templateEngine.process("mytemplate", ctx, httpServletResponse.getWriter()); * *
- * The "mytemplate" String argument is the template name, and it + * The {@code "mytemplate"} String argument is the template name, and it * will relate to the physical/logical location of the template itself in a way * configured at the template resolver/s. *
@@ -225,11 +225,11 @@ public class TemplateEngine implements ITemplateEngine { /** *- * Name of the TIMER logger. This logger will output the time required + * Name of the {@code TIMER} logger. This logger will output the time required * for executing each template processing operation. *
*- * The value of this constant is org.thymeleaf.TemplateEngine.TIMER. This + * The value of this constant is {@code org.thymeleaf.TemplateEngine.TIMER}. This * allows you to set a specific configuration and/or appenders for timing info at your logging * system configuration. *
@@ -261,10 +261,10 @@ public class TemplateEngine implements ITemplateEngine { /** *- * Constructor for TemplateEngine objects. + * Constructor for {@code TemplateEngine} objects. *
*- * This is the only way to create a TemplateEngine instance (which + * This is the only way to create a {@code TemplateEngine} instance (which * should be configured after creation). *
*/ @@ -309,7 +309,7 @@ private void checkNotInitialized() { * THIS METHOD IS INTERNAL AND SHOULD NEVER BE CALLED DIRECTLY. * *- * If a subclass of TemplateEngine needs additional steps for + * If a subclass of {@code TemplateEngine} needs additional steps for * initialization, the {@link #initializeSpecific()} method should * be overridden. *
@@ -360,7 +360,7 @@ final void initialize() { /** ** This method performs additional initializations required for a - * TemplateEngine subclass instance. This method + * {@code TemplateEngine} subclass instance. This method * is called before the first execution of * {@link TemplateEngine#process(String, org.thymeleaf.context.IContext)} * or {@link TemplateEngine#processThrottled(String, org.thymeleaf.context.IContext)} @@ -372,7 +372,7 @@ final void initialize() { *
** The base implementation of this method does nothing, and it is designed - * for being overridden by subclasses of TemplateEngine. + * for being overridden by subclasses of {@code TemplateEngine}. *
*/ protected void initializeSpecific() { @@ -383,16 +383,16 @@ protected void initializeSpecific() { /** *- * Checks whether the TemplateEngine has already been initialized - * or not. A TemplateEngine is initialized when the {@link #initialize()} + * Checks whether the {@code TemplateEngine} has already been initialized + * or not. A {@code TemplateEngine} is initialized when the {@link #initialize()} * method is called the first time a template is processed. *
** Normally, there is no good reason why users would need to call this method. *
* - * @return true if the template engine has already been initialized, - * false if not. + * @return {@code true} if the template engine has already been initialized, + * {@code false} if not. */ public final boolean isInitialized() { return this.initialized; diff --git a/src/main/java/org/thymeleaf/TemplateSpec.java b/src/main/java/org/thymeleaf/TemplateSpec.java index 0509e9787..777f8d4c1 100644 --- a/src/main/java/org/thymeleaf/TemplateSpec.java +++ b/src/main/java/org/thymeleaf/TemplateSpec.java @@ -36,7 +36,7 @@ ** Specification class containing everything needed by the template engine related to the * template to be processed. Objects of this class are normally used as an argument to the - * different process(...) methods at {@link ITemplateEngine}. + * different {@code process(...)} methods at {@link ITemplateEngine}. *
** The only required value in a template specification is the template, which normally @@ -107,7 +107,7 @@ public TemplateSpec(final String template, final TemplateMode templateMode) { *
* Build a new object of this class, specifying template and also output content type * (MIME type). Most of the times this will force a template mode for template execution - * (e.g. text/html, application/javascript), but not always (e.g. text/event-stream). + * (e.g. {@code text/html}, {@code application/javascript}), but not always (e.g. {@code text/event-stream}). *
** The template normally represents the template name, but can be the entire template @@ -118,16 +118,16 @@ public TemplateSpec(final String template, final TemplateMode templateMode) { * Supported relations between template mode and output content type are: *
*- * The text/event-stream content type will also be supported, but will have no effect in + * The {@code text/event-stream} content type will also be supported, but will have no effect in * forcing a template mode. Instead, it will put the engine into Server-Sent Event (SSE) output mode. *
*
@@ -166,7 +166,7 @@ public TemplateSpec(final String template, final String outputContentType) {
* so they will be used as a part of the keys for cached templates. It is therefore
* required that template attribute maps contain values with valid {@link #equals(Object)}
* and {@link #hashCode()} implementations. Therefore, using simple (and fast)
- * Map<String,String> maps is the recommended option.
+ * {@code Map
* This constructor will set no template selectors or forced template mode.
@@ -193,7 +193,7 @@ public TemplateSpec(final String template, final Map
* Template selectors allow the possibility to process only a part of the specified template, expressing
* this selection in a syntax similar to jQuery, CSS or XPath selectors. Note this is only available for
- * markup template modes (HTML, XML). For more info on template selectors
+ * markup template modes ({@code HTML}, {@code XML}). For more info on template selectors
* syntax, have a look at AttoParser's markup selectors
* documentation.
*
* Build a new object of this class, specifying an output content type (MIME type). Most of the times this - * will force a template mode for template execution (e.g. text/html, application/javascript), - * but not always (e.g. text/event-stream). + * will force a template mode for template execution (e.g. {@code text/html}, {@code application/javascript}), + * but not always (e.g. {@code text/event-stream}). *
** The template usually represents the template name, but can be the entire template @@ -241,7 +241,7 @@ public TemplateSpec( *
* Template selectors allow the possibility to process only a part of the specified template, expressing * this selection in a syntax similar to jQuery, CSS or XPath selectors. Note this is only available for - * markup template modes (HTML, XML). For more info on template selectors + * markup template modes ({@code HTML}, {@code XML}). For more info on template selectors * syntax, have a look at AttoParser's markup selectors * documentation. *
@@ -254,16 +254,16 @@ public TemplateSpec( * Supported relations between template mode and output content type are: * *- * The text/event-stream content type will also be supported, but will have no effect in + * The {@code text/event-stream} content type will also be supported, but will have no effect in * forcing a template mode. Instead, it will put the engine into Server-Sent Event (SSE) output mode. *
*
@@ -274,7 +274,7 @@ public TemplateSpec(
* so they will be used as a part of the keys for cached templates. It is therefore
* required that template attribute maps contain values with valid {@link #equals(Object)}
* and {@link #hashCode()} implementations. Therefore, using simple (and fast)
- * Map<String,String> maps is the recommended option.
+ * {@code Map
* Template selectors allow the possibility to process only a part of the specified template, expressing * this selection in a syntax similar to jQuery, CSS or XPath selectors. Note this is only available for - * markup template modes (HTML, XML). For more info on template selectors + * markup template modes ({@code HTML}, {@code XML}). For more info on template selectors * syntax, have a look at AttoParser's markup selectors * documentation. *
* - * @return the template selectors, or null if there are none. + * @return the template selectors, or {@code null} if there are none. */ public Set* Returns the output content type (MIME type). Most of the times this - * will force a template mode for template execution (e.g. text/html, application/javascript), - * but not always (e.g. text/event-stream). + * will force a template mode for template execution (e.g. {@code text/html}, {@code application/javascript}), + * but not always (e.g. {@code text/event-stream}). *
** Supported relations between template mode and output content type are: *
*- * The text/event-stream content type will also be supported, but will have no effect in + * The {@code text/event-stream} content type will also be supported, but will have no effect in * forcing a template mode. Instead, it will put the engine into Server-Sent Event (SSE) output mode. *
** Note content type parameters will be ignored (only the mime type itself will be used). *
* - * @return the output content type, or null if none was specified. + * @return the output content type, or {@code null} if none was specified. */ public String getOutputContentType() { return this.outputContentType; @@ -509,7 +509,7 @@ public String getOutputContentType() { * Returns whether output should be Server-Sent Events (SSE) or not. * *- * Server-Sent Events mode is enabled by setting the text/event-stream mime type + * Server-Sent Events mode is enabled by setting the {@code text/event-stream} mime type * as *output content type* constructor argument. *
* diff --git a/src/main/java/org/thymeleaf/Thymeleaf.java b/src/main/java/org/thymeleaf/Thymeleaf.java index 85aab7b46..d66081c2f 100644 --- a/src/main/java/org/thymeleaf/Thymeleaf.java +++ b/src/main/java/org/thymeleaf/Thymeleaf.java @@ -22,6 +22,7 @@ import java.util.Properties; import org.thymeleaf.util.ClassLoaderUtils; +import org.thymeleaf.util.VersionUtils; /** @@ -36,15 +37,37 @@ */ public final class Thymeleaf { + private static final String STABLE_RELEASE_QUALIFIER = "RELEASE"; + + /** + * @deprecated Deprecated in 3.0.12. Use {@link #getVersion()} instead. Will be removed in Thymeleaf 3.1. + */ public static final String VERSION; + /** + * @deprecated Deprecated in 3.0.12. Use {@link #getBuildTimestamp()} instead. Will be removed in Thymeleaf 3.1. + */ public static final String BUILD_TIMESTAMP; - + /** + * @deprecated Deprecated in 3.0.12. Use {@link #getVersionMajor()} instead. Will be removed in Thymeleaf 3.1. + */ public static final int VERSION_MAJOR; + /** + * @deprecated Deprecated in 3.0.12. Use {@link #getVersionMinor()} instead. Will be removed in Thymeleaf 3.1. + */ public static final int VERSION_MINOR; + /** + * @deprecated Deprecated in 3.0.12. Use {@link #getVersionPatch()} instead. Will be removed in Thymeleaf 3.1. + */ public static final int VERSION_BUILD; + /** + * @deprecated Deprecated in 3.0.12. Use {@link #getVersionQualifier()} instead. Will be removed in Thymeleaf 3.1. + */ public static final String VERSION_TYPE; + private static final VersionUtils.VersionSpec VERSION_SPEC; + + static { String version = null; @@ -58,51 +81,51 @@ public final class Thymeleaf { // Ignored: we don't have such information, might be due to IDE configuration } - VERSION = version; - BUILD_TIMESTAMP = buildTimestamp; - if (VERSION == null || VERSION.trim().length() == 0) { + VERSION_SPEC = VersionUtils.parseVersion(version, buildTimestamp); - VERSION_MAJOR = 0; - VERSION_MINOR = 0; - VERSION_BUILD = 0; - VERSION_TYPE = "UNKNOWN"; + VERSION = VERSION_SPEC.getVersion(); + BUILD_TIMESTAMP = VERSION_SPEC.getBuildTimestamp(); + VERSION_MAJOR = VERSION_SPEC.getMajor(); + VERSION_MINOR = VERSION_SPEC.getMinor(); + VERSION_BUILD = VERSION_SPEC.getPatch(); + VERSION_TYPE = VERSION_SPEC.getQualifier(); - } else { + } - try { - String versionRemainder = VERSION; - int separatorIdx = versionRemainder.indexOf('.'); - VERSION_MAJOR = Integer.parseInt(versionRemainder.substring(0,separatorIdx)); - versionRemainder = versionRemainder.substring(separatorIdx + 1); - separatorIdx = versionRemainder.indexOf('.'); - VERSION_MINOR = Integer.parseInt(versionRemainder.substring(0, separatorIdx)); - versionRemainder = versionRemainder.substring(separatorIdx + 1); - separatorIdx = versionRemainder.indexOf('.'); - if (separatorIdx < 0) { - separatorIdx = versionRemainder.indexOf('-'); - } - VERSION_BUILD = Integer.parseInt(versionRemainder.substring(0, separatorIdx)); - VERSION_TYPE = versionRemainder.substring(separatorIdx + 1); - } catch (final Exception e) { - throw new ExceptionInInitializerError( - "Exception during initialization of Thymeleaf versioning utilities. Identified Thymeleaf " + - "version is '" + VERSION + "', which does not follow the {major}.{minor}.{build}[.|-]{type} " + - "scheme"); - } - } + public static String getVersion() { + return VERSION_SPEC.getVersion(); + } + + public static String getBuildTimestamp() { + return VERSION_SPEC.getBuildTimestamp(); + } + + public static int getVersionMajor() { + return VERSION_SPEC.getMajor(); + } + + public static int getVersionMinor() { + return VERSION_SPEC.getMinor(); + } + + public static int getVersionPatch() { + return VERSION_SPEC.getPatch(); + } + public static String getVersionQualifier() { + return VERSION_SPEC.getQualifier(); } public static boolean isVersionStableRelease() { - return "RELEASE".equals(VERSION_TYPE); + return STABLE_RELEASE_QUALIFIER.equals(VERSION_SPEC.getQualifier()); } diff --git a/src/main/java/org/thymeleaf/cache/AbstractCacheManager.java b/src/main/java/org/thymeleaf/cache/AbstractCacheManager.java index 09a32106f..f05e90568 100755 --- a/src/main/java/org/thymeleaf/cache/AbstractCacheManager.java +++ b/src/main/java/org/thymeleaf/cache/AbstractCacheManager.java @@ -29,7 +29,7 @@ ** Common abstract class for {@link ICacheManager} implementations, useful * for taking care of the lazy initialization of cache objects when their - * corresponding getXCache() methods are called. + * corresponding {@code getXCache()} methods are called. *
*
* Note a class with this name existed since 2.0.0, but it was completely reimplemented
diff --git a/src/main/java/org/thymeleaf/cache/ICache.java b/src/main/java/org/thymeleaf/cache/ICache.java
index 7a7b24f52..742f4879f 100755
--- a/src/main/java/org/thymeleaf/cache/ICache.java
+++ b/src/main/java/org/thymeleaf/cache/ICache.java
@@ -94,7 +94,7 @@ public interface ICache
* Returns all the keys contained in this cache. Note this method might return keys for entries
* that are already invalid, so the result of calling {@link #get(Object)} for these keys might
- * be null.
+ * be {@code null}.
*
* Defines the logic needed to (optionally) validate an entry living in an - * {@link ICache} object before returning it as the result of a get + * {@link ICache} object before returning it as the result of a {@code get} * operation. If not valid, the entry will be removed * from the cache (and null will be returned). *
diff --git a/src/main/java/org/thymeleaf/cache/ICacheManager.java b/src/main/java/org/thymeleaf/cache/ICacheManager.java index 85d4e5935..0bf827e15 100755 --- a/src/main/java/org/thymeleaf/cache/ICacheManager.java +++ b/src/main/java/org/thymeleaf/cache/ICacheManager.java @@ -30,7 +30,7 @@ * ** This class is in charge of providing the corresponding cache objects to - * the template engine. Every call to each of the getXCache() + * the template engine. Every call to each of the {@code getXCache()} * methods must always return the XCache object (i.e. only one cache object * should be ever created for each type of cache, and returned every time it * is requested). @@ -98,7 +98,7 @@ public interface ICacheManager { *
* Keys are the expressions themselves (their String representation), along with * a type that is normally used for identifying the nature of the object being - * cached (for example {"ognl","person.name"}). + * cached (for example {@code {"ognl","person.name"}}). *
* * @return the cache of expression artifacts @@ -116,7 +116,7 @@ public interface ICacheManager { * they should use this method to retrieve them by their name. * *- * Note the default {@link StandardCacheManager} will return null for every + * Note the default {@link StandardCacheManager} will return {@code null} for every * call to this method, as it should be custom implementations of this interface (or * extensions of {@link AbstractCacheManager} or extensions {@link StandardCacheManager}) * who implement these specific caches and offer their names through the @@ -140,7 +140,7 @@ public interface ICacheManager { * Might return null if no specific caches are managed. *
*- * Note the default {@link StandardCacheManager} will return null, as it should + * Note the default {@link StandardCacheManager} will return {@code null}, as it should * be custom implementations of this interface (or * extensions of {@link AbstractCacheManager} or extensions {@link StandardCacheManager}) * who implement these specific caches and offer their names through the diff --git a/src/main/java/org/thymeleaf/cache/StandardCache.java b/src/main/java/org/thymeleaf/cache/StandardCache.java index 4f30c21e6..c7beefb4b 100755 --- a/src/main/java/org/thymeleaf/cache/StandardCache.java +++ b/src/main/java/org/thymeleaf/cache/StandardCache.java @@ -217,7 +217,7 @@ public V get(final K key, final ICacheEntryValidityChecker super K, ? super V> *
* Returns all the keys contained in this cache. Note this method might return keys for entries * that are already invalid, so the result of calling {@link #get(Object)} for these keys might - * be null. + * be {@code null}. *
* * @return the complete set of cache keys. Might include keys for already-invalid (non-cleaned) entries. diff --git a/src/main/java/org/thymeleaf/cache/StandardCacheManager.java b/src/main/java/org/thymeleaf/cache/StandardCacheManager.java index cad0f3bff..b655266c8 100755 --- a/src/main/java/org/thymeleaf/cache/StandardCacheManager.java +++ b/src/main/java/org/thymeleaf/cache/StandardCacheManager.java @@ -40,20 +40,20 @@ ** Contexts used during template processing by the engine are always implementations of this interface. * If the Template Engine is called with an implementation of this {@link IEngineContext} as - * context, the same object will be used (so that users can actually provide their own implementations). - * On the other side, if the context specified to the Template Engine is not an implementation of this + * {@code context}, the same object will be used (so that users can actually provide their own implementations). + * On the other side, if the {@code context} specified to the Template Engine is not an implementation of this * interface, an implementation of {@link IEngineContext} will be internally created by the engine, the original * context's variables and other info will be cloned, and used instead. *
@@ -107,10 +107,10 @@ public interface IEngineContext extends ITemplateContext { /** *- * Set a selection target. Usually the consequence of executing a th:object processor. + * Set a selection target. Usually the consequence of executing a {@code th:object} processor. *
*- * Once set, all selection expressions (*{...}) will be executed on this target. + * Once set, all selection expressions ({@code *{...}}) will be executed on this target. *
** This selection target will have the consideration of a local variable and thus depend on @@ -123,7 +123,7 @@ public interface IEngineContext extends ITemplateContext { /** *
- * Set an inliner. Usually the consequence of executing a th:inline processor. + * Set an inliner. Usually the consequence of executing a {@code th:inline} processor. *
** This inliner will have the consideration of a local variable and thus depend on @@ -141,7 +141,7 @@ public interface IEngineContext extends ITemplateContext { * decreased below the current level) originally belonged to a different template. *
*- * A call on this method is usually the consequence of th:insert or th:replace. + * A call on this method is usually the consequence of {@code th:insert} or {@code th:replace}. *
* * @param template the template data. @@ -180,7 +180,7 @@ public interface IEngineContext extends ITemplateContext { * * * @param name the name of the variable to be checked. - * @return true if the variable is local (level > 0), false if not (level == 0). + * @return {@code true} if the variable is local (level > 0), {@code false} if not (level == 0). */ public boolean isVariableLocal(final String name); diff --git a/src/main/java/org/thymeleaf/context/IEngineContextFactory.java b/src/main/java/org/thymeleaf/context/IEngineContextFactory.java index 62aef3419..ff510162f 100644 --- a/src/main/java/org/thymeleaf/context/IEngineContextFactory.java +++ b/src/main/java/org/thymeleaf/context/IEngineContextFactory.java @@ -32,7 +32,7 @@ ** Engine Contexts (implementations of {@link IEngineContext}) are the type of context really used by the engine * during template processing. These factories will be called in order to create {@link IEngineContext} instances - * from the original {@link IContext} implementations (the much simpler context objects that were used + * from the original {@link IContext} implementations (the much simpler {@code context} objects that were used * for calling the template engine). *
*@@ -62,18 +62,18 @@ public interface IEngineContextFactory { *
* Note this factory method will be only called once during the processing of a template. Once a engine context * instance has been created, the engine will try to reuse it for any nested processing operations as far as - * possible. This means that, e.g., the templateData specified here will only be the root-level + * possible. This means that, e.g., the {@code templateData} specified here will only be the root-level * template data (the one for the template that is actually being used as an - * {@link org.thymeleaf.ITemplateEngine}.process(...) argument). Any th:insert or - * th:replace operations inside that template will not ask this factory to create a new engine context, + * {@link org.thymeleaf.ITemplateEngine}{@code .process(...)} argument). Any {@code th:insert} or + * {@code th:replace} operations inside that template will not ask this factory to create a new engine context, * but instead just increase the nesting level of the already-existing one * (see {@link IEngineContext#increaseLevel()}) and set the new, nested template data for that level * (see {@link IEngineContext#setTemplateData(TemplateData)}). *
*- * Note also that the context object passed here as an argument will normally correspond to the + * Note also that the {@code context} object passed here as an argument will normally correspond to the * simple {@link IContext} implementation used for calling - * {@link org.thymeleaf.ITemplateEngine}.process(...) and, therefore, will normally be an object + * {@link org.thymeleaf.ITemplateEngine}{@code .process(...)} and, therefore, will normally be an object * of class {@link EngineContext}, {@link WebContext} or similar. *
* diff --git a/src/main/java/org/thymeleaf/context/IExpressionContext.java b/src/main/java/org/thymeleaf/context/IExpressionContext.java index 9d6880dfb..a9fdf136d 100644 --- a/src/main/java/org/thymeleaf/context/IExpressionContext.java +++ b/src/main/java/org/thymeleaf/context/IExpressionContext.java @@ -56,7 +56,7 @@ public interface IExpressionContext extends IContext { /** ** Returns the {@link IExpressionObjects} instance to be used for retrieving (and maybe building - * lazily) expression objects (${#expobj}) to be used at Standard Thymeleaf Expressions. + * lazily) expression objects ({@code ${#expobj}}) to be used at Standard Thymeleaf Expressions. *
* @return the expression objects instance. */ diff --git a/src/main/java/org/thymeleaf/context/ILazyContextVariable.java b/src/main/java/org/thymeleaf/context/ILazyContextVariable.java index 1d96108ae..bff7d6807 100644 --- a/src/main/java/org/thymeleaf/context/ILazyContextVariable.java +++ b/src/main/java/org/thymeleaf/context/ILazyContextVariable.java @@ -33,7 +33,7 @@ * ** Note this lazy resolution can only be performed when the lazy variable is added to the context as a - * first-level variable. i.e. ${lazy} will work, but ${container.lazy} + * first-level variable. i.e. {@code ${lazy}} will work, but {@code ${container.lazy}} * will not. *
*diff --git a/src/main/java/org/thymeleaf/context/ITemplateContext.java b/src/main/java/org/thymeleaf/context/ITemplateContext.java index 4a49105c4..61ffa63a6 100644 --- a/src/main/java/org/thymeleaf/context/ITemplateContext.java +++ b/src/main/java/org/thymeleaf/context/ITemplateContext.java @@ -61,7 +61,7 @@ public interface ITemplateContext extends IExpressionContext { *
* Note that the {@link TemplateData} returned here corresponds with the origin of the elements or * nodes being currently processed. This is, if a processor is being executed for an element inserted - * from an external template (via a th:insert, for example), then this method will return + * from an external template (via a {@code th:insert}, for example), then this method will return * the template data for the template in which the inserted fragment lives, not the one it was inserted * into. *
@@ -77,7 +77,7 @@ public interface ITemplateContext extends IExpressionContext { ** Note that the {@link TemplateMode} returned here corresponds with origin of the elements or nodes being * currently processed. This is, if a processor is being executed for an element inserted from an external - * template (via a th:insert, for example), then this method will return the template mode + * template (via a {@code th:insert}, for example), then this method will return the template mode * for the template in which the inserted fragment lives, not the one it was inserted into. *
* @@ -96,7 +96,7 @@ public interface ITemplateContext extends IExpressionContext { * ** The first element in this list will always be the top-level template (the one called at the - * {@link org.thymeleaf.ITemplateEngine} process(...) methods). + * {@link org.thymeleaf.ITemplateEngine} {@code process(...)} methods). *
* * @return the stack of templates (list of {@link TemplateData}). @@ -129,7 +129,7 @@ public interface ITemplateContext extends IExpressionContext { /** *- * Returns the map of configuration items that have been specified at the process(...) methods of + * Returns the map of configuration items that have been specified at the {@code process(...)} methods of * {@link org.thymeleaf.ITemplateEngine}, aimed at further configuring the template being used and its * resolution by means of the {@link org.thymeleaf.templateresolver.ITemplateResolver}s. *
@@ -158,22 +158,22 @@ public interface ITemplateContext extends IExpressionContext { * execution or not. * *- * Selection targets are objects on which all *{...} expression will be executed (instead of on the - * root context). They are normally set by means of th:objects. + * Selection targets are objects on which all {@code *{...}} expression will be executed (instead of on the + * root context). They are normally set by means of {@code th:objects}. *
* - * @return true if there is a selection target, false if not. + * @return {@code true} if there is a selection target, {@code false} if not. */ public boolean hasSelectionTarget(); /** *- * Returns the selection target set for the current point of execution (or null if there + * Returns the selection target set for the current point of execution (or {@code null} if there * isn't any). *
*- * Selection targets are objects on which all *{...} expression will be executed (instead of on the - * root context). They are normally set by means of th:objects. + * Selection targets are objects on which all {@code *{...}} expression will be executed (instead of on the + * root context). They are normally set by means of {@code th:objects}. *
* * @return the selection target, or null if there isn't any. @@ -206,7 +206,7 @@ public interface ITemplateContext extends IExpressionContext { * the case that the message does not exist * (see {@link org.thymeleaf.messageresolver.IMessageResolver}). * @return the requested message, correctly formatted. Or an absent message representation, or - * null if no absent message representations are allowed. + * {@code null} if no absent message representations are allowed. */ public String getMessage( final Class> origin, final String key, final Object[] messageParameters, final boolean useAbsentMessageRepresentation); diff --git a/src/main/java/org/thymeleaf/context/IdentifierSequences.java b/src/main/java/org/thymeleaf/context/IdentifierSequences.java index 48a1c7a86..50a278fe3 100644 --- a/src/main/java/org/thymeleaf/context/IdentifierSequences.java +++ b/src/main/java/org/thymeleaf/context/IdentifierSequences.java @@ -28,7 +28,7 @@ /** ** Objects of this class are kept at {@link ITemplateContext} in order to provide templates - * with a way to create unique id attribute values during template processing. + * with a way to create unique {@code id} attribute values during template processing. *
* * @author Daniel Fernández @@ -55,7 +55,7 @@ public IdentifierSequences() { /** ** Returns a new index (ID count) for a specific - * value of the id attribute, and increments + * value of the {@code id} attribute, and increments * the count. *
* @@ -76,7 +76,7 @@ public Integer getAndIncrementIDSeq(final String id) { /** ** Returns the index (ID count) for a specific - * value of the id attribute without incrementing + * value of the {@code id} attribute without incrementing * the count. *
* @@ -96,7 +96,7 @@ public Integer getNextIDSeq(final String id) { /** ** Returns the last index (ID count) returned for a specific - * value of the id attribute (without incrementing + * value of the {@code id} attribute (without incrementing * the count). *
* diff --git a/src/main/java/org/thymeleaf/context/StandardEngineContextFactory.java b/src/main/java/org/thymeleaf/context/StandardEngineContextFactory.java index 54a8cb9a5..d70778295 100644 --- a/src/main/java/org/thymeleaf/context/StandardEngineContextFactory.java +++ b/src/main/java/org/thymeleaf/context/StandardEngineContextFactory.java @@ -33,7 +33,7 @@ * Standard implementation of the {@link IEngineContextFactory} interface. * *- * This factory will examine the context being passed as a parameter and, depending on whether + * This factory will examine the {@code context} being passed as a parameter and, depending on whether * this context object implements the {@link IWebContext} interface or not (i.e. whether support for the * Servlet API should be enabled or not), return a {@link WebEngineContext} or an {@link EngineContext} * instance as a result. diff --git a/src/main/java/org/thymeleaf/dialect/IProcessorDialect.java b/src/main/java/org/thymeleaf/dialect/IProcessorDialect.java index 68f18f977..5ba4c8226 100644 --- a/src/main/java/org/thymeleaf/dialect/IProcessorDialect.java +++ b/src/main/java/org/thymeleaf/dialect/IProcessorDialect.java @@ -29,12 +29,12 @@ * Base interface for all dialects providing processors ({@link IProcessor} objects) to the template engine. *
*- * Dialects of this kind can specify a prefix (see {@link #getPrefix()}) which will be considered the + * Dialects of this kind can specify a {@code prefix} (see {@link #getPrefix()}) which will be considered the * default prefix for that dialect. Users can however change the prefix to be used at the moment the * dialect is added to the template engine. *
*- * Also, prefix can be null, in which case the dialect's processors will be acting on + * Also, prefix can be {@code null}, in which case the dialect's processors will be acting on * attributes and elements without a namespace. *
*diff --git a/src/main/java/org/thymeleaf/engine/AbstractTemplateHandler.java b/src/main/java/org/thymeleaf/engine/AbstractTemplateHandler.java index 60d894efe..7ae5176e2 100644 --- a/src/main/java/org/thymeleaf/engine/AbstractTemplateHandler.java +++ b/src/main/java/org/thymeleaf/engine/AbstractTemplateHandler.java @@ -40,7 +40,7 @@ * interface and offers a good base for the easy implementation of custom template handlers. *
*- * All handleX() implementations in this class are set to simply delegate to the + * All {@code handleX()} implementations in this class are set to simply delegate to the * next handler in the chain, so that subclasses can override only the handling methods that are * really relevant to them. *
diff --git a/src/main/java/org/thymeleaf/engine/DataDrivenTemplateIterator.java b/src/main/java/org/thymeleaf/engine/DataDrivenTemplateIterator.java index d26657125..3b396a39e 100644 --- a/src/main/java/org/thymeleaf/engine/DataDrivenTemplateIterator.java +++ b/src/main/java/org/thymeleaf/engine/DataDrivenTemplateIterator.java @@ -158,7 +158,7 @@ public void finishIteration() { * needed or not. The typical use of this is to be able to switch between the "head" and the "data/buffer" phase. * * - * @return true if this iterator has been queried, false if not. + * @return {@code true} if this iterator has been queried, {@code false} if not. * * @since 3.0.3 */ diff --git a/src/main/java/org/thymeleaf/engine/TemplateData.java b/src/main/java/org/thymeleaf/engine/TemplateData.java index 84fe36985..4b5c5c7cb 100644 --- a/src/main/java/org/thymeleaf/engine/TemplateData.java +++ b/src/main/java/org/thymeleaf/engine/TemplateData.java @@ -69,7 +69,7 @@ public final class TemplateData { /** *- * Builds a new TemplateData object. + * Builds a new {@code TemplateData} object. *
** This constructor should be considered internal, as there should be no reason why @@ -126,7 +126,7 @@ public String getTemplate() { * Returns whether this spec has template selectors specified or not. *
* - * @return true of there are template selectors, false if not. + * @return {@code true} of there are template selectors, {@code false} if not. */ public boolean hasTemplateSelectors() { // Checking for null is enough, as we have already processed this in the constructor @@ -141,12 +141,12 @@ public boolean hasTemplateSelectors() { ** Template selectors allow the possibility to process only a part of the specified template, expressing * this selection in a syntax similar to jQuery, CSS or XPath selectors. Note this is only available for - * markup template modes (HTML, XML). For more info on template selectors + * markup template modes ({@code HTML}, {@code XML}). For more info on template selectors * syntax, have a look at AttoParser's markup selectors * documentation. *
* - * @return the template selectors, or null if there are none. + * @return the template selectors, or {@code null} if there are none. */ public Set- * Note that, even if this resource object will never be null, the existence of the + * Note that, even if this resource object will never be {@code null}, the existence of the * resource object does not necessarily imply the existence of the resource itself unless * the template resolver was configured for calling {@link ITemplateResource#exists()} upon * template resolution. diff --git a/src/main/java/org/thymeleaf/exceptions/TemplateAssertionException.java b/src/main/java/org/thymeleaf/exceptions/TemplateAssertionException.java index 1bc525840..46c3f5b88 100755 --- a/src/main/java/org/thymeleaf/exceptions/TemplateAssertionException.java +++ b/src/main/java/org/thymeleaf/exceptions/TemplateAssertionException.java @@ -25,7 +25,7 @@ *
** In the Standard Dialects, this exception might be raised by the - * th:assert attribute. + * {@code th:assert} attribute. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/Aggregates.java b/src/main/java/org/thymeleaf/expression/Aggregates.java index b811df499..7c8f62766 100755 --- a/src/main/java/org/thymeleaf/expression/Aggregates.java +++ b/src/main/java/org/thymeleaf/expression/Aggregates.java @@ -31,7 +31,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #aggregates. + * {@code #aggregates}. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/Arrays.java b/src/main/java/org/thymeleaf/expression/Arrays.java index ce3f84186..61a11e092 100755 --- a/src/main/java/org/thymeleaf/expression/Arrays.java +++ b/src/main/java/org/thymeleaf/expression/Arrays.java @@ -30,7 +30,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #arrays. + * {@code #arrays}. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/Bools.java b/src/main/java/org/thymeleaf/expression/Bools.java index 5d4a520ff..60cc19a21 100755 --- a/src/main/java/org/thymeleaf/expression/Bools.java +++ b/src/main/java/org/thymeleaf/expression/Bools.java @@ -34,7 +34,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #bools. + * {@code #bools}. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/Calendars.java b/src/main/java/org/thymeleaf/expression/Calendars.java index c274d148d..5c5607d01 100755 --- a/src/main/java/org/thymeleaf/expression/Calendars.java +++ b/src/main/java/org/thymeleaf/expression/Calendars.java @@ -37,7 +37,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #calendars. + * {@code #calendars}. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/Conversions.java b/src/main/java/org/thymeleaf/expression/Conversions.java index cb92e6459..c8ae3b7c4 100755 --- a/src/main/java/org/thymeleaf/expression/Conversions.java +++ b/src/main/java/org/thymeleaf/expression/Conversions.java @@ -32,7 +32,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #conversions. + * {@code #conversions}. *
** Note a class with this name existed since 2.1.0, but it was completely reimplemented diff --git a/src/main/java/org/thymeleaf/expression/Dates.java b/src/main/java/org/thymeleaf/expression/Dates.java index 36cd4fd7e..c0be69574 100755 --- a/src/main/java/org/thymeleaf/expression/Dates.java +++ b/src/main/java/org/thymeleaf/expression/Dates.java @@ -37,7 +37,7 @@ *
** An object of this class is usually available in variable evaluation expressions with the name - * #dates. + * {@code #dates}. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/ExecutionInfo.java b/src/main/java/org/thymeleaf/expression/ExecutionInfo.java index a3b7c5b62..6888c20f5 100644 --- a/src/main/java/org/thymeleaf/expression/ExecutionInfo.java +++ b/src/main/java/org/thymeleaf/expression/ExecutionInfo.java @@ -35,7 +35,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #execInfo. + * {@code #execInfo}. *
* * @author Daniel Fernández @@ -63,7 +63,7 @@ public ExecutionInfo(final ITemplateContext context) { ** Note that the template name returned here corresponds with origin of the elements or nodes being * currently processed. This is, if a processor is being executed for an element inserted from an external - * template (via a th:insert, for example), then this method will return the template mode + * template (via a {@code th:insert}, for example), then this method will return the template mode * for the template in which the inserted fragment lives, not the one it was inserted into. *
* @@ -81,7 +81,7 @@ public String getTemplateName() { ** Note that the {@link TemplateMode} returned here corresponds with origin of the elements or nodes being * currently processed. This is, if a processor is being executed for an element inserted from an external - * template (via a th:insert, for example), then this method will return the template mode + * template (via a {@code th:insert}, for example), then this method will return the template mode * for the template in which the inserted fragment lives, not the one it was inserted into. *
* diff --git a/src/main/java/org/thymeleaf/expression/IExpressionObjectFactory.java b/src/main/java/org/thymeleaf/expression/IExpressionObjectFactory.java index f32c8d462..c793903e2 100644 --- a/src/main/java/org/thymeleaf/expression/IExpressionObjectFactory.java +++ b/src/main/java/org/thymeleaf/expression/IExpressionObjectFactory.java @@ -58,7 +58,7 @@ public interface IExpressionObjectFactory { * * @param context the context being used for processing the template. * @param expressionObjectName the name of the expression object to be built. - * @return the built object, or null if the object could not be built. + * @return the built object, or {@code null} if the object could not be built. */ public Object buildObject(final IExpressionContext context, final String expressionObjectName); @@ -72,7 +72,7 @@ public interface IExpressionObjectFactory { * executed during a single template execution. * * @param expressionObjectName the name of the expression object. - * @return true is the object is to be considered cacheable, false if not. + * @return {@code true} is the object is to be considered cacheable, {@code false} if not. */ public boolean isCacheable(final String expressionObjectName); diff --git a/src/main/java/org/thymeleaf/expression/Ids.java b/src/main/java/org/thymeleaf/expression/Ids.java index 0953ece44..f36cbb499 100755 --- a/src/main/java/org/thymeleaf/expression/Ids.java +++ b/src/main/java/org/thymeleaf/expression/Ids.java @@ -24,12 +24,12 @@ /** *- * Expression Object for performing operations related to markup id attributes inside Thymeleaf + * Expression Object for performing operations related to markup {@code id} attributes inside Thymeleaf * Standard Expressions. *
** An object of this class is usually available in variable evaluation expressions with the name - * #ids. + * {@code #ids}. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/Lists.java b/src/main/java/org/thymeleaf/expression/Lists.java index a6dc29b70..2f56c3f70 100755 --- a/src/main/java/org/thymeleaf/expression/Lists.java +++ b/src/main/java/org/thymeleaf/expression/Lists.java @@ -32,7 +32,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #lists. + * {@code #lists}. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/Maps.java b/src/main/java/org/thymeleaf/expression/Maps.java index a39b1291a..b3c9d89ed 100755 --- a/src/main/java/org/thymeleaf/expression/Maps.java +++ b/src/main/java/org/thymeleaf/expression/Maps.java @@ -31,7 +31,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #maps. + * {@code #maps}. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/Messages.java b/src/main/java/org/thymeleaf/expression/Messages.java index 62aeae3a7..6f2c68815 100755 --- a/src/main/java/org/thymeleaf/expression/Messages.java +++ b/src/main/java/org/thymeleaf/expression/Messages.java @@ -33,7 +33,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #messages. + * {@code #messages}. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/Numbers.java b/src/main/java/org/thymeleaf/expression/Numbers.java index dbb1a7fce..385cf6df0 100755 --- a/src/main/java/org/thymeleaf/expression/Numbers.java +++ b/src/main/java/org/thymeleaf/expression/Numbers.java @@ -36,7 +36,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #numbers. + * {@code #numbers}. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/Objects.java b/src/main/java/org/thymeleaf/expression/Objects.java index 9a8216e84..ad5029157 100755 --- a/src/main/java/org/thymeleaf/expression/Objects.java +++ b/src/main/java/org/thymeleaf/expression/Objects.java @@ -34,7 +34,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #objects. + * {@code #objects}. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/Sets.java b/src/main/java/org/thymeleaf/expression/Sets.java index 8cb7e89f4..f61d725f3 100755 --- a/src/main/java/org/thymeleaf/expression/Sets.java +++ b/src/main/java/org/thymeleaf/expression/Sets.java @@ -31,7 +31,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #sets. + * {@code #sets}. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/expression/Strings.java b/src/main/java/org/thymeleaf/expression/Strings.java index e66575535..2763a700c 100755 --- a/src/main/java/org/thymeleaf/expression/Strings.java +++ b/src/main/java/org/thymeleaf/expression/Strings.java @@ -35,7 +35,7 @@ * ** An object of this class is usually available in variable evaluation expressions with the name - * #strings. + * {@code #strings}. *
* * @author Daniel Fernández @@ -63,12 +63,12 @@ public Strings(final Locale locale) { /** *- * Performs a null-safe toString() operation. + * Performs a null-safe {@code toString()} operation. *
* * @param target the object on which toString will be executed - * @return the result of calling target.toString() if target is not null, - * null if target is null. + * @return the result of calling {@code target.toString()} if target is not null, + * {@code null} if target is null. * @since 2.0.12 */ public String toString(final Object target) { @@ -81,13 +81,13 @@ public String toString(final Object target) { /** *- * Performs a null-safe toString() operation on each + * Performs a null-safe {@code toString()} operation on each * element of the array. *
* * @param target the array of objects on which toString will be executed - * @return for each element: the result of calling target.toString() - * if target is not null, null if target is null. + * @return for each element: the result of calling {@code target.toString()} + * if target is not null, {@code null} if target is null. * @since 2.0.12 */ public String[] arrayToString(final Object[] target) { @@ -104,13 +104,13 @@ public String[] arrayToString(final Object[] target) { /** *- * Performs a null-safe toString() operation on each + * Performs a null-safe {@code toString()} operation on each * element of the list. *
* * @param target the list of objects on which toString will be executed - * @return for each element: the result of calling target.toString() - * if target is not null, null if target is null. + * @return for each element: the result of calling {@code target.toString()} + * if target is not null, {@code null} if target is null. * @since 2.0.12 */ public List- * Performs a null-safe toString() operation on each + * Performs a null-safe {@code toString()} operation on each * element of the set. *
* * @param target the set of objects on which toString will be executed - * @return for each element: the result of calling target.toString() - * if target is not null, null if target is null. + * @return for each element: the result of calling {@code target.toString()} + * if target is not null, {@code null} if target is null. * @since 2.0.12 */ public Set* An object of this class is usually available in variable evaluation expressions with the name - * #uris. + * {@code #uris}. *
* * @author Daniel Fernández @@ -47,36 +47,36 @@ public Uris() { /** ** Perform am URI path escape operation - * on a String input using UTF-8 as encoding. + * on a {@code String} input using {@code UTF-8} as encoding. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
** The following are the only allowed chars in an URI path (will not be escaped): *
** All other chars will be escaped by converting them to the sequence of bytes that - * represents them in the UTF-8 and then representing each byte - * in %HH syntax, being HH the hexadecimal representation of the byte. + * represents them in the {@code UTF-8} and then representing each byte + * in {@code %HH} syntax, being {@code HH} the hexadecimal representation of the byte. *
** This method is thread-safe. *
* - * @param text the String to be escaped. - * @return The escaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no escaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @param text the {@code String} to be escaped. + * @return The escaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no escaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String escapePath(final String text) { return UriEscape.escapeUriPath(text); @@ -85,31 +85,31 @@ public String escapePath(final String text) { /** ** Perform am URI path unescape operation - * on a String input using UTF-8 as encoding. + * on a {@code String} input using {@code UTF-8} as encoding. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
*- * This method will unescape every percent-encoded (%HH) sequences present in input, + * This method will unescape every percent-encoded ({@code %HH}) sequences present in input, * even for those characters that do not need to be percent-encoded in this context (unreserved characters * can be percent-encoded even if/when this is not required, though it is not generally considered a * good practice). *
*- * This method will use UTF-8 in order to determine the characters specified in the + * This method will use {@code UTF-8} in order to determine the characters specified in the * percent-encoded byte sequences. *
** This method is thread-safe. *
* - * @param text the String to be unescaped. - * @return The unescaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no unescaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @param text the {@code String} to be unescaped. + * @return The unescaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no unescaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String unescapePath(final String text) { return UriEscape.unescapeUriPath(text); @@ -118,37 +118,37 @@ public String unescapePath(final String text) { /** ** Perform am URI path escape operation - * on a String input. + * on a {@code String} input. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
** The following are the only allowed chars in an URI path (will not be escaped): *
** All other chars will be escaped by converting them to the sequence of bytes that * represents them in the specified encoding and then representing each byte - * in %HH syntax, being HH the hexadecimal representation of the byte. + * in {@code %HH} syntax, being {@code HH} the hexadecimal representation of the byte. *
** This method is thread-safe. *
* - * @param text the String to be escaped. + * @param text the {@code String} to be escaped. * @param encoding the encoding to be used for unescaping. - * @return The escaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no escaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @return The escaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no escaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String escapePath(final String text, final String encoding) { return UriEscape.escapeUriPath(text, encoding); @@ -157,32 +157,32 @@ public String escapePath(final String text, final String encoding) { /** ** Perform am URI path unescape operation - * on a String input. + * on a {@code String} input. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
*- * This method will unescape every percent-encoded (%HH) sequences present in input, + * This method will unescape every percent-encoded ({@code %HH}) sequences present in input, * even for those characters that do not need to be percent-encoded in this context (unreserved characters * can be percent-encoded even if/when this is not required, though it is not generally considered a * good practice). *
*- * This method will use the specified encoding in order to determine the characters specified in the + * This method will use the specified {@code encoding} in order to determine the characters specified in the * percent-encoded byte sequences. *
** This method is thread-safe. *
* - * @param text the String to be unescaped. + * @param text the {@code String} to be unescaped. * @param encoding the encoding to be used for unescaping. - * @return The unescaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no unescaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @return The unescaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no unescaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String unescapePath(final String text, final String encoding) { return UriEscape.unescapeUriPath(text, encoding); @@ -193,35 +193,35 @@ public String unescapePath(final String text, final String encoding) { /** ** Perform am URI path segment escape operation - * on a String input using UTF-8 as encoding. + * on a {@code String} input using {@code UTF-8} as encoding. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
** The following are the only allowed chars in an URI path segment (will not be escaped): *
** All other chars will be escaped by converting them to the sequence of bytes that - * represents them in the UTF-8 and then representing each byte - * in %HH syntax, being HH the hexadecimal representation of the byte. + * represents them in the {@code UTF-8} and then representing each byte + * in {@code %HH} syntax, being {@code HH} the hexadecimal representation of the byte. *
** This method is thread-safe. *
* - * @param text the String to be escaped. - * @return The escaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no escaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @param text the {@code String} to be escaped. + * @return The escaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no escaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String escapePathSegment(final String text) { return UriEscape.escapeUriPathSegment(text); @@ -230,31 +230,31 @@ public String escapePathSegment(final String text) { /** ** Perform am URI path segment unescape operation - * on a String input using UTF-8 as encoding. + * on a {@code String} input using {@code UTF-8} as encoding. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
*- * This method will unescape every percent-encoded (%HH) sequences present in input, + * This method will unescape every percent-encoded ({@code %HH}) sequences present in input, * even for those characters that do not need to be percent-encoded in this context (unreserved characters * can be percent-encoded even if/when this is not required, though it is not generally considered a * good practice). *
*- * This method will use UTF-8 in order to determine the characters specified in the + * This method will use {@code UTF-8} in order to determine the characters specified in the * percent-encoded byte sequences. *
** This method is thread-safe. *
* - * @param text the String to be unescaped. - * @return The unescaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no unescaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @param text the {@code String} to be unescaped. + * @return The unescaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no unescaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String unescapePathSegment(final String text) { return UriEscape.unescapeUriPathSegment(text); @@ -263,36 +263,36 @@ public String unescapePathSegment(final String text) { /** ** Perform am URI path segment escape operation - * on a String input. + * on a {@code String} input. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
** The following are the only allowed chars in an URI path segment (will not be escaped): *
** All other chars will be escaped by converting them to the sequence of bytes that * represents them in the specified encoding and then representing each byte - * in %HH syntax, being HH the hexadecimal representation of the byte. + * in {@code %HH} syntax, being {@code HH} the hexadecimal representation of the byte. *
** This method is thread-safe. *
* - * @param text the String to be escaped. + * @param text the {@code String} to be escaped. * @param encoding the encoding to be used for escaping. - * @return The escaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no escaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @return The escaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no escaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String escapePathSegment(final String text, final String encoding) { return UriEscape.escapeUriPathSegment(text, encoding); @@ -301,32 +301,32 @@ public String escapePathSegment(final String text, final String encoding) { /** ** Perform am URI path segment unescape operation - * on a String input. + * on a {@code String} input. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
*- * This method will unescape every percent-encoded (%HH) sequences present in input, + * This method will unescape every percent-encoded ({@code %HH}) sequences present in input, * even for those characters that do not need to be percent-encoded in this context (unreserved characters * can be percent-encoded even if/when this is not required, though it is not generally considered a * good practice). *
*- * This method will use specified encoding in order to determine the characters specified in the + * This method will use specified {@code encoding} in order to determine the characters specified in the * percent-encoded byte sequences. *
** This method is thread-safe. *
* - * @param text the String to be unescaped. + * @param text the {@code String} to be unescaped. * @param encoding the encoding to be used for unescaping. - * @return The unescaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no unescaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @return The unescaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no unescaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String unescapePathSegment(final String text, final String encoding) { return UriEscape.unescapeUriPathSegment(text, encoding); @@ -337,36 +337,36 @@ public String unescapePathSegment(final String text, final String encoding) { /** ** Perform am URI fragment identifier escape operation - * on a String input using UTF-8 as encoding. + * on a {@code String} input using {@code UTF-8} as encoding. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
** The following are the only allowed chars in an URI fragment identifier (will not be escaped): *
** All other chars will be escaped by converting them to the sequence of bytes that - * represents them in the UTF-8 and then representing each byte - * in %HH syntax, being HH the hexadecimal representation of the byte. + * represents them in the {@code UTF-8} and then representing each byte + * in {@code %HH} syntax, being {@code HH} the hexadecimal representation of the byte. *
** This method is thread-safe. *
* - * @param text the String to be escaped. - * @return The escaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no escaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @param text the {@code String} to be escaped. + * @return The escaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no escaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String escapeFragmentId(final String text) { return UriEscape.escapeUriFragmentId(text); @@ -375,31 +375,31 @@ public String escapeFragmentId(final String text) { /** ** Perform am URI fragment identifier unescape operation - * on a String input using UTF-8 as encoding. + * on a {@code String} input using {@code UTF-8} as encoding. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
*- * This method will unescape every percent-encoded (%HH) sequences present in input, + * This method will unescape every percent-encoded ({@code %HH}) sequences present in input, * even for those characters that do not need to be percent-encoded in this context (unreserved characters * can be percent-encoded even if/when this is not required, though it is not generally considered a * good practice). *
*- * This method will use UTF-8 in order to determine the characters specified in the + * This method will use {@code UTF-8} in order to determine the characters specified in the * percent-encoded byte sequences. *
** This method is thread-safe. *
* - * @param text the String to be unescaped. - * @return The unescaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no unescaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @param text the {@code String} to be unescaped. + * @return The unescaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no unescaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String unescapeFragmentId(final String text) { return UriEscape.unescapeUriFragmentId(text); @@ -408,37 +408,37 @@ public String unescapeFragmentId(final String text) { /** ** Perform am URI fragment identifier escape operation - * on a String input. + * on a {@code String} input. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
** The following are the only allowed chars in an URI fragment identifier (will not be escaped): *
** All other chars will be escaped by converting them to the sequence of bytes that * represents them in the specified encoding and then representing each byte - * in %HH syntax, being HH the hexadecimal representation of the byte. + * in {@code %HH} syntax, being {@code HH} the hexadecimal representation of the byte. *
** This method is thread-safe. *
* - * @param text the String to be escaped. + * @param text the {@code String} to be escaped. * @param encoding the encoding to be used for escaping. - * @return The escaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no escaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @return The escaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no escaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String escapeFragmentId(final String text, final String encoding) { return UriEscape.escapeUriFragmentId(text, encoding); @@ -447,32 +447,32 @@ public String escapeFragmentId(final String text, final String encoding) { /** ** Perform am URI fragment identifier unescape operation - * on a String input. + * on a {@code String} input. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
*- * This method will unescape every percent-encoded (%HH) sequences present in input, + * This method will unescape every percent-encoded ({@code %HH}) sequences present in input, * even for those characters that do not need to be percent-encoded in this context (unreserved characters * can be percent-encoded even if/when this is not required, though it is not generally considered a * good practice). *
*- * This method will use specified encoding in order to determine the characters specified in the + * This method will use specified {@code encoding} in order to determine the characters specified in the * percent-encoded byte sequences. *
** This method is thread-safe. *
* - * @param text the String to be unescaped. + * @param text the {@code String} to be unescaped. * @param encoding the encoding to be used for unescaping. - * @return The unescaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no unescaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @return The unescaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no unescaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String unescapeFragmentId(final String text, final String encoding) { return UriEscape.unescapeUriFragmentId(text, encoding); @@ -483,36 +483,36 @@ public String unescapeFragmentId(final String text, final String encoding) { /** ** Perform am URI query parameter (name or value) escape operation - * on a String input using UTF-8 as encoding. + * on a {@code String} input using {@code UTF-8} as encoding. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
** The following are the only allowed chars in an URI query parameter (will not be escaped): *
** All other chars will be escaped by converting them to the sequence of bytes that - * represents them in the UTF-8 and then representing each byte - * in %HH syntax, being HH the hexadecimal representation of the byte. + * represents them in the {@code UTF-8} and then representing each byte + * in {@code %HH} syntax, being {@code HH} the hexadecimal representation of the byte. *
** This method is thread-safe. *
* - * @param text the String to be escaped. - * @return The escaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no escaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @param text the {@code String} to be escaped. + * @return The escaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no escaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String escapeQueryParam(final String text) { return UriEscape.escapeUriQueryParam(text); @@ -521,31 +521,31 @@ public String escapeQueryParam(final String text) { /** ** Perform am URI query parameter (name or value) unescape operation - * on a String input using UTF-8 as encoding. + * on a {@code String} input using {@code UTF-8} as encoding. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
*- * This method will unescape every percent-encoded (%HH) sequences present in input, + * This method will unescape every percent-encoded ({@code %HH}) sequences present in input, * even for those characters that do not need to be percent-encoded in this context (unreserved characters * can be percent-encoded even if/when this is not required, though it is not generally considered a * good practice). *
*- * This method will use UTF-8 in order to determine the characters specified in the + * This method will use {@code UTF-8} in order to determine the characters specified in the * percent-encoded byte sequences. *
** This method is thread-safe. *
* - * @param text the String to be unescaped. - * @return The unescaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no unescaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @param text the {@code String} to be unescaped. + * @return The unescaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no unescaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String unescapeQueryParam(final String text) { return UriEscape.unescapeUriQueryParam(text); @@ -554,37 +554,37 @@ public String unescapeQueryParam(final String text) { /** ** Perform am URI query parameter (name or value) escape operation - * on a String input. + * on a {@code String} input. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
** The following are the only allowed chars in an URI query parameter (will not be escaped): *
** All other chars will be escaped by converting them to the sequence of bytes that * represents them in the specified encoding and then representing each byte - * in %HH syntax, being HH the hexadecimal representation of the byte. + * in {@code %HH} syntax, being {@code HH} the hexadecimal representation of the byte. *
** This method is thread-safe. *
* - * @param text the String to be escaped. + * @param text the {@code String} to be escaped. * @param encoding the encoding to be used for escaping. - * @return The escaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no escaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @return The escaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no escaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String escapeQueryParam(final String text, final String encoding) { return UriEscape.escapeUriQueryParam(text, encoding); @@ -593,32 +593,32 @@ public String escapeQueryParam(final String text, final String encoding) { /** ** Perform am URI query parameter (name or value) unescape operation - * on a String input. + * on a {@code String} input. *
*- * This method simply calls the equivalent method in the UriEscape class from the + * This method simply calls the equivalent method in the {@code UriEscape} class from the * Unbescape library. *
*- * This method will unescape every percent-encoded (%HH) sequences present in input, + * This method will unescape every percent-encoded ({@code %HH}) sequences present in input, * even for those characters that do not need to be percent-encoded in this context (unreserved characters * can be percent-encoded even if/when this is not required, though it is not generally considered a * good practice). *
*- * This method will use specified encoding in order to determine the characters specified in the + * This method will use specified {@code encoding} in order to determine the characters specified in the * percent-encoded byte sequences. *
** This method is thread-safe. *
* - * @param text the String to be unescaped. + * @param text the {@code String} to be unescaped. * @param encoding the encoding to be used for unescaping. - * @return The unescaped result String. As a memory-performance improvement, will return the exact - * same object as the text input argument if no unescaping modifications were required (and - * no additional String objects will be created during processing). Will - * return null if text is null. + * @return The unescaped result {@code String}. As a memory-performance improvement, will return the exact + * same object as the {@code text} input argument if no unescaping modifications were required (and + * no additional {@code String} objects will be created during processing). Will + * return {@code null} if {@code text} is {@code null}. */ public String unescapeQueryParam(final String text, final String encoding) { return UriEscape.unescapeUriQueryParam(text, encoding); diff --git a/src/main/java/org/thymeleaf/inline/IInliner.java b/src/main/java/org/thymeleaf/inline/IInliner.java index 9fb6dd031..c25dc9c32 100644 --- a/src/main/java/org/thymeleaf/inline/IInliner.java +++ b/src/main/java/org/thymeleaf/inline/IInliner.java @@ -31,7 +31,7 @@ ** Inliners are objects in charge of processing logic appearing on textual-oriented nodes * ({@link IText}, {@link ICDATASection} and {@link IComment}), as opposed to on elements. - * For example, inlined output expressions ([[${...}]]), javascript inlining artifacts, etc. + * For example, inlined output expressions ({@code [[${...}]]}), javascript inlining artifacts, etc. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/linkbuilder/ILinkBuilder.java b/src/main/java/org/thymeleaf/linkbuilder/ILinkBuilder.java index 025e6ba5d..359406a73 100644 --- a/src/main/java/org/thymeleaf/linkbuilder/ILinkBuilder.java +++ b/src/main/java/org/thymeleaf/linkbuilder/ILinkBuilder.java @@ -72,7 +72,7 @@ public interface ILinkBuilder { /** *- * Build a link, returning null if not possible. + * Build a link, returning {@code null} if not possible. *
* * @param context the {@link IExpressionContext} object being used for template processing. Cannot be null. diff --git a/src/main/java/org/thymeleaf/linkbuilder/StandardLinkBuilder.java b/src/main/java/org/thymeleaf/linkbuilder/StandardLinkBuilder.java index e35a73c17..3664b34e6 100644 --- a/src/main/java/org/thymeleaf/linkbuilder/StandardLinkBuilder.java +++ b/src/main/java/org/thymeleaf/linkbuilder/StandardLinkBuilder.java @@ -43,17 +43,17 @@ * This class will build link URLs using (by default) the Java Servlet API when the specified URLs are * context-relative, given the need to obtain the context path and add it to the URL. Also, when an * {@link org.thymeleaf.context.IWebContext} implementation is used as context, URLs will be passed to - * the standard HttpSerlvetResponse.encodeURL(...) method before returning. + * the standard {@code HttpSerlvetResponse.encodeURL(...)} method before returning. * ** Note however that the Servlet-API specific part of this behaviour is configurable and confined to a set of - * protected methods that can be overwritten by subclasses that want to offer a link building + * {@code protected} methods that can be overwritten by subclasses that want to offer a link building * behaviour very similar to the standard one, but without any dependencies on the Servlet API (e.g. extracting - * URL context paths from a framework artifact other than HttpServletRequest). + * URL context paths from a framework artifact other than {@code HttpServletRequest}). *
*- * This implementation will only return null at {@link #buildLink(IExpressionContext, String, Map)} - * if the specified base argument is null. + * This implementation will only return {@code null} at {@link #buildLink(IExpressionContext, String, Map)} + * if the specified {@code base} argument is {@code null}. *
* * @author Daniel Fernández @@ -90,6 +90,8 @@ public final String buildLink( final Map- * By default, this method will obtain the context path from HttpServletRequest.getContextPath(), - * throwing an exception if context is not an instance of IWebContext given context-relative + * By default, this method will obtain the context path from {@code HttpServletRequest.getContextPath()}, + * throwing an exception if {@code context} is not an instance of {@code IWebContext} given context-relative * URLs are (by default) only allowed in web contexts. *
*@@ -505,9 +528,9 @@ protected String computeContextPath( * Process an already-built URL just before returning it. *
*- * By default, this method will apply the HttpServletResponse.encodeURL(url) mechanism, as standard - * when using the Java Servlet API. Note however that this will only be applied if context is - * an implementation of IWebContext (i.e. the Servlet API will only be applied in web environments). + * By default, this method will apply the {@code HttpServletResponse.encodeURL(url)} mechanism, as standard + * when using the Java Servlet API. Note however that this will only be applied if {@code context} is + * an implementation of {@code IWebContext} (i.e. the Servlet API will only be applied in web environments). *
** This method can be overridden by any subclasses that want to change this behaviour (e.g. in order to diff --git a/src/main/java/org/thymeleaf/messageresolver/IMessageResolver.java b/src/main/java/org/thymeleaf/messageresolver/IMessageResolver.java index 341578e38..c888eb69d 100755 --- a/src/main/java/org/thymeleaf/messageresolver/IMessageResolver.java +++ b/src/main/java/org/thymeleaf/messageresolver/IMessageResolver.java @@ -34,13 +34,13 @@ *
* Note that message resolution will return null if no message is found, in which case callers will have the * possibility to choose between asking the resolver to create an absent message representation or not. - * This is precisely what the useAbsentMessageRepresentation flag does in + * This is precisely what the {@code useAbsentMessageRepresentation} flag does in * {@link ITemplateContext#getMessage(Class, String, Object[], boolean)}. *
*- * An absent message representation looks like ??mymessage_gl_ES?? and is useful to quickly determine - * when a message is lacking from the application's configuration. Note #{...} message expressions will - * always ask for an absent message representation, whereas methods in the #messages + * An absent message representation looks like {@code ??mymessage_gl_ES??} and is useful to quickly determine + * when a message is lacking from the application's configuration. Note {@code #{...}} message expressions will + * always ask for an {@code absent message representation}, whereas methods in the {@code #messages} * expression object will do it depending on the specific method being called. *
*@@ -78,12 +78,12 @@ public interface IMessageResolver { /** *
- * Resolve the message, returning the requested message (or null if not found). + * Resolve the message, returning the requested message (or {@code null} if not found). *
*- * Message resolvers should perform resolution of the key + messageParameters pair - * based on the context and origin specified. The context will provide - * information about the template and the (optional) origin about the point in template execution from + * Message resolvers should perform resolution of the {@code key} + {@code messageParameters} pair + * based on the {@code context} and {@code origin} specified. The context will provide + * information about the template and the (optional) {@code origin} about the point in template execution from * which the message is being requested (usually an {@link org.thymeleaf.processor.IProcessor} or * the {@link org.thymeleaf.standard.expression.MessageExpression} class). *
@@ -92,7 +92,7 @@ public interface IMessageResolver { * @param origin the origin of the message request, usually a processor or expression class. Can be null. * @param key the message key. * @param messageParameters the (optional) message parameters. - * @return the resolved message, or null if the message could not be resolved. + * @return the resolved message, or {@code null} if the message could not be resolved. */ public String resolveMessage( final ITemplateContext context, final Class> origin, final String key, final Object[] messageParameters); @@ -104,8 +104,8 @@ public String resolveMessage( * ** Once the entire chain of configured {@link IMessageResolver} objects is asked for a specific message - * and all of them return null, the engine will call this method on the first resolver in the chain. - * If the first resolver returns null as a representation, the following resolver will be called, and + * and all of them return {@code null}, the engine will call this method on the first resolver in the chain. + * If the first resolver returns {@code null} as a representation, the following resolver will be called, and * so on until a resolver returns a non-null result. The empty String will be used if all resolvers return null. *
* @@ -113,7 +113,7 @@ public String resolveMessage( * @param origin the origin of the message request, usually a processor or expression class. Can be null. * @param key the message key. * @param messageParameters the (optional) message parameters. - * @return the absent message representation, of null if the resolver cannot create such representation. + * @return the absent message representation, of {@code null} if the resolver cannot create such representation. */ public String createAbsentMessageRepresentation( final ITemplateContext context, final Class> origin, final String key, final Object[] messageParameters); diff --git a/src/main/java/org/thymeleaf/messageresolver/StandardMessageResolver.java b/src/main/java/org/thymeleaf/messageresolver/StandardMessageResolver.java index 079de49b4..f39e3b5c1 100755 --- a/src/main/java/org/thymeleaf/messageresolver/StandardMessageResolver.java +++ b/src/main/java/org/thymeleaf/messageresolver/StandardMessageResolver.java @@ -52,19 +52,19 @@ * at children (inserted fragment) templates. * *- * For each of these templates, several .properties files will be examined. For example, - * a message in template /WEB-INF/templates/home.html for locale - * gl_ES-gheada ("gl" = language, "ES" = country, "gheada" = variant) would be looked for - * in .properties files in the following sequence: + * For each of these templates, several {@code .properties} files will be examined. For example, + * a message in template {@code /WEB-INF/templates/home.html} for locale + * {@code gl_ES-gheada} ("gl" = language, "ES" = country, "gheada" = variant) would be looked for + * in {@code .properties} files in the following sequence: *
*- * Note the resolution mechanism used for accessing these template-based .properties files will + * Note the resolution mechanism used for accessing these template-based {@code .properties} files will * be the same used for resolving the templates themselves. So for templates resolved from the ServletContext * its messages files will be searched at the ServletContext, for templates resolved from URL the corresponding * derived URLs will be called, etc. @@ -74,19 +74,19 @@ *
** If no suitable message value is found during template-based resolution, origin-based resolution - * is performed. This allows the resolution of messages from .properties files living + * is performed. This allows the resolution of messages from {@code .properties} files living * in the classpath (and only in the classpath) in files corresponding with the names of the * classes being used as origin. *
*- * For example, a processor my.company.processor.SomeDataProcessor using its own class + * For example, a processor {@code my.company.processor.SomeDataProcessor} using its own class * as origin will be able to resolve messages from a - * my/company/processor/SomeDataProcessor_gl_ES.properties file in the classpath. + * {@code my/company/processor/SomeDataProcessor_gl_ES.properties} file in the classpath. *
** Also, if a message is not found there, resolution will be tried for each of the superclasses this - * my.company.processor.SomeDataProcessor class extends, until a suitable message is found, or - * no more superclasses (except java.lang.Object exist). + * {@code my.company.processor.SomeDataProcessor} class extends, until a suitable message is found, or + * no more superclasses (except {@code java.lang.Object} exist). *
** Step 3: Defaults-based message resolution @@ -105,13 +105,13 @@ *
* Message resolution will return null if no message is found, in which case callers will have the possibility * to choose between asking the resolver to create an absent message representation or not. - * This is precisely what the useAbsentMessageRepresentation flag does in + * This is precisely what the {@code useAbsentMessageRepresentation} flag does in * {@link ITemplateContext#getMessage(Class, String, Object[], boolean)}. *
*- * An absent message representation looks like ??mymessage_gl_ES?? and is useful to quickly determine - * when a message is lacking from the application's configuration. Note #{...} message expressions will - * always ask for an absent message representation, whereas methods in the #messages + * An absent message representation looks like {@code ??mymessage_gl_ES??} and is useful to quickly determine + * when a message is lacking from the application's configuration. Note {@code #{...}} message expressions will + * always ask for an {@code absent message representation}, whereas methods in the {@code #messages} * expression object will do it depending on the specific method being called. *
*@@ -366,7 +366,7 @@ public final String resolveMessage( * message resolution mechanisms. *
*- * The standard mechanism will look for .properties files at the same location as + * The standard mechanism will look for {@code .properties} files at the same location as * the template (using the same resource resolution mechanism), and with the same name base. *
* @@ -394,7 +394,7 @@ protected Map* The standard mechanism will look for files in the classpath (only classpath), - * at the same package and with the same name as the origin class, with .properties + * at the same package and with the same name as the origin class, with {@code .properties} * extension. *
* diff --git a/src/main/java/org/thymeleaf/model/IAttribute.java b/src/main/java/org/thymeleaf/model/IAttribute.java index a26a3e08c..045207eb5 100644 --- a/src/main/java/org/thymeleaf/model/IAttribute.java +++ b/src/main/java/org/thymeleaf/model/IAttribute.java @@ -72,7 +72,7 @@ public interface IAttribute { * Returns the operator specified for this attribute. * *- * The operator itself, if present, is always an equals sign (=), but the reason this is specified as a separate + * The operator itself, if present, is always an equals sign ({@code =}), but the reason this is specified as a separate * field is that it could be surrounded by white space, which should be respected in output when present at * the input template. *
diff --git a/src/main/java/org/thymeleaf/model/ICDATASection.java b/src/main/java/org/thymeleaf/model/ICDATASection.java index d5704f368..a1a803293 100644 --- a/src/main/java/org/thymeleaf/model/ICDATASection.java +++ b/src/main/java/org/thymeleaf/model/ICDATASection.java @@ -35,7 +35,7 @@ public interface ICDATASection extends ITemplateEvent, CharSequence { /** *- * Returns the whole CDATA Section, including the <![CDATA[...]]> prefix and suffix. + * Returns the whole CDATA Section, including the {@code } prefix and suffix. *
* * @return the CDATA Section. diff --git a/src/main/java/org/thymeleaf/model/IComment.java b/src/main/java/org/thymeleaf/model/IComment.java index e51be6825..22fe493c4 100644 --- a/src/main/java/org/thymeleaf/model/IComment.java +++ b/src/main/java/org/thymeleaf/model/IComment.java @@ -35,7 +35,7 @@ public interface IComment extends ITemplateEvent, CharSequence { /** *- * Returns the whole Comment, including the <!--...--> prefix and suffix. + * Returns the whole Comment, including the {@code } prefix and suffix. *
* * @return the Comment. diff --git a/src/main/java/org/thymeleaf/model/IDocType.java b/src/main/java/org/thymeleaf/model/IDocType.java index 26c152747..6c90e760f 100644 --- a/src/main/java/org/thymeleaf/model/IDocType.java +++ b/src/main/java/org/thymeleaf/model/IDocType.java @@ -36,7 +36,7 @@ public interface IDocType extends ITemplateEvent { /** ** Returns the keyword of the DOCTYPE clause in its original - * case (usually DOCTYPE). + * case (usually {@code DOCTYPE}). *
* * @return the DOCTYPE keyword. @@ -46,7 +46,7 @@ public interface IDocType extends ITemplateEvent { /** ** Returns the root element name in the DOCTYPE clause. Will normally be - * html in HTML or XHTML documents. + * {@code html} in HTML or XHTML documents. *
* * @return the element name @@ -55,7 +55,7 @@ public interface IDocType extends ITemplateEvent { /** *- * Returns the type of DOCTYPE, usually null, PUBLIC or SYSTEM. + * Returns the type of DOCTYPE, usually {@code null}, {@code PUBLIC} or {@code SYSTEM}. *
* * @return the type of DOCTYPE (might be null). diff --git a/src/main/java/org/thymeleaf/model/IModel.java b/src/main/java/org/thymeleaf/model/IModel.java index 049e9f547..7562d8c6c 100644 --- a/src/main/java/org/thymeleaf/model/IModel.java +++ b/src/main/java/org/thymeleaf/model/IModel.java @@ -123,7 +123,7 @@ public interface IModel { /** ** Add an entire model at the end of the sequence. This effectively appends the - * model argument's sequence to this one. + * {@code model} argument's sequence to this one. *
* * @param model the model to be appended. diff --git a/src/main/java/org/thymeleaf/model/IModelFactory.java b/src/main/java/org/thymeleaf/model/IModelFactory.java index a7d549da3..70571da6c 100644 --- a/src/main/java/org/thymeleaf/model/IModelFactory.java +++ b/src/main/java/org/thymeleaf/model/IModelFactory.java @@ -73,8 +73,8 @@ public interface IModelFactory { * Parse the template specified as String and return the result as a model. * *- * Note the template argument specified here is the template content itself, not a name to be resolved - * by a template resolver. The ownerTemplate argument is mandatory, and specifies the template that + * Note the {@code template} argument specified here is the template content itself, not a name to be resolved + * by a template resolver. The {@code ownerTemplate} argument is mandatory, and specifies the template that * is being processed and as a part of which process the String template is being parsed. *
* @@ -130,7 +130,7 @@ public interface IModelFactory { * Create a DOCTYPE clause event, specifying all its components. * * - * @param keyword the keyword value (should be DOCTYPE, but case might vary). + * @param keyword the keyword value (should be {@code DOCTYPE}, but case might vary). * @param elementName the root element name. * @param publicId the public ID (might be null). * @param systemId the system ID (might be null). @@ -184,7 +184,7 @@ public IDocType createDocType( * ** This is equivalent to calling {@link #createStandaloneElementTag(String, boolean, boolean)} with - * false as a value for synthetic and true as a value for minimized. + * {@code false} as a value for {@code synthetic} and {@code true} as a value for {@code minimized}. *
* * @param elementName the element name. @@ -198,7 +198,7 @@ public IDocType createDocType( * ** This is equivalent to calling {@link #createStandaloneElementTag(String, String, String, boolean, boolean)} with - * false as a value for synthetic and true as a value for minimized. + * {@code false} as a value for {@code synthetic} and {@code true} as a value for {@code minimized}. *
* * @param elementName the element name. @@ -216,8 +216,8 @@ public IDocType createDocType( * @param elementName the element name. * @param synthetic whether the tag is synthetic or not. Synthetic tags are used for balancing of markup and * will not appear on output. - * @param minimized whether the tag is minimized or not, i.e. whether it ends in /> or simply - * >. + * @param minimized whether the tag is minimized or not, i.e. whether it ends in {@code />} or simply + * {@code >}. * @return the standalone tag. */ public IStandaloneElementTag createStandaloneElementTag(final String elementName, final boolean synthetic, final boolean minimized); @@ -232,8 +232,8 @@ public IDocType createDocType( * @param attributeValue the value of the attribute to be added to the tag. * @param synthetic whether the tag is synthetic or not. Synthetic tags are used for balancing of markup and * will not appear on output. - * @param minimized whether the tag is minimized or not, i.e. whether it ends in /> or simply - * >. + * @param minimized whether the tag is minimized or not, i.e. whether it ends in {@code />} or simply + * {@code >}. * @return the standalone tag. */ public IStandaloneElementTag createStandaloneElementTag(final String elementName, final String attributeName, final String attributeValue, final boolean synthetic, final boolean minimized); @@ -248,8 +248,8 @@ public IDocType createDocType( * @param attributeValueQuotes the type of quotes to be used for representing the attribute values. * @param synthetic whether the tag is synthetic or not. Synthetic tags are used for balancing of markup and * will not appear on output. - * @param minimized whether the tag is minimized or not, i.e. whether it ends in /> or simply - * >. + * @param minimized whether the tag is minimized or not, i.e. whether it ends in {@code />} or simply + * {@code >}. * @return the standalone tag. */ public IStandaloneElementTag createStandaloneElementTag(final String elementName, final Map* This is equivalent to calling {@link #createOpenElementTag(String, boolean)} with - * false as a value for synthetic. + * {@code false} as a value for {@code synthetic}. *
* * @param elementName the element name. @@ -275,7 +275,7 @@ public IDocType createDocType( * ** This is equivalent to calling {@link #createOpenElementTag(String, String, String, boolean)} with - * false as a value for synthetic. + * {@code false} as a value for {@code synthetic}. *
* * @param elementName the element name. @@ -332,7 +332,7 @@ public IDocType createDocType( * ** This is equivalent to calling {@link #createCloseElementTag(String, boolean, boolean)} with - * false as a value for synthetic and also false as a value for unmatched. + * {@code false} as a value for {@code synthetic} and also {@code false} as a value for {@code unmatched}. *
* * @param elementName the element name. diff --git a/src/main/java/org/thymeleaf/model/IXMLDeclaration.java b/src/main/java/org/thymeleaf/model/IXMLDeclaration.java index 08c51e292..fd5ad04e2 100644 --- a/src/main/java/org/thymeleaf/model/IXMLDeclaration.java +++ b/src/main/java/org/thymeleaf/model/IXMLDeclaration.java @@ -36,7 +36,7 @@ public interface IXMLDeclaration extends ITemplateEvent { /** ** Returns the keyword of the XML Declaration in its original - * case (usually xml). + * case (usually {@code xml}). *
* * @return the XML Declaration keyword. @@ -54,7 +54,7 @@ public interface IXMLDeclaration extends ITemplateEvent { /** *- * Returns the value of the encoding attribute specified at the + * Returns the value of the {@code encoding} attribute specified at the * XML Declaration (if specified). *
* @@ -64,7 +64,7 @@ public interface IXMLDeclaration extends ITemplateEvent { /** *- * Returns the value of the standalone attribute specified at the + * Returns the value of the {@code standalone} attribute specified at the * XML Declaration (if specified). *
* diff --git a/src/main/java/org/thymeleaf/processor/element/IElementModelProcessor.java b/src/main/java/org/thymeleaf/processor/element/IElementModelProcessor.java index d0e1da418..895da88a1 100644 --- a/src/main/java/org/thymeleaf/processor/element/IElementModelProcessor.java +++ b/src/main/java/org/thymeleaf/processor/element/IElementModelProcessor.java @@ -60,7 +60,7 @@ * useful for traversing an entire model looking for specific nodes or relevant data the Visitor pattern. * *- * Using the structureHandler + * Using the {@code structureHandler} *
** Model processors are passed a structure handler object that allows them to instruct the engine to take diff --git a/src/main/java/org/thymeleaf/processor/element/IElementModelStructureHandler.java b/src/main/java/org/thymeleaf/processor/element/IElementModelStructureHandler.java index 5af36f20e..83128fe4a 100644 --- a/src/main/java/org/thymeleaf/processor/element/IElementModelStructureHandler.java +++ b/src/main/java/org/thymeleaf/processor/element/IElementModelStructureHandler.java @@ -71,8 +71,8 @@ public interface IElementModelStructureHandler { * Instructs the engine to set a new selection target. *
*- * The selection target is the object on which selection expressions (*{...}) are executed. - * In the Standard Dialect, this selection target is usually modified by means of the th:object + * The selection target is the object on which selection expressions {@code (*{...})} are executed. + * In the Standard Dialect, this selection target is usually modified by means of the {@code th:object} * attribute, but custom processors can do it too. Note the selection target has the same scope as a local * variable, and will therefore be accessible only inside the body of the element being processed. *
diff --git a/src/main/java/org/thymeleaf/processor/element/IElementTagProcessor.java b/src/main/java/org/thymeleaf/processor/element/IElementTagProcessor.java index d3f48b1b3..e174b7c6a 100644 --- a/src/main/java/org/thymeleaf/processor/element/IElementTagProcessor.java +++ b/src/main/java/org/thymeleaf/processor/element/IElementTagProcessor.java @@ -32,7 +32,7 @@ * (see {@link IElementProcessor}. * *- * Using the structureHandler + * Using the {@code structureHandler} *
** For any actions involving modifications to the tag being processed or the markup structure, processors will diff --git a/src/main/java/org/thymeleaf/processor/element/IElementTagStructureHandler.java b/src/main/java/org/thymeleaf/processor/element/IElementTagStructureHandler.java index 746a936ca..03fcdf322 100644 --- a/src/main/java/org/thymeleaf/processor/element/IElementTagStructureHandler.java +++ b/src/main/java/org/thymeleaf/processor/element/IElementTagStructureHandler.java @@ -151,8 +151,8 @@ public interface IElementTagStructureHandler { * Instructs the engine to set a new selection target. *
*- * The selection target is the object on which selection expressions (*{...}) are executed. - * In the Standard Dialect, this selection target is usually modified by means of the th:object + * The selection target is the object on which selection expressions {@code (*{...})} are executed. + * In the Standard Dialect, this selection target is usually modified by means of the {@code th:object} * attribute, but custom processors can do it too. Note the selection target has the same scope as a local * variable, and will therefore be accessible only inside the body of the element being processed. *
@@ -200,11 +200,11 @@ public interface IElementTagStructureHandler { /** *- * Instructs the engine to set a new body for the current element, in the form of a CharSequence. + * Instructs the engine to set a new body for the current element, in the form of a {@code CharSequence}. *
** This is the way a processor can change what is shown inside an element during processing. For example, - * it is this way how th:text changes the contents of its containing element. + * it is this way how {@code th:text} changes the contents of its containing element. *
* * @param text the text to be used as the new body. @@ -220,7 +220,7 @@ public interface IElementTagStructureHandler { * ** This is the way a processor can change what is shown inside an element during processing. For example, - * it is this way how th:utext changes the contents of its containing element. + * it is this way how {@code th:utext} changes the contents of its containing element. *
* * @param model the model to be used as the new body. @@ -262,7 +262,7 @@ public interface IElementTagStructureHandler { /** *- * Instructs the engine to replace the current element with the specified text (a CharSequence). + * Instructs the engine to replace the current element with the specified text (a {@code CharSequence}). *
** Note it is the complete element that will be replaced with the specified text, i.e. the @@ -325,7 +325,7 @@ public interface IElementTagStructureHandler { *
** This method specifies the name of both the iteration variable name and the iterStatus variable - * name, and also the object that should be iterated (usually a Collection, Iterable or + * name, and also the object that should be iterated (usually a {@code Collection}, {@code Iterable} or * similar). *
* diff --git a/src/main/java/org/thymeleaf/processor/templateboundaries/ITemplateBoundariesStructureHandler.java b/src/main/java/org/thymeleaf/processor/templateboundaries/ITemplateBoundariesStructureHandler.java index 306782ed8..4a52f533a 100644 --- a/src/main/java/org/thymeleaf/processor/templateboundaries/ITemplateBoundariesStructureHandler.java +++ b/src/main/java/org/thymeleaf/processor/templateboundaries/ITemplateBoundariesStructureHandler.java @@ -70,8 +70,8 @@ public interface ITemplateBoundariesStructureHandler { * Instructs the engine to set a new selection target. * *- * The selection target is the object on which selection expressions (*{...}) are executed. - * In the Standard Dialect, this selection target is usually modified by means of the th:object + * The selection target is the object on which selection expressions {@code (*{...})} are executed. + * In the Standard Dialect, this selection target is usually modified by means of the {@code th:object} * attribute, but custom processors can do it too. Note the selection target has the same scope as a local * variable, and will therefore be accessible only inside the body of the element being processed. *
diff --git a/src/main/java/org/thymeleaf/standard/StandardDialect.java b/src/main/java/org/thymeleaf/standard/StandardDialect.java index 6eb50df6a..9f7de4738 100644 --- a/src/main/java/org/thymeleaf/standard/StandardDialect.java +++ b/src/main/java/org/thymeleaf/standard/StandardDialect.java @@ -96,11 +96,11 @@ /** ** Standard Dialect. This is the class containing the implementation of Thymeleaf Standard Dialect, including all - * th:* processors, expression objects, etc. + * {@code th:*} processors, expression objects, etc. *
** Note this dialect uses OGNL as an expression language. There is a Spring-integrated version - * of the Standard Dialect called the SpringStandard Dialect at the thymeleaf-spring* packages, + * of the Standard Dialect called the SpringStandard Dialect at the {@code thymeleaf-spring*} packages, * which uses SpringEL as an expression language. *
*@@ -125,18 +125,18 @@ public class StandardDialect // We will avoid setting this variableExpressionEvaluator variable to "OgnlVariableExpressionEvaluator.INSTANCE" // in order to not cause this OGNL-related class to initialize, therefore introducing a forced dependency on OGNL // to Spring users (who don't need OGNL at all). - private IStandardVariableExpressionEvaluator variableExpressionEvaluator = null; + protected IStandardVariableExpressionEvaluator variableExpressionEvaluator = null; // These variables will be initialized lazily if needed (because no value is set to them via their setters) // This should improve startup times (esp. Jackson for the JS serializer) and avoid losing time initializing // objects that might not be used after all if they are overridden via setter. - private IStandardExpressionParser expressionParser = null; - private IStandardConversionService conversionService = null; - private IStandardJavaScriptSerializer javaScriptSerializer = null; - private IStandardCSSSerializer cssSerializer = null; + protected IStandardExpressionParser expressionParser = null; + protected IStandardConversionService conversionService = null; + protected IStandardJavaScriptSerializer javaScriptSerializer = null; + protected IStandardCSSSerializer cssSerializer = null; // Note this is not settable - just lazily initialized - private IExpressionObjectFactory expressionObjectFactory = null; + protected IExpressionObjectFactory expressionObjectFactory = null; diff --git a/src/main/java/org/thymeleaf/standard/expression/Fragment.java b/src/main/java/org/thymeleaf/standard/expression/Fragment.java index 98f110b48..946d57299 100644 --- a/src/main/java/org/thymeleaf/standard/expression/Fragment.java +++ b/src/main/java/org/thymeleaf/standard/expression/Fragment.java @@ -33,7 +33,7 @@ /** *
* Class that models the result of a {@link FragmentExpression}, i.e. the result of a fragment expression in - * the form of ~{template :: fragment? (parameters)?} + * the form of {@code ~{template :: fragment? (parameters)?}} *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/standard/expression/FragmentExpression.java b/src/main/java/org/thymeleaf/standard/expression/FragmentExpression.java index 6a43f4698..edfe541bb 100644 --- a/src/main/java/org/thymeleaf/standard/expression/FragmentExpression.java +++ b/src/main/java/org/thymeleaf/standard/expression/FragmentExpression.java @@ -55,7 +55,7 @@ public final class FragmentExpression extends SimpleExpression { private static final long serialVersionUID = -130371297698708001L; /** - * This constant contains the {@link FragmentExpression} object representing the EMPTY FRAGMENT (~{}) + * This constant contains the {@link FragmentExpression} object representing the EMPTY FRAGMENT ({@code ~{}}) */ public static final FragmentExpression EMPTY_FRAGMENT_EXPRESSION = new FragmentExpression(); diff --git a/src/main/java/org/thymeleaf/standard/expression/FragmentSignature.java b/src/main/java/org/thymeleaf/standard/expression/FragmentSignature.java index 953b9c009..354aa0e15 100755 --- a/src/main/java/org/thymeleaf/standard/expression/FragmentSignature.java +++ b/src/main/java/org/thymeleaf/standard/expression/FragmentSignature.java @@ -30,7 +30,7 @@ /** ** Represents a fragment signature, including both a name and an (optional) sequence of parameter names to be - * applied. Typically the result of parsing a th:fragment attribute. + * applied. Typically the result of parsing a {@code th:fragment} attribute. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/standard/expression/FragmentSignatureUtils.java b/src/main/java/org/thymeleaf/standard/expression/FragmentSignatureUtils.java index 69fe3925a..fe6322a43 100755 --- a/src/main/java/org/thymeleaf/standard/expression/FragmentSignatureUtils.java +++ b/src/main/java/org/thymeleaf/standard/expression/FragmentSignatureUtils.java @@ -138,7 +138,7 @@ static FragmentSignature internalParseFragmentSignature(final String input) { * ** This processing matches the specified parameters against the ones in the signature, allowing the specified - * ones (usually coming from a fragment selection like th:include) to be nameless, so that their values + * ones (usually coming from a fragment selection like {@code th:include}) to be nameless, so that their values * are matched to their corresponding variable name during this parameter processing operation. *
*diff --git a/src/main/java/org/thymeleaf/standard/expression/IStandardConversionService.java b/src/main/java/org/thymeleaf/standard/expression/IStandardConversionService.java index 89cb5224a..a6a6401fd 100755 --- a/src/main/java/org/thymeleaf/standard/expression/IStandardConversionService.java +++ b/src/main/java/org/thymeleaf/standard/expression/IStandardConversionService.java @@ -26,14 +26,14 @@ * Common interface for all implementations of a conversion service, to be used during template execution. *
*- * Thymeleaf conversion services work in a way similar to Spring Framework's ConversionService interface, + * Thymeleaf conversion services work in a way similar to Spring Framework's {@code ConversionService} interface, * but this is a generic mechanism (not dependent on Spring). *
** Default implementation —registered by {@link org.thymeleaf.standard.StandardDialect}— * is {@link StandardConversionService}, which performs some standard conversions, but the * Spring Standard Dialect used by the Thymeleaf + Spring integration module automatically registers an implementation - * of this interface that delegates on any existing Spring ConversionService objects (thus using + * of this interface that delegates on any existing Spring {@code ConversionService} objects (thus using * the Converters and Formatters registered at the Spring Application Context). *
*diff --git a/src/main/java/org/thymeleaf/standard/expression/IStandardVariableExpressionEvaluator.java b/src/main/java/org/thymeleaf/standard/expression/IStandardVariableExpressionEvaluator.java index c2e8e2870..40b53005e 100755 --- a/src/main/java/org/thymeleaf/standard/expression/IStandardVariableExpressionEvaluator.java +++ b/src/main/java/org/thymeleaf/standard/expression/IStandardVariableExpressionEvaluator.java @@ -23,7 +23,7 @@ /** *
- * Common interface for all objects in charge of executing variable expressions (${...}) inside + * Common interface for all objects in charge of executing variable expressions ({@code ${...}}) inside * Thymeleaf Standard Expressions. *
*diff --git a/src/main/java/org/thymeleaf/standard/expression/LinkExpression.java b/src/main/java/org/thymeleaf/standard/expression/LinkExpression.java index fb2ade1f7..be2d64677 100755 --- a/src/main/java/org/thymeleaf/standard/expression/LinkExpression.java +++ b/src/main/java/org/thymeleaf/standard/expression/LinkExpression.java @@ -269,6 +269,8 @@ static Object executeLinkExpression(final IExpressionContext context, final Link } if (base == null || StringUtils.isEmptyOrWhitespace((String) base)) { base = ""; + } else { + base = ((String) base).trim(); } /* diff --git a/src/main/java/org/thymeleaf/standard/expression/LiteralSubstitutionUtil.java b/src/main/java/org/thymeleaf/standard/expression/LiteralSubstitutionUtil.java index 6fabeb652..dea52baf0 100755 --- a/src/main/java/org/thymeleaf/standard/expression/LiteralSubstitutionUtil.java +++ b/src/main/java/org/thymeleaf/standard/expression/LiteralSubstitutionUtil.java @@ -69,6 +69,7 @@ static String performLiteralSubstitution(final String input) { boolean inLiteralSubstitution = false; boolean inLiteralSubstitutionInsertion = false; + int literalSubstitutionIndex = -1; int expLevel = 0; boolean inLiteral = false; @@ -86,15 +87,24 @@ static String performLiteralSubstitution(final String input) { strBuilder.append(input,0,i); } inLiteralSubstitution = true; + literalSubstitutionIndex = i; } else if (c == LITERAL_SUBSTITUTION_DELIMITER && inLiteralSubstitution && inNothing) { - if (inLiteralSubstitutionInsertion) { + if ((i - literalSubstitutionIndex) == 1) { + // This was an empty literal substitution, which we are not going to process so that it + // cannot be used to mangle in the parsing, interpretation and validity checks of other + // expressions. + strBuilder + .append(LITERAL_SUBSTITUTION_DELIMITER) + .append(LITERAL_SUBSTITUTION_DELIMITER); + } else if (inLiteralSubstitutionInsertion) { strBuilder.append('\''); inLiteralSubstitutionInsertion = false; } inLiteralSubstitution = false; + literalSubstitutionIndex = -1; } else if (inNothing && (c == VariableExpression.SELECTOR || diff --git a/src/main/java/org/thymeleaf/standard/expression/OGNLVariableExpressionEvaluator.java b/src/main/java/org/thymeleaf/standard/expression/OGNLVariableExpressionEvaluator.java index ae71970d9..a8bab7c29 100644 --- a/src/main/java/org/thymeleaf/standard/expression/OGNLVariableExpressionEvaluator.java +++ b/src/main/java/org/thymeleaf/standard/expression/OGNLVariableExpressionEvaluator.java @@ -19,9 +19,16 @@ */ package org.thymeleaf.standard.expression; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.Collections; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import ognl.ClassResolver; +import ognl.DefaultMemberAccess; +import ognl.MemberAccess; import ognl.OgnlContext; import ognl.OgnlException; import ognl.OgnlRuntime; @@ -35,10 +42,11 @@ import org.thymeleaf.exceptions.TemplateProcessingException; import org.thymeleaf.expression.IExpressionObjects; import org.thymeleaf.standard.util.StandardExpressionUtils; +import org.thymeleaf.util.ExpressionUtils; /** *
- * Evaluator for variable expressions (${...}) in Thymeleaf Standard Expressions, using the + * Evaluator for variable expressions ({@code ${...}}) in Thymeleaf Standard Expressions, using the * OGNL expression language. *
*
@@ -65,6 +73,8 @@ public final class OGNLVariableExpressionEvaluator
OGNLContextPropertyAccessor.RESTRICT_REQUEST_PARAMETERS,
OGNLContextPropertyAccessor.RESTRICT_REQUEST_PARAMETERS);
+ private static MemberAccess MEMBER_ACCESS = new ThymeleafACLMemberAccess();
+ private static ThymeleafACLClassResolver CLASS_RESOLVER = new ThymeleafACLClassResolver();
private final boolean applyOGNLShortcuts;
@@ -120,7 +130,7 @@ private static Object evaluate(
}
final ComputedOGNLExpression parsedExpression =
- obtainComputedOGNLExpression(configuration, expression, exp, applyOGNLShortcuts);
+ obtainComputedOGNLExpression(configuration, expression, exp, expContext, applyOGNLShortcuts);
final Map
- * Expression preprocessor, in charge of executing __...__ fragments in Thymeleaf Standard Expressions.
+ * Expression preprocessor, in charge of executing {@code __...__} fragments in Thymeleaf Standard Expressions.
*
* Note a class with this name existed since 2.1.0, but it was completely reimplemented
diff --git a/src/main/java/org/thymeleaf/standard/expression/VariableExpression.java b/src/main/java/org/thymeleaf/standard/expression/VariableExpression.java
index 5fc620ce2..64650631c 100755
--- a/src/main/java/org/thymeleaf/standard/expression/VariableExpression.java
+++ b/src/main/java/org/thymeleaf/standard/expression/VariableExpression.java
@@ -26,6 +26,7 @@
import org.slf4j.LoggerFactory;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.IExpressionContext;
+import org.thymeleaf.exceptions.TemplateProcessingException;
import org.thymeleaf.util.Validate;
@@ -162,7 +163,27 @@ static Object executeVariableExpression(
final StandardExpressionExecutionContext evalExpContext =
(expression.getConvertToString()? expContext.withTypeConversion() : expContext.withoutTypeConversion());
- return expressionEvaluator.evaluate(context, expression, evalExpContext);
+ final Object result = expressionEvaluator.evaluate(context, expression, evalExpContext);
+
+ if (!expContext.getForbidUnsafeExpressionResults()) {
+ return result;
+ }
+
+ // We are only allowing results of type Number and Boolean, and cosidering the rest of data types "unsafe",
+ // as they could be rendered into a non-trustable String. This is mainly useful for helping prevent code
+ // injection in th:on* event handlers.
+ if (result == null
+ || result instanceof Number
+ || result instanceof Boolean) {
+ return result;
+ }
+
+ throw new TemplateProcessingException(
+ "Only variable expressions returning numbers or booleans are allowed in this context, any other data" +
+ "types are not trusted in the context of this expression, including Strings or any other " +
+ "object that could be rendered as a text literal. A typical case is HTML attributes for event handlers (e.g. " +
+ "\"onload\"), in which textual data from variables should better be output to \"data-*\" attributes and then " +
+ "read from the event handler.");
}
diff --git a/src/main/java/org/thymeleaf/standard/processor/AbstractStandardAttributeModifierTagProcessor.java b/src/main/java/org/thymeleaf/standard/processor/AbstractStandardAttributeModifierTagProcessor.java
index 1831ca33c..896cfe6da 100644
--- a/src/main/java/org/thymeleaf/standard/processor/AbstractStandardAttributeModifierTagProcessor.java
+++ b/src/main/java/org/thymeleaf/standard/processor/AbstractStandardAttributeModifierTagProcessor.java
@@ -26,6 +26,7 @@
import org.thymeleaf.engine.IAttributeDefinitionsAware;
import org.thymeleaf.model.IProcessableElementTag;
import org.thymeleaf.processor.element.IElementTagStructureHandler;
+import org.thymeleaf.standard.expression.StandardExpressionExecutionContext;
import org.thymeleaf.standard.util.StandardProcessorUtils;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.util.EscapedAttributeUtils;
@@ -93,6 +94,29 @@ protected AbstractStandardAttributeModifierTagProcessor(
}
+ /**
+ *
+ * Build a new instance of this tag processor.
+ *
* Build a new instance of this tag processor.
@@ -153,6 +177,37 @@ protected AbstractStandardAttributeModifierTagProcessor(
}
+ /**
+ *
+ * Build a new instance of this tag processor.
+ *
+ * Build a new instance of this tag processor.
+ *
* CSS serializer objects are in charge of outputting values both in templates using
* {@link org.thymeleaf.templatemode.TemplateMode#CSS} and in inlined code by means of e.g.
- * th:inline="css" blocks.
+ * {@code th:inline="css"} blocks.
*
* JavaScript serializer objects are in charge of outputting values both in templates using
* {@link org.thymeleaf.templatemode.TemplateMode#JAVASCRIPT} and in inlined code by means of e.g.
- * th:inline="javascript" blocks.
+ * {@code th:inline="javascript"} blocks.
*
* Note that, even if Jackson is present in the classpath, its usage can be prevented by means of the - * useJacksonIfAvailable constructor flag. + * {@code useJacksonIfAvailable} constructor flag. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/standard/util/StandardConditionalCommentUtils.java b/src/main/java/org/thymeleaf/standard/util/StandardConditionalCommentUtils.java index 372172101..271d2fd61 100755 --- a/src/main/java/org/thymeleaf/standard/util/StandardConditionalCommentUtils.java +++ b/src/main/java/org/thymeleaf/standard/util/StandardConditionalCommentUtils.java @@ -48,7 +48,7 @@ public final class StandardConditionalCommentUtils { * ** Result is an object of class {@link ConditionalCommentParsingResult}, or - * null if text does not have the expected format for a conditional comment. + * {@code null} if text does not have the expected format for a conditional comment. *
* * @param text the text to be parsed diff --git a/src/main/java/org/thymeleaf/standard/util/StandardExpressionUtils.java b/src/main/java/org/thymeleaf/standard/util/StandardExpressionUtils.java index 8460cdc08..7fcc2b20f 100644 --- a/src/main/java/org/thymeleaf/standard/util/StandardExpressionUtils.java +++ b/src/main/java/org/thymeleaf/standard/util/StandardExpressionUtils.java @@ -32,6 +32,11 @@ public final class StandardExpressionUtils { private static final char[] EXEC_INFO_ARRAY = "ofnIcexe".toCharArray(); // Inverted "execInfo" private static final int EXEC_INFO_LEN = EXEC_INFO_ARRAY.length; + private static final char[] NEW_ARRAY = "wen".toCharArray(); // Inverted "new" + private static final int NEW_LEN = NEW_ARRAY.length; + private static final char[] PARAM_ARRAY = "marap".toCharArray(); // Inverted "param" + private static final int PARAM_LEN = PARAM_ARRAY.length; + public static boolean mightNeedExpressionObjects(final String expression) { /* @@ -60,7 +65,7 @@ public static boolean mightNeedExpressionObjects(final String expression) { } } else { if (ei > 0) { - // We 'restart' the matching counter just in case we had a partial match + // We 'restart' the counter (just after the first matched char) in case we had a partial match n += ei; } ei = 0; @@ -70,6 +75,94 @@ public static boolean mightNeedExpressionObjects(final String expression) { } + /** + * + * @since 3.0.12 + */ + public static boolean containsOGNLInstantiationOrStaticOrParam(final String expression) { + + /* + * Checks whether the expression contains instantiation of objects ("new SomeClass") or makes use of + * static methods ("@SomeClass@") as both are forbidden in certain contexts in restricted mode. + */ + + final int explen = expression.length(); + int n = explen; + int ni = 0; // index for computing position in the NEW_ARRAY + int pi = 0; // index for computing position in the PARAM_ARRAY + int si = -1; + char c; + while (n-- != 0) { + + c = expression.charAt(n); + + // When checking for the "new" keyword, we need to identify that it is not a part of a larger + // identifier, i.e. there is whitespace after it and no character that might be a part of an + // identifier before it. + if (ni < NEW_LEN + && c == NEW_ARRAY[ni] + && (ni > 0 || ((n + 1 < explen) && Character.isWhitespace(expression.charAt(n + 1))))) { + ni++; + if (ni == NEW_LEN && (n == 0 || !isSafeIdentifierChar(expression.charAt(n - 1)))) { + return true; // we found an object instantiation + } + continue; + } + + if (ni > 0) { + // We 'restart' the matching counter just in case we had a partial match + n += ni; + ni = 0; + if (si < n) { + // This has to be restarted too + si = -1; + } + continue; + } + + ni = 0; + + // When checking for the "param" keyword, we need to identify that it is not a part of a larger + // identifier. + if (pi < PARAM_LEN + && c == PARAM_ARRAY[pi] + && (pi > 0 || ((n + 1 < explen) && !isSafeIdentifierChar(expression.charAt(n + 1))))) { + pi++; + if (pi == PARAM_LEN && (n == 0 || !isSafeIdentifierChar(expression.charAt(n - 1)))) { + return true; // we found a param access + } + continue; + } + + if (pi > 0) { + // We 'restart' the matching counter just in case we had a partial match + n += pi; + pi = 0; + continue; + } + + pi = 0; + + if (c == '@') { + if (si > n) { + return true; + } + si = n; + } else if (si > n && !(Character.isJavaIdentifierPart(c) || Character.isWhitespace(c) || c == '.')) { + si = -1; + } + + } + + return false; + + } + + + private static boolean isSafeIdentifierChar(final char c) { + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_'; + } + diff --git a/src/main/java/org/thymeleaf/templateparser/markup/decoupled/IDecoupledTemplateLogicResolver.java b/src/main/java/org/thymeleaf/templateparser/markup/decoupled/IDecoupledTemplateLogicResolver.java index 883cfe95f..6ccf78541 100644 --- a/src/main/java/org/thymeleaf/templateparser/markup/decoupled/IDecoupledTemplateLogicResolver.java +++ b/src/main/java/org/thymeleaf/templateparser/markup/decoupled/IDecoupledTemplateLogicResolver.java @@ -67,7 +67,7 @@ public interface IDecoupledTemplateLogicResolver { * @param templateSelectors the selectors to be used, defining the fragments that should be processed. * @param resource the resource of the resolved template. * @param templateMode the template mode to be applied to the resolved template. - * @return the resource containing the decoupled template logic, or null if there isn't any. + * @return the resource containing the decoupled template logic, or {@code null} if there isn't any. */ public ITemplateResource resolveDecoupledTemplateLogic( final IEngineConfiguration configuration, diff --git a/src/main/java/org/thymeleaf/templateparser/markup/decoupled/StandardDecoupledTemplateLogicResolver.java b/src/main/java/org/thymeleaf/templateparser/markup/decoupled/StandardDecoupledTemplateLogicResolver.java index 2a082223c..df5aa58ac 100644 --- a/src/main/java/org/thymeleaf/templateparser/markup/decoupled/StandardDecoupledTemplateLogicResolver.java +++ b/src/main/java/org/thymeleaf/templateparser/markup/decoupled/StandardDecoupledTemplateLogicResolver.java @@ -35,16 +35,16 @@ * ** By default, the relative location resolved will be formed as - * resource.getBaseName() + DECOUPLED_TEMPLATE_LOGIC_FILE_SUFFIX (see + * {@code resource.getBaseName() + DECOUPLED_TEMPLATE_LOGIC_FILE_SUFFIX} (see * {@link ITemplateResource#getBaseName()} and {@link #DECOUPLED_TEMPLATE_LOGIC_FILE_SUFFIX}. - * So for a template resource /WEB-INF/templates/main.html, the main.th.xml relative + * So for a template resource {@code /WEB-INF/templates/main.html}, the {@code main.th.xml} relative * location will be used to call {@link ITemplateResource#relative(String)}. *
*- * However this can be modified by specifying different prefix and suffix values so that, if a - * prefix with value "../logic/" is specified, for a template resource - * /WEB-INF/templates/main.html, the ../viewlogic/main.th.xml relative path will be resolved, normally - * resulting in the /WEB-INF/viewlogic/main.th.xml resource. + * However this can be modified by specifying different {@code prefix} and {@code suffix} values so that, if a + * {@code prefix} with value {@code "../logic/"} is specified, for a template resource + * {@code /WEB-INF/templates/main.html}, the {@code ../viewlogic/main.th.xml} relative path will be resolved, normally + * resulting in the {@code /WEB-INF/viewlogic/main.th.xml} resource. *
** This class is thread-safe. diff --git a/src/main/java/org/thymeleaf/templateresolver/AbstractConfigurableTemplateResolver.java b/src/main/java/org/thymeleaf/templateresolver/AbstractConfigurableTemplateResolver.java index 4dfb92910..e9153ab69 100755 --- a/src/main/java/org/thymeleaf/templateresolver/AbstractConfigurableTemplateResolver.java +++ b/src/main/java/org/thymeleaf/templateresolver/AbstractConfigurableTemplateResolver.java @@ -150,9 +150,9 @@ public final void setPrefix(final String prefix) { *
** Note that this suffix may not be applied to the template name if the template name - * already ends in a known file name suffix: .html, .htm, .xhtml, - * .xml, .js, .json, - * .css, .rss, .atom, .txt. If this behaviour needs to be overridden so + * already ends in a known file name suffix: {@code .html}, {@code .htm}, {@code .xhtml}, + * {@code .xml}, {@code .js}, {@code .json}, + * {@code .css}, {@code .rss}, {@code .atom}, {@code .txt}. If this behaviour needs to be overridden so * that suffix is always applied, the {@link #setForceSuffix(boolean)} will need to be set. *
* @@ -170,9 +170,9 @@ public final String getSuffix() { * ** Note that this suffix may not be applied to the template name if the template name - * already ends in a known file name suffix: .html, .htm, .xhtml, - * .xml, .js, .json, - * .css, .rss, .atom, .txt. If this behaviour needs to be overridden so + * already ends in a known file name suffix: {@code .html}, {@code .htm}, {@code .xhtml}, + * {@code .xml}, {@code .js}, {@code .json}, + * {@code .css}, {@code .rss}, {@code .atom}, {@code .txt}. If this behaviour needs to be overridden so * that suffix is always applied, the {@link #setForceSuffix(boolean)} will need to be set. *
* @@ -190,11 +190,11 @@ public final void setSuffix(final String suffix) { * ** When forced, suffix will be appended to the template name even if the template - * name ends in a known suffix: .html, .htm, .xhtml, - * .xml, .js, .json, - * .css, .rss, .atom, .txt. + * name ends in a known suffix: {@code .html}, {@code .htm}, {@code .xhtml}, + * {@code .xml}, {@code .js}, {@code .json}, + * {@code .css}, {@code .rss}, {@code .atom}, {@code .txt}. *
- *Default value is false
. + *Default value is {@code false}
. * * @return whether the suffix will be forced or not. * @since 3.0.6 @@ -211,11 +211,11 @@ public final boolean getForceSuffix() { * ** When forced, suffix will be appended to the template name even if the template - * name ends in a known suffix: .html, .htm, .xhtml, - * .xml, .js, .json, - * .css, .rss, .atom, .txt. + * name ends in a known suffix: {@code .html}, {@code .htm}, {@code .xhtml}, + * {@code .xml}, {@code .js}, {@code .json}, + * {@code .css}, {@code .rss}, {@code .atom}, {@code .txt}. *
- *Default value is false
. + *Default value is {@code false}
. * * @param forceSuffix whether the suffix should be forced or not. * @since 3.0.6 @@ -262,9 +262,9 @@ public final void setCharacterEncoding(final String characterEncoding) { * ** Note that this template mode also may not be applied if the template resource name - * ends in a known file name suffix: .html, .htm, .xhtml, - * .xml, .js, .json, - * .css, .rss, .atom, .txt. If this behaviour needs to be overridden so + * ends in a known file name suffix: {@code .html}, {@code .htm}, {@code .xhtml}, + * {@code .xml}, {@code .js}, {@code .json}, + * {@code .css}, {@code .rss}, {@code .atom}, {@code .txt}. If this behaviour needs to be overridden so * that template name is always applied, the {@link #setForceTemplateMode(boolean)} will need to be set. *
* @@ -286,9 +286,9 @@ public final TemplateMode getTemplateMode() { * ** Note that this template mode also may not be applied if the template resource name - * ends in a known file name suffix: .html, .htm, .xhtml, - * .xml, .js, .json, - * .css, .rss, .atom, .txt. If this behaviour needs to be overridden so + * ends in a known file name suffix: {@code .html}, {@code .htm}, {@code .xhtml}, + * {@code .xml}, {@code .js}, {@code .json}, + * {@code .css}, {@code .rss}, {@code .atom}, {@code .txt}. If this behaviour needs to be overridden so * that template name is always applied, the {@link #setForceTemplateMode(boolean)} will need to be set. *
* @@ -315,9 +315,9 @@ public final void setTemplateMode(final TemplateMode templateMode) { * ** Note that this template mode also may not be applied if the template resource name - * ends in a known file name suffix: .html, .htm, .xhtml, - * .xml, .js, .json, - * .css, .rss, .atom, .txt. If this behaviour needs to be overridden so + * ends in a known file name suffix: {@code .html}, {@code .htm}, {@code .xhtml}, + * {@code .xml}, {@code .js}, {@code .json}, + * {@code .css}, {@code .rss}, {@code .atom}, {@code .txt}. If this behaviour needs to be overridden so * that template name is always applied, the {@link #setForceTemplateMode(boolean)} will need to be set. *
* @@ -340,11 +340,11 @@ public final void setTemplateMode(final String templateMode) { ** When forced, the configured template mode ({@link #setTemplateMode(TemplateMode)} will * be applied even if the template resource name ends in a known suffix: - * .html, .htm, .xhtml, - * .xml, .js, .json, - * .css, .rss, .atom, .txt. + * {@code .html}, {@code .htm}, {@code .xhtml}, + * {@code .xml}, {@code .js}, {@code .json}, + * {@code .css}, {@code .rss}, {@code .atom}, {@code .txt}. *
- *Default value is false
. + *Default value is {@code false}
. * * @return whether the suffix will be forced or not. * @since 3.0.6 @@ -362,11 +362,11 @@ public final boolean getForceTemplateMode() { ** When forced, the configured template mode ({@link #setTemplateMode(TemplateMode)} will * be applied even if the template resource name ends in a known suffix: - * .html, .htm, .xhtml, - * .xml, .js, .json, - * .css, .rss, .atom, .txt. + * {@code .html}, {@code .htm}, {@code .xhtml}, + * {@code .xml}, {@code .js}, {@code .json}, + * {@code .css}, {@code .rss}, {@code .atom}, {@code .txt}. *
- *Default value is false
. + *Default value is {@code false}
. * * @param forceTemplateMode whether the configured template mode should be forced or not. * @since 3.0.6 diff --git a/src/main/java/org/thymeleaf/templateresolver/AbstractTemplateResolver.java b/src/main/java/org/thymeleaf/templateresolver/AbstractTemplateResolver.java index 47d855d63..11885ff86 100755 --- a/src/main/java/org/thymeleaf/templateresolver/AbstractTemplateResolver.java +++ b/src/main/java/org/thymeleaf/templateresolver/AbstractTemplateResolver.java @@ -200,11 +200,11 @@ public void setResolvablePatterns(final Set- * Default value is FALSE. + * Default value is {@code FALSE}. *
** Checking resources for existence will make the template resolver execute {@link ITemplateResource#exists()} - * for each resolved resource before returning a {@link TemplateResolution}, returning null if the + * for each resolved resource before returning a {@link TemplateResolution}, returning {@code null} if the * resource does not exist. *
*
@@ -217,10 +217,10 @@ public void setResolvablePatterns(final Set
* If this existence check is enabled and a resource is determined to not exist, - * {@link ITemplateResolver#resolveTemplate(IEngineConfiguration, String, String, Map)} will return null. + * {@link ITemplateResolver#resolveTemplate(IEngineConfiguration, String, String, Map)} will return {@code null}. *
* - * @return true if resource existence will be checked, false if not + * @return {@code true} if resource existence will be checked, {@code false} if not * * @since 3.0.0 * @@ -235,11 +235,11 @@ public final boolean getCheckExistence() { * Sets whether template resources will be checked for existence before being returned or not. * *- * Default value is FALSE. + * Default value is {@code FALSE}. *
** Checking resources for existence will make the template resolver execute {@link ITemplateResource#exists()} - * for each resolved resource before returning a {@link TemplateResolution}, returning null if the + * for each resolved resource before returning a {@link TemplateResolution}, returning {@code null} if the * resource does not exist. *
*@@ -252,10 +252,10 @@ public final boolean getCheckExistence() { *
** If this existence check is enabled and a resource is determined to not exist, - * {@link ITemplateResolver#resolveTemplate(IEngineConfiguration, String, String, Map)} will return null. + * {@link ITemplateResolver#resolveTemplate(IEngineConfiguration, String, String, Map)} will return {@code null}. *
* - * @param checkExistence true if resource existence should be checked, false if not + * @param checkExistence {@code true} if resource existence should be checked, {@code false} if not * * @since 3.0.0 * @@ -278,8 +278,8 @@ public void setCheckExistence(final boolean checkExistence) { * interface. * *- * Note this flag can only be true for the {@link TemplateMode#HTML} and {@link TemplateMode#XML} - * template modes. Also, note that setting this flag to true does not mean that a resource with + * Note this flag can only be {@code true} for the {@link TemplateMode#HTML} and {@link TemplateMode#XML} + * template modes. Also, note that setting this flag to {@code true} does not mean that a resource with * decoupled logic must exist for the resolved template, only that it can exist. *
*@@ -288,10 +288,10 @@ public void setCheckExistence(final boolean checkExistence) { * for non-cacheable templates, and completely removes any overhead for cached templates. *
*- * Default value is FALSE. + * Default value is {@code FALSE}. *
* - * @return true if decoupled logic resources should be checked, false if not. + * @return {@code true} if decoupled logic resources should be checked, {@code false} if not. * * @since 3.0.0 * @@ -313,8 +313,8 @@ public final boolean getUseDecoupledLogic() { * interface. * *- * Note this flag can only be true for the {@link TemplateMode#HTML} and {@link TemplateMode#XML} - * template modes. Also, note that setting this flag to true does not mean that a resource with + * Note this flag can only be {@code true} for the {@link TemplateMode#HTML} and {@link TemplateMode#XML} + * template modes. Also, note that setting this flag to {@code true} does not mean that a resource with * decoupled logic must exist for the resolved template, only that it can exist and therefore it should be * checked. *
@@ -324,10 +324,10 @@ public final boolean getUseDecoupledLogic() { * for non-cacheable templates, and completely removes any overhead for cached templates. * *- * Default value is FALSE. + * Default value is {@code FALSE}. *
* - * @param useDecoupledLogic true if resource existence should be checked, false if not + * @param useDecoupledLogic {@code true} if resource existence should be checked, {@code false} if not * * @since 3.0.0 * diff --git a/src/main/java/org/thymeleaf/templateresolver/ITemplateResolver.java b/src/main/java/org/thymeleaf/templateresolver/ITemplateResolver.java index f10daa9f9..84da6c3ed 100755 --- a/src/main/java/org/thymeleaf/templateresolver/ITemplateResolver.java +++ b/src/main/java/org/thymeleaf/templateresolver/ITemplateResolver.java @@ -118,7 +118,7 @@ public interface ITemplateResolver { * return a {@link TemplateResolution} object. * *- * The ownerTemplate, which might be null, will be specified when the template + * The {@code ownerTemplate}, which might be null, will be specified when the template * is resolved in order to be used as a fragent to be inserted into a higher level * template (the owner). Most template resolver implementations will simply ignore * this argument, but others might change their resolution results depending on the diff --git a/src/main/java/org/thymeleaf/templateresolver/StringTemplateResolver.java b/src/main/java/org/thymeleaf/templateresolver/StringTemplateResolver.java index 8f00b08e1..13595decf 100755 --- a/src/main/java/org/thymeleaf/templateresolver/StringTemplateResolver.java +++ b/src/main/java/org/thymeleaf/templateresolver/StringTemplateResolver.java @@ -38,12 +38,12 @@ * and creates {@link StringTemplateResource} instances for template resources. *
*- * This template resolvers will consider the template being resolved as the template itself, + * This template resolvers will consider the {@code template} being resolved as the template itself, * this is, its contents. No external file or resource will be therefore accessed. *
** This template resolver will consider its resolved templates non-cacheable by default, - * given its nature of being used for resolving arbitrary String objects. + * given its nature of being used for resolving arbitrary {@code String} objects. *
** Also, the {@link TemplateMode#HTML} template mode will be used by default. diff --git a/src/main/java/org/thymeleaf/templateresolver/TemplateResolution.java b/src/main/java/org/thymeleaf/templateresolver/TemplateResolution.java index 3300b8661..c711d4597 100755 --- a/src/main/java/org/thymeleaf/templateresolver/TemplateResolution.java +++ b/src/main/java/org/thymeleaf/templateresolver/TemplateResolution.java @@ -99,7 +99,7 @@ public TemplateResolution( * {@link org.thymeleaf.templateresolver.ITemplateResolver}. *
*- * Note that, even if this resource object will never be null, the existence of the + * Note that, even if this resource object will never be {@code null}, the existence of the * resource object does not necessarily imply the existence of the resource itself unless * the template resolver was configured for calling {@link ITemplateResource#exists()} upon * template resolution. @@ -135,11 +135,11 @@ public TemplateMode getTemplateMode() { * been already verified to actually exist by the template resolver during resolution. *
*- * This allows avoiding further checks in case the resource.exists() execution is + * This allows avoiding further checks in case the {@code resource.exists()} execution is * costly. *
*- * Note a false here does not mean the resource does not exist, but simply that + * Note a {@code false} here does not mean the resource does not exist, but simply that * its existence was not verified (true) during resolution. *
* @@ -156,7 +156,7 @@ public boolean isTemplateResourceExistenceVerified() { * for this template during parsing. * *- * Note a true here does not mean that a decoupled logic resource has to necessarily exist for this + * Note a {@code true} here does not mean that a decoupled logic resource has to necessarily exist for this * template, only that its existence should be checked and used if it exists. *
* diff --git a/src/main/java/org/thymeleaf/templateresource/ITemplateResource.java b/src/main/java/org/thymeleaf/templateresource/ITemplateResource.java index 0cc9397b1..98347f008 100644 --- a/src/main/java/org/thymeleaf/templateresource/ITemplateResource.java +++ b/src/main/java/org/thymeleaf/templateresource/ITemplateResource.java @@ -65,14 +65,14 @@ public interface ITemplateResource { /** *- * Returns a String describing the resource. + * Returns a {@code String} describing the resource. *
** Note this should not be taken for a valid resource name, as depending on the implementation * it could be too verbose/descriptive or not unique enough to be used for identification purposes. *
* - * @return the resource description. Should never return null. + * @return the resource description. Should never return {@code null}. */ public String getDescription(); @@ -86,12 +86,12 @@ public interface ITemplateResource { * the deepest level of the resource path. * *- * For example, a file resource located at /home/user/template/main.html should return - * main as its base name, so that names like main.properties, - * main.th.xml or similar can be derived, and afterwards resolved using {@link #relative(String)}. + * For example, a file resource located at {@code /home/user/template/main.html} should return + * {@code main} as its base name, so that names like {@code main.properties}, + * {@code main.th.xml} or similar can be derived, and afterwards resolved using {@link #relative(String)}. *
* - * @return the base name, or null if it cannot be computed for the specific type of resource. + * @return the base name, or {@code null} if it cannot be computed for the specific type of resource. */ public String getBaseName(); @@ -109,10 +109,10 @@ public interface ITemplateResource { * This mechanism will be used by Template Resolvers extending from * {@link org.thymeleaf.templateresolver.AbstractTemplateResolver} for checking real resource existence * if the {@link org.thymeleaf.templateresolver.AbstractTemplateResolver#setCheckExistence(boolean)} flag - * is set to true. + * is set to {@code true}. * * - * @return true if the resource exists, false if not. + * @return {@code true} if the resource exists, {@code false} if not. */ public boolean exists(); @@ -129,7 +129,7 @@ public interface ITemplateResource { * Note this readers should be closed after being fully consumed, just like any other resources. * * - * @return a {@link Reader} on the template contents. Should never return null. + * @return a {@link Reader} on the template contents. Should never return {@code null}. * @throws IOException if an input/output exception happens or if the resource does not exist (e.g. * {@link java.io.FileNotFoundException}). */ @@ -146,7 +146,7 @@ public interface ITemplateResource { * * * @param relativeLocation the location of the resource we want to obtain, relative to the current one. Required. - * @return the relative resource. Should never return null. + * @return the relative resource. Should never return {@code null}. */ public ITemplateResource relative(final String relativeLocation); diff --git a/src/main/java/org/thymeleaf/templateresource/ServletContextTemplateResource.java b/src/main/java/org/thymeleaf/templateresource/ServletContextTemplateResource.java index e799b147d..5b9b44ac4 100644 --- a/src/main/java/org/thymeleaf/templateresource/ServletContextTemplateResource.java +++ b/src/main/java/org/thymeleaf/templateresource/ServletContextTemplateResource.java @@ -37,7 +37,7 @@ ** Implementation of {@link ITemplateResource} accessible from the {@link ServletContext} in a web application. * The paths of these resources start at the web application root, and are normally stored inside - * /WEB-INF. + * {@code /WEB-INF}. *
** Objects of this class are usually created by {@link org.thymeleaf.templateresolver.ServletContextTemplateResolver}. diff --git a/src/main/java/org/thymeleaf/templateresource/StringTemplateResource.java b/src/main/java/org/thymeleaf/templateresource/StringTemplateResource.java index 5dd5d5807..312197285 100644 --- a/src/main/java/org/thymeleaf/templateresource/StringTemplateResource.java +++ b/src/main/java/org/thymeleaf/templateresource/StringTemplateResource.java @@ -29,7 +29,7 @@ /** *
* Implementation of {@link ITemplateResource} that represents a template completely contained in memory inside - * a String object. + * a {@code String} object. *
** Objects of this class are usually created by {@link org.thymeleaf.templateresolver.StringTemplateResolver}. diff --git a/src/main/java/org/thymeleaf/util/ClassLoaderUtils.java b/src/main/java/org/thymeleaf/util/ClassLoaderUtils.java index 88b417112..fdbc51d8b 100755 --- a/src/main/java/org/thymeleaf/util/ClassLoaderUtils.java +++ b/src/main/java/org/thymeleaf/util/ClassLoaderUtils.java @@ -90,11 +90,11 @@ public static ClassLoader getClassLoader(final Class> clazz) { *
* First the context class loader will be used. If this class loader is not * able to load the class, then the class class loader - * (ClassLoaderUtils.class.getClassLoader()) will be used if it is different from + * ({@code ClassLoaderUtils.class.getClassLoader()}) will be used if it is different from * the thread context one. Last, the System class loader will be tried. *
*- * This method does never return null. + * This method does never return {@code null}. *
* * @param className the name of the class to be obtained. @@ -166,15 +166,15 @@ public static Class> loadClass(final String className) throws ClassNotFoundExc /** *- * Try to obtain a class by name, returning null if not found. + * Try to obtain a class by name, returning {@code null} if not found. *
*- * This method works very similarly to {@link #loadClass(String)} but will just return null + * This method works very similarly to {@link #loadClass(String)} but will just return {@code null} * if the class is not found by the sequence of class loaders being tried. *
* * @param className the name of the class to be obtained. - * @return the found class, or null if it could not be found. + * @return the found class, or {@code null} if it could not be found. * * @since 3.0.3 * @@ -194,12 +194,12 @@ public static Class> findClass(final String className) { * Checks whether a class is present at the application's class path. * *- * This method works very similarly to {@link #findClass(String)} but will just return true - * or false depending on whether the class could be found or not. + * This method works very similarly to {@link #findClass(String)} but will just return {@code true} + * or {@code false} depending on whether the class could be found or not. *
* * @param className the name of the class to be checked. - * @return true if the class was found (by any class loader), false if not. + * @return {@code true} if the class was found (by any class loader), {@code false} if not. * * @since 3.0.3 * @@ -213,17 +213,17 @@ public static boolean isClassPresent(final String className) { /** *- * Try to obtain a resource by name, returning null if it could not be located. + * Try to obtain a resource by name, returning {@code null} if it could not be located. *
** First the context class loader will be used. If this class loader is not * able to locate the resource, then the class class loader - * (ClassLoaderUtils.class.getClassLoader()) will be used if it is different from + * ({@code ClassLoaderUtils.class.getClassLoader()}) will be used if it is different from * the thread context one. Last, the System class loader will be tried. *
* * @param resourceName the name of the resource to be obtained. - * @return the found resource, or null if it could not be located. + * @return the found resource, or {@code null} if it could not be located. * * @since 3.0.3 * @@ -281,12 +281,12 @@ public static URL findResource(final String resourceName) { * Checks whether a resource is present at the application's class path. * *- * This method works very similarly to {@link #findResource(String)} but will just return true - * or false depending on whether the resource could be located or not. + * This method works very similarly to {@link #findResource(String)} but will just return {@code true} + * or {@code false} depending on whether the resource could be located or not. *
* * @param resourceName the name of the resource to be checked. - * @return true if the class was located (by any class loader), false if not. + * @return {@code true} if the class was located (by any class loader), {@code false} if not. * * @since 3.0.3 * @@ -305,11 +305,11 @@ public static boolean isResourcePresent(final String resourceName) { ** First the context class loader will be used. If this class loader is not * able to locate the resource, then the class class loader - * (ClassLoaderUtils.class.getClassLoader()) will be used if it is different from + * ({@code ClassLoaderUtils.class.getClassLoader()}) will be used if it is different from * the thread context one. Last, the System class loader will be tried. *
*- * This method does never return null. + * This method does never return {@code null}. *
* * @param resourceName the name of the resource to be obtained. @@ -334,15 +334,15 @@ public static InputStream loadResourceAsStream(final String resourceName) throws /** *- * Try to obtain a resource by name, returning null if it could not be located. + * Try to obtain a resource by name, returning {@code null} if it could not be located. *
*- * This method works very similarly to {@link #loadResourceAsStream(String)} but will just return null + * This method works very similarly to {@link #loadResourceAsStream(String)} but will just return {@code null} * if the resource cannot be located by the sequence of class loaders being tried. *
* * @param resourceName the name of the resource to be obtained. - * @return an input stream on the resource, or null if it could not be located. + * @return an input stream on the resource, or {@code null} if it could not be located. * * @since 3.0.3 * diff --git a/src/main/java/org/thymeleaf/util/ExpressionUtils.java b/src/main/java/org/thymeleaf/util/ExpressionUtils.java new file mode 100644 index 000000000..35cf8f8ac --- /dev/null +++ b/src/main/java/org/thymeleaf/util/ExpressionUtils.java @@ -0,0 +1,72 @@ +/* + * ============================================================================= + * + * Copyright (c) 2011-2022, The THYMELEAF team (http://www.thymeleaf.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============================================================================= + */ + +package org.thymeleaf.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public final class ExpressionUtils { + + private static final Set* This will be used by a variety of implementations providing the capability to write text generated by * the engine somehow directly to output (to the output writer, which will correspond to an - * HttpServletResponse#getWriter() writer in most web applications). This avoids the need to generate - * a large number of (possibly large) String object in memory before these values being output. + * {@code HttpServletResponse#getWriter()} writer in most web applications). This avoids the need to generate + * a large number of (possibly large) {@code String} object in memory before these values being output. *
* * @author Daniel Fernández diff --git a/src/main/java/org/thymeleaf/util/LazyEscapingCharSequence.java b/src/main/java/org/thymeleaf/util/LazyEscapingCharSequence.java index e5ee2c982..b8f59b32d 100644 --- a/src/main/java/org/thymeleaf/util/LazyEscapingCharSequence.java +++ b/src/main/java/org/thymeleaf/util/LazyEscapingCharSequence.java @@ -34,7 +34,7 @@ /** *- * Character sequence that performs a lazy escaping of a text, so that it is directly written to a Writer + * Character sequence that performs a lazy escaping of a text, so that it is directly written to a {@code Writer} * output during the escape operation itself. *
*diff --git a/src/main/java/org/thymeleaf/util/NumberUtils.java b/src/main/java/org/thymeleaf/util/NumberUtils.java index 69bbcb4a3..ca98558eb 100755 --- a/src/main/java/org/thymeleaf/util/NumberUtils.java +++ b/src/main/java/org/thymeleaf/util/NumberUtils.java @@ -223,7 +223,7 @@ private static DecimalFormatSymbols computeDecimalFormatSymbols( Validate.notNull(thousandsPointType, "Thousands point type cannot be null"); Validate.notNull(locale, "Locale cannot be null"); - final DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US); + final DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale); switch (decimalPointType) { case POINT : @@ -236,8 +236,7 @@ private static DecimalFormatSymbols computeDecimalFormatSymbols( symbols.setDecimalSeparator(' '); break; case DEFAULT : - final DecimalFormatSymbols dfs = new DecimalFormatSymbols(locale); - symbols.setDecimalSeparator(dfs.getDecimalSeparator()); + // No changes needed to the "symbols" variable defined above break; case NONE : // This should never happen @@ -255,8 +254,7 @@ private static DecimalFormatSymbols computeDecimalFormatSymbols( symbols.setGroupingSeparator(' '); break; case DEFAULT : - final DecimalFormatSymbols dfs = new DecimalFormatSymbols(locale); - symbols.setGroupingSeparator(dfs.getGroupingSeparator()); + // No changes needed to the "symbols" variable defined above break; case NONE : // This should never be shown diff --git a/src/main/java/org/thymeleaf/util/StringUtils.java b/src/main/java/org/thymeleaf/util/StringUtils.java index 09c6b463b..f39b7d5fe 100755 --- a/src/main/java/org/thymeleaf/util/StringUtils.java +++ b/src/main/java/org/thymeleaf/util/StringUtils.java @@ -37,7 +37,7 @@ *
* This class is used as a basis for the methods offered by * {@link org.thymeleaf.expression.Strings}, which in turn are the - * methods offered by the #strings utility object in variable + * methods offered by the {@code #strings} utility object in variable * expressions. *
* @@ -55,12 +55,12 @@ public final class StringUtils { /** *- * Performs a null-safe toString() operation. + * Performs a null-safe {@code toString()} operation. *
* * @param target the object on which toString will be executed - * @return the result of calling target.toString() if target is not null, - * null if target is null. + * @return the result of calling {@code target.toString()} if target is not null, + * {@code null} if target is null. * @since 2.0.12 */ public static String toString(final Object target) { @@ -198,7 +198,7 @@ public static String substring(final Object target, final int beginIndex, final * * @param target source of the copy. * @param beginIndex index where the copy start. - * @return part of target, or null if target is null. + * @return part of target, or {@code null} if target is null. * @since 1.1.2 */ public static String substring(final Object target, final int beginIndex) { @@ -551,6 +551,39 @@ public static String trim(final Object target) { } + /** + * Removes all whitespaces and control chars at all positions, and + * transforms to lower case. + * + * @param target the string to be packed + * @return the packed string + * + * @since 3.0.12 + */ + public static String pack(final String target) { + if (target == null) { + return null; + } + final int targetLen = target.length(); + StringBuilder strBuilder = null; + char c; + for (int i = 0; i < targetLen; i++) { + c = target.charAt(i); + if (Character.isWhitespace(c) || c <= ' ') { + if (strBuilder == null) { + strBuilder = new StringBuilder(); + strBuilder.append(target, 0, i); + } + } else { + if (strBuilder != null) { + strBuilder.append(c); + } + } + } + return (strBuilder == null) ? target.toLowerCase() : strBuilder.toString().toLowerCase(); + } + + /** ** Convert the first letter of target to uppercase (title-case, in fact). diff --git a/src/main/java/org/thymeleaf/util/TextUtils.java b/src/main/java/org/thymeleaf/util/TextUtils.java index a5503acc5..9e9e9be8b 100644 --- a/src/main/java/org/thymeleaf/util/TextUtils.java +++ b/src/main/java/org/thymeleaf/util/TextUtils.java @@ -22,7 +22,7 @@ /** *
- * Utility class for char[] operations (mainly matching/comparing) + * Utility class for {@code char[]} operations (mainly matching/comparing) *
* * @author Daniel Fernández @@ -35,7 +35,7 @@ public final class TextUtils { /** *- * Check equality of two CharSequence objects. This is equivalent to {@link java.lang.String#equals(Object)} + * Check equality of two {@code CharSequence} objects. This is equivalent to {@link java.lang.String#equals(Object)} * and {@link java.lang.String#equalsIgnoreCase(String)}. *
* @@ -68,7 +68,7 @@ public static boolean equals(final boolean caseSensitive, final CharSequence tex /** *- * Check equality between a CharSequence and a char[] object. + * Check equality between a {@code CharSequence} and a {@code char[]} object. *
* * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. @@ -83,7 +83,7 @@ public static boolean equals(final boolean caseSensitive, final CharSequence tex /** *- * Check equality between two char[] objects. + * Check equality between two {@code char[]} objects. *
* * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. @@ -98,7 +98,7 @@ public static boolean equals(final boolean caseSensitive, final char[] text1, fi /** *- * Check equality between two char[] objects, specifying (offset,len) pairs for limiting + * Check equality between two {@code char[]} objects, specifying (offset,len) pairs for limiting * the fragments to be checked. *
* @@ -173,7 +173,7 @@ public static boolean equals( /** *- * Check equality between a CharSequence and a char[] object, specifying (offset,len) pairs + * Check equality between a {@code CharSequence} and a {@code char[]} object, specifying (offset,len) pairs * for limiting the fragments to be checked. *
* @@ -244,7 +244,7 @@ public static boolean equals( /** *- * Check equality between two CharSequence objects, specifying (offset,len) pairs + * Check equality between two {@code CharSequence} objects, specifying (offset,len) pairs * for limiting the fragments to be checked. *
* @@ -1448,8 +1448,8 @@ public static boolean contains( * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. * @param text1 the first text to be compared. * @param text2 the second text to be compared. - * @return the value 0 if both texts are equal; a value less than 0 if the first text - * is lexicographically less than the second text; and a value greater than 0 if the + * @return the value {@code 0} if both texts are equal; a value less than {@code 0} if the first text + * is lexicographically less than the second text; and a value greater than {@code 0} if the * first text is lexicographically greater than the second text. */ public static int compareTo(final boolean caseSensitive, final CharSequence text1, final CharSequence text2) { @@ -1492,8 +1492,8 @@ public static int compareTo(final boolean caseSensitive, final CharSequence text * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. * @param text1 the first text to be compared. * @param text2 the second text to be compared. - * @return the value 0 if both texts are equal; a value less than 0 if the first text - * is lexicographically less than the second text; and a value greater than 0 if the + * @return the value {@code 0} if both texts are equal; a value less than {@code 0} if the first text + * is lexicographically less than the second text; and a value greater than {@code 0} if the * first text is lexicographically greater than the second text. */ public static int compareTo(final boolean caseSensitive, final CharSequence text1, final char[] text2) { @@ -1523,8 +1523,8 @@ public static int compareTo(final boolean caseSensitive, final CharSequence text * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. * @param text1 the first text to be compared. * @param text2 the second text to be compared. - * @return the value 0 if both texts are equal; a value less than 0 if the first text - * is lexicographically less than the second text; and a value greater than 0 if the + * @return the value {@code 0} if both texts are equal; a value less than {@code 0} if the first text + * is lexicographically less than the second text; and a value greater than {@code 0} if the * first text is lexicographically greater than the second text. */ public static int compareTo(final boolean caseSensitive, final char[] text1, final char[] text2) { @@ -1558,8 +1558,8 @@ public static int compareTo(final boolean caseSensitive, final char[] text1, fin * @param text2 the second text to be compared. * @param text2Offset the offset of the second text. * @param text2Len the length of the second text. - * @return the value 0 if both texts are equal; a value less than 0 if the first text - * is lexicographically less than the second text; and a value greater than 0 if the + * @return the value {@code 0} if both texts are equal; a value less than {@code 0} if the first text + * is lexicographically less than the second text; and a value greater than {@code 0} if the * first text is lexicographically greater than the second text. */ public static int compareTo( @@ -1644,8 +1644,8 @@ public static int compareTo( * @param text2 the second text to be compared. * @param text2Offset the offset of the second text. * @param text2Len the length of the second text. - * @return the value 0 if both texts are equal; a value less than 0 if the first text - * is lexicographically less than the second text; and a value greater than 0 if the + * @return the value {@code 0} if both texts are equal; a value less than {@code 0} if the first text + * is lexicographically less than the second text; and a value greater than {@code 0} if the * first text is lexicographically greater than the second text. */ public static int compareTo( @@ -1726,8 +1726,8 @@ public static int compareTo( * @param text2 the second text to be compared. * @param text2Offset the offset of the second text. * @param text2Len the length of the second text. - * @return the value 0 if both texts are equal; a value less than 0 if the first text - * is lexicographically less than the second text; and a value greater than 0 if the + * @return the value {@code 0} if both texts are equal; a value less than {@code 0} if the first text + * is lexicographically less than the second text; and a value greater than {@code 0} if the * first text is lexicographically greater than the second text. */ public static int compareTo( @@ -1792,11 +1792,11 @@ public static int compareTo( /** *- * Searches the specified array of texts (values) for the specified text —or a fragment, using an + * Searches the specified array of texts ({@code values}) for the specified text —or a fragment, using an * (offset,len) specification— using the binary search algorithm. *
*- * Note the specified values parameter must be lexicographically ordered. + * Note the specified {@code values} parameter must be lexicographically ordered. *
* * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. @@ -1806,7 +1806,7 @@ public static int compareTo( * @param textOffset the offset of the text to search. * @param textLen the length of the text to search. * @return index of the search key, if it is contained in the values array; otherwise, - * (-(insertion point) - 1). The insertion point is defined as the point at + * {@code (-(insertion point) - 1)}. The insertion point is defined as the point at * which the key would be inserted into the array. Note that this guarantees that the return value will * be >= 0 if and only if the key is found. */ @@ -1824,11 +1824,11 @@ public static int binarySearch( /** *- * Searches the specified array of texts (values) for the specified text —or a fragment, using an + * Searches the specified array of texts ({@code values}) for the specified text —or a fragment, using an * (offset,len) specification— using the binary search algorithm. *
*- * Note the specified values parameter must be lexicographically ordered. + * Note the specified {@code values} parameter must be lexicographically ordered. *
* * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. @@ -1838,7 +1838,7 @@ public static int binarySearch( * @param textOffset the offset of the text to search. * @param textLen the length of the text to search. * @return index of the search key, if it is contained in the values array; otherwise, - * (-(insertion point) - 1). The insertion point is defined as the point at + * {@code (-(insertion point) - 1)}. The insertion point is defined as the point at * which the key would be inserted into the array. Note that this guarantees that the return value will * be >= 0 if and only if the key is found. */ @@ -1856,11 +1856,11 @@ public static int binarySearch( /** *- * Searches the specified array of texts (values) for the specified text —or a fragment, using an + * Searches the specified array of texts ({@code values}) for the specified text —or a fragment, using an * (offset,len) specification— using the binary search algorithm. *
*- * Note the specified values parameter must be lexicographically ordered. + * Note the specified {@code values} parameter must be lexicographically ordered. *
* * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. @@ -1870,7 +1870,7 @@ public static int binarySearch( * @param textOffset the offset of the text to search. * @param textLen the length of the text to search. * @return index of the search key, if it is contained in the values array; otherwise, - * (-(insertion point) - 1). The insertion point is defined as the point at + * {@code (-(insertion point) - 1)}. The insertion point is defined as the point at * which the key would be inserted into the array. Note that this guarantees that the return value will * be >= 0 if and only if the key is found. */ @@ -1888,11 +1888,11 @@ public static int binarySearch( /** *- * Searches the specified array of texts (values) for the specified text —or a fragment, using an + * Searches the specified array of texts ({@code values}) for the specified text —or a fragment, using an * (offset,len) specification— using the binary search algorithm. *
*- * Note the specified values parameter must be lexicographically ordered. + * Note the specified {@code values} parameter must be lexicographically ordered. *
* * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. @@ -1902,7 +1902,7 @@ public static int binarySearch( * @param textOffset the offset of the text to search. * @param textLen the length of the text to search. * @return index of the search key, if it is contained in the values array; otherwise, - * (-(insertion point) - 1). The insertion point is defined as the point at + * {@code (-(insertion point) - 1)}. The insertion point is defined as the point at * which the key would be inserted into the array. Note that this guarantees that the return value will * be >= 0 if and only if the key is found. */ @@ -1920,11 +1920,11 @@ public static int binarySearch( /** *- * Searches the specified array of texts (values) for the specified text —or a fragment, using an + * Searches the specified array of texts ({@code values}) for the specified text —or a fragment, using an * (offset,len) specification— using the binary search algorithm. *
*- * Note the specified values parameter must be lexicographically ordered. + * Note the specified {@code values} parameter must be lexicographically ordered. *
* * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. @@ -1937,7 +1937,7 @@ public static int binarySearch( * @param textOffset the offset of the text to search. * @param textLen the length of the text to search. * @return index of the search key, if it is contained in the values array; otherwise, - * (-(insertion point) - 1). The insertion point is defined as the point at + * {@code (-(insertion point) - 1)}. The insertion point is defined as the point at * which the key would be inserted into the array. Note that this guarantees that the return value will * be >= 0 if and only if the key is found. */ @@ -1984,11 +1984,11 @@ public static int binarySearch( /** *- * Searches the specified array of texts (values) for the specified text —or a fragment, using an + * Searches the specified array of texts ({@code values}) for the specified text —or a fragment, using an * (offset,len) specification— using the binary search algorithm. *
*- * Note the specified values parameter must be lexicographically ordered. + * Note the specified {@code values} parameter must be lexicographically ordered. *
* * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. @@ -2001,7 +2001,7 @@ public static int binarySearch( * @param textOffset the offset of the text to search. * @param textLen the length of the text to search. * @return index of the search key, if it is contained in the values array; otherwise, - * (-(insertion point) - 1). The insertion point is defined as the point at + * {@code (-(insertion point) - 1)}. The insertion point is defined as the point at * which the key would be inserted into the array. Note that this guarantees that the return value will * be >= 0 if and only if the key is found. */ @@ -2048,11 +2048,11 @@ public static int binarySearch( /** *- * Searches the specified array of texts (values) for the specified text —or a fragment, using an + * Searches the specified array of texts ({@code values}) for the specified text —or a fragment, using an * (offset,len) specification— using the binary search algorithm. *
*- * Note the specified values parameter must be lexicographically ordered. + * Note the specified {@code values} parameter must be lexicographically ordered. *
* * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. @@ -2065,7 +2065,7 @@ public static int binarySearch( * @param textOffset the offset of the text to search. * @param textLen the length of the text to search. * @return index of the search key, if it is contained in the values array; otherwise, - * (-(insertion point) - 1). The insertion point is defined as the point at + * {@code (-(insertion point) - 1)}. The insertion point is defined as the point at * which the key would be inserted into the array. Note that this guarantees that the return value will * be >= 0 if and only if the key is found. */ @@ -2112,11 +2112,11 @@ public static int binarySearch( /** *- * Searches the specified array of texts (values) for the specified text —or a fragment, using an + * Searches the specified array of texts ({@code values}) for the specified text —or a fragment, using an * (offset,len) specification— using the binary search algorithm. *
*- * Note the specified values parameter must be lexicographically ordered. + * Note the specified {@code values} parameter must be lexicographically ordered. *
* * @param caseSensitive whether the comparison must be done in a case-sensitive or case-insensitive way. @@ -2129,7 +2129,7 @@ public static int binarySearch( * @param textOffset the offset of the text to search. * @param textLen the length of the text to search. * @return index of the search key, if it is contained in the values array; otherwise, - * (-(insertion point) - 1). The insertion point is defined as the point at + * {@code (-(insertion point) - 1)}. The insertion point is defined as the point at * which the key would be inserted into the array. Note that this guarantees that the return value will * be >= 0 if and only if the key is found. */ diff --git a/src/main/java/org/thymeleaf/util/VersionUtils.java b/src/main/java/org/thymeleaf/util/VersionUtils.java new file mode 100644 index 000000000..0556bb373 --- /dev/null +++ b/src/main/java/org/thymeleaf/util/VersionUtils.java @@ -0,0 +1,280 @@ +/* + * ============================================================================= + * + * Copyright (c) 2011-2018, The THYMELEAF team (http://www.thymeleaf.org) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============================================================================= + */ +package org.thymeleaf.util; + + +/** + *+ * Utility class for processing version numbers. + *
+ * + * @author Daniel Fernández + * + * @since 3.0.12 + * + */ +public final class VersionUtils { + + + public static VersionSpec parseVersion(final String version) { + return parseVersion(version, null); + } + + + public static VersionSpec parseVersion(final String version, final String buildTimestamp) { + + if (version == null || version.trim().length() == 0) { + + // Build an UNKNOWN version + return new VersionSpec(buildTimestamp); + + } else { + + try { + + final String ver = version.trim(); + + final String numVer; + final Character qualifierSeparator; + final String qualifier; + + final int endOfNumericVersionIdx = findEndOfNumericVersion(ver); + if (endOfNumericVersionIdx < 0) { + numVer = ver; + qualifierSeparator = null; + qualifier = null; + } else { + numVer = ver.substring(0, endOfNumericVersionIdx); + final char c = ver.charAt(endOfNumericVersionIdx); + if (Character.isLetter(c)) { + qualifierSeparator = null; + qualifier = ver.substring(endOfNumericVersionIdx); + } else { + qualifierSeparator = Character.valueOf(ver.charAt(endOfNumericVersionIdx)); + qualifier = ver.substring(endOfNumericVersionIdx + 1); + if (qualifier == null || qualifier.trim().length() == 0) { + // Build an UNKNOWN version + return new VersionSpec(buildTimestamp); + } + } + } + + + final int major; + final Integer minor; + final Integer patch; + + final int separator1Idx = numVer.indexOf('.'); + if (separator1Idx < 0) { + major = Integer.parseInt(numVer); + minor = null; + patch = null; + } else { + major = Integer.parseInt(numVer.substring(0, separator1Idx)); + final int separator2Idx = numVer.indexOf('.', separator1Idx + 1); + if (separator2Idx < 0) { + minor = Integer.valueOf(numVer.substring(separator1Idx + 1)); + patch = null; + } else { + minor = Integer.valueOf(numVer.substring(separator1Idx + 1, separator2Idx)); + patch = Integer.valueOf(numVer.substring(separator2Idx + 1)); + } + } + + return new VersionSpec(major, minor, patch, qualifierSeparator, qualifier, buildTimestamp); + + } catch (final Exception e) { + // Build an UNKNOWN version + return new VersionSpec(buildTimestamp); + } + + } + + } + + + private static int findEndOfNumericVersion(final CharSequence sequence) { + final int seqLen = sequence.length(); + char c; + for (int i = 0; i < seqLen; i++) { + c = sequence.charAt(i); + if (c != '.' && !Character.isDigit(c)) { + if (i > 1 && sequence.charAt(i - 1) == '.') { + return i - 1; + } + return i; + } + } + return -1; + } + + + + + private VersionUtils() { + super(); + } + + + + public static final class VersionSpec { + + private static final String UNKNOWN_VERSION = "UNKNOWN"; + + private boolean unknown; + + private int major; + private int minor; + private int patch; + private String qualifier; + private String buildTimestamp; + + private String versionCore; + private String version; + private String fullVersion; + + + + // UNKNOWN version + private VersionSpec(final String buildTimestamp) { + + super(); + + this.unknown = true; + + this.major = 0; + this.minor = 0; + this.patch = 0; + this.qualifier = null; + this.buildTimestamp = buildTimestamp; + + this.versionCore = UNKNOWN_VERSION; + this.version = this.versionCore; + + // Version might be UNKNOWN but still full version specify a build timestamp + this.fullVersion = + (this.buildTimestamp != null) ? + String.format("%s (%s)", this.version, this.buildTimestamp) : this.version; + + } + + + private VersionSpec( + final int major, final Integer minor, final Integer patch, + final Character qualifierSeparator, final String qualifier, + final String buildTimestamp) { + + super(); + + Validate.isTrue(major >= 0, "Major version must be >= 0"); + Validate.isTrue(minor == null || minor.intValue() >= 0, "Minor version must be >= 0"); + Validate.isTrue(patch == null || patch.intValue() >= 0, "Patch version must be >= 0"); + Validate.isTrue(patch == null || minor != null, "Patch version present without minor"); + + this.unknown = false; + + this.major = major; + this.minor = (minor != null) ? minor.intValue() : 0; + this.patch = (patch != null) ? patch.intValue() : 0; + this.qualifier = qualifier; + this.buildTimestamp = buildTimestamp; + + this.versionCore = + (patch != null) ? + String.format("%d.%d.%d", Integer.valueOf(major), minor, patch) : + (minor != null) ? + String.format("%d.%d", Integer.valueOf(major), minor) : String.valueOf(major); + + this.version = + (qualifier == null) ? + this.versionCore : + (qualifierSeparator != null) ? + String.format("%s%c%s", this.versionCore, qualifierSeparator, qualifier) : + String.format("%s%s", this.versionCore, qualifier); + + // Version might be UNKNOWN but still full version specify a build timestamp + this.fullVersion = + (buildTimestamp != null) ? + String.format("%s (%s)", this.version, this.buildTimestamp) : this.version; + + } + + public boolean isUnknown() { + return this.unknown; + } + + public int getMajor() { + return this.major; + } + + public int getMinor() { + return this.minor; + } + + public int getPatch() { + return this.patch; + } + + public boolean hasQualifier() { + return this.qualifier != null; + } + + public String getQualifier() { + return this.qualifier; + } + + public String getVersionCore() { + return this.versionCore; + } + + public String getVersion() { + return this.version; + } + + public boolean hasBuildTimestamp() { + return this.buildTimestamp != null; + } + + public String getBuildTimestamp() { + return this.buildTimestamp; + } + + public String getFullVersion() { + return this.fullVersion; + } + + public boolean isAtLeast(final int major) { + return isAtLeast(major, 0); + } + + public boolean isAtLeast(final int major, final int minor) { + return isAtLeast(major, minor, 0); + } + + public boolean isAtLeast(final int major, final int minor, final int patch) { + return this.major > major || + (this.major == major && this.minor > minor) || + (this.major == major && this.minor == minor && this.patch >= patch); + } + + } + + +} \ No newline at end of file