This file provides guidance to agents when working with code in this repository.
# Build (all checks + tests)
mvn clean install
# Quick build (skip tests, formatting, license checks)
mvn clean install -Pquick-build
# Unit tests only
mvn test
# Run a specific test class
mvn test -Dtest=RegistryTest
# Integration tests (requires Docker/Podman for Testcontainers)
mvn verify
# Check and apply code formatting (Palantir Java Format via Spotless)
mvn spotless:check
mvn spotless:apply
# Check and fix Apache 2.0 license headers
mvn license:check-file-header
mvn license:format
# Generate JavaDoc (failOnWarnings=true — keep Javadoc clean)
mvn javadoc:javadocoras-java is a Java SDK for ORAS (OCI Registry as Storage), enabling applications to push and pull OCI artifacts to/from OCI-conformant registries.
Single-module Maven project. Main packages under src/main/java/land/oras/:
| Package | Purpose |
|---|---|
land.oras |
Core API — Registry, OCILayout, OCI, data models |
land.oras.auth |
Authentication providers and HTTP client |
land.oras.utils |
Constants, JSON/TOML/YAML utils, digest, compression, archive |
land.oras.exception |
OrasException and OCI error model |
OCI<T> is a sealed abstract class that defines operations shared between remote registries and local layouts:
Registry extends OCI<ContainerRef>— remote registry operations (push/pull blobs and manifests, list tags/repos/referrers). This is the main entry point for most users. Built viaRegistry.Builder.OCILayout extends OCI<LayoutRef>— local OCI layout on disk. Built viaOCILayout.Builder.
All OCI data models live in the root land.oras package and are serialized/deserialized with Jackson. They are annotated with @OrasModel and use @JsonPropertyOrder to ensure deterministic JSON output (required for digest stability).
Descriptor is a sealed class with four permitted subtypes:
Descriptor (sealed)
├── Config — the manifest's config object (often the empty config: {})
├── Layer — a single content layer within a manifest
├── Manifest — an OCI image manifest (schemaVersion, config, layers, subject, annotations)
└── Index — an OCI image index / multi-arch manifest list (schemaVersion, manifests[])
Common fields on Descriptor: mediaType, digest, size, artifactType, annotations.
Additional fields:
Manifestadds:schemaVersion,config(Config),layers(List<Layer>),subject(Subject)Indexadds:schemaVersion,manifests(List<ManifestDescriptor>)Layer/Configadd:data(optional base64 inline content)
Supporting classes (not subtypes of Descriptor):
ManifestDescriptor— an entry inside anIndex.manifests[]list; carriesmediaType,digest,size,annotations,artifactType,platformSubject— the referrer target inside aManifest; same shape as a descriptorContainerRef— parses[registry/]namespace/repository[:tag][@digest]with regex validationLayoutRef— reference inside a local OCI layout (path + tag/digest)LocalPath— wraps a local file or directory for push operationsAnnotations,Platform,ArtifactType— thin value-objects
All models are immutable-style; use with*() methods to derive modified copies.
OCI Image Index (index.json at the root of an OCI layout):
{
"schemaVersion": 2,
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:cb1d49ba...",
"size": 556,
"annotations": {
"org.opencontainers.image.created": "2025-03-08T08:20:56Z",
"org.opencontainers.image.ref.name": "latest"
},
"artifactType": "foo/bar"
}
]
}OCI Image Manifest (stored as a blob, referenced by the index):
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"artifactType": "foo/bar",
"config": {
"mediaType": "application/vnd.oci.empty.v1+json",
"digest": "sha256:44136fa3...",
"size": 2,
"data": "e30="
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar",
"digest": "sha256:98ea6e4f...",
"size": 3,
"annotations": { "org.opencontainers.image.title": "hi.txt" }
}
],
"annotations": { "org.opencontainers.image.created": "2025-03-08T08:20:56Z" }
}Manifest with subject (referrer — attached to another manifest via the Referrers API):
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"artifactType": "application/vnd.text.file.v1+json",
"config": {
"mediaType": "application/vnd.oci.empty.v1+json",
"digest": "sha256:44136fa3...",
"size": 2,
"data": "e30="
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar",
"digest": "sha256:e094bc80...",
"size": 4,
"annotations": { "org.opencontainers.image.title": "hi2.txt" }
}
],
"subject": {
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:bb329f10...",
"size": 554
},
"annotations": { "org.opencontainers.image.created": "2025-04-07T14:54:25Z" }
}The empty config blob ({}, base64 e30=, digest sha256:44136fa3...) is used as the standard no-op config for non-image ORAS artifacts.
AuthProvider interface with implementations:
AuthStoreAuthenticationProvider— reads~/.docker/config.jsonor$XDG_RUNTIME_DIR/containers/auth.jsonUsernamePasswordProvider,BearerTokenProvider,NoAuthProvider
HttpClient integrates AuthProvider and handles token caching (Caffeine) with automatic refresh.
- Unit tests (
*Test.java): Use WireMock for HTTP mocking and Testcontainers (ZotContainer) for in-process OCI registry. Parallel execution via@Execution(ExecutionMode.CONCURRENT). - Integration tests (
*ITCase.java): Run against real external registries. Require credentials and Docker/Podman.
Test resources with OCI layout fixtures live in src/test/resources/oci/.
- Jackson 3.x (JSON/TOML/YAML)
- Micrometer (metrics)
- Caffeine (token caching)
- Commons Compress + Zstd-JNI (archive/compression)
- BouncyCastle (cryptography)
- JSpecify (null-safety annotations — use
@Nullable/@NonNullwhere appropriate) - JUnit Jupiter + Testcontainers + WireMock + Mockito (tests)
- Java 17, formatted with Palantir Java Format (enforced via
mvn spotless:apply) - All source files require an Apache 2.0 license header (enforced via
mvn license:format) - JavaDoc must compile without warnings (
failOnWarnings=true) - CI tests against Java 17, 21, and 25