Skip to content

Commit 753d106

Browse files
committed
Merge branch 'main' into TIKA-4763-improve-serialization
2 parents e671ad4 + 29cdf6a commit 753d106

6 files changed

Lines changed: 124 additions & 12 deletions

File tree

CHANGES.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ Release 4.0.0-beta-1 - unreleased
1818
The extra jars are also forwarded onto forked pipes/server worker processes,
1919
so they are available where parsing actually happens (TIKA-4755).
2020

21+
OTHER CHANGES
22+
23+
* Release artifacts are now channel-specific. Maven Central gets slim
24+
per-module jars (plus pom, sources and javadoc); the Apache dist area
25+
gets runnable zip distributions (tika-app, tika-server-standard,
26+
tika-eval-app) and drop-in pf4j plugin zips; Docker Hub gets ready-to-run
27+
images. Fat/shaded artifacts no longer go to Maven Central, and release
28+
staging is validated so a missing artifact fails the build (TIKA-4733).
29+
30+
* Improved charset (encoding) detection and junk/garbage-text detection,
31+
including more efficient common-token lookups via bloom filters
32+
(TIKA-4731, TIKA-4745, TIKA-4754).
33+
34+
* Dependency upgrades, including Jetty 11 -> 12.0.36,
35+
CXF 4.0 -> 4.1.7, plus routine library updates (TIKA-4327).
36+
2137

2238
Release 4.0.0-alpha-1 - 5/4/2026
2339

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@
105105
<groupId>org.apache.maven.plugins</groupId>
106106
<artifactId>maven-antrun-plugin</artifactId>
107107
<version>${maven.antrun.version}</version>
108+
<!-- This dist-staging step is aggregator-only: it copies release artifacts and
109+
CHANGES.txt relative to the reactor root's ${basedir}. tika-docs has <parent>tika</parent>,
110+
so without inherited=false it also runs here with ${basedir}=docs/, where CHANGES.txt
111+
and the artifacts don't exist, and the staging <fail> guards trip. Run only on root. -->
112+
<inherited>false</inherited>
108113
<executions>
109114
<execution>
110115
<goals>

tika-parent/pom.xml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@
288288
<maven.compiler.release>17</maven.compiler.release>
289289
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
290290
<project.reporting.outputEncoding>${project.build.sourceEncoding}</project.reporting.outputEncoding>
291-
<project.build.outputTimestamp>2026-05-04T23:37:57Z</project.build.outputTimestamp>
291+
<project.build.outputTimestamp>2026-06-25T20:24:03Z</project.build.outputTimestamp>
292292
<!-- plugin versions -->
293293
<!-- updates may not be detected by the maven versions plugin:
294294
https://github.com/mojohaus/versions/issues/1070 -->
@@ -393,7 +393,7 @@
393393
<juniversalchardet.version>2.5.0</juniversalchardet.version>
394394
<junrar.version>7.6.0</junrar.version>
395395
<jwarc.version>0.36.0</jwarc.version>
396-
<kafka.version>4.3.0</kafka.version>
396+
<kafka.version>4.3.1</kafka.version>
397397
<kotlin-stdlib.version>2.4.0</kotlin-stdlib.version>
398398
<libpst.version>0.9.3</libpst.version>
399399
<log4j2.version>2.26.0</log4j2.version>
@@ -413,7 +413,7 @@
413413
<netty.version>4.2.15.Final</netty.version>
414414
<oak.jackrabbit.version>2.2.0</oak.jackrabbit.version>
415415
<openjson.version>1.0.13</openjson.version>
416-
<opennlp.version>2.5.9</opennlp.version>
416+
<opennlp.version>2.5.10</opennlp.version>
417417
<ops4j.version>1.5.1</ops4j.version>
418418
<optimaize.version>0.6</optimaize.version>
419419
<osgi.compendium.version>5.0.0</osgi.compendium.version>
@@ -1217,7 +1217,7 @@
12171217
<dependency>
12181218
<groupId>io.swagger.core.v3</groupId>
12191219
<artifactId>swagger-annotations</artifactId>
1220-
<version>2.2.51</version>
1220+
<version>2.2.52</version>
12211221
</dependency>
12221222
<dependency>
12231223
<groupId>org.jetbrains.kotlin</groupId>
@@ -1234,11 +1234,11 @@
12341234
<artifactId>jakarta.inject-api</artifactId>
12351235
<version>2.0.1.MR</version>
12361236
</dependency>
1237-
<!-- TODO try removing after updating aws2, last tested with 2.46.10, trouble with transcribe -->
1237+
<!-- TODO try removing after updating aws2, last tested with 2.46.17, trouble with transcribe -->
12381238
<dependency>
12391239
<groupId>org.apache.httpcomponents.core5</groupId>
12401240
<artifactId>httpcore5</artifactId>
1241-
<version>5.4.2</version>
1241+
<version>5.4.3</version>
12421242
</dependency>
12431243
</dependencies>
12441244
</dependencyManagement>
@@ -1500,6 +1500,10 @@
15001500
<version>3.3.1</version>
15011501
<configuration>
15021502
<autoVersionSubmodules>true</autoVersionSubmodules>
1503+
<!-- 'install' (not the default 'verify') so the install-only pf4j plugin zips
1504+
(attach=false, installed via install:install-file; see tika-pipes plugins)
1505+
are available in the local repo for sibling modules that depend on them. -->
1506+
<preparationGoals>clean install</preparationGoals>
15031507
</configuration>
15041508
<dependencies>
15051509
<dependency>

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/SevenZParser.java

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,19 @@
2323
import java.util.Collections;
2424
import java.util.Set;
2525

