How package-source/ Works in the Torello Build System

In the Torello Build Tool, each Java package directory (such as Torello/HTML or Torello/Java/Build) contains a special subdirectory named package-source/. This subdirectory holds all of the source files that make up the exported API of that package — even if they're nested in deeply organized subdirectories.

Why Use package-source/?

Traditional Java enforces a tight coupling between the directory layout of source files and their declared package names. But UNIX developers have long appreciated the value of organizing files into subdirectories for better readability, logical grouping, and maintainability.

The package-source/ system bridges those worlds. It gives you the freedom to place source files in arbitrarily deep subdirectories — while still declaring them as part of a flat Java package like package Torello.HTML;.
This organization is fully supported by both the Torello.Java.Build system and the JavaDoc Upgrader Tool.

How Compilation Works

During Stage 1 of the build process (the Compilation Stage), the build tool performs these steps:
  1. Recursively scans package-source/ for all .java files.
  2. Invokes javac on each file using its full absolute path.
  3. Lets javac compile the sources in-place — this means the generated .class files are placed right next to the original source files, no matter how deep.
  4. Once compilation finishes, the build tool moves all generated .class files from their deep subdirectories into the root of the package directory (e.g. into Torello/HTML/).
Because of this relocation step, it is required that each .java file inside the package-source/ tree declares the correct package statement at the top — for example, package Torello.HTML;. This declaration must match the name of the root directory where the .class files will ultimately be moved.

If a source file declares the wrong package — or omits the package statement entirely — javac may still compile the file successfully, depending on the code inside. However, after the resulting .class file is copied into Torello/HTML/, it will become invisible to the Java runtime and compiler. This is because the internal package name encoded in the .class file will no longer match its physical location in the directory structure.

Why It Still Works

Java's classpath resolution and runtime behavior are still satisfied because:
This approach provides the best of both worlds: strict Java packaging, and flexible UNIX-style organization — as long as developers ensure the declared package names in the source files match the build output location.

Takeaway

The package-source/ design allows you to maintain readable, organized, and scalable Java projects — especially as your API packages grow in size and complexity. It’s a simple convention that turns into a powerful feature when paired with the Torello Build System.

Visualizing File Structure Before and After Compilation


