Package org.apache.maven.buildcache
Class CacheControllerImpl
java.lang.Object
org.apache.maven.buildcache.CacheControllerImpl
- All Implemented Interfaces:
CacheController
CacheControllerImpl
-
Field Summary
Fields -
Constructor Summary
ConstructorsConstructorDescriptionCacheControllerImpl(org.apache.maven.project.MavenProjectHelper projectHelper, org.eclipse.aether.RepositorySystem repoSystem, org.apache.maven.artifact.handler.manager.ArtifactHandlerManager artifactHandlerManager, XmlService xmlService, LocalCacheRepository localCache, RemoteCacheRepository remoteCache, CacheConfig cacheConfig, ProjectInputCalculator projectInputCalculator, RestoredArtifactHandler restoreArtifactHandler, javax.inject.Provider<LifecyclePhasesHelper> providerLifecyclePhasesHelper) -
Method Summary
Modifier and TypeMethodDescriptionvoidattachGeneratedSources(org.apache.maven.project.MavenProject project, org.apache.maven.buildcache.CacheControllerImpl.ProjectCacheState state, long buildStartTime) findCachedBuild(org.apache.maven.execution.MavenSession session, org.apache.maven.project.MavenProject project, List<org.apache.maven.plugin.MojoExecution> mojoExecutions, boolean skipCache) booleanisForcedExecution(org.apache.maven.project.MavenProject project, org.apache.maven.plugin.MojoExecution execution) voidproduceDiffReport(CacheResult cacheResult, Build build) restoreProjectArtifacts(CacheResult cacheResult) voidrestoreStagedArtifacts(org.apache.maven.execution.MavenSession session, org.apache.maven.project.MavenProject project) Restore artifacts from staging directory after save() completes.voidsave(CacheResult cacheResult, List<org.apache.maven.plugin.MojoExecution> mojoExecutions, Map<String, org.apache.maven.execution.MojoExecutionEvent> executionEvents) voidsaveCacheReport(org.apache.maven.execution.MavenSession session) voidstagePreExistingArtifacts(org.apache.maven.execution.MavenSession session, org.apache.maven.project.MavenProject project) Move pre-existing build artifacts to staging directory to prevent caching stale files.
-
Field Details
-
ERROR_MSG_RESTORATION_OUTSIDE_PROJECT
- See Also:
-
-
Constructor Details
-
CacheControllerImpl
@Inject public CacheControllerImpl(org.apache.maven.project.MavenProjectHelper projectHelper, org.eclipse.aether.RepositorySystem repoSystem, org.apache.maven.artifact.handler.manager.ArtifactHandlerManager artifactHandlerManager, XmlService xmlService, LocalCacheRepository localCache, RemoteCacheRepository remoteCache, CacheConfig cacheConfig, ProjectInputCalculator projectInputCalculator, RestoredArtifactHandler restoreArtifactHandler, javax.inject.Provider<LifecyclePhasesHelper> providerLifecyclePhasesHelper)
-
-
Method Details
-
findCachedBuild
@Nonnull public CacheResult findCachedBuild(org.apache.maven.execution.MavenSession session, org.apache.maven.project.MavenProject project, List<org.apache.maven.plugin.MojoExecution> mojoExecutions, boolean skipCache) - Specified by:
findCachedBuildin interfaceCacheController
-
restoreProjectArtifacts
- Specified by:
restoreProjectArtifactsin interfaceCacheController
-
save
public void save(CacheResult cacheResult, List<org.apache.maven.plugin.MojoExecution> mojoExecutions, Map<String, org.apache.maven.execution.MojoExecutionEvent> executionEvents) - Specified by:
savein interfaceCacheController
-
produceDiffReport
-
isForcedExecution
public boolean isForcedExecution(org.apache.maven.project.MavenProject project, org.apache.maven.plugin.MojoExecution execution) - Specified by:
isForcedExecutionin interfaceCacheController
-
saveCacheReport
public void saveCacheReport(org.apache.maven.execution.MavenSession session) - Specified by:
saveCacheReportin interfaceCacheController
-
attachGeneratedSources
public void attachGeneratedSources(org.apache.maven.project.MavenProject project, org.apache.maven.buildcache.CacheControllerImpl.ProjectCacheState state, long buildStartTime) throws IOException - Throws:
IOException
-
stagePreExistingArtifacts
public void stagePreExistingArtifacts(org.apache.maven.execution.MavenSession session, org.apache.maven.project.MavenProject project) throws IOException Move pre-existing build artifacts to staging directory to prevent caching stale files.Artifacts Staged:
target/classes- Compiled main classes directorytarget/test-classes- Compiled test classes directorytarget/*.jar- Main project artifact (JAR/WAR files)- Other directories configured via
attachedOutputsin cache configuration
DESIGN RATIONALE - Staleness Detection via Staging Directory:
This approach solves three critical problems that timestamp-based checking cannot handle:
Problem 1: Future Timestamps from Clock Skew
- Machine A (clock ahead at 11:00 AM) builds and caches artifacts
- Machine B (correct clock at 10:00 AM) restores cache
- Restored files have timestamps from the future (11:00 AM)
- User switches branches or updates sources (sources timestamped 10:02 AM)
- Maven incremental compiler sees: sources (10:02 AM) < classes (11:00 AM)
- Maven skips compilation (thinks sources older than classes)
- Wrong classes from old source version get cached!
Problem 2: Orphaned Class Files from Deleted Sources
- Version A has Foo.java → compiles Foo.class
- Switch to Version B (no Foo.java)
- Foo.class remains in target/classes (orphaned)
- Cache miss on new version triggers mojos
- Without protection, orphaned Foo.class gets cached
- Future cache hits restore Foo.class (which shouldn't exist!)
Problem 3: Stale JARs/WARs from Previous Builds
- Yesterday: built myapp.jar on old version
- Today: switched to new version, sources changed
- mvn package runs (cache miss)
- If JAR wasn't rebuilt, stale JAR could be cached
Solution: Staging Directory Physical Separation
- Before mojos run: Move pre-existing artifacts to target/.maven-build-cache-stash/
- Maven sees clean target/ with no pre-existing artifacts
- Maven compiler MUST compile (can't skip based on timestamps)
- Fresh correct files created in target/
- save() only sees fresh files (stale ones are in staging directory)
- After save(): Restore artifacts from staging (delete if fresh version exists)
Why Better Than Timestamp Checking:
- No clock skew calculations needed
- Physical file separation (not heuristics)
- Forces correct incremental compilation
- Handles interrupted builds gracefully (just delete staging directory)
- Simpler and more robust
- Easier cleanup - delete one directory instead of filtering files
Interrupted Build Handling: If staging directory exists from interrupted previous run, it's deleted and recreated.
- Specified by:
stagePreExistingArtifactsin interfaceCacheController- Parameters:
session- The Maven sessionproject- The Maven project being built- Throws:
IOException- if file move operations fail
-
restoreStagedArtifacts
public void restoreStagedArtifacts(org.apache.maven.execution.MavenSession session, org.apache.maven.project.MavenProject project) Restore artifacts from staging directory after save() completes.For each artifact in staging:
- If fresh version exists in target/: Delete staged version (was rebuilt correctly)
- If fresh version missing: Move staged version back to target/ (wasn't rebuilt, still valid)
This ensures:
- save() only cached fresh files (stale ones were in staging directory)
- Developers see complete target/ directory after build
- Incremental builds work correctly (unchanged files restored)
Finally, deletes the staging directory.
- Specified by:
restoreStagedArtifactsin interfaceCacheController- Parameters:
session- The Maven sessionproject- The Maven project being built
-