Aspose.Slides FOSS for Java
Aspose.Slides FOSS for Java is a free, open-source, pure-Java library for creating, reading, and editing PowerPoint .pptx presentations. The Presentation class is the root of the object model — it owns slides, shapes, images, comment authors, and document properties — and every operation runs without Microsoft Office, COM automation, or any proprietary runtime. Unknown XML content encountered while loading a presentation is never silently discarded on save. The sections below walk through its core features, installation, and full API surface.
It builds the Office Open XML package itself, so it needs no PowerPoint installation, no native
code, and no runtime dependencies at all — the CycloneDX SBOM the build produces lists zero
components.
It is for developers who generate or modify decks on a server or in a build, and who are working
inside the file format. It is not a renderer or a converter: there is no PDF, HTML, SVG, or image
output, and everything it cannot do is listed under
Scope and Limitations.
Navigation
At a Glance
flowchart TD
subgraph StartingPoints["Starting Points"]
direction TB
i1["Nothing — authored from scratch"]
i2["An existing PPTX presentation"]
end
PRODUCT["Aspose.Slides FOSS for Java"]
subgraph Capabilities["Core Capabilities"]
direction LR
subgraph capl[" "]
direction TB
c1["Presentation and slide creation and editing"]
c2["Shape creation (AutoShape, Table, Connector, PictureFrame)"]
c3["Text formatting (TextFrame, Paragraph, Portion)"]
c4["Fill, line, and 3D shape styling"]
end
subgraph capr[" "]
direction TB
c5["Visual effects (shadow, glow, blur, reflection)"]
c6["Document properties (core, app, custom)"]
c7["Speaker notes and threaded comments"]
c8["Image embedding"]
end
end
subgraph Outputs["Outputs"]
direction TB
o1["A PPTX presentation"]
end
StartingPoints --> PRODUCT --> Capabilities --> Outputs
Key Capabilities
Everything below was exercised through the public API and then confirmed by reading the XML
inside the file that came out — not by asking the library to read its own file back.
- The
Presentation class is the root of the object model, implements AutoCloseable, and is always used inside a try-with-resources block; open an existing .pptx with new Presentation(path) or start empty with new Presentation(), then persist it with save(path, format) or save(stream, format) to any of the three formats save() writes — SaveFormat.PPTX, PPSX, and POTX — see Scope and Limitations for the rest of SaveFormat.
- Add, remove, and clone slides through
SlideCollection's addClone(), addEmptySlide(), insertEmptySlide(), and removeAt() methods, iterate getSlides() directly, and control per-slide visibility during a slideshow with ISlide.setHidden()/isHidden() (written as <p:sld show="0">); MasterSlideCollection.addClone() also exists, but see Scope and Limitations for a real defect in what survives it.
- Insert AutoShapes, PictureFrames, Tables, and Connectors via
ShapeCollection's addAutoShape(), addPictureFrame(), addTable(), and addConnector() methods, each returning a real IShape-derived object — 190 ShapeType values are supported, writing 187 distinct <a:prstGeom prst="…"> tokens between them (NOT_DEFINED/CUSTOM both write rect, and ROUND_RECTANGLE/ROUND_CORNER_RECTANGLE both write roundRect).
- Format text at the
TextFrame, Paragraph, and Portion level — character formatting (bold,
italic, underline, strikethrough, size, spacing, caps, latin/east-Asian/complex-script/symbol
fonts) via PortionFormat, paragraph formatting (alignment, indent, margins, spacing, symbol/
numbered/picture bullets) via ParagraphFormat, and frame-level formatting (margins, wrap,
anchor, autofit, columns) via TextFrameFormat.
Installation
aspose-slides-foss is published on Maven Central as org.aspose:aspose-slides-foss:26.7.0.
Maven:
<dependency>
<groupId>org.aspose</groupId>
<artifactId>aspose-slides-foss</artifactId>
<version>26.7.0</version>
</dependency>
Gradle:
implementation 'org.aspose:aspose-slides-foss:26.7.0'
Before you depend on 26.7.0, read this. It predates a hardening fix: every parser and
serializer in the current source is created by a secure XML factory that refuses a <!DOCTYPE>
declaration outright and disables external entities, external DTD loading, and XInclude. 26.7.0
does not have that fix, and SECURITY.md lists it as not supported for that reason —
before the fix, a .pptx part could declare an external entity that got resolved while loading the
file, so opening a presentation from an untrusted source could read a local file or open a network
connection. If your program opens .pptx files that come from somewhere you do not control, build
from source (below) rather than depending on 26.7.0.
This source tree is 26.8.0, not yet released to Maven Central — the save-format refusal described
under Scope and Limitations is also new in 26.8.0, not in 26.7.0.
Until 26.8.0 is out, build from source if you need either fix.
The published jar declares Automatic-Module-Name: org.aspose.slides.foss, so it can go on the
module path under a stable name.
JDK 21 or later is required, and the library has no runtime dependencies beyond the JDK itself.
Dependencies
Required Package Dependencies
No required third-party package dependencies.
Native and System Requirements
- JDK 21 or later —
maven.compiler.release is pinned to 21 in pom.xml, and the build fails
on an older JDK with a readable message rather than silently targeting a downlevel bytecode
version. This is enforced, not just declared: the sources use List.getFirst(),
List.removeLast(), and an unconditional instanceof pattern, none of which compile below 21.
- Tested on Linux, Windows, and macOS, on Java 21 and Java 25, on every push and every pull
request.
Development Dependencies
Quick Start
Create a presentation, add a rectangle AutoShape, apply a solid fill, and save it as .pptx:
import org.aspose.slides.foss.Presentation;
import org.aspose.slides.foss.ShapeType;
import org.aspose.slides.foss.FillType;
import org.aspose.slides.foss.IAutoShape;
import org.aspose.slides.foss.ISlide;
import org.aspose.slides.foss.drawing.Color;
import org.aspose.slides.foss.export.SaveFormat;
try (Presentation pres = new Presentation()) {
ISlide slide = pres.getSlides().get(0);
slide.getShapes().clear();
IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.RECTANGLE, 50, 50, 200, 100);
shape.getFillFormat().setFillType(FillType.SOLID);
shape.getFillFormat().getSolidFillColor().setColor(Color.fromArgb(255, 0, 128, 255));
pres.save("hello.pptx", SaveFormat.PPTX);
}
Compiled against this tree and run, this leaves a real, working hello.pptx behind that opens
directly in PowerPoint. Three
things worth knowing before the second program you write:
save and the Presentation(String) constructor throw IOException. close() does not,
so try-with-resources needs nothing extra.
IShapeCollection.get(int) returns IShape. Cast to IAutoShape, ITable, IConnector,
or IPictureFrame to reach the members only those have. ISlideCollection implements
Iterable, so a for-each over getSlides() works; IShapeCollection does not, so iterate it
with an index or with getShapes().asIEnumerable().
- Coordinates and sizes are points — 1 point = 1/72 inch. Slide and shape indices are
zero-based.
Additional Examples
Every example below was compiled against this tree and run. Beyond basic shape creation, the integration test suite exercises connectors, comments, notes, document properties, effects, and images end to end (create, save, reopen, re-verify). The flagship example below wires two shapes together with a connector; more usage examples are collapsed below it.
Connect two shapes with a bent connector, choosing a specific connection site on each end:
import org.aspose.slides.foss.*;
import org.aspose.slides.foss.export.SaveFormat;
try (Presentation pres = new Presentation()) {
ISlide slide = pres.getSlides().get(0);
slide.getShapes().clear();
IAutoShape s1 = slide.getShapes().addAutoShape(ShapeType.RECTANGLE, 50, 50, 100, 60);
IAutoShape s2 = slide.getShapes().addAutoShape(ShapeType.RECTANGLE, 350, 200, 100, 60);
IConnector conn = slide.getShapes().addConnector(ShapeType.BENT_CONNECTOR3, 0, 0, 1, 1);
conn.setStartShapeConnectedTo(s1);
conn.setStartShapeConnectionSiteIndex(3);
conn.setEndShapeConnectedTo(s2);
conn.setEndShapeConnectionSiteIndex(1);
pres.save("connector.pptx", SaveFormat.PPTX);
}
Add a Threaded Comment to a Slide
import org.aspose.slides.foss.*;
import org.aspose.slides.foss.drawing.PointF;
import org.aspose.slides.foss.export.SaveFormat;
import java.time.LocalDateTime;
try (Presentation pres = new Presentation()) {
ICommentAuthor author = pres.getCommentAuthors().addAuthor("Alice", "A");
ISlide slide = pres.getSlides().get(0);
LocalDateTime now = LocalDateTime.of(2026, 1, 15, 12, 0, 0);
IComment comment = author.getComments().addComment("Review note", slide,
new PointF(2.0f, 3.0f), now);
pres.save("comments.pptx", SaveFormat.PPTX);
}
Set Document Properties
import org.aspose.slides.foss.*;
import org.aspose.slides.foss.export.SaveFormat;
try (Presentation pres = new Presentation()) {
IDocumentProperties props = pres.getDocumentProperties();
props.setTitle("My Presentation");
props.setSubject("Demo Subject");
props.setAuthor("John Doe");
props.setKeywords("demo, test");
props.setCategory("Examples");
pres.save("properties.pptx", SaveFormat.PPTX);
}
Apply an Outer Shadow Effect to a Shape
import org.aspose.slides.foss.*;
import org.aspose.slides.foss.drawing.Color;
import org.aspose.slides.foss.export.SaveFormat;
try (Presentation pres = new Presentation()) {
ISlide slide = pres.getSlides().get(0);
slide.getShapes().clear();
IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.RECTANGLE, 100, 100, 200, 100);
IEffectFormat ef = shape.getEffectFormat();
ef.enableOuterShadowEffect();
IOuterShadow shadow = ef.getOuterShadowEffect();
shadow.setBlurRadius(10);
shadow.setDirection(315);
shadow.setDistance(8);
shadow.getShadowColor().setColor(Color.fromArgb(128, 0, 0, 0));
pres.save("shadow.pptx", SaveFormat.PPTX);
}
Add Speaker Notes to a Slide
import org.aspose.slides.foss.*;
import org.aspose.slides.foss.export.SaveFormat;
try (Presentation pres = new Presentation()) {
ISlide slide = pres.getSlides().get(0);
INotesSlide notes = slide.getNotesSlideManager().addNotesSlide();
notes.getNotesTextFrame().setText("Speaker notes");
pres.save("notes.pptx", SaveFormat.PPTX);
}
Embed an Image as a Picture Frame
import org.aspose.slides.foss.*;
import org.aspose.slides.foss.export.SaveFormat;
try (Presentation pres = new Presentation()) {
IPPImage img = pres.getImages().addImage(imageBytes);
pres.getSlides().get(0).getShapes().addPictureFrame(
ShapeType.RECTANGLE, 50, 50, 100, 100, img);
pres.save("picture.pptx", SaveFormat.PPTX);
}
Clone a Slide
import org.aspose.slides.foss.*;
try (Presentation pres = new Presentation()) {
ISlide slide = pres.getSlides().get(0);
slide.getShapes().addAutoShape(ShapeType.RECTANGLE, 50, 50, 200, 100);
pres.getSlides().addClone(slide);
// pres.getSlides().size() is now 2
}
Open an Existing Presentation
import org.aspose.slides.foss.Presentation;
import java.nio.file.Path;
try (Presentation pres = new Presentation(Path.of("Presentation.pptx").toString())) {
// pres.getSlides().size() reflects the real slide count in the file
}
Save a Presentation to an In-Memory Stream
import org.aspose.slides.foss.Presentation;
import org.aspose.slides.foss.export.SaveFormat;
import java.io.ByteArrayOutputStream;
try (Presentation pres = new Presentation()) {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
pres.save(buf, SaveFormat.PPTX);
}
Format a Text Portion's Font Size, Weight, and Color
import org.aspose.slides.foss.*;
import org.aspose.slides.foss.drawing.Color;
import org.aspose.slides.foss.export.SaveFormat;
try (Presentation pres = new Presentation()) {
IAutoShape shape = pres.getSlides().get(0).getShapes()
.addAutoShape(ShapeType.RECTANGLE, 50, 50, 400, 150);
shape.addTextFrame("Formatted text");
IPortionFormat fmt = shape.getTextFrame().getParagraphs().get(0)
.getPortions().get(0).getPortionFormat();
fmt.setFontHeight(24);
fmt.setFontBold(NullableBool.TRUE);
fmt.getFillFormat().setFillType(FillType.SOLID);
fmt.getFillFormat().getSolidFillColor().setColor(Color.fromArgb(255, 0, 70, 127));
pres.save("text.pptx", SaveFormat.PPTX);
}
Create a Table and Set Cell Text
import org.aspose.slides.foss.*;
import org.aspose.slides.foss.export.SaveFormat;
try (Presentation pres = new Presentation()) {
ITable table = pres.getSlides().get(0).getShapes()
.addTable(50, 50, new double[]{120, 120, 120}, new double[]{40, 40});
table.getRows().get(0).get(0).getTextFrame().setText("Name");
table.getRows().get(0).get(1).getTextFrame().setText("Value");
pres.save("table.pptx", SaveFormat.PPTX);
}
Save a Subset of Slides
save(path, slides, format) takes a zero-based slide-index array; repeats are ignored and the
slides kept stay in document order:
import org.aspose.slides.foss.Presentation;
import org.aspose.slides.foss.export.SaveFormat;
try (Presentation pres = new Presentation("deck.pptx")) {
pres.save("first-and-third.pptx", new int[]{0, 2}, SaveFormat.PPTX);
}
API Reference
The primary entry point is Presentation, which owns an ISlideCollection of Slide objects; each slide exposes an IShapeCollection of Shape-derived objects (AutoShape, Connector, Table, PictureFrame) built through ShapeCollection's addAutoShape(), addConnector(), addTable(), and addPictureFrame() methods.
Foss
| Class | Description |
|---|
AdjustValue | Represents a single geometry adjustment value backed by an OOXML `` element. |
AdjustValueCollection | Represents a collection of shape's adjustments backed by an OOXML `` element. |
AutoShape | Represents an AutoShape. |
BaseHandoutNotesSlideHeaderFooterManager | Represents abstract base class for handout and notes slide header/footer managers. |
BasePortionFormat | Common text portion formatting properties. |
BaseShapeLock | Base class for shape locks. |
BaseSlide | Represents common data for all slide types. |
Blur | Represents a Blur effect that is applied to the entire shape, including its fill. |
BulletFormat | Represents paragraph bullet formatting properties. |
Camera | Represents 3D camera settings. |
Cell | Represents a cell of a table. |
CellCollection | Represents a collection of cells. |
CellFormat | Represents format of a table cell. |
Color | Immutable value type representing an ARGB color. |
ColorFormat | Represents a color used in a presentation. |
Column | Represents a column in a table. |
ColumnCollection | Represents collection of columns in a table. |
ColumnFormat | Represents formatting properties of a table column. |
Comment | Represents a comment on a presentation slide. |
CommentAuthor | Represents an author of comments. |
CommentAuthorCollection | Represents a collection of comment authors in a presentation. |
CommentCollection | Represents a collection of comments of one author. |
Interfaces
| Class | Description |
|---|
IAdjustValue | Represents a geometry shape adjustment value. |
IAdjustValueCollection | Represents a collection of shape adjustment values. |
IAutoShape | Represents an AutoShape. |
IBaseHandoutNotesSlideHeaderFooterManager | Represents base interface for handout and notes slide header/footer managers. |
IBaseHeaderFooterManager | Represents base interface for header/footer managers. |
IBasePortionFormat | Represents common text portion formatting properties. |
IBaseSlide | Represents common data for all slide types. |
IBaseSlideHeaderFooterManager | Represents base interface for slide header/footer managers that manage footer, slide number, and date-time placeholders. |
IBlur | Represents a Blur effect that is applied to the entire shape, including its fill. |
IBulkTextFormattable | Represents an object with the possibility of bulk setting child text elements' formats. |
IBulletFormat | Represents paragraph bullet formatting properties. |
ICamera | Represents Camera. |
ICell | Represents a cell in a table. |
ICellCollection | Represents a collection of cells. |
ICellFormat | Represents format of a table cell. |
IColorFormat | Represents a color used in a presentation. |
IColumn | Represents a column in a table. |
IColumnCollection | Represents collection of columns in a table. |
IColumnFormat | Represents format of a table column. |
IComment | Represents a comment on a presentation slide. |
ICommentAuthor | Represents a comment author in a presentation. |
|
Enumerations
| Class | Description |
|---|
BevelPresetType | Constants which define 3D bevel of shape. |
BulletType | Represents the type of the extended bullets. |
CameraPresetType | Constants which define camera preset type. |
ColorType | Represents different color modes. |
FillBlendMode | Determines blend mode. |
FillType | Specifies the interior fill type of various visual objects. |
FontAlignment | Represents vertical font alignment. |
GradientDirection | Represents the gradient style. |
GradientShape | Represents the shape of gradient fill. |
LightRigPresetType | Constants which define light preset types. |
LightingDirection | Constants which define light directions. |
LineAlignment | Represents the lines alignment type. |
LineArrowheadLength | Represents the length of an arrowhead. |
LineArrowheadStyle | Represents the style of an arrowhead. |
LineArrowheadWidth | Represents the width of an arrowhead. |
LineCapStyle | Represents the line cap style. |
LineDashStyle | Represents the line dash style. |
LineJoinStyle | Represents the lines join style. |
LineStyle | Represents the style of a line. |
MaterialPresetType | Constants which define material of shape. |
NullableBool | Represents triple boolean values. |
NumberedBulletStyle | Represents the style of the numbered bullets. |
PatternStyle | Represents the pattern style. |
PictureFillMode |
Detailed Member Reference
Presentation — the root object; owns slides, images, comment authors, and document properties.
Presentation(), Presentation(path), Presentation(in) -> Presentation
getSlides() -> ISlideCollection, getImages() -> IImageCollection, getCommentAuthors() -> ICommentAuthorCollection
getDocumentProperties() -> IDocumentProperties, getLayoutSlides() -> IGlobalLayoutSlideCollection, getMasters() -> IMasterSlideCollection
save(path, format) -> void, save(stream, format) -> void, dispose() -> void
SlideCollection — the real ISlideCollection implementation returned by Presentation.getSlides().
get(index) -> ISlide, size() -> int, addClone(sourceSlide) -> ISlide, addEmptySlide(layout) -> ISlide, insertEmptySlide(index, layout) -> ISlide, removeAt(index) -> void, indexOf(slide) -> int
ShapeCollection — the real IShapeCollection implementation returned by Slide.getShapes().
addAutoShape(shapeType, x, y, width, height) -> IAutoShape, addConnector(shapeType, x, y, width, height) -> IConnector
addTable(x, y, colWidths, rowHeights) -> ITable, addPictureFrame(shapeType, x, y, width, height, image) -> IPictureFrame
get(index) -> IShape, size() -> int, remove(shape) -> void, removeAt(index) -> void, clear() -> void, reorder(index, shape) -> void
AutoShape — a preset-geometry shape (rectangle, ellipse, and every other ShapeType).
getShapeType() -> ShapeType, addTextFrame(text) -> ITextFrame, getTextFrame() -> ITextFrame, getFillFormat() -> IFillFormat, getLineFormat() -> ILineFormat, getEffectFormat() -> IEffectFormat, getThreeDFormat() -> IThreeDFormat
Connector — a shape-to-shape connector line.
getStartShapeConnectedTo() -> IShape, , ,
Documentation & Resources
This library mirrors the naming of the commercial Aspose.Slides for Java product, so that
product's own documentation is often the fastest way to understand what a shared type name means —
it describes a much larger API, so check Scope and Limitations before
relying on anything read there.
- Getting started guide — setup, core concepts, and step-by-step guides for Aspose.Slides FOSS for Java.
- How-to guides & FAQ — task-focused how-to articles for common presentation operations.
- Full API reference — the complete, browsable reference (the API Reference section above covers the essentials).
- Contributor guide — build commands, core concepts, and import patterns for working on the source.
- Publishing guide — how releases are built and published to Maven Central.
Searching
search.maven.org itself finds nothing — a limitation of that particular search
index, not of the release — but the artifact resolves normally from repo1.maven.org and lists
correctly on central.sonatype.com.
- Found a bug or have a feature request? Open an issue on GitHub.
Choosing an Edition
There are four editions of this library and they are not interchangeable. Three of them — .NET,
Java, and C++ — are the same design in three languages; Python is a larger and different one.
| .NET | Java | C++ | Python |
|---|
| Create, open, round-trip, save | yes | yes | yes | yes |
| Text, tables, connectors, fills, all 8 effects, 3-D | yes | yes | yes | yes |
| Notes and classic comments | yes | yes | yes | yes |
| Threaded comment part | no | yes | no | yes |
| Save to a stream | yes | yes | no | yes |
| Add a picture from a stream | yes | yes | no | yes |
| Clone a slide, with its text | yes | yes | partial | yes |
| Clone a master | yes | no | no | yes |
| Sections | yes | no | no | no |
| Charts, animations, transitions, themes, backgrounds, group shapes, hyperlinks | no | no | no | yes |
Formats save writes | 3 | 3 | 6 | 7 |
| Default slide size of a new deck | 4:3 | 4:3 | 4:3 | 16:9 |
If you need charts, animations, transitions, themes, backgrounds, group shapes, or hyperlinks, none
of them exist in this edition — use the Python one. If you need sections, only the .NET edition has
them. Code written against the Python examples does not port here, and a new deck is not even the
same shape.
When you want the commercial product instead: if you need to render or convert — PDF, images,
HTML, thumbnails — or need charts, SmartArt, animations, OLE objects, or macro-enabled files, or
need a supported product with a licence behind it, none of that is here and none of it is planned
in this repository. This library is the right choice when you are reading and writing .pptx and
want an MIT-licensed dependency that brings nothing else with it.
Scope and Limitations
This section is the point of this file. Nothing here is a "coming soon"; it is what the API does
not contain today.
-
Not in the public API: charts (no IShapeCollection.addChart); SmartArt, OLE objects, video,
and audio (not modelled); animations and slide transitions (no ISlide.getTimeline, no
ISlide.getSlideShowTransition); group shapes (no IShapeCollection.addGroupShape — no shape
can hold child shapes); hyperlinks (no setHyperlinkClick on a shape or a text portion); sections
(no IPresentation.getSections); slide backgrounds (no ISlide.getBackground); themes (no
IPresentation.getMasterTheme); slide size (no IPresentation.getSlideSize — a new deck is 4:3,
cx="9144000" cy="6858000" type="screen4x3", with no supported way to change it); and rendering
or conversion of any kind (no PDF, HTML, SVG, image, or text export); VBA macros, digital
signatures, and encryption are not modelled either.
-
A known defect: cloning a master. getMasters().addClone(...) returns and the collection
then reports a size of 2 — but the saved package contains one <p:sldMasterId> and one
ppt/slideMasters/slideMaster1.xml. The clone never reaches the file, and nothing reports a
problem. Do not rely on it.
-
Save formats: SaveFormat declares 25 values. save() writes three of them — PPTX,
PPSX, and POTX, each a genuinely different package with its own main-part content type — and
raises UnsupportedOperationException for the other 22 (PPT, PDF, XPS, TIFF, ODP,
PPTM, PPSM, POTM, HTML, HTML5, SWF, OTP, PPS, POT, FODP, GIF, MD, XML,
SVG, JPEG, PNG, BMP); it never writes a package under a name that claims to be a format
it did not produce, and nothing is left on disk when it refuses. The macro-enabled formats are
refused because their content type declares a VBA project this library does not write. The
refusal names the alternatives:
Export format 'Pdf' is not supported. Writable formats are: Pptx, Ppsx, Potx
Give the file the extension its format uses — save("deck.pptx", SaveFormat.POTX) writes a
correct template that PowerPoint refuses to open, because the content type says template and the
name says presentation.
These limitations don't apply to Aspose.Slides for Java — Enterprise Edition, which adds full format export (PDF, HTML, XPS, images, and more), charts, animations, VBA macro support, and every other capability outside this FOSS build's scope.
Development and Testing
git clone https://github.com/aspose-slides-foss/Aspose.Slides-FOSS-for-Java.git
cd Aspose.Slides-FOSS-for-Java
mvn verify -Dgpg.skip=true
JDK 21 or later and Maven are required; the build refuses to start otherwise. That one command
runs the whole test suite — unit tests under src/test/java plus the integration tests under
tests/integration and the conformance tests under tests/conformance (both wired in as
additional test source directories via the build-helper-maven-plugin in pom.xml) — and builds
the jar, the sources jar, the javadoc jar, and a CycloneDX SBOM into target/. The conformance
tests unzip the produced .pptx and assert on the package itself, never on what this library reads
back — the same rule CONTRIBUTING.md states explicitly: a writer fix ships
with a test that asserts on the produced package, not on what the library reads back.
-Dgpg.skip=true skips artifact signing, which is part of verify and needs the release key.
Compiler warnings fail the build (-Xlint:all), and so does a javadoc error. Two builds of the
same source produce byte-identical jars — project.build.outputTimestamp fixes the build date
instead of taking it from the clock, and CI proves it by building twice and comparing the hashes.
Every push and every pull request runs that build on Linux, Windows, and macOS, on Java 21 and Java
25 (.github/workflows/build.yml). The jar, sources jar, javadoc
jar, and SBOM from each run are downloadable from the run's page.
Releases publish to Maven Central via
maven-central-release.yml — see
PUBLISHING.md for the full release process.
Pull requests are welcome — CONTRIBUTING.md explains the build and the test
suites. By participating you agree to the Code of Conduct. Changes between releases,
including behaviour changes and removed API, are in CHANGELOG.md.
Do not report a vulnerability in a public issue — SECURITY.md has the reporting
route.
License
This project is licensed under the MIT License. The MIT License permits use, copying, modification, distribution, sublicensing, and commercial use, provided its copyright and permission notice are retained. The software is provided without warranty.