Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .github/workflows/main-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ jobs:
java-version: ${{ matrix.java }}
cache: 'maven'
- name: maven build
env:
MAVEN_EXTRA_ARGS: -Prewrite
run: ./etc/scripts/regen.sh
- name: archive logs
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-build-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ jobs:
- name: maven build
if: ${{ !inputs.skip_full_build }}
env:
MAVEN_EXTRA_ARGS: ${{ matrix.maven_extra_args || '' }}
MAVEN_EXTRA_ARGS: ${{ matrix.maven_extra_args || '' }} -Prewrite
run: ./etc/scripts/regen.sh
- name: Quick dependency build
if: ${{ inputs.skip_full_build }}
Expand Down
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,16 @@ Annotations:
add `security = "insecure:ssl"` / `"insecure:serialization"` / `"insecure:dev"` on `@UriParam`.
See [`proposals/security.adoc`](proposals/security.adoc) for categories and rationale.

Import Style:
- Do NOT use fully qualified class names (FQCNs) in Java code. Always add an `import` statement
and use the simple class name (e.g., write `List` not `java.util.List`).
- Exception: when two classes share the same simple name (e.g., `java.util.Date` and `java.sql.Date`),
import the most-used one and qualify the other.
- This applies to all code: production, test, and test-infra.
- Generated code (`src/generated/`) is excluded from this rule.
- The build automatically shortens unnecessary FQCNs via OpenRewrite (`rewrite-maven-plugin`).
CI will fail if uncommitted FQCN changes are detected after the build.

## Adding Components

### Direct child of components/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,7 @@ private static Document createDocument() throws ParserConfigurationException {
private static void createJacocoXmlFile(Document document, File file) throws TransformerException {
String xmlFilePath = file.toString() + "/xmlJacoco.xml";
TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
Transformer transformer = factory.newTransformer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ public void setConnectionFactory(ConnectionFactory connectionFactory) {

@Override
protected ConnectionFactory createConnectionFactory() {
org.apache.activemq.ActiveMQConnectionFactory answer
= new org.apache.activemq.ActiveMQConnectionFactory();
ActiveMQConnectionFactory answer
= new ActiveMQConnectionFactory();
answer.setTrustAllPackages(trustAllPackages);
if (getUsername() != null) {
answer.setUserName(getUsername());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ public void setConnectionFactory(ConnectionFactory connectionFactory) {

@Override
protected ConnectionFactory createConnectionFactory() {
org.apache.activemq.ActiveMQConnectionFactory answer
= new org.apache.activemq.ActiveMQConnectionFactory();
ActiveMQConnectionFactory answer
= new ActiveMQConnectionFactory();
answer.setTrustAllPackages(trustAllPackages);
if (getUsername() != null) {
answer.setUserName(getUsername());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import ai.docling.core.DoclingDocument;
import ai.docling.core.DoclingDocument.DocumentOrigin;
import ai.docling.serve.api.DoclingServeApi;
import ai.docling.serve.api.chunk.request.ChunkDocumentRequest;
import ai.docling.serve.api.chunk.request.HierarchicalChunkDocumentRequest;
import ai.docling.serve.api.chunk.request.HybridChunkDocumentRequest;
import ai.docling.serve.api.chunk.request.options.HierarchicalChunkerOptions;
Expand Down Expand Up @@ -618,7 +619,7 @@ private void processChunkHierarchical(Exchange exchange) throws Exception {
}

private void addSourceToChunkRequest(
ai.docling.serve.api.chunk.request.ChunkDocumentRequest.Builder requestBuilder, String inputSource)
ChunkDocumentRequest.Builder requestBuilder, String inputSource)
throws IOException {
if (inputSource.startsWith("http://") || inputSource.startsWith("https://")) {
requestBuilder.source(
Expand Down Expand Up @@ -731,7 +732,7 @@ private DocumentMetadata parseMetadataFromJson(String jsonOutput, String inputPa
if (configuration.isIncludeRawMetadata()) {
JsonNode rootNode = objectMapper.readTree(jsonOutput);
@SuppressWarnings("unchecked")
Map<String, Object> rawMap = objectMapper.convertValue(rootNode, java.util.Map.class);
Map<String, Object> rawMap = objectMapper.convertValue(rootNode, Map.class);
metadata.setRawMetadata(rawMap);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.camel.CamelExecutionException;
import org.apache.camel.builder.RouteBuilder;
Expand Down Expand Up @@ -46,7 +48,7 @@ void customArgsWithOutputFlagAreRejected() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--output", "/tmp/other-dir")));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--output", "/tmp/other-dir")));
});

assertInstanceOf(IllegalArgumentException.class, ex.getCause());
Expand All @@ -61,7 +63,7 @@ void customArgsWithOutputEqualsFormAreRejected() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--output=/tmp/other-dir")));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--output=/tmp/other-dir")));
});

assertInstanceOf(IllegalArgumentException.class, ex.getCause());
Expand All @@ -75,7 +77,7 @@ void customArgsWithShortOutputFlagAreRejected() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("-o", "/tmp/other-dir")));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("-o", "/tmp/other-dir")));
});

