[ 
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

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}

> 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)

Reply via email to