[
https://issues.apache.org/jira/browse/TEXT-233?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17817498#comment-17817498
]
Gary D. Gregory edited comment on TEXT-233 at 2/14/24 10:23 PM:
----------------------------------------------------------------
See also
* [https://github.com/bndtools/bnd/issues/544]
* https://issues.apache.org/jira/browse/FELIX-4626
Reproducer:
{noformat}
git clone [https://gitbox.apache.org/repos/asf/commons-text.git]
git checkout 1001fb35902e52f1c19442a197a5ff914f7d8432
mvn clean verify
unzip -p target/commons-text-1.11.1-SNAPSHOT.jar META-INF/MANIFEST.MF
{noformat}
was (Author: garydgregory):
See also
* https://github.com/bndtools/bnd/issues/544
* https://issues.apache.org/jira/browse/FELIX-4626
> Missing OSGi import-package commons-lang3 version can make commons-text
> unusable in OSGi
> ----------------------------------------------------------------------------------------
>
> Key: TEXT-233
> URL: https://issues.apache.org/jira/browse/TEXT-233
> Project: Commons Text
> Issue Type: Bug
> Affects Versions: 1.11.0
> Reporter: K P
> Priority: Major
>
> Since commons-text 1.11.0, there's commons-text codes that requires the
> presence of commons-lang3 3.13.0 or higher. However, in an OSGi environment,
> this requirement is not enforced due to shortcoming an the commons-text
> 1.11.0 MANIFEST.MF, which may lead to unpredictable, uncontrollable failure
> when trying to use commons-text 1.11.0.
> Some more detail:
> Since commons-text 1.11.0, the NumericEntityEscaper makes uses of the method
> *Range.{_}+of+{_}(...)* in commons-lang3 :
>
> {code:java}
> private NumericEntityEscaper(final int below, final int above, final boolean
> between) {
> this.range = Range.of(below, above);
> this.between = between;
> }{code}
>
> Method Range.of(...) was added in *commons-lang3 3.13.0* :
>
> {code:java}
> * @since 3.13.0
> */
> public static <T extends Comparable<? super T>> Range<T> of(final T
> fromInclusive, final T toInclusive) {{code}
>
> Previously, in commons-text 1.10.0 or earlier, NumericEntityEscaper made use
> of the the commons-lang3 method *Range.{_}+between+{_}(...)* (which is now
> marked as deprecated since commons-lang3 3.13.0)
>
> {code:java}
> private NumericEntityEscaper(final int below, final int above, final boolean
> between) {
> this.range = Range.between(below, above);
> this.between = between;
> }{code}
>
> This is all fine in a non-OSGi environment.
>
> However, to always resolve this correctly in an OSGi environment, some
> essential information is missing in the commons-text 1.11.0 {*}MANIFEST.MF{*}.
> The commons-text 1.11.0 declares the following *Import-Package* in its
> manifest:
>
> {noformat}
> Import-Package: javax.script,javax.xml.xpath,org.apache.commons.lang3,or
> g.apache.commons.lang3.time,org.xml.sax
> {noformat}
> Notice how this indeed imports the required package
> "{_}org.apache.commons.lang3{_}", but this import {+}is not qualified with a
> version number{+}.
> When an OSGi package is not qualified by a version number or version range,
> then during package resolution, OSGi may resolve this import against whatever
> version of commons-lang3 it can find and that exports this package.
> In other words, because there's no version restriction in this import as far
> as OSGi is concerned : if you have an OSGi environment where also an older
> version older version of commons-lang3 is already present, e.g. commons-lang
> "3.12.0", then the import-package of commons-text 1.11.0 will happily be
> satisfied by that package and resolve and link its import-package requirement
> against the 3.12.0 version.
> So when loading these OSGi bundles, all will look fine. The OSGi will nicely
> resolve everything without complaining at this point.
> However in the above example environment, maybe much much later, when at a
> given moment a user of the 1.11.0 commons-text NumericEntityEscaper (e.g.
> some of the StringEscapeUtils method being called by user code) is invoked,
> then that commons-text 1.11.0 NumericEntityEscaper will see the 3.12.0
> version of the Range class in its classpath. It will try to invoke the method
> Range.of(...) ... but this method didn't exist yet in this 3.12.0 version of
> the Range class.
> Which will fail with a NoSuchMethodError:
>
> {noformat}
> java.lang.NoSuchMethodError:
> org.apache.commons.lang3.Range.of(Ljava/lang/Comparable;Ljava/lang/Comparable;)Lorg/apache/commons/lang3/Range;
> at
> org.apache.commons.text.translate.NumericEntityEscaper.<init>(NumericEntityEscaper.java:97)
> ~[?:?]{noformat}
>
> To avoid this, it is +required+ that the commons-text 1.11.0 *MANIFEST.MF*
> correctly specifies the minimally required version of the commons-lang3
> package in its Import-Package:
> E.g. by adding a version directive: *{{;version="3.13"}}* : in OSGi, 1 single
> version number means a minimal version number, i.e. an open range 3.13.0 or
> higher.
> Example:
> {code:java}
> Import-Package:
> javax.script,javax.xml.xpath,org.apache.commons.lang3;version="3.13",or
> g.apache.commons.lang3.time;version="3.13",org.xml.sax{code}
> That way, when OSGi resolves commons-text 1.11.0, it will now only be
> satisifed by version 3.13 of those package, or higher, and therefore be
> guaranteed to link its org.apache.commons.lang3 Import-Package against the
> package from commons-lang3 3.13.0 or higher.
> Then at runtime, whenever the NumericEntityEscaper calls a method on the
> Range class, it sees a 3.13.0 (or higher) version of the Range class, where
> the method Range.of(...) exists.
> (Note: a manifst example from another Apache Project:
> this snippet is from the MANIFEST.MF of the Apache Velocity Engine jar:
>
> {code:java}
> Import-Package: javax.naming,javax.sql,org.apache.commons.lang3;versio
> n="[3.11,4)",
> {code}
> Notice how they've specified a version range, which is also a possibility in
> OSGi: range _"[3.11,4)"_ means: import from any version from 3.11 (inclusive)
> to version 4 (exclusive). )
>
> I know that the commons-text OSGi MANIFEST.MF headers are generated by the
> "maven-bundle-plugin", which is defined somewhere in the "commons-parent"
> pom.xml I believe? But I assume that it should be possible to overrule some
> of the default (wildcard) generic maven-bundle-plugin settings with
> project-specific Import-Package directives, so that a version number (3.13)
> can be specified explicitly org.apache.commons.lang3 packages?
>
> {color:#000000} In the current state, as shown above, the commons-text 1.11.0
> code may fail unpredictably in an OSGi environment. Due to the dynamic nature
> of OSGi, bundles (jars) may come and go. Older versions of commons-lang3 may
> be present or not. So when the commons-text import-package doesn't impose a
> minimal version number in its Import-Package, it may unpredictably resolve
> against a commons-lang3 3.13. or 3.14.0, but just as well against an older
> version where the required Range.of() method is missing, causing the failure.
> In a dynamic environment, such application may sometimes run successfully by
> chance, but may just unpredictably fail later, outside the control of the
> developer or user.{color}{color:#7f0055}
> {color}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)