This diagram compares how source and class files are arranged in the Torello Build System:
Before Compilation
(Nested source layout)
After Compilation
(Flattened .class output)
Torello/HTML/package-source/ ├── EXPORT_PORTAL.java ├── package-info.java ├── Core Data/ │ ├── CommentNode.java │ ├── DotPair.java │ ├── HTMLNode.java │ ├── PageStats.java │ ├── TagNode.java │ ├── TextNode.java │ ├── TagNode/ │ │ ├── CaseChange.java │ │ ├── ClassIDStyle.java │ │ ├── DataAttributes.java │ │ ├── GeneralPurpose.java │ │ ├── GetSetAttr.java │ │ ├── HasAndTest.java │ │ ├── IsTag.java │ │ ├── KeyOnlyAttributes.java │ │ ├── QuotationMarks.java │ │ ├── RemoveAttributes.java │ │ ├── RetrieveAllAttr.java ├── Enums/ │ ├── AUM.java │ ├── MetaTagName.java │ ├── Robots.java │ ├── SD.java │ ├── TC.java ├── HTML Processors/ │ ├── Attributes.java │ ├── Balance.java │ ├── DPUtil.java │ ├── Debug.java │ ├── Escape.java │ ├── Features.java │ ├── InnerTags.java │ ├── Links.java │ ├── Listeners.java │ ├── PrettyPrint.java │ ├── ReplaceNodes.java │ ├── SplashBridge.java │ ├── Surrounding.java │ ├── Util.java │ ├── Attributes/ │ │ ├── Remove.java │ │ ├── RemoveAll.java │ │ ├── RemoveData.java │ │ ├── Retrieve.java │ │ ├── Update.java │ │ ├── UpdateWithFilter.java │ │ ├── UsingStrFilter.java │ │ ├── WhiteListFilter.java │ ├── OTHER/ │ │ ├── EscapeRepl.java │ │ ├── HTMLTagCounter.java │ │ ├── LinksResolve_KE.java │ ├── Pretty/ │ │ ├── AddNewLines.java │ │ ├── RemAllIndent.java ├── Interfaces/ │ ├── ReplaceFunction.java │ ├── URLFilter.java ├── Parse and Scrape/ │ ├── HTMLPage.java │ ├── HTMLPageMWT.java │ ├── HTMLTags.java │ ├── HTTPCodes.java │ ├── Scrape.java │ ├── parser/ │ │ ├── HTMLRegEx.java │ │ ├── ParserRE.java │ │ ├── ParserREInternal.java ├── Replaceables/ │ ├── CommentNodeIndex.java │ ├── NodeIndex.java │ ├── Replaceable.java │ ├── ReplaceableAdapter.java │ ├── Replacement.java │ ├── SubSection.java │ ├── TagNodeIndex.java │ ├── TextNodeIndex.java ├── Throwables/ │ ├── BalancedHTMLException.java │ ├── ClosingTagNodeException.java │ ├── ClosingTagNodeExpectedException.java │ ├── HREFException.java │ ├── HTMLTokException.java │ ├── InnerTagKeyException.java │ ├── InnerTagValueException.java │ ├── MalformedHTMLException.java │ ├── MalformedTagNodeException.java │ ├── NodeExpectedException.java │ ├── NodeNotFoundException.java │ ├── OpeningTagNodeExpectedException.java │ ├── QuotesException.java │ ├── ReplaceableException.java │ ├── ReplaceableOutOfBoundsException.java │ ├── ReplaceablesOverlappingException.java │ ├── ReplaceablesUnsortedException.java │ ├── SRCException.java │ ├── ScrapeException.java │ ├── SingletonException.java │ ├── TagNodeExpectedException.java │ ├── TextNodeExpectedException.java Torello/HTML/ ├── EXPORT_PORTAL.class ├── package-info.class ├── CommentNode.class ├── DotPair.class ├── HTMLNode.class ├── PageStats.class ├── TagNode.class ├── TextNode.class ├── CaseChange.class ├── ClassIDStyle.class ├── DataAttributes.class ├── GeneralPurpose.class ├── GetSetAttr.class ├── HasAndTest.class ├── IsTag.class ├── KeyOnlyAttributes.class ├── QuotationMarks.class ├── RemoveAttributes.class ├── RetrieveAllAttr.class ├── AUM.class ├── MetaTagName.class ├── Robots.class ├── SD.class ├── TC.class ├── Attributes.class ├── Balance.class ├── DPUtil.class ├── Debug.class ├── Escape.class ├── Features.class ├── InnerTags.class ├── Links.class ├── Listeners.class ├── PrettyPrint.class ├── ReplaceNodes.class ├── SplashBridge.class ├── Surrounding.class ├── Util.class ├── Remove.class ├── RemoveAll.class ├── RemoveData.class ├── Retrieve.class ├── Update.class ├── UpdateWithFilter.class ├── UsingStrFilter.class ├── WhiteListFilter.class ├── EscapeRepl.class ├── HTMLTagCounter.class ├── LinksResolve_KE.class ├── AddNewLines.class ├── RemAllIndent.class ├── ReplaceFunction.class ├── URLFilter.class ├── HTMLPage.class ├── HTMLPageMWT.class ├── HTMLTags.class ├── HTTPCodes.class ├── Scrape.class ├── HTMLRegEx.class ├── ParserRE.class ├── ParserREInternal.class ├── CommentNodeIndex.class ├── NodeIndex.class ├── Replaceable.class ├── ReplaceableAdapter.class ├── Replacement.class ├── SubSection.class ├── TagNodeIndex.class ├── TextNodeIndex.class ├── BalancedHTMLException.class ├── ClosingTagNodeException.class ├── ClosingTagNodeExpectedException.class ├── HREFException.class ├── HTMLTokException.class ├── InnerTagKeyException.class ├── InnerTagValueException.class ├── MalformedHTMLException.class ├── MalformedTagNodeException.class ├── NodeExpectedException.class ├── NodeNotFoundException.class ├── OpeningTagNodeExpectedException.class ├── QuotesException.class ├── ReplaceableException.class ├── ReplaceableOutOfBoundsException.class ├── ReplaceablesOverlappingException.class ├── ReplaceablesUnsortedException.class ├── SRCException.class ├── ScrapeException.class ├── SingletonException.class ├── TagNodeExpectedException.class ├── TextNodeExpectedException.class

All source files (.java) are organized in logical subdirectories under package-source/ for developer clarity and modularity. However, when Stage-01 Compilation completes, the compiled .class files are relocated into the root Torello/HTML/ directory.

This relocation aligns with Java's classpath requirements, which expect class files to be discoverable based on their declared package names — not based on the developer's source folder structure. The Build Tool bridges this gap by flattening the output structure after compilation.

Page originally drafted by ChatGPT on 2025-06-12.
Edited and formatted by Ralph Torello for use in the Torello Build Tool documentation.