assertInstanceOf(IllegalArgumentException.class, ex.getCause());
Expand All @@ -89,7 +91,7 @@ void customArgsWithPathTraversalAreRejected() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--artifacts-path", "../../etc/passwd")));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--artifacts-path", "../../etc/passwd")));
});

assertInstanceOf(IllegalArgumentException.class, ex.getCause());
Expand All @@ -99,13 +101,13 @@ void customArgsWithPathTraversalAreRejected() throws Exception {
@Test
void customArgsWithNullEntryAreRejected() throws Exception {
Path inputFile = createInputFile();
List<String> argsWithNull = new java.util.ArrayList<>();
List<String> argsWithNull = new ArrayList<>();
argsWithNull.add(null);

CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, argsWithNull));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, argsWithNull));
});

assertInstanceOf(IllegalArgumentException.class, ex.getCause());
Expand All @@ -123,7 +125,7 @@ void safeCustomArgsPassValidation() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--verbose", "--table-mode", "fast")));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--verbose", "--table-mode", "fast")));
});

// The failure should be from process execution, not from argument validation
Expand Down Expand Up @@ -154,7 +156,7 @@ void customArgsWithSemicolonAreRejected() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--verbose", "; rm -rf /")));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--verbose", "; rm -rf /")));
});

assertInstanceOf(IllegalArgumentException.class, ex.getCause());
Expand All @@ -168,7 +170,7 @@ void customArgsWithPipeAreRejected() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--verbose", "| cat /etc/passwd")));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--verbose", "| cat /etc/passwd")));
});

assertInstanceOf(IllegalArgumentException.class, ex.getCause());
Expand All @@ -182,7 +184,7 @@ void customArgsWithBacktickAreRejected() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--verbose", "`whoami`")));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--verbose", "`whoami`")));
});

assertInstanceOf(IllegalArgumentException.class, ex.getCause());
Expand All @@ -196,7 +198,7 @@ void customArgsWithCommandSubstitutionAreRejected() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--verbose", "$(id)")));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--verbose", "$(id)")));
});

assertInstanceOf(IllegalArgumentException.class, ex.getCause());
Expand All @@ -212,7 +214,7 @@ void customArgsWithUnknownFlagAreRejected() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--unknown-flag")));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("--unknown-flag")));
});

assertInstanceOf(IllegalArgumentException.class, ex.getCause());
Expand All @@ -226,7 +228,7 @@ void customArgsWithUnknownShortFlagAreRejected() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("-x")));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("-x")));
});

assertInstanceOf(IllegalArgumentException.class, ex.getCause());
Expand All @@ -241,7 +243,7 @@ void customArgsWithVerbosityLevelsAreAccepted() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("-vv")));
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS, List.of("-vv")));
});

