diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml deleted file mode 100644 index 4e4120d..0000000 --- a/.github/workflows/main.yaml +++ /dev/null @@ -1,83 +0,0 @@ -name: Main -permissions: - contents: write - actions: write - deployments: write - packages: write -on: - push: - branches: - - main -jobs: - build: - runs-on: ubuntu-latest - name: "Deploying" - env: - JDK_VERSION: "21" - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - java-version: ${{ env.JDK_VERSION }} - cache: "maven" - distribution: "corretto" - - - name: "Removing snapshot from version" - run: | - mvn -q build-helper:parse-version versions:set -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.incrementalVersion} versions:commit - - - name: Setup central - uses: actions/setup-java@v4 - with: - java-version: ${{ env.JDK_VERSION }} - cache: "maven" - distribution: "corretto" - server-id: central - server-username: MAVEN_USERNAME - server-password: MAVEN_TOKEN - gpg-private-key: ${{secrets.CODESIGN_PGP_KEY}} - gpg-passphrase: PASSPHRASE - - - name: "Maven deploy maven central" - run: mvn deploy --batch-mode -DskipTests --activate-profiles central --no-transfer-progress - env: - MAVEN_USERNAME: ${{secrets.MAVEN_TOKEN_USER}} - MAVEN_TOKEN: ${{secrets.MAVEN_TOKEN}} - PASSPHRASE: ${{secrets.CODESIGN_PGP_PASSPHRASE}} - - - name: Setup github packages - uses: actions/setup-java@v4 - with: - java-version: ${{ env.JDK_VERSION }} - cache: "maven" - distribution: "corretto" - - - name: "Maven deploy github packages" - run: mvn deploy --batch-mode -DskipTests --activate-profiles github --no-transfer-progress - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: "Tag release and rev version" - run: | - # tagging release: - VERSION=$(grep \ pom.xml | xargs | awk -F '[<>]' '{ print $3}') - - echo "################### using version: v$VERSION ###################" - - # tag repo - git config --global user.email "ci@uvasoftware.com" - git config --global user.name "CI" - git tag -a v"${VERSION}" -m "Release by Github Actions v${VERSION}" - git push origin v"${VERSION}" - - # bumping it to a new snapshot release: - mvn -q build-helper:parse-version versions:set -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.nextMinorVersion}.0-SNAPSHOT versions:commit - - VERSION=$(grep \ pom.xml | xargs | awk -F '[<>]' '{ print $3}') - - echo "next version is: $VERSION" - - #commit version change - git status - git commit -a -m "bump to ${VERSION} [ci skip]" - git push origin main diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..b5ff4c8 --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,78 @@ +name: PR + +on: pull_request + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + verify: + name: JDK ${{ matrix.jdk }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + jdk: [21, 25] + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.jdk }} + distribution: corretto + cache: maven + - name: Download scanii-cli + shell: bash + run: | + set -euo pipefail + # Resolve latest version + VERSION=$(curl -fsSL -H "Authorization: Bearer ${{ github.token }}" \ + https://api.github.com/repos/scanii/scanii-cli/releases/latest \ + | grep '"tag_name":' | sed -E 's/.*"v?([^"]+)".*/\1/') + echo "scanii-cli version: $VERSION" + + # Map runner to GoReleaser's OS/arch naming + case "${{ runner.os }}" in + Linux) OS=linux ; EXT=tar.gz ;; + macOS) OS=darwin ; EXT=tar.gz ;; + Windows) OS=windows; EXT=zip ;; + esac + case "$(uname -m)" in + x86_64|amd64) ARCH=amd64 ;; + arm64|aarch64) ARCH=arm64 ;; + *) ARCH=amd64 ;; + esac + + ASSET="scanii-cli-${VERSION}-${OS}-${ARCH}.${EXT}" + URL="https://github.com/scanii/scanii-cli/releases/download/v${VERSION}/${ASSET}" + echo "downloading $URL" + curl -fsSL "$URL" -o "$ASSET" + + # Unpack + if [ "$EXT" = "tar.gz" ]; then + tar -xzf "$ASSET" + else + unzip -q "$ASSET" + fi + + # Binary is inside a subdirectory due to wrap_in_directory: true + BINEXT="" + [ "$OS" = "windows" ] && BINEXT=".exe" + cp "scanii-cli-${VERSION}-${OS}-${ARCH}/sc${BINEXT}" "./sc${BINEXT}" + chmod +x ./sc 2>/dev/null || true + + - name: Start scanii-cli server + shell: bash + run: | + EXT="" + [ "${{ runner.os }}" = "Windows" ] && EXT=".exe" + ./sc${EXT} server & + # wait for the server to be ready + for i in $(seq 1 15); do + curl -sf http://localhost:4000/v2.2/ping && break || sleep 1 + done + + - name: mvn verify + run: mvn -B verify diff --git a/.github/workflows/pull-request.yaml b/.github/workflows/pull-request.yaml deleted file mode 100644 index 2bbe2d2..0000000 --- a/.github/workflows/pull-request.yaml +++ /dev/null @@ -1,24 +0,0 @@ -on: pull_request -name: Pull Requests -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - build: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ ubuntu-latest, windows-latest, macos-latest ] - jdk: [ 11, 17, 21, 25 ] - name: JDK ${{ matrix.jdk }} on ${{ matrix.os }}. - steps: - - uses: actions/checkout@v5 - - uses: actions/setup-java@v5 - with: - java-version: ${{ matrix.jdk }} - cache: "maven" - distribution: "corretto" - - run: mvn -B clean package - env: - SCANII_CREDS: ${{ secrets.SCANII_CREDS }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e857aaf --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,54 @@ +name: Release + +on: + push: + tags: + - 'v*.*.*' + +permissions: + contents: write + +jobs: + release: + name: Release to Maven Central + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Java for signing and publishing + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: corretto + cache: maven + server-id: central + server-username: MAVEN_USERNAME + server-password: MAVEN_TOKEN + gpg-private-key: ${{ secrets.CODESIGN_PGP_KEY }} + gpg-passphrase: PASSPHRASE + + - name: Strip snapshot from version + run: | + mvn -q build-helper:parse-version versions:set \ + -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.incrementalVersion} \ + versions:commit + + - name: Publish to Maven Central + run: mvn deploy --batch-mode -DskipTests --activate-profiles central --no-transfer-progress + env: + MAVEN_USERNAME: ${{ secrets.MAVEN_TOKEN_USER }} + MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }} + PASSPHRASE: ${{ secrets.CODESIGN_PGP_PASSPHRASE }} + + - name: Create GitHub Release + uses: actions/github-script@v7 + with: + script: | + const tag = context.ref.replace('refs/tags/', ''); + await github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: tag, + name: tag, + generate_release_notes: true, + }); diff --git a/.gitignore b/.gitignore index c93f80e..2c1f3ce 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,6 @@ .idea target *.iml +.claude release.properties pom.xml.releaseBackup diff --git a/.run/Run Tests.run.xml b/.run/Run Tests.run.xml deleted file mode 100644 index f13976e..0000000 --- a/.run/Run Tests.run.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a040480 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,44 @@ +# Changelog + +## [8.0.0] — 2026-04-23 + +### Breaking changes + +- **groupId renamed:** `com.uvasoftware` → `com.scanii` +- **Package renamed:** `com.uvasoftware.scanii` → `com.scanii` +- **Java minimum version raised:** Java 11 → Java 21 LTS + +### Changes + +- Rebranded to `com.scanii:scanii-java` +- Java source and target updated to 21 +- Integration tests now run against [scanii-cli](https://github.com/scanii/scanii-cli) — no real credentials required +- CI matrix: Java 21 and 25 across Ubuntu, macOS, and Windows +- JUnit 5.12.2 + +### Migration + +Update your Maven dependency: + +```xml + + + com.uvasoftware + scanii-java + 7.x.x + + + + + com.scanii + scanii-java + 8.0.0 + +``` + +Then update your imports: +``` +import com.uvasoftware.scanii.* → import com.scanii.* +``` + +The old `com.uvasoftware:scanii-java` coordinates are deprecated. See the migration guide at https://github.com/scanii/scanii-java. diff --git a/README.md b/README.md index 000ad92..7f72376 100644 --- a/README.md +++ b/README.md @@ -1,48 +1,69 @@ -### A pure Java interface to the Scanii content processing service - https://www.scanii.com +# scanii-java -### How to use this client +Official Java SDK for the [Scanii](https://www.scanii.com) content processing API. -#### Installing using Maven coordinates: +## SDK Principles -```xml +1. **Light.** Zero runtime dependencies, stdlib only. +2. **Up to date.** Always current with the latest Scanii API. +3. **Integration-only.** Wraps the REST API — retries, concurrency, and batching are the caller's responsibility. + +## Install +```xml - com.uvasoftware + com.scanii scanii-java - ${latest.release.version} + 8.0.0 ``` -### Sample usage: +## Quickstart ```java -package com.uvasoftware.scanii; +import com.scanii.ScaniiClient; +import com.scanii.ScaniiClients; +import com.scanii.models.ScaniiProcessingResult; +import java.nio.file.Paths; -import com.uvasoftware.scanii.models.ScaniiProcessingResult; +ScaniiClient client = ScaniiClients.createDefault("your-api-key", "your-api-secret"); +ScaniiProcessingResult result = client.process(Paths.get("/path/to/file")); +System.out.printf("findings: %s%n", result.getFindings()); +``` -import java.nio.file.Paths; +## Regional endpoints + +| Constant | Endpoint | +|---|---| +| `ScaniiTarget.AUTO` | `https://api.scanii.com` | +| `ScaniiTarget.US1` | `https://api-us1.scanii.com` | +| `ScaniiTarget.EU1` | `https://api-eu1.scanii.com` | +| `ScaniiTarget.EU2` | `https://api-eu2.scanii.com` | +| `ScaniiTarget.AP1` | `https://api-ap1.scanii.com` | +| `ScaniiTarget.AP2` | `https://api-ap2.scanii.com` | +| `ScaniiTarget.CA1` | `https://api-ca1.scanii.com` | + +## Local development with scanii-cli + +Run integration tests against a local mock server — no real credentials needed: + +```bash +docker run -d --name scanii-cli -p 4000:4000 ghcr.io/scanii/scanii-cli:latest server +mvn verify +``` + +Test credentials: key `key`, secret `secret`, endpoint `http://localhost:4000`. + +## Migration from com.uvasoftware:scanii-java + +Replace the Maven coordinates and rename imports: -public class Sample { - public static void main(String[] args) { - // in this example args contains the key secret and file path: - String key = args[0]; - String secret = args[1]; - ScaniiClient client = ScaniiClients.createDefault(key, secret); - ScaniiProcessingResult result = client.process(Paths.get(args[2])); - System.out.printf("checksum: %s, content-type: %s and findings: %s%n", - result.getChecksum(), - result.getContentType(), - result.getFindings()); - if (result.getFindings().isEmpty()) { - System.out.println("Content is safe!"); - } - } -} ``` +com.uvasoftware.scanii → com.scanii +``` + +The old artifact `com.uvasoftware:scanii-java` is deprecated and will not receive further updates. -Please note that you will need a valid scanii.com account and API Credentials. +## License -* More advanced usage examples can be - found [here](https://github.com/uvasoftware/scanii-java/blob/master/src/test/java/com/uvasoftware/scanii/ScaniiClientTest.java) -* General documentation on scanii can be found [here](http://docs.scanii.com) -* Javadocs can be found [here](https://www.javadoc.io/doc/com.uvasoftware/scanii-java/latest/index.html) +Apache 2.0 — see [LICENSE](LICENSE). diff --git a/pom.xml b/pom.xml index 555b4ab..567fb17 100644 --- a/pom.xml +++ b/pom.xml @@ -2,24 +2,24 @@ 4.0.0 - com.uvasoftware + com.scanii scanii-java - 7.4.0-SNAPSHOT + 8.0.0-SNAPSHOT jar Scanii.com Java SDK scanii-java - https://github.com/uvasoftware/scanii-java + https://github.com/scanii/scanii-java - Uva Software + Scanii https://www.scanii.com UTF-8 UTF-8 - 11 - 11 + 21 + 21 @@ -29,17 +29,17 @@ - scm:git:git@github.com:uvasoftware/scanii-java.git - scm:git:git@github.com:uvasoftware/scanii-java.git - https://github.com/uvasoftware/scanii-java/tree/main + scm:git:git@github.com:scanii/scanii-java.git + scm:git:git@github.com:scanii/scanii-java.git + https://github.com/scanii/scanii-java/tree/main - Uva Software engineers - ping@uvasoftware.com - Uva Software, LLC - https://www.uvasoftware.com + Scanii engineers + hi@scanii.com + Scanii + https://www.scanii.com @@ -58,7 +58,7 @@ true - com.uvasoftware + com.scanii true @@ -149,7 +149,7 @@ 3.6.3 false - 11 + 21 -Xdoclint:none @@ -189,53 +189,5 @@ - - github - - - github - GitHub Packages - https://maven.pkg.github.com/uvasoftware/scanii-java - - - - - - org.apache.maven.plugins - maven-source-plugin - 3.3.0 - - - attach-sources - package - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.6.3 - - false - 11 - - -Xdoclint:none - - - - - attach-javadocs - - jar - - - - - - - diff --git a/src/main/java/com/uvasoftware/scanii/ScaniiClient.java b/src/main/java/com/scanii/ScaniiClient.java similarity index 67% rename from src/main/java/com/uvasoftware/scanii/ScaniiClient.java rename to src/main/java/com/scanii/ScaniiClient.java index 5dbb542..0bbe663 100644 --- a/src/main/java/com/uvasoftware/scanii/ScaniiClient.java +++ b/src/main/java/com/scanii/ScaniiClient.java @@ -1,9 +1,9 @@ -package com.uvasoftware.scanii; +package com.scanii; -import com.uvasoftware.scanii.models.ScaniiAccountInfo; -import com.uvasoftware.scanii.models.ScaniiAuthToken; -import com.uvasoftware.scanii.models.ScaniiPendingResult; -import com.uvasoftware.scanii.models.ScaniiProcessingResult; +import com.scanii.models.ScaniiAccountInfo; +import com.scanii.models.ScaniiAuthToken; +import com.scanii.models.ScaniiPendingResult; +import com.scanii.models.ScaniiProcessingResult; import java.io.InputStream; import java.nio.file.Path; @@ -14,7 +14,7 @@ public interface ScaniiClient { /** - * Submits a file to be processed @see http://docs.scanii.com/v2.1/resources.html#files + * Submits a file to be processed @see https://docs.scanii.com/v2.2/resources.html#files * * @param content path to the file to be processed * @param metadata optional metadata to be added to this file @@ -23,7 +23,7 @@ public interface ScaniiClient { ScaniiProcessingResult process(Path content, Map metadata); /** - * Submits a file stream to be processed @see http://docs.scanii.com/v2.1/resources.html#files + * Submits a file stream to be processed @see https://docs.scanii.com/v2.2/resources.html#files * * @param content stream of the file to be processed * @param metadata optional metadata to be added to this file @@ -32,7 +32,7 @@ public interface ScaniiClient { ScaniiProcessingResult process(InputStream content, Map metadata); /** - * Submits a file to be processed @see http://docs.scanii.com/v2.1/resources.html#files with optional callback. + * Submits a file to be processed @see https://docs.scanii.com/v2.2/resources.html#files with optional callback. * * @param content path to the file to be processed * @param callback location (URL) to be notified and receive the result @@ -43,7 +43,7 @@ public interface ScaniiClient { /** - * Submits a file stream to be processed @see http://docs.scanii.com/v2.1/resources.html#files with optional callback. + * Submits a file stream to be processed @see https://docs.scanii.com/v2.2/resources.html#files with optional callback. * * @param content file content to be processed * @param callback location (URL) to be notified and receive the result @@ -53,7 +53,7 @@ public interface ScaniiClient { ScaniiProcessingResult process(InputStream content, String callback, Map metadata); /** - * Submits a file to be processed @see http://docs.scanii.com/v2.1/resources.html#files + * Submits a file to be processed @see https://docs.scanii.com/v2.2/resources.html#files * * @param content path to the file to be processed * @return scanii result {@link ScaniiProcessingResult} @@ -61,7 +61,7 @@ public interface ScaniiClient { ScaniiProcessingResult process(Path content); /** - * Submits a file stream to be processed @see http://docs.scanii.com/v2.1/resources.html#files + * Submits a file stream to be processed @see https://docs.scanii.com/v2.2/resources.html#files * * @param content stream of the file to be processed * @return scanii result {@link ScaniiProcessingResult} @@ -69,7 +69,7 @@ public interface ScaniiClient { ScaniiProcessingResult process(InputStream content); /** - * Submits a file to be processed asynchronously @see http://docs.scanii.com/v2.1/resources.html#files + * Submits a file to be processed asynchronously @see https://docs.scanii.com/v2.2/resources.html#files * * @param content path to the file to be processed * @param metadata optional metadata to be added to this file @@ -78,7 +78,7 @@ public interface ScaniiClient { ScaniiPendingResult processAsync(Path content, Map metadata); /** - * Submits a file stream to be processed asynchronously @see http://docs.scanii.com/v2.1/resources.html#files + * Submits a file stream to be processed asynchronously @see https://docs.scanii.com/v2.2/resources.html#files * * @param content stream of the file to be processed * @param metadata optional metadata to be added to this file @@ -87,7 +87,7 @@ public interface ScaniiClient { ScaniiPendingResult processAsync(InputStream content, Map metadata); /** - * Submits a file to be processed asynchronously @see http://docs.scanii.com/v2.1/resources.html#files + * Submits a file to be processed asynchronously @see https://docs.scanii.com/v2.2/resources.html#files * * @param content path to the file to be processed * @param callback location (URL) to be notified and receive the result @@ -97,7 +97,7 @@ public interface ScaniiClient { ScaniiPendingResult processAsync(Path content, String callback, Map metadata); /** - * Submits a file stream to be processed @see http://docs.scanii.com/v2.1/resources.html#files with optional callback. + * Submits a file stream to be processed @see https://docs.scanii.com/v2.2/resources.html#files with optional callback. * * @param content file content to be processed * @param callback location (URL) to be notified and receive the result @@ -107,7 +107,7 @@ public interface ScaniiClient { ScaniiPendingResult processAsync(InputStream content, String callback, Map metadata); /** - * Submits a file to be processed asynchronously @see http://docs.scanii.com/v2.1/resources.html#files + * Submits a file to be processed asynchronously @see https://docs.scanii.com/v2.2/resources.html#files * * @param content path to the file to be processed * @return processing result {@link ScaniiPendingResult} @@ -115,7 +115,7 @@ public interface ScaniiClient { ScaniiPendingResult processAsync(Path content); /** - * Submits a file content stream to be processed asynchronously @see http://docs.scanii.com/v2.1/resources.html#files + * Submits a file content stream to be processed asynchronously @see https://docs.scanii.com/v2.2/resources.html#files * * @param content stream of the file to be processed * @return processing result {@link ScaniiPendingResult} @@ -123,7 +123,7 @@ public interface ScaniiClient { ScaniiPendingResult processAsync(InputStream content); /** - * Fetches the results of a previously processed file @see http://docs.scanii.com/v2.1/resources.html#files + * Fetches the results of a previously processed file @see https://docs.scanii.com/v2.2/resources.html#files * * @param id id of the content/file to be retrieved * @return optional {@link ScaniiProcessingResult} @@ -131,7 +131,7 @@ public interface ScaniiClient { Optional retrieve(String id); /** - * Makes a fetch call to scanii @see http://docs.scanii.com/v2.1/resources.html#files + * Makes a fetch call to scanii @see https://docs.scanii.com/v2.2/resources.html#files * * @param location location (URL) of the content to be processed * @return scanii result {@link ScaniiPendingResult} @@ -139,7 +139,7 @@ public interface ScaniiClient { ScaniiPendingResult fetch(String location); /** - * Makes a fetch call to scanii @see http://docs.scanii.com/v2.1/resources.html#files + * Makes a fetch call to scanii @see https://docs.scanii.com/v2.2/resources.html#files * * @param location location (URL) of the content to be processed * @param callback location (URL) to be notified and receive the result @@ -148,7 +148,7 @@ public interface ScaniiClient { ScaniiPendingResult fetch(String location, String callback); /** - * Makes a fetch call to scanii @see http://docs.scanii.com/v2.1/resources.html#files + * Makes a fetch call to scanii @see https://docs.scanii.com/v2.2/resources.html#files * * @param location location (URL) of the content to be processed * @param callback location (URL) to be notified and receive the result @@ -158,14 +158,14 @@ public interface ScaniiClient { ScaniiPendingResult fetch(String location, String callback, Map metadata); /** - * Pings the scanii service using the credentials provided @see http://docs.scanii.com/v2.1/resources.html#ping + * Pings the scanii service using the credentials provided @see https://docs.scanii.com/v2.2/resources.html#ping * * @return true if we saw a pong back from scanii, false otherwise */ boolean ping(); /** - * Creates a new temporary authentication token @see http://docs.scanii.com/v2.1/resources.html#auth-tokens + * Creates a new temporary authentication token @see https://docs.scanii.com/v2.2/resources.html#auth-tokens * * @param timeout how long the token should be valid for" * @param timeoutUnit unit used to calculate the timeout @@ -189,7 +189,7 @@ public interface ScaniiClient { ScaniiAuthToken retrieveAuthToken(String id); /** - * Retrieves account information @see https://docs.scanii.com/v2.1/resources.html#account + * Retrieves account information @see https://docs.scanii.com/v2.2/resources.html#account * * @return your account information */ diff --git a/src/main/java/com/uvasoftware/scanii/ScaniiClientBuilder.java b/src/main/java/com/scanii/ScaniiClientBuilder.java similarity index 95% rename from src/main/java/com/uvasoftware/scanii/ScaniiClientBuilder.java rename to src/main/java/com/scanii/ScaniiClientBuilder.java index 0913ca3..7d80f9f 100644 --- a/src/main/java/com/uvasoftware/scanii/ScaniiClientBuilder.java +++ b/src/main/java/com/scanii/ScaniiClientBuilder.java @@ -1,7 +1,7 @@ -package com.uvasoftware.scanii; +package com.scanii; -import com.uvasoftware.scanii.internal.DefaultScaniiClient; -import com.uvasoftware.scanii.models.ScaniiAuthToken; +import com.scanii.internal.DefaultScaniiClient; +import com.scanii.models.ScaniiAuthToken; import java.net.http.HttpClient; import java.util.Collections; diff --git a/src/main/java/com/uvasoftware/scanii/ScaniiClients.java b/src/main/java/com/scanii/ScaniiClients.java similarity index 97% rename from src/main/java/com/uvasoftware/scanii/ScaniiClients.java rename to src/main/java/com/scanii/ScaniiClients.java index 3daf968..328f886 100644 --- a/src/main/java/com/uvasoftware/scanii/ScaniiClients.java +++ b/src/main/java/com/scanii/ScaniiClients.java @@ -1,6 +1,6 @@ -package com.uvasoftware.scanii; +package com.scanii; -import com.uvasoftware.scanii.models.ScaniiAuthToken; +import com.scanii.models.ScaniiAuthToken; import java.net.http.HttpClient; diff --git a/src/main/java/com/uvasoftware/scanii/ScaniiException.java b/src/main/java/com/scanii/ScaniiException.java similarity index 91% rename from src/main/java/com/uvasoftware/scanii/ScaniiException.java rename to src/main/java/com/scanii/ScaniiException.java index 12cc626..dd40ac7 100644 --- a/src/main/java/com/uvasoftware/scanii/ScaniiException.java +++ b/src/main/java/com/scanii/ScaniiException.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii; +package com.scanii; /** * Unchecked exception wrapper. diff --git a/src/main/java/com/uvasoftware/scanii/ScaniiTarget.java b/src/main/java/com/scanii/ScaniiTarget.java similarity index 97% rename from src/main/java/com/uvasoftware/scanii/ScaniiTarget.java rename to src/main/java/com/scanii/ScaniiTarget.java index c48acb7..841cb5e 100644 --- a/src/main/java/com/uvasoftware/scanii/ScaniiTarget.java +++ b/src/main/java/com/scanii/ScaniiTarget.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii; +package com.scanii; import java.net.URI; import java.util.List; diff --git a/src/main/java/com/uvasoftware/scanii/internal/DefaultScaniiClient.java b/src/main/java/com/scanii/internal/DefaultScaniiClient.java similarity index 97% rename from src/main/java/com/uvasoftware/scanii/internal/DefaultScaniiClient.java rename to src/main/java/com/scanii/internal/DefaultScaniiClient.java index 33c13f2..ef48943 100644 --- a/src/main/java/com/uvasoftware/scanii/internal/DefaultScaniiClient.java +++ b/src/main/java/com/scanii/internal/DefaultScaniiClient.java @@ -1,10 +1,10 @@ -package com.uvasoftware.scanii.internal; +package com.scanii.internal; -import com.uvasoftware.scanii.ScaniiClient; -import com.uvasoftware.scanii.ScaniiClients; -import com.uvasoftware.scanii.ScaniiException; -import com.uvasoftware.scanii.ScaniiTarget; -import com.uvasoftware.scanii.models.*; +import com.scanii.ScaniiClient; +import com.scanii.ScaniiClients; +import com.scanii.ScaniiException; +import com.scanii.ScaniiTarget; +import com.scanii.models.*; import java.io.IOException; import java.io.InputStream; import java.net.URI; @@ -23,7 +23,7 @@ * Thread safe client to the Scanii content processing service. * Please note that this client does not throw checked exceptions; all exceptions are wrapped around a ScaniiException that extends RuntimeException * - * @see spec + * @see spec */ public class DefaultScaniiClient implements ScaniiClient { private static final System.Logger LOG = System.getLogger(DefaultScaniiClient.class.getName()); @@ -258,7 +258,7 @@ public ScaniiAuthToken createAuthToken(int timeout, TimeUnit timeoutUnit) { HttpResponse response = send(req); - if (response.statusCode() != 201) { + if (response.statusCode() != 201 && response.statusCode() != 200) { parseAndThrowError(response); } diff --git a/src/main/java/com/uvasoftware/scanii/internal/HttpHeaders.java b/src/main/java/com/scanii/internal/HttpHeaders.java similarity index 91% rename from src/main/java/com/uvasoftware/scanii/internal/HttpHeaders.java rename to src/main/java/com/scanii/internal/HttpHeaders.java index 921c89d..abcbaf9 100644 --- a/src/main/java/com/uvasoftware/scanii/internal/HttpHeaders.java +++ b/src/main/java/com/scanii/internal/HttpHeaders.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii.internal; +package com.scanii.internal; class HttpHeaders { public static final String LOCATION = "Location"; diff --git a/src/main/java/com/uvasoftware/scanii/internal/JSON.java b/src/main/java/com/scanii/internal/JSON.java similarity index 97% rename from src/main/java/com/uvasoftware/scanii/internal/JSON.java rename to src/main/java/com/scanii/internal/JSON.java index 1153413..d817e9b 100644 --- a/src/main/java/com/uvasoftware/scanii/internal/JSON.java +++ b/src/main/java/com/scanii/internal/JSON.java @@ -1,9 +1,9 @@ -package com.uvasoftware.scanii.internal; +package com.scanii.internal; -import com.uvasoftware.scanii.models.ScaniiAccountInfo; -import com.uvasoftware.scanii.models.ScaniiAuthToken; -import com.uvasoftware.scanii.models.ScaniiPendingResult; -import com.uvasoftware.scanii.models.ScaniiProcessingResult; +import com.scanii.models.ScaniiAccountInfo; +import com.scanii.models.ScaniiAuthToken; +import com.scanii.models.ScaniiPendingResult; +import com.scanii.models.ScaniiProcessingResult; import java.time.Instant; import java.util.*; diff --git a/src/main/java/com/uvasoftware/scanii/internal/MultipartBodyPublisher.java b/src/main/java/com/scanii/internal/MultipartBodyPublisher.java similarity index 98% rename from src/main/java/com/uvasoftware/scanii/internal/MultipartBodyPublisher.java rename to src/main/java/com/scanii/internal/MultipartBodyPublisher.java index f13cbcb..c39b337 100644 --- a/src/main/java/com/uvasoftware/scanii/internal/MultipartBodyPublisher.java +++ b/src/main/java/com/scanii/internal/MultipartBodyPublisher.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii.internal; +package com.scanii.internal; import java.io.ByteArrayInputStream; import java.io.IOException; diff --git a/src/main/java/com/uvasoftware/scanii/models/ScaniiAccountInfo.java b/src/main/java/com/scanii/models/ScaniiAccountInfo.java similarity index 98% rename from src/main/java/com/uvasoftware/scanii/models/ScaniiAccountInfo.java rename to src/main/java/com/scanii/models/ScaniiAccountInfo.java index 54dc9ed..b1c1980 100644 --- a/src/main/java/com/uvasoftware/scanii/models/ScaniiAccountInfo.java +++ b/src/main/java/com/scanii/models/ScaniiAccountInfo.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii.models; +package com.scanii.models; import java.time.Instant; import java.util.Map; diff --git a/src/main/java/com/uvasoftware/scanii/models/ScaniiAuthToken.java b/src/main/java/com/scanii/models/ScaniiAuthToken.java similarity index 95% rename from src/main/java/com/uvasoftware/scanii/models/ScaniiAuthToken.java rename to src/main/java/com/scanii/models/ScaniiAuthToken.java index 31aa54c..053a287 100644 --- a/src/main/java/com/uvasoftware/scanii/models/ScaniiAuthToken.java +++ b/src/main/java/com/scanii/models/ScaniiAuthToken.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii.models; +package com.scanii.models; import java.time.Instant; diff --git a/src/main/java/com/uvasoftware/scanii/models/ScaniiPendingResult.java b/src/main/java/com/scanii/models/ScaniiPendingResult.java similarity index 90% rename from src/main/java/com/uvasoftware/scanii/models/ScaniiPendingResult.java rename to src/main/java/com/scanii/models/ScaniiPendingResult.java index 72c23e1..7e893f0 100644 --- a/src/main/java/com/uvasoftware/scanii/models/ScaniiPendingResult.java +++ b/src/main/java/com/scanii/models/ScaniiPendingResult.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii.models; +package com.scanii.models; public class ScaniiPendingResult extends ScaniiResult { private String resourceId; diff --git a/src/main/java/com/uvasoftware/scanii/models/ScaniiProcessingResult.java b/src/main/java/com/scanii/models/ScaniiProcessingResult.java similarity index 98% rename from src/main/java/com/uvasoftware/scanii/models/ScaniiProcessingResult.java rename to src/main/java/com/scanii/models/ScaniiProcessingResult.java index dbbcfd9..ba7ad7c 100644 --- a/src/main/java/com/uvasoftware/scanii/models/ScaniiProcessingResult.java +++ b/src/main/java/com/scanii/models/ScaniiProcessingResult.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii.models; +package com.scanii.models; import java.time.Instant; import java.util.ArrayList; diff --git a/src/main/java/com/uvasoftware/scanii/models/ScaniiResult.java b/src/main/java/com/scanii/models/ScaniiResult.java similarity index 95% rename from src/main/java/com/uvasoftware/scanii/models/ScaniiResult.java rename to src/main/java/com/scanii/models/ScaniiResult.java index f10b71c..0ce4e35 100644 --- a/src/main/java/com/uvasoftware/scanii/models/ScaniiResult.java +++ b/src/main/java/com/scanii/models/ScaniiResult.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii.models; +package com.scanii.models; public class ScaniiResult { private String rawResponse; diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 1c2de9e..6f7d322 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -1,6 +1,6 @@ -module com.uvasoftware.scanii { +module com.scanii { requires java.net.http; - exports com.uvasoftware.scanii; - exports com.uvasoftware.scanii.models; + exports com.scanii; + exports com.scanii.models; } diff --git a/src/test/java/com/uvasoftware/scanii/IntegrationTest.java b/src/test/java/com/scanii/IntegrationTest.java similarity index 95% rename from src/test/java/com/uvasoftware/scanii/IntegrationTest.java rename to src/test/java/com/scanii/IntegrationTest.java index b7554d5..1ce7d9f 100644 --- a/src/test/java/com/uvasoftware/scanii/IntegrationTest.java +++ b/src/test/java/com/scanii/IntegrationTest.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii; +package com.scanii; import java.time.Duration; import java.time.Instant; diff --git a/src/test/java/com/uvasoftware/scanii/Sample.java b/src/test/java/com/scanii/Sample.java similarity index 86% rename from src/test/java/com/uvasoftware/scanii/Sample.java rename to src/test/java/com/scanii/Sample.java index 456d037..75b9e51 100644 --- a/src/test/java/com/uvasoftware/scanii/Sample.java +++ b/src/test/java/com/scanii/Sample.java @@ -1,6 +1,6 @@ -package com.uvasoftware.scanii; +package com.scanii; -import com.uvasoftware.scanii.models.ScaniiProcessingResult; +import com.scanii.models.ScaniiProcessingResult; import java.nio.file.Path; diff --git a/src/test/java/com/uvasoftware/scanii/ScaniiClientBuilderTest.java b/src/test/java/com/scanii/ScaniiClientBuilderTest.java similarity index 96% rename from src/test/java/com/uvasoftware/scanii/ScaniiClientBuilderTest.java rename to src/test/java/com/scanii/ScaniiClientBuilderTest.java index 61b65bf..9501578 100644 --- a/src/test/java/com/uvasoftware/scanii/ScaniiClientBuilderTest.java +++ b/src/test/java/com/scanii/ScaniiClientBuilderTest.java @@ -1,7 +1,7 @@ -package com.uvasoftware.scanii; +package com.scanii; -import com.uvasoftware.scanii.internal.DefaultScaniiClient; -import com.uvasoftware.scanii.models.ScaniiAuthToken; +import com.scanii.internal.DefaultScaniiClient; +import com.scanii.models.ScaniiAuthToken; import org.junit.jupiter.api.Test; import java.net.http.HttpClient; diff --git a/src/test/java/com/scanii/ScaniiClientTest.java b/src/test/java/com/scanii/ScaniiClientTest.java new file mode 100644 index 0000000..f4d9af5 --- /dev/null +++ b/src/test/java/com/scanii/ScaniiClientTest.java @@ -0,0 +1,192 @@ +package com.scanii; + +import com.scanii.misc.EICAR; +import com.scanii.misc.Systems; +import com.scanii.models.ScaniiAuthToken; +import com.scanii.models.ScaniiPendingResult; +import com.scanii.models.ScaniiProcessingResult; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.nio.file.Files; +import java.time.Duration; +import java.util.HashMap; +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Integration tests against a locally-running scanii-cli mock server. + * + * Start the server before running: + * docker run -d --name scanii-cli -p 4000:4000 ghcr.io/scanii/scanii-cli:latest server + * + * Endpoint: http://localhost:4000 Key: key Secret: secret + */ +class ScaniiClientTest extends IntegrationTest { + private static final String ENDPOINT = System.getenv().getOrDefault("SCANII_ENDPOINT", "http://localhost:4000"); + private static final String KEY = "key"; + private static final String SECRET = "secret"; + + private ScaniiClient client; + + @BeforeEach + void before() { + client = ScaniiClients.createDefault(new ScaniiTarget(ENDPOINT), KEY, SECRET); + } + + @Test + void testProcess() throws Exception { + // clean file — no findings + ScaniiProcessingResult result = client.process(Systems.randomFile(1024)); + assertNotNull(result.getResourceId()); + assertNotNull(result.getChecksum()); + assertNotNull(result.getResourceLocation()); + assertNotNull(result.getRawResponse()); + assertNotNull(result.getRequestId()); + assertNotNull(result.getContentType()); + assertNotNull(result.getHostId()); + assertNotNull(result.getFindings()); + assertTrue(result.getFindings().isEmpty()); + + // EICAR — should trigger finding (decoded in-memory, never written to disk) + result = client.process(new ByteArrayInputStream(EICAR.decode())); + assertNotNull(result.getResourceId()); + assertNotNull(result.getFindings()); + assertEquals(1, result.getFindings().size()); + assertEquals("content.malicious.eicar-test-signature", result.getFindings().get(0)); + } + + @Test + void testProcessWithMetadata() throws Exception { + ScaniiProcessingResult result = client.process(Systems.randomFile(1024), new HashMap<>() {{ + put("foo", "bar"); + }}); + assertNotNull(result.getResourceId()); + assertEquals("bar", result.getMetadata().get("foo")); + } + + @Test + void testProcessInputStreamWithMetadata() throws Exception { + FileInputStream is = new FileInputStream(Systems.randomFile(1024).toFile()); + ScaniiProcessingResult result = client.process(is, new HashMap<>() {{ + put("foo", "bar"); + }}); + assertNotNull(result.getResourceId()); + assertEquals("bar", result.getMetadata().get("foo")); + } + + @Test + void shouldThrowErrorsIfInvalidPost() throws Exception { + assertThrows(ScaniiException.class, () -> client.process(Files.createTempFile(null, null))); + } + + @Test + void shouldThrowErrorsIfInvalidCredentials() { + ScaniiClient badClient = ScaniiClients.createDefault(new ScaniiTarget(ENDPOINT), "bad-key", "bad-secret"); + assertThrows(ScaniiException.class, () -> badClient.process(Systems.randomFile(1024))); + } + + @Test + void testProcessAsync() throws Exception { + ScaniiPendingResult result = client.processAsync(Systems.randomFile(1024)); + assertNotNull(result.getResourceId()); + assertNotNull(result.getResourceLocation()); + assertNotNull(result.getRawResponse()); + assertNotNull(result.getRequestId()); + assertNotNull(result.getHostId()); + + ScaniiProcessingResult actualResult = pollForResult( + () -> client.retrieve(result.getResourceId()).orElse(null), + Duration.ofMinutes(1)); + assertNotNull(actualResult.getResourceId()); + assertNotNull(actualResult.getChecksum()); + assertNull(actualResult.getResourceLocation()); + assertNotNull(actualResult.getRawResponse()); + assertNotNull(actualResult.getRequestId()); + assertNotNull(actualResult.getContentType()); + assertNotNull(actualResult.getHostId()); + assertNotNull(actualResult.getFindings()); + assertTrue(actualResult.getFindings().isEmpty()); + } + + @Test + void testProcessAsyncWithMetadata() throws Exception { + ScaniiPendingResult result = client.processAsync(Systems.randomFile(1024), new HashMap<>() {{ + put("foo", "bar"); + }}); + ScaniiProcessingResult actualResult = pollForResult( + () -> client.retrieve(result.getResourceId()).orElse(null), + Duration.ofMinutes(1)); + assertNotNull(actualResult.getResourceId()); + assertEquals("bar", actualResult.getMetadata().get("foo")); + } + + @Test + void testProcessAsyncInputStreamWithMetadata() throws Exception { + FileInputStream is = new FileInputStream(Systems.randomFile(1024).toFile()); + ScaniiPendingResult result = client.processAsync(is, new HashMap<>() {{ + put("foo", "bar"); + }}); + ScaniiProcessingResult actualResult = pollForResult( + () -> client.retrieve(result.getResourceId()).orElse(null), + Duration.ofMinutes(1)); + assertNotNull(actualResult.getResourceId()); + assertEquals("bar", actualResult.getMetadata().get("foo")); + } + + @Test + void testFetchWithoutCallback() throws InterruptedException { + // scanii-cli fetch endpoint: accepts any location URL + ScaniiPendingResult result = client.fetch("https://scanii.s3.amazonaws.com/eicarcom2.zip"); + assertNotNull(result.getResourceId()); + assertNotNull(result.getResourceLocation()); + assertNotNull(result.getRawResponse()); + assertNotNull(result.getRequestId()); + assertNotNull(result.getHostId()); + + ScaniiProcessingResult actualResult = pollForResult( + () -> client.retrieve(result.getResourceId()).orElse(null), + Duration.ofMinutes(1)); + assertNotNull(actualResult.getResourceId()); + } + + @Test + void testPing() { + assertTrue(client.ping()); + } + + @Test + void testCreateAuthToken() { + ScaniiAuthToken result = client.createAuthToken(1, TimeUnit.HOURS); + assertNotNull(result.getResourceId()); + } + + @Test + void testDeleteAuthToken() { + ScaniiAuthToken result = client.createAuthToken(1, TimeUnit.HOURS); + assertTrue(client.deleteAuthToken(result.getResourceId())); + } + + @Test + void testRetrieveAuthToken() { + ScaniiAuthToken result = client.createAuthToken(1, TimeUnit.HOURS); + ScaniiAuthToken result2 = client.retrieveAuthToken(result.getResourceId()); + assertEquals(result.getResourceId(), result2.getResourceId()); + } + + /** + * TODO: callback integration test — requires scanii-cli callback support. + * See RAFAEL_CHECKLIST.md §1.6 for the prerequisite work. Once scanii-cli + * ships callback simulation, implement this test by spinning up a local HTTP + * server, passing its URL as the callback parameter, and asserting the payload. + */ + @Test + @Disabled("TODO: scanii-cli callback support not yet available — see RAFAEL_CHECKLIST.md §1.6") + void testProcessWithCallback() { + // stub — implement after scanii-cli adds callback simulation + } +} diff --git a/src/test/java/com/uvasoftware/scanii/ScaniiClientsTest.java b/src/test/java/com/scanii/ScaniiClientsTest.java similarity index 93% rename from src/test/java/com/uvasoftware/scanii/ScaniiClientsTest.java rename to src/test/java/com/scanii/ScaniiClientsTest.java index fd45800..328043c 100644 --- a/src/test/java/com/uvasoftware/scanii/ScaniiClientsTest.java +++ b/src/test/java/com/scanii/ScaniiClientsTest.java @@ -1,7 +1,7 @@ -package com.uvasoftware.scanii; +package com.scanii; -import com.uvasoftware.scanii.internal.DefaultScaniiClient; -import com.uvasoftware.scanii.models.ScaniiAuthToken; +import com.scanii.internal.DefaultScaniiClient; +import com.scanii.models.ScaniiAuthToken; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/uvasoftware/scanii/ScaniiTargetTest.java b/src/test/java/com/scanii/ScaniiTargetTest.java similarity index 97% rename from src/test/java/com/uvasoftware/scanii/ScaniiTargetTest.java rename to src/test/java/com/scanii/ScaniiTargetTest.java index c80bfe1..7319843 100644 --- a/src/test/java/com/uvasoftware/scanii/ScaniiTargetTest.java +++ b/src/test/java/com/scanii/ScaniiTargetTest.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii; +package com.scanii; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/uvasoftware/scanii/internal/DefaultScaniiClientTest.java b/src/test/java/com/scanii/internal/DefaultScaniiClientTest.java similarity index 90% rename from src/test/java/com/uvasoftware/scanii/internal/DefaultScaniiClientTest.java rename to src/test/java/com/scanii/internal/DefaultScaniiClientTest.java index 6667dce..7fc3e05 100644 --- a/src/test/java/com/uvasoftware/scanii/internal/DefaultScaniiClientTest.java +++ b/src/test/java/com/scanii/internal/DefaultScaniiClientTest.java @@ -1,6 +1,6 @@ -package com.uvasoftware.scanii.internal; +package com.scanii.internal; -import com.uvasoftware.scanii.ScaniiTarget; +import com.scanii.ScaniiTarget; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/uvasoftware/scanii/internal/JSONTest.java b/src/test/java/com/scanii/internal/JSONTest.java similarity index 98% rename from src/test/java/com/uvasoftware/scanii/internal/JSONTest.java rename to src/test/java/com/scanii/internal/JSONTest.java index 134338c..e245423 100644 --- a/src/test/java/com/uvasoftware/scanii/internal/JSONTest.java +++ b/src/test/java/com/scanii/internal/JSONTest.java @@ -1,9 +1,9 @@ -package com.uvasoftware.scanii.internal; +package com.scanii.internal; -import com.uvasoftware.scanii.models.ScaniiAccountInfo; -import com.uvasoftware.scanii.models.ScaniiAuthToken; -import com.uvasoftware.scanii.models.ScaniiPendingResult; -import com.uvasoftware.scanii.models.ScaniiProcessingResult; +import com.scanii.models.ScaniiAccountInfo; +import com.scanii.models.ScaniiAuthToken; +import com.scanii.models.ScaniiPendingResult; +import com.scanii.models.ScaniiProcessingResult; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.Execution; diff --git a/src/test/java/com/uvasoftware/scanii/internal/MultipartBodyPublisherTest.java b/src/test/java/com/scanii/internal/MultipartBodyPublisherTest.java similarity index 99% rename from src/test/java/com/uvasoftware/scanii/internal/MultipartBodyPublisherTest.java rename to src/test/java/com/scanii/internal/MultipartBodyPublisherTest.java index 18c5131..94be29d 100644 --- a/src/test/java/com/uvasoftware/scanii/internal/MultipartBodyPublisherTest.java +++ b/src/test/java/com/scanii/internal/MultipartBodyPublisherTest.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii.internal; +package com.scanii.internal; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/uvasoftware/scanii/misc/EICAR.java b/src/test/java/com/scanii/misc/EICAR.java similarity index 88% rename from src/test/java/com/uvasoftware/scanii/misc/EICAR.java rename to src/test/java/com/scanii/misc/EICAR.java index 60c47f7..2ffdafe 100644 --- a/src/test/java/com/uvasoftware/scanii/misc/EICAR.java +++ b/src/test/java/com/scanii/misc/EICAR.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii.misc; +package com.scanii.misc; import java.util.Base64; diff --git a/src/test/java/com/uvasoftware/scanii/misc/Systems.java b/src/test/java/com/scanii/misc/Systems.java similarity index 96% rename from src/test/java/com/uvasoftware/scanii/misc/Systems.java rename to src/test/java/com/scanii/misc/Systems.java index 2c24b2a..f431e5d 100644 --- a/src/test/java/com/uvasoftware/scanii/misc/Systems.java +++ b/src/test/java/com/scanii/misc/Systems.java @@ -1,4 +1,4 @@ -package com.uvasoftware.scanii.misc; +package com.scanii.misc; import java.io.IOException; import java.nio.charset.Charset; diff --git a/src/test/java/com/uvasoftware/scanii/ScaniiClientTest.java b/src/test/java/com/uvasoftware/scanii/ScaniiClientTest.java deleted file mode 100644 index fa7eaf2..0000000 --- a/src/test/java/com/uvasoftware/scanii/ScaniiClientTest.java +++ /dev/null @@ -1,383 +0,0 @@ -package com.uvasoftware.scanii; - -import com.uvasoftware.scanii.misc.EICAR; -import com.uvasoftware.scanii.misc.Systems; -import com.uvasoftware.scanii.models.ScaniiAccountInfo; -import com.uvasoftware.scanii.models.ScaniiAuthToken; -import com.uvasoftware.scanii.models.ScaniiPendingResult; -import com.uvasoftware.scanii.models.ScaniiProcessingResult; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.ByteArrayInputStream; -import java.io.FileInputStream; -import java.nio.file.Files; -import java.time.Duration; -import java.util.HashMap; -import java.util.Objects; -import java.util.concurrent.TimeUnit; - -class ScaniiClientTest extends IntegrationTest { - private static final String KEY; - private static final String SECRET; - - static { - KEY = System.getenv("SCANII_CREDS").split(":")[0]; - SECRET = System.getenv("SCANII_CREDS").split(":")[1]; - } - - private ScaniiClient client; - - @BeforeEach - void before() { - client = ScaniiClients.createDefault(ScaniiTarget.AUTO, KEY, SECRET); - } - - @Test - void testProcess() throws Exception { - - ScaniiProcessingResult result; - // simple processing clean - result = client.process(Systems.randomFile(1024)); - Assertions.assertNotNull(result.getResourceId()); - Assertions.assertNotNull(result.getChecksum()); - Assertions.assertNotNull(result.getResourceLocation()); - Assertions.assertNotNull(result.getRawResponse()); - Assertions.assertNotNull(result.getRequestId()); - Assertions.assertNotNull(result.getContentType()); - Assertions.assertNotNull(result.getHostId()); - Assertions.assertNotNull(result.getFindings()); - Assertions.assertTrue(result.getFindings().isEmpty()); - System.out.println(result); - - // with findings (EICAR decoded in-memory, never written to disk) - result = client.process(new ByteArrayInputStream(EICAR.decode())); - Assertions.assertNotNull(result.getResourceId()); - Assertions.assertNotNull(result.getChecksum()); - Assertions.assertNotNull(result.getResourceLocation()); - Assertions.assertNotNull(result.getRawResponse()); - Assertions.assertNotNull(result.getRequestId()); - Assertions.assertNotNull(result.getContentType()); - Assertions.assertNotNull(result.getHostId()); - Assertions.assertNotNull(result.getFindings()); - Assertions.assertEquals(1, result.getFindings().size()); - Assertions.assertEquals("content.malicious.eicar-test-signature", result.getFindings().get(0)); - System.out.println(result); - - // failures: - - } - - @Test - void testProcessWithMetadata() throws Exception { - - ScaniiProcessingResult result; - - // simple processing clean - result = client.process(Systems.randomFile(1024), new HashMap<>() {{ - put("foo", "bar"); - }}); - Assertions.assertNotNull(result.getResourceId()); - Assertions.assertEquals("bar", result.getMetadata().get("foo")); - System.out.println(result); - } - - @Test - void testProcessInputStreamWithMetadata() throws Exception { - - ScaniiProcessingResult result; - - FileInputStream is = new FileInputStream(Systems.randomFile(1024).toFile()); - - // simple processing clean - result = client.process(is, new HashMap<>() {{ - put("foo", "bar"); - }}); - Assertions.assertNotNull(result.getResourceId()); - Assertions.assertEquals("bar", result.getMetadata().get("foo")); - System.out.println(result); - } - - @Test - void testProcessWithMetadataAndCallback() throws Exception { - ScaniiProcessingResult result; - - // simple processing clean - result = client.process(Systems.randomFile(1024), "https://httpbin.org/post", new HashMap<>() {{ - put("foo", "bar"); - }}); - Assertions.assertNotNull(result.getResourceId()); - Assertions.assertEquals("bar", result.getMetadata().get("foo")); - System.out.println(result); - } - - - @Test - void testProcessInputStreamWithMetadataAndCallback() throws Exception { - ScaniiProcessingResult result; - - FileInputStream is = new FileInputStream(Systems.randomFile(1024).toFile()); - - // simple processing clean - result = client.process(is, "https://httpbin.org/post", new HashMap<>() {{ - put("foo", "bar"); - }}); - Assertions.assertNotNull(result.getResourceId()); - Assertions.assertEquals("bar", result.getMetadata().get("foo")); - System.out.println(result); - } - - - @Test - void shouldThrowErrorsIfInvalidPost() { - // empty file: - Assertions.assertThrows(ScaniiException.class, () -> client.process(Files.createTempFile(null, null))); - } - - @Test - void shouldThrowErrorsIfInvalidCredentials() { - ScaniiClient client = ScaniiClients.createDefault("foo", "bar"); - - // empty file: - Assertions.assertThrows(ScaniiException.class, () -> client.process(Files.createTempFile(null, null))); - - } - - @Test - void testProcessAsync() throws Exception { - - ScaniiPendingResult result = client.processAsync(Systems.randomFile(1024)); - Assertions.assertNotNull(result.getResourceId()); - Assertions.assertNotNull(result.getResourceLocation()); - Assertions.assertNotNull(result.getRawResponse()); - Assertions.assertNotNull(result.getRequestId()); - Assertions.assertNotNull(result.getHostId()); - System.out.println(result); - - ScaniiProcessingResult actualResult = pollForResult(() -> client.retrieve(result.getResourceId()).orElse(null), - Duration.ofMinutes(1)); - // now fetching the retrieve - Assertions.assertNotNull(actualResult.getResourceId()); - Assertions.assertNotNull(actualResult.getChecksum()); - Assertions.assertNull(actualResult.getResourceLocation()); - Assertions.assertNotNull(actualResult.getRawResponse()); - Assertions.assertNotNull(actualResult.getRequestId()); - Assertions.assertNotNull(actualResult.getContentType()); - Assertions.assertNotNull(actualResult.getHostId()); - Assertions.assertNotNull(actualResult.getFindings()); - Assertions.assertTrue(actualResult.getFindings().isEmpty()); - - } - - @Test - void testProcessAsyncWithMetadata() throws Exception { - ScaniiPendingResult result = client.processAsync(Systems.randomFile(1024), new HashMap<>() {{ - put("foo", "bar"); - }}); - - - ScaniiProcessingResult actualResult = pollForResult((() -> client.retrieve(result.getResourceId()) - .orElse(null)), Duration.ofMinutes(1)); - - // now fetching the retrieve - Assertions.assertNotNull(actualResult.getResourceId()); - Assertions.assertEquals("bar", actualResult.getMetadata().get("foo")); - } - - @Test - void testProcessAsyncInputStreamWithMetadata() throws Exception { - - FileInputStream is = new FileInputStream(Systems.randomFile(1024).toFile()); - - ScaniiPendingResult result = client.processAsync(is, new HashMap<>() {{ - put("foo", "bar"); - }}); - - ScaniiProcessingResult actualResult = pollForResult(() -> client.retrieve(result.getResourceId()) - .orElse(null), Duration.ofMinutes(1)); - Assertions.assertNotNull(actualResult.getResourceId()); - Assertions.assertEquals("bar", actualResult.getMetadata().get("foo")); - } - - @Test - void testProcessAsyncWithMetadataAndCallback() throws Exception { - ScaniiPendingResult result = client.processAsync(Systems.randomFile(1024), "https://httpbin.org/post", new HashMap<>() {{ - put("foo", "bar"); - }}); - - ScaniiProcessingResult actualResult = pollForResult(() -> client.retrieve(result.getResourceId()) - .orElse(null), Duration.ofMinutes(1)); - - Assertions.assertNotNull(actualResult.getResourceId()); - Assertions.assertEquals("bar", actualResult.getMetadata().get("foo")); - } - - @Test - void testProcessAsyncInputStreamWithMetadataAndCallback() throws Exception { - - FileInputStream is = new FileInputStream(Systems.randomFile(1024).toFile()); - - ScaniiPendingResult result = client.processAsync(is, "https://httpbin.org/post", new HashMap<>() {{ - put("foo", "bar"); - }}); - - ScaniiProcessingResult actualResult = pollForResult(() -> client.retrieve(result.getResourceId()) - .orElse(null), Duration.ofMinutes(1)); - - Assertions.assertNotNull(actualResult.getResourceId()); - Assertions.assertEquals("bar", actualResult.getMetadata().get("foo")); - } - - @Test - void testFetchWithoutCallback() throws InterruptedException { - - // simple processing clean - ScaniiPendingResult result = client.fetch("https://scanii.s3.amazonaws.com/eicarcom2.zip"); - Assertions.assertNotNull(result.getResourceId()); - Assertions.assertNotNull(result.getResourceLocation()); - Assertions.assertNotNull(result.getRawResponse()); - Assertions.assertNotNull(result.getRequestId()); - Assertions.assertNotNull(result.getHostId()); - System.out.println(result); - - ScaniiProcessingResult actualResult = pollForResult(() -> client.retrieve(result.getResourceId()) - .orElse(null), Duration.ofMinutes(1)); - - Assertions.assertNotNull(actualResult.getResourceId()); - Assertions.assertNotNull(actualResult.getChecksum()); - Assertions.assertNull(actualResult.getResourceLocation()); - Assertions.assertNotNull(actualResult.getRawResponse()); - Assertions.assertNotNull(actualResult.getRequestId()); - Assertions.assertNotNull(actualResult.getContentType()); - Assertions.assertNotNull(actualResult.getHostId()); - Assertions.assertNotNull(actualResult.getFindings()); - Assertions.assertEquals("content.malicious.eicar-test-signature", actualResult.getFindings().get(0)); - } - - @Test - void testFetchWithCallback() throws InterruptedException { - - // simple processing clean - ScaniiPendingResult result = client.fetch("https://scanii.s3.amazonaws.com/eicarcom2.zip", "https://httpbin.org/post"); - Assertions.assertNotNull(result.getResourceId()); - Assertions.assertNotNull(result.getResourceLocation()); - Assertions.assertNotNull(result.getRawResponse()); - Assertions.assertNotNull(result.getRequestId()); - Assertions.assertNotNull(result.getHostId()); - System.out.println(result); - - ScaniiProcessingResult actualResult = pollForResult(() -> client.retrieve(result.getResourceId()) - .orElse(null), Duration.ofMinutes(1)); - - Assertions.assertNotNull(actualResult.getResourceId()); - Assertions.assertNotNull(actualResult.getChecksum()); - Assertions.assertNull(actualResult.getResourceLocation()); - Assertions.assertNotNull(actualResult.getRawResponse()); - Assertions.assertNotNull(actualResult.getRequestId()); - Assertions.assertNotNull(actualResult.getContentType()); - Assertions.assertNotNull(actualResult.getHostId()); - Assertions.assertNotNull(actualResult.getFindings()); - Assertions.assertEquals("content.malicious.eicar-test-signature", actualResult.getFindings().get(0)); - } - - @Test - void testFetchWithMetadata() throws Exception { - - ScaniiPendingResult result = client.fetch("https://scanii.s3.amazonaws.com/eicarcom2.zip", "http://google.com", new HashMap<>() {{ - put("foo", "bar"); - }}); - Assertions.assertNotNull(result.getResourceId()); - - - ScaniiProcessingResult actualResult = pollForResult(() -> { - System.out.println("attempting to load result " + result.getResourceId()); - return client.retrieve(result.getResourceId()).orElse(null); - }, Duration.ofMinutes(1)); - - Assertions.assertEquals("bar", actualResult.getMetadata().get("foo")); - System.out.println(result); - - - } - - @Test - void testPing() { - Assertions.assertTrue(client.ping()); - } - - @Test - void testCreateAuthToken() throws Exception { - ScaniiAuthToken result = client.createAuthToken(1, TimeUnit.HOURS); - Assertions.assertNotNull(result.getResourceId()); - Assertions.assertNotNull(result.getExpirationDate()); - Assertions.assertNotNull(result.getCreationDate()); - - // now using the auth token to create a new client and process content - ScaniiClient tempClient = ScaniiClients.createDefault(ScaniiTarget.AUTO, result); - ScaniiProcessingResult processingResult = tempClient.process(Systems.randomFile(1024)); - Assertions.assertNotNull(processingResult.getResourceId()); - Assertions.assertNotNull(processingResult.getChecksum()); - Assertions.assertNotNull(processingResult.getResourceLocation()); - Assertions.assertNotNull(processingResult.getRawResponse()); - Assertions.assertNotNull(processingResult.getRequestId()); - Assertions.assertNotNull(processingResult.getContentType()); - Assertions.assertNotNull(processingResult.getHostId()); - Assertions.assertNotNull(processingResult.getFindings()); - Assertions.assertTrue(processingResult.getFindings().isEmpty()); - System.out.println(processingResult); - - } - - @Test - void testDeleteAuthToken() { - ScaniiAuthToken result = client.createAuthToken(1, TimeUnit.HOURS); - Assertions.assertTrue(client.deleteAuthToken(result.getResourceId())); - Assertions.assertThrows(ScaniiException.class, () -> client.deleteAuthToken("abc")); - } - - @Test - void testRetrieveAuthToken() { - ScaniiAuthToken result = client.createAuthToken(1, TimeUnit.HOURS); - ScaniiAuthToken result2 = client.retrieveAuthToken(result.getResourceId()); - Assertions.assertEquals(result.getResourceId(), result2.getResourceId()); - Assertions.assertEquals(result.getCreationDate(), result2.getCreationDate()); - Assertions.assertEquals(result.getExpirationDate(), result2.getExpirationDate()); - } - - - @Test - void shouldPingAllRegions() { - for (ScaniiTarget target : ScaniiTarget.all()) { - System.out.println(target); - ScaniiClient client = ScaniiClients.createDefault(target, KEY, SECRET); - Assertions.assertTrue(client.ping()); - } - } - - @Test - void shouldRetrieveAccountInfo() { - ScaniiAccountInfo account = client.retrieveAccountInfo(); - Assertions.assertNotNull(account.getName()); - Assertions.assertTrue(account.getBalance() > 0); - Assertions.assertTrue(account.getStartingBalance() > 0); - Assertions.assertNotNull(account.getCreationDate()); - Assertions.assertNotNull(account.getModificationDate()); - Assertions.assertFalse(account.getUsers().isEmpty()); - Assertions.assertFalse(account.getKeys().isEmpty()); - Assertions.assertFalse(account.getKeys().isEmpty()); - - var firstKey = account.getKeys().values().stream().findFirst().orElseThrow(); - Assertions.assertNotNull(firstKey.getCreationDate()); - Assertions.assertNotNull(firstKey.getLastSeenDate()); - Assertions.assertNotNull(firstKey.getDetectionCategoriesEnabled()); - - - } - - @Test - void shouldErrorIfPingToInvalidUrl() { - ScaniiClient client = ScaniiClients.createDefault(new ScaniiTarget("http://example.com"), "foo", "bar"); - client.ping(); - } -} diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml index 85ed488..4d1e05e 100644 --- a/src/test/resources/logback.xml +++ b/src/test/resources/logback.xml @@ -9,7 +9,7 @@ - +