-
Notifications
You must be signed in to change notification settings - Fork 3
Add Resources API with Path-based methods #104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Copilot
wants to merge
4
commits into
master
Choose a base branch
from
copilot/add-new-resources-api
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 3 commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
5c1d60c
Initial plan
Copilot 47df1a9
Add new Resources API with Path-based methods
Copilot b9f0758
Address code review feedback on Resources API documentation
Copilot 495f4ad
Use LegacySupport to get Maven project basedir in Resources.getPath()…
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
142 changes: 142 additions & 0 deletions
142
src/main/java/org/codehaus/plexus/build/resources/DefaultResources.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| /* | ||
| Copyright (c) 2008 Sonatype, Inc. All rights reserved. | ||
|
|
||
| This program is licensed to you under the Apache License Version 2.0, | ||
| and you may not use this file except in compliance with the Apache License Version 2.0. | ||
| You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. | ||
|
|
||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the Apache License Version 2.0 is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. | ||
| */ | ||
| package org.codehaus.plexus.build.resources; | ||
|
|
||
| import javax.inject.Inject; | ||
| import javax.inject.Named; | ||
| import javax.inject.Singleton; | ||
|
|
||
| import java.io.IOException; | ||
| import java.io.InputStream; | ||
| import java.io.OutputStream; | ||
| import java.nio.file.Files; | ||
| import java.nio.file.Path; | ||
|
|
||
| import org.codehaus.plexus.build.BuildContext; | ||
|
|
||
| /** | ||
| * Default implementation of the Resources interface. | ||
| * <p> | ||
| * This implementation delegates to the BuildContext for compatibility with existing | ||
| * build infrastructure. It provides a transition path from the File-based API to the | ||
| * modern Path-based API. | ||
| * </p> | ||
| */ | ||
| @Named("default") | ||
| @Singleton | ||
| public class DefaultResources implements Resources { | ||
|
|
||
| private final BuildContext buildContext; | ||
|
|
||
| /** | ||
| * Creates a new DefaultResources instance. | ||
| * | ||
| * @param buildContext the BuildContext to which operations will be delegated | ||
| */ | ||
| @Inject | ||
| public DefaultResources(BuildContext buildContext) { | ||
| this.buildContext = buildContext; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean hasDelta(Path file) { | ||
| if (file == null) { | ||
| return false; | ||
| } | ||
| return buildContext.hasDelta(file.toFile()); | ||
| } | ||
|
|
||
| @Override | ||
| public void refresh(Path file) { | ||
| if (file != null) { | ||
| buildContext.refresh(file.toFile()); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public OutputStream newOutputStream(Path file) throws IOException { | ||
| if (file == null) { | ||
| throw new IllegalArgumentException("file cannot be null"); | ||
| } | ||
| return buildContext.newFileOutputStream(file.toFile()); | ||
| } | ||
|
|
||
| @Override | ||
| public OutputStream newOutputStream(Path file, boolean derived) throws IOException { | ||
| OutputStream outputStream = newOutputStream(file); | ||
| if (derived) { | ||
| // Mark the file as derived after creating the output stream. | ||
| // In the default implementation, markDerived is a no-op, so the timing doesn't matter. | ||
| // Custom implementations that track derived files should consider wrapping the stream | ||
| // to defer marking until successful close() to avoid marking files on failed writes. | ||
| markDerived(file); | ||
| } | ||
| return outputStream; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isUptodate(Path target, Path source) { | ||
| if (target == null || source == null) { | ||
| return false; | ||
| } | ||
| return buildContext.isUptodate(target.toFile(), source.toFile()); | ||
| } | ||
|
|
||
| @Override | ||
| public Path getPath(String relpath) { | ||
| if (relpath == null) { | ||
| throw new IllegalArgumentException("relpath cannot be null"); | ||
| } | ||
| // Note: The BuildContext API doesn't expose basedir directly. | ||
| // This default implementation resolves paths relative to the current working directory. | ||
| // Custom implementations (e.g., IDE integrations) should override this method | ||
| // to resolve against the actual build context basedir. | ||
| return java.nio.file.Paths.get(relpath); | ||
| } | ||
|
|
||
| @Override | ||
| public void markDerived(Path file) { | ||
| // No-op in the default implementation | ||
| // Custom implementations (e.g., IDE integrations) can override this | ||
| // to provide actual derived file tracking | ||
| } | ||
|
|
||
| @Override | ||
| public void copy(Path source, Path target) throws IOException { | ||
| if (source == null) { | ||
| throw new IllegalArgumentException("source cannot be null"); | ||
| } | ||
| if (target == null) { | ||
| throw new IllegalArgumentException("target cannot be null"); | ||
| } | ||
|
|
||
| // Only copy if the target is not up-to-date with the source | ||
| if (!isUptodate(target, source)) { | ||
| // Ensure parent directory exists | ||
| Path parentDir = target.getParent(); | ||
| if (parentDir != null && !Files.exists(parentDir)) { | ||
| Files.createDirectories(parentDir); | ||
| } | ||
|
|
||
| // Copy using Files API and newOutputStream to ensure proper change detection | ||
| try (InputStream in = Files.newInputStream(source); | ||
| OutputStream out = newOutputStream(target)) { | ||
| byte[] buffer = new byte[8192]; | ||
| int bytesRead; | ||
| while ((bytesRead = in.read(buffer)) != -1) { | ||
| out.write(buffer, 0, bytesRead); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
184 changes: 184 additions & 0 deletions
184
src/main/java/org/codehaus/plexus/build/resources/Resources.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,184 @@ | ||
| /* | ||
| Copyright (c) 2008 Sonatype, Inc. All rights reserved. | ||
|
|
||
| This program is licensed to you under the Apache License Version 2.0, | ||
| and you may not use this file except in compliance with the Apache License Version 2.0. | ||
| You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. | ||
|
|
||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the Apache License Version 2.0 is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. | ||
| */ | ||
| package org.codehaus.plexus.build.resources; | ||
|
|
||
| import java.io.IOException; | ||
| import java.io.OutputStream; | ||
| import java.nio.file.Path; | ||
|
|
||
| /** | ||
| * <p>Resources interface.</p> | ||
| * <p> | ||
| * This API provides a modern, flexible way to manage build resources using Path-based methods. | ||
| * It separates resource management concerns from logging/messaging functionality and provides | ||
| * better control over file operations during the build process. | ||
| * </p> | ||
| * <p> | ||
| * Example usage: | ||
| * </p> | ||
| * <pre> | ||
| * // Convert relative path to absolute Path | ||
| * Path sourceFile = resources.getPath("src/main/java/Example.java"); | ||
| * Path targetFile = resources.getPath("target/classes/Example.class"); | ||
| * | ||
| * // Copy source to target only if needed | ||
| * resources.copy(sourceFile, targetFile); | ||
| * | ||
| * // Mark generated file as derived | ||
| * resources.markDerived(targetFile); | ||
| * </pre> | ||
| */ | ||
| public interface Resources { | ||
|
|
||
| /** | ||
| * Returns <code>true</code> if the file has changed since last build. | ||
| * <p> | ||
| * <strong>Important:</strong> This is a "best effort" hint and should primarily be used | ||
| * for user-editable source files where you want to detect changes. For generated | ||
| * files or when there is a clear input/output relationship, prefer using | ||
| * {@link #isUptodate(Path, Path)} instead, as it handles cases where target files | ||
| * may be deleted or modified outside of the build process. | ||
| * </p> | ||
| * | ||
| * @param file the file to check for changes | ||
| * @return <code>true</code> if the file has changed or if the file is not under basedir | ||
| */ | ||
| boolean hasDelta(Path file); | ||
|
|
||
| /** | ||
| * Indicates that the file or folder content has been modified during the build. | ||
| * <p> | ||
| * This method should be called when file content is modified through means other | ||
| * than {@link #newOutputStream(Path)} or {@link #newOutputStream(Path, boolean)}. | ||
| * Files changed using OutputStreams returned by those methods do not need to be | ||
| * explicitly refreshed. | ||
| * </p> | ||
| * | ||
| * @param file the file that was modified | ||
| */ | ||
| void refresh(Path file); | ||
|
|
||
| /** | ||
| * Returns a new OutputStream that writes to the specified file. | ||
| * <p> | ||
| * Files changed using OutputStream returned by this method do not need to be | ||
| * explicitly refreshed using {@link #refresh(Path)}. | ||
| * </p> | ||
| * <p> | ||
| * As an optimization, some implementations may attempt to avoid writing to the file | ||
| * if the file content has not changed. This ensures that file timestamps are only | ||
| * updated when actual changes occur, which is important for incremental build performance. | ||
| * This optimization is implementation-dependent and may not apply to all implementations. | ||
| * </p> | ||
| * | ||
| * @param file the file to write to | ||
| * @return an OutputStream for writing to the file | ||
| * @throws IOException if an I/O error occurs | ||
| */ | ||
| OutputStream newOutputStream(Path file) throws IOException; | ||
|
|
||
| /** | ||
| * Returns a new OutputStream that writes to the specified file and optionally | ||
| * marks it as derived. | ||
| * <p> | ||
| * Files changed using OutputStream returned by this method do not need to be | ||
| * explicitly refreshed using {@link #refresh(Path)}. | ||
| * </p> | ||
| * <p> | ||
| * As an optimization, some implementations may attempt to avoid writing to the file | ||
| * if the file content has not changed. This optimization is implementation-dependent | ||
| * and may not apply to all implementations. | ||
| * </p> | ||
| * <p> | ||
| * When <code>derived</code> is <code>true</code>, the file is marked as generated/derived, | ||
| * which can be used by IDEs to warn users if they attempt to edit the file. | ||
| * This is useful for code generators that will overwrite any manual changes on | ||
| * subsequent builds. | ||
| * </p> | ||
| * | ||
| * @param file the file to write to | ||
| * @param derived <code>true</code> to mark the file as derived/generated | ||
| * @return an OutputStream for writing to the file | ||
| * @throws IOException if an I/O error occurs | ||
| */ | ||
| OutputStream newOutputStream(Path file, boolean derived) throws IOException; | ||
|
|
||
| /** | ||
| * Returns <code>true</code> if the target file exists and is up-to-date compared | ||
| * to the source file. | ||
| * <p> | ||
| * More specifically, this method returns <code>true</code> when both target and | ||
| * source files exist, do not have changes since last incremental build, and the | ||
| * target file was last modified later than the source file. Returns <code>false</code> | ||
| * in all other cases. | ||
| * </p> | ||
| * <p> | ||
| * This method should be preferred over {@link #hasDelta(Path)} when there is a | ||
| * clear input/output relationship between files, as it properly handles cases | ||
| * where the target file may be deleted or modified outside of the build process. | ||
| * </p> | ||
| * | ||
| * @param target the target/output file | ||
| * @param source the source/input file | ||
| * @return <code>true</code> if the target is up-to-date with the source | ||
| */ | ||
| boolean isUptodate(Path target, Path source); | ||
|
|
||
| /** | ||
| * Converts a relative path string to an absolute Path based on the build context basedir. | ||
| * <p> | ||
| * This method is useful for converting relative paths (e.g., "src/main/java/Example.java") | ||
| * to absolute Paths that can be used with other methods in this interface. | ||
| * </p> | ||
| * | ||
| * @param relpath the relative path string | ||
| * @return the absolute Path resolved against the build context basedir | ||
| */ | ||
| Path getPath(String relpath); | ||
|
|
||
| /** | ||
| * Marks a file as derived (generated) by the build process. | ||
| * <p> | ||
| * This is useful for code generators and other build plugins that create files | ||
| * that should not be edited manually. IDEs can use this information to warn | ||
| * users if they attempt to modify derived files, as such changes will typically | ||
| * be overwritten on the next build. | ||
| * </p> | ||
| * <p> | ||
| * Note: In the default implementation, this is a no-op. Custom implementations | ||
| * (e.g., IDE integrations) may provide actual derived file tracking. | ||
| * </p> | ||
| * | ||
| * @param file the file to mark as derived | ||
| */ | ||
| void markDerived(Path file); | ||
|
|
||
| /** | ||
| * Copies the source file to the target file if the target is not up-to-date. | ||
| * <p> | ||
| * This is a convenience method that combines {@link #isUptodate(Path, Path)} | ||
| * checking with file copying using {@link #newOutputStream(Path)}. The copy | ||
| * only occurs when the target does not exist or is not up-to-date with the source. | ||
| * </p> | ||
| * <p> | ||
| * The implementation uses the Files API to open an input stream from the source | ||
| * and copies it to an output stream obtained from {@link #newOutputStream(Path)}, | ||
| * ensuring that the target's timestamp is only updated if the content actually changes. | ||
| * </p> | ||
| * | ||
| * @param source the source file to copy from | ||
| * @param target the target file to copy to | ||
| * @throws IOException if an I/O error occurs during the copy operation | ||
| */ | ||
| void copy(Path source, Path target) throws IOException; | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use
LegacySupporthere to get the current maven project and return the basedir then.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to use LegacySupport to get the current Maven project and resolve paths against the project basedir. Falls back to current working directory if project is not available. See commit 495f4ad.