26+
import org.apache.commons.compress.MemoryLimitException;
2627
import org.apache.commons.compress.PasswordRequiredException;
2728
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
2829
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
2930
import org.xml.sax.ContentHandler;
3031
import org.xml.sax.SAXException;
3132

33+
import org.apache.tika.config.ConfigDeserializer;
34+
import org.apache.tika.config.JsonConfig;
3235
import org.apache.tika.config.TikaComponent;
3336
import org.apache.tika.exception.EncryptedDocumentException;
3437
import org.apache.tika.exception.TikaException;
38+
import org.apache.tika.exception.TikaMemoryLimitException;
3539
import org.apache.tika.extractor.EmbeddedDocumentExtractor;
3640
import org.apache.tika.extractor.EmbeddedDocumentUtil;
3741
import org.apache.tika.io.TemporaryResources;
@@ -60,6 +64,37 @@ public class SevenZParser extends AbstractArchiveParser {
6064

6165
private static final Set<MediaType> SUPPORTED_TYPES = Collections.singleton(SEVENZ);
6266

67+
/**
68+
* Configuration class for JSON deserialization.
69+
*/
70+
public static class Config {
71+
// Cap the LZMA/LZMA2 dictionary allocation. A tiny 7z can declare a huge dictionary
72+
// (a single header byte), forcing an eager multi-GiB allocation and OOMing the parser.
73+
// Mirrors CompressorParser's default.
74+
private int memoryLimitInKb = 100000;
75+
76+
public int getMemoryLimitInKb() {
77+
return memoryLimitInKb;
78+
}
79+
80+
public void setMemoryLimitInKb(int memoryLimitInKb) {
81+
this.memoryLimitInKb = memoryLimitInKb;
82+
}
83+
}
84+
85+
private Config defaultConfig = new Config();
86+
87+
public SevenZParser() {
88+
}
89+
90+
public SevenZParser(Config config) {
91+
this.defaultConfig = config;
92+
}
93+
94+
public SevenZParser(JsonConfig jsonConfig) {
95+
this(ConfigDeserializer.buildConfig(jsonConfig, Config.class));
96+
}
97+
6398
@Override
6499
public Set<MediaType> getSupportedTypes(ParseContext context) {
65100
return SUPPORTED_TYPES;
@@ -78,14 +113,21 @@ public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata
78113

79114
SevenZFile sevenZFile;
80115
try {
81-
SevenZFile.Builder builder = new SevenZFile.Builder().setFile(tis.getFile());
116+
// Use setMaxMemoryLimitKiB (direct KiB); setMaxMemoryLimitKb divides the arg by 1024.
117+
SevenZFile.Builder builder = new SevenZFile.Builder()
118+
.setFile(tis.getFile())
119+
.setMaxMemoryLimitKiB(defaultConfig.getMemoryLimitInKb());
82120
if (password == null) {
83121
sevenZFile = builder.get();
84122
} else {
85123
sevenZFile = builder.setPassword(password.toCharArray()).get();
86124
}
87125
} catch (PasswordRequiredException e) {
88126
throw new EncryptedDocumentException(e);
127+
} catch (MemoryLimitException e) {
128+
// The limit can be exceeded at open time (assertValidity) as well as lazily on the
129+
// first getNextEntry() when the LZMA/LZMA2 dictionary is allocated.
130+
throw new TikaMemoryLimitException(e.getMessage());
89131
}
90132

91133
metadata.set(Metadata.CONTENT_TYPE, SEVENZ.toString());
@@ -106,6 +148,8 @@ public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata
106148
}
107149
} catch (PasswordRequiredException e) {
108150
throw new EncryptedDocumentException(e);
151+
} catch (MemoryLimitException e) {
152+
throw new TikaMemoryLimitException(e.getMessage());
109153
} finally {
110154
sevenZFile.close();
111155
xhtml.endDocument();

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/test/java/org/apache/tika/parser/pkg/Seven7ParserTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@
1919
import static org.junit.jupiter.api.Assertions.assertEquals;
2020
import static org.junit.jupiter.api.Assertions.assertNotNull;
2121
import static org.junit.jupiter.api.Assertions.assertNull;
22+
import static org.junit.jupiter.api.Assertions.assertThrows;
2223
import static org.junit.jupiter.api.Assertions.assertTrue;
2324

2425
import org.junit.jupiter.api.Test;
2526
import org.xml.sax.ContentHandler;
2627

28+
import org.apache.tika.exception.TikaMemoryLimitException;
2729
import org.apache.tika.io.TikaInputStream;
2830
import org.apache.tika.metadata.Metadata;
31+
import org.apache.tika.parser.ParseContext;
2932
import org.apache.tika.sax.BodyContentHandler;
3033

3134
/**
@@ -71,4 +74,23 @@ public void testEmbedded() throws Exception {
7174
assertTrue(mod.startsWith("20"), "Modified at " + mod);
7275
}
7376
}
77+
78+
/**
79+
* A 7z whose declared LZMA2 dictionary exceeds the configured limit must fail with a
80+
* {@link TikaMemoryLimitException} rather than eagerly allocating the dictionary (which a
81+
* tiny crafted 7z can drive to multiple GiB, OOMing the parser). The default-limit control
82+
* is {@link #testEmbedded()} above, which would fail if the limit were applied in the wrong
83+
* unit (e.g. via setMaxMemoryLimitKb, which divides the argument by 1024).
84+
*/
85+
@Test
86+
public void testMemoryLimit() throws Exception {
87+
SevenZParser.Config config = new SevenZParser.Config();
88+
config.setMemoryLimitInKb(1); // 1 KiB, smaller than any real LZMA2 dictionary
89+
SevenZParser parser = new SevenZParser(config);
90+
91+
try (TikaInputStream tis = getResourceAsStream("/test-documents/test-documents.7z")) {
92+
assertThrows(TikaMemoryLimitException.class, () -> parser.parse(tis,
93+
new BodyContentHandler(), new Metadata(), new ParseContext()));
94+
}
95+
}
7496
}