assertFalse(ex.getCause() instanceof IllegalArgumentException,
Expand All @@ -256,7 +258,7 @@ void customArgsWithNormalizedPathTraversalAreRejected() throws Exception {
CamelExecutionException ex = assertThrows(CamelExecutionException.class, () -> {
template.requestBodyAndHeaders("direct:cli-convert",
inputFile.toString(),
java.util.Map.of(DoclingHeaders.CUSTOM_ARGUMENTS,
Map.of(DoclingHeaders.CUSTOM_ARGUMENTS,
List.of("--artifacts-path", "/safe/path/subdir/../../etc/passwd")));
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.camel.CamelExecutionException;
import org.apache.camel.Exchange;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.support.SynchronizationAdapter;
import org.apache.camel.test.junit6.CamelTestSupport;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;
Expand Down Expand Up @@ -97,7 +98,7 @@ public void configure() {
// Use a Synchronization to capture directory permissions before cleanup
Exchange exchange = createExchangeWithBody("Text content for permission test");
exchange.getExchangeExtension().addOnCompletion(
new org.apache.camel.support.SynchronizationAdapter() {
new SynchronizationAdapter() {
@Override
public void onDone(Exchange exchange) {
// Check all docling dirs created during this exchange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.List;

import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.docling.BatchConversionResult;
import org.apache.camel.component.docling.BatchProcessingResults;
Expand Down Expand Up @@ -232,11 +233,11 @@ public void testBatchSplitWithSplitter() throws Exception {
getMockEndpoint("mock:individual-result").assertIsSatisfied();

// Verify each exchange contains a BatchConversionResult
List<org.apache.camel.Exchange> exchanges = getMockEndpoint("mock:individual-result").getReceivedExchanges();
List<Exchange> exchanges = getMockEndpoint("mock:individual-result").getReceivedExchanges();
assertEquals(3, exchanges.size());

for (int i = 0; i < exchanges.size(); i++) {
org.apache.camel.Exchange exchange = exchanges.get(i);
Exchange exchange = exchanges.get(i);
BatchConversionResult result = exchange.getIn().getBody(BatchConversionResult.class);

assertNotNull(result, "Exchange " + i + " should contain a BatchConversionResult");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.time.Duration;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicReference;

import ai.docling.core.DoclingDocument;
Expand Down Expand Up @@ -208,7 +209,7 @@ void testAsyncConversionWithHeaderOverride() throws Exception {
// Use sync endpoint but override with async header
String result = template.requestBodyAndHeaders("direct:convert-markdown-serve",
testFile.toString(),
new java.util.HashMap<String, Object>() {
new HashMap<String, Object>() {
{
put(DoclingHeaders.INPUT_FILE_PATH, testFile.toString());
put(DoclingHeaders.USE_ASYNC_MODE, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ void testMetadataExtractionFromPdf() throws Exception {

private Path createTestPdfFile() throws IOException {
try (InputStream is = getClass().getClassLoader().getResourceAsStream("multi_page.pdf")) {
java.nio.file.Path tempFile = Files.createTempFile("docling-test-multi_page", ".pdf");
Path tempFile = Files.createTempFile("docling-test-multi_page", ".pdf");
Files.copy(is, tempFile.toAbsolutePath(), StandardCopyOption.REPLACE_EXISTING);
return tempFile;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Collections;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;

import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.mcp.client.McpClient;
Expand Down Expand Up @@ -271,7 +272,7 @@ public static List<Class<?>> parseGuardrailClasses(String[] guardrailClassNames)
.filter(name -> !name.isEmpty())
.map(AgentConfiguration::loadGuardrailClass)
.filter(clazz -> clazz != null)
.collect(java.util.stream.Collectors.toList());
.collect(Collectors.toList());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package org.apache.camel.component.langchain4j.agent.api;

import java.io.Serializable;
import java.util.List;

import org.junit.jupiter.api.Test;
Expand All @@ -37,7 +38,7 @@ public void testParseGuardrailClasses_WithValidClasses() {
assertEquals(3, result.size());
assertTrue(result.contains(String.class));
assertTrue(result.contains(List.class));
assertTrue(result.contains(java.io.Serializable.class));
assertTrue(result.contains(Serializable.class));
}

@Test
Expand Down Expand Up @@ -99,7 +100,7 @@ public void testParseGuardrailClasses_WithExtraWhitespace() {
assertEquals(3, result.size());
assertTrue(result.contains(String.class));
assertTrue(result.contains(List.class));
assertTrue(result.contains(java.io.Serializable.class));
assertTrue(result.contains(Serializable.class));
}

@Test
Expand All @@ -113,7 +114,7 @@ public void testParseGuardrailClasses_WithEmptyClassNames() {
assertEquals(3, result.size());
assertTrue(result.contains(String.class));
assertTrue(result.contains(List.class));
assertTrue(result.contains(java.io.Serializable.class));
assertTrue(result.contains(Serializable.class));
}

@Test
Expand Down Expand Up @@ -151,7 +152,7 @@ public void testParseGuardrailClasses_WithValidClassesArray() {
assertEquals(3, result.size());
assertTrue(result.contains(String.class));
assertTrue(result.contains(List.class));
assertTrue(result.contains(java.io.Serializable.class));
assertTrue(result.contains(Serializable.class));
}

@Test
Expand Down Expand Up @@ -196,7 +197,7 @@ public void testParseGuardrailClasses_WithArrayContainingEmptyStrings() {
assertEquals(3, result.size());
assertTrue(result.contains(String.class));
assertTrue(result.contains(List.class));
assertTrue(result.contains(java.io.Serializable.class));
assertTrue(result.contains(Serializable.class));
}

// Tests for fluent methods with arrays
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
*/
package org.apache.camel.component.langchain4j.agent.api.guardrails;

import java.util.regex.Pattern;

import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.guardrail.InputGuardrailResult;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -171,7 +173,7 @@ void testBuilderCustomPattern() {
.clearPatterns()
.addPattern(
PromptInjectionGuardrail.InjectionCategory.JAILBREAK,
java.util.regex.Pattern.compile("(?i)custom\\s+attack"))
Pattern.compile("(?i)custom\\s+attack"))
.strict(true)
.build();

Expand Down
Loading
Loading