tika-pipes/tika-pipes-plugins/tika-pipes-http/pom.xml

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,33 @@
156156
<goals>
157157
<goal>single</goal>
158158
</goals>
159+
</execution>
160+
</executions>
161+
</plugin>
162+
<!-- The plugin zip is built into target/ (the release artifact, like every other plugin).
163+
Copy it into target/plugins/ so the self-test can load it via PF4J
164+
(plugin-roots=target/plugins). Bound after make-assembly (process-test-resources). -->
165+
<plugin>
166+
<groupId>org.apache.maven.plugins</groupId>
167+
<artifactId>maven-resources-plugin</artifactId>
168+
<executions>
169+
<execution>
170+
<id>copy-plugin-zip-for-self-test</id>
171+
<phase>process-test-classes</phase>
172+
<goals>
173+
<goal>copy-resources</goal>
174+
</goals>
159175
<configuration>
160176
<outputDirectory>${project.build.directory}/plugins</outputDirectory>
177+
<resources>
178+
<resource>
179+
<directory>${project.build.directory}</directory>
180+
<includes>
181+
<include>${project.artifactId}-${project.version}.zip</include>
182+
</includes>
183+
<filtering>false</filtering>
184+
</resource>
185+
</resources>
161186
</configuration>
162187
</execution>
163188
</executions>
@@ -185,10 +210,6 @@
185210
deployed to Maven Central. Sibling modules declare this plugin zip
186211
as a test-scope Maven dep, so we install-file it locally to satisfy
187212
reactor resolution without making it part of the project artifacts.
188-
189-
tika-pipes-http writes its zip to target/plugins/ (not target/) so
190-
that its own self-tests can load the plugin via PF4J in deployment
191-
mode; reflect that path here.
192213
-->
193214
<execution>
194215
<id>install-plugin-zip-locally</id>
@@ -197,7 +218,7 @@
197218
<goal>install-file</goal>
198219
</goals>
199220
<configuration>
200-
<file>${project.build.directory}/plugins/${project.artifactId}-${project.version}.zip</file>
221+
<file>${project.build.directory}/${project.artifactId}-${project.version}.zip</file>
201222
<groupId>${project.groupId}</groupId>
202223
<artifactId>${project.artifactId}</artifactId>
203224
<version>${project.version}</version>

0 commit comments

Comments
 (0)