diff --git a/README.md b/README.md index 84a33e8..4509abf 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,45 @@ The project was relocated from . Als ## Provided APIs +### Messages API + +The Messages API provides a modern, flexible way to create and manage build messages/markers that inform users in an IDE about issues in their files. It uses a builder pattern for constructing messages in a more convenient and extensible way compared to the legacy BuildContext message methods. + +**Key Features:** +- Builder pattern for flexible message construction +- Clear separation of concerns from resource operations +- Support for error, warning, and info messages +- File path-based message management +- Optional line and column information +- Optional exception cause association + +**Example Usage:** + +```java +@Inject +private Messages messages; + +public void execute() { + // Create an error message + messages.error(Paths.get("/path/to/file.java")) + .line(42) + .column(10) + .cause(exception) + .create("Syntax error"); + + // Create a warning message + messages.warning(Paths.get("/path/to/file.java")) + .line(15) + .create("Deprecated method used"); + + // Clear messages for a specific file + messages.clear(Paths.get("/path/to/file.java")); + + // Clear all messages + messages.clearAll(); +} +``` + ### Progress The API allows a mojo to report progress in a way that is suitable to be shown as a progressbar as well as check if the user wants the mojo to gracefully abort its current operation. diff --git a/src/main/java/org/codehaus/plexus/build/BuildContext.java b/src/main/java/org/codehaus/plexus/build/BuildContext.java index 8f54425..f132223 100644 --- a/src/main/java/org/codehaus/plexus/build/BuildContext.java +++ b/src/main/java/org/codehaus/plexus/build/BuildContext.java @@ -209,7 +209,9 @@ public interface BuildContext { * @param cause A Throwable object associated with the message. Can be null. * @since 0.0.7 * @param message a {@link java.lang.String} object. + * @deprecated Use {@link org.codehaus.plexus.build.messages.Messages} API instead */ + @Deprecated void addMessage(File file, int line, int column, String message, int severity, Throwable cause); /** @@ -218,7 +220,9 @@ public interface BuildContext { * * @since 0.0.7 * @param file a {@link java.io.File} object. + * @deprecated Use {@link org.codehaus.plexus.build.messages.Messages#clear(java.nio.file.Path)} instead */ + @Deprecated void removeMessages(File file); /** diff --git a/src/main/java/org/codehaus/plexus/build/messages/DefaultMessages.java b/src/main/java/org/codehaus/plexus/build/messages/DefaultMessages.java new file mode 100644 index 0000000..b10d36f --- /dev/null +++ b/src/main/java/org/codehaus/plexus/build/messages/DefaultMessages.java @@ -0,0 +1,134 @@ +/* +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.messages; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import java.nio.file.Path; + +import org.codehaus.plexus.build.BuildContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Default implementation of the Messages interface. + *

+ * This implementation delegates to the BuildContext for compatibility with existing + * message handling infrastructure. It logs messages and calls the legacy BuildContext + * message API. + *

+ */ +@Named("default") +@Singleton +public class DefaultMessages implements Messages { + + private static final Logger logger = LoggerFactory.getLogger(DefaultMessages.class); + + private final BuildContext buildContext; + + /** + * Creates a new DefaultMessages instance. + * + * @param buildContext the BuildContext to which messages will be delegated + */ + @Inject + public DefaultMessages(BuildContext buildContext) { + this.buildContext = buildContext; + } + + @Override + public void clearAll() { + // This is a no-op in the default implementation + // Custom implementations may provide actual clearing functionality + } + + @Override + public void clear(Path path) { + if (path != null) { + buildContext.removeMessages(path.toFile()); + } + } + + @Override + public MessageBuilder error(Path path) { + return build(MessageType.ERROR, path); + } + + @Override + public MessageBuilder warning(Path path) { + return build(MessageType.WARNING, path); + } + + @Override + public MessageBuilder info(Path path) { + return build(MessageType.INFO, path); + } + + @Override + public MessageBuilder build(MessageType type, Path path) { + return new MessageBuilder(type, path, this::handleMessage); + } + + /** + * Handles a message by logging it and delegating to the BuildContext. + * + * @param message the message to handle + */ + private void handleMessage(Message message) { + // Log the message + String logMessage = message.toString(); + + switch (message.getType()) { + case ERROR: + logger.error(logMessage, message.getCause()); + break; + case WARNING: + logger.warn(logMessage, message.getCause()); + break; + case INFO: + logger.info(logMessage, message.getCause()); + break; + } + + // Delegate to BuildContext for compatibility + if (message.getPath() != null) { + int severity = mapTypeToSeverity(message.getType()); + buildContext.addMessage( + message.getPath().toFile(), + message.getLine(), + message.getColumn(), + message.getMessage(), + severity, + message.getCause()); + } + } + + /** + * Maps a MessageType to a BuildContext severity level. + * + * @param type the message type + * @return the corresponding BuildContext severity + */ + private int mapTypeToSeverity(MessageType type) { + switch (type) { + case ERROR: + return BuildContext.SEVERITY_ERROR; + case WARNING: + return BuildContext.SEVERITY_WARNING; + case INFO: + default: + // BuildContext supports 0 as an info severity level (undocumented) + return 0; + } + } +} diff --git a/src/main/java/org/codehaus/plexus/build/messages/Message.java b/src/main/java/org/codehaus/plexus/build/messages/Message.java new file mode 100644 index 0000000..3709b27 --- /dev/null +++ b/src/main/java/org/codehaus/plexus/build/messages/Message.java @@ -0,0 +1,126 @@ +/* +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.messages; + +import java.nio.file.Path; + +/** + * Represents a message with all its parameters. + * This class holds the collected parameters for a message that can be created through the MessageBuilder. + */ +public class Message { + private final MessageType type; + private final Path path; + private final int line; + private final int column; + private final String message; + private final Throwable cause; + + /** + * Creates a new message with the specified parameters. + * + * @param type the message type + * @param path the file path associated with this message + * @param line the line number (1-based, 0 for unknown) + * @param column the column number (1-based, 0 for unknown) + * @param message the message text + * @param cause the exception cause, can be null + */ + Message(MessageType type, Path path, int line, int column, String message, Throwable cause) { + this.type = type; + this.path = path; + this.line = line; + this.column = column; + this.message = message; + this.cause = cause; + } + + /** + * @return the message type + */ + public MessageType getType() { + return type; + } + + /** + * @return the file path + */ + public Path getPath() { + return path; + } + + /** + * @return the line number (1-based, 0 for unknown) + */ + public int getLine() { + return line; + } + + /** + * @return the column number (1-based, 0 for unknown) + */ + public int getColumn() { + return column; + } + + /** + * @return the message text + */ + public String getMessage() { + return message; + } + + /** + * @return the exception cause, or null if none + */ + public Throwable getCause() { + return cause; + } + + /** + * Returns a string representation of this message. + * The format is: path [line:column]: message + * + * @return the formatted message string + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + if (path != null) { + sb.append(path.toAbsolutePath()); + } + + if (line > 0 && column > 0) { + sb.append(" ["); + sb.append(line); + sb.append(':').append(column); + sb.append("]"); + } else if (line > 0) { + sb.append(" ["); + sb.append(line); + sb.append("]"); + } else if (column > 0) { + sb.append(" [:"); + sb.append(column); + sb.append("]"); + } + + if (message != null) { + if (sb.length() > 0) { + sb.append(": "); + } + sb.append(message); + } + + return sb.toString(); + } +} diff --git a/src/main/java/org/codehaus/plexus/build/messages/MessageBuilder.java b/src/main/java/org/codehaus/plexus/build/messages/MessageBuilder.java new file mode 100644 index 0000000..55c8491 --- /dev/null +++ b/src/main/java/org/codehaus/plexus/build/messages/MessageBuilder.java @@ -0,0 +1,96 @@ +/* +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.messages; + +import java.nio.file.Path; +import java.util.function.Consumer; + +/** + * Builder class for constructing messages. + *

+ * This class implements the builder pattern for creating messages with various parameters. + * It is typically not called directly by client code, but is used internally by the Messages API + * implementations. + *

+ */ +public class MessageBuilder { + private final MessageType type; + private final Path path; + private final Consumer consumer; + + private int line = 0; + private int column = 0; + private Throwable cause; + + /** + * Creates a new MessageBuilder. + *

+ * Note: This constructor is usually not called by client code. Use the builder methods + * provided by the {@link Messages} interface instead (e.g., buildError, buildWarning, buildInfo). + *

+ * + * @param type the type of message to build + * @param path the file path for which the message should be created + * @param consumer the consumer that will receive the constructed message + */ + public MessageBuilder(MessageType type, Path path, Consumer consumer) { + this.type = type; + this.path = path; + this.consumer = consumer; + } + + /** + * Sets the line number for the message. + * + * @param line the line number (1-based, use 0 for unknown) + * @return this builder for method chaining + */ + public MessageBuilder line(int line) { + this.line = line; + return this; + } + + /** + * Sets the column number for the message. + * + * @param column the column number (1-based, use 0 for unknown) + * @return this builder for method chaining + */ + public MessageBuilder column(int column) { + this.column = column; + return this; + } + + /** + * Sets the exception cause for the message. + * + * @param cause the exception that caused this message + * @return this builder for method chaining + */ + public MessageBuilder cause(Throwable cause) { + this.cause = cause; + return this; + } + + /** + * Creates the message object with all collected parameters and informs the consumer. + * This method finalizes the builder and creates the message. + * + * @param message the message text (must not be null or blank) + */ + public void create(String message) { + if (message == null || message.trim().isEmpty()) { + throw new IllegalArgumentException("Message text must not be null or blank"); + } + Message msg = new Message(type, path, line, column, message, cause); + consumer.accept(msg); + } +} diff --git a/src/main/java/org/codehaus/plexus/build/messages/MessageType.java b/src/main/java/org/codehaus/plexus/build/messages/MessageType.java new file mode 100644 index 0000000..69a859c --- /dev/null +++ b/src/main/java/org/codehaus/plexus/build/messages/MessageType.java @@ -0,0 +1,31 @@ +/* +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.messages; + +/** + * Enum representing the type/severity of a message. + */ +public enum MessageType { + /** + * Informational message + */ + INFO, + + /** + * Warning message + */ + WARNING, + + /** + * Error message + */ + ERROR +} diff --git a/src/main/java/org/codehaus/plexus/build/messages/Messages.java b/src/main/java/org/codehaus/plexus/build/messages/Messages.java new file mode 100644 index 0000000..52030d2 --- /dev/null +++ b/src/main/java/org/codehaus/plexus/build/messages/Messages.java @@ -0,0 +1,81 @@ +/* +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.messages; + +import java.nio.file.Path; + +/** + *

Messages interface.

+ *

+ * This API provides a modern, flexible way to create and manage build messages/markers + * that inform users in an IDE about issues in their files. It uses a builder pattern + * for constructing messages in a more convenient and extensible way compared to the + * legacy BuildContext message methods. + *

+ *

+ * Example usage: + *

+ *
+ * messages.error(Paths.get("/path/to/file.java"))
+ *     .line(42)
+ *     .column(10)
+ *     .create("Syntax error");
+ * 
+ */ +public interface Messages { + + /** + * Clears all messages. + * This removes all messages that were previously created through this API. + */ + void clearAll(); + + /** + * Clears messages associated with a specific path. + * + * @param path the file path for which to clear messages + */ + void clear(Path path); + + /** + * Creates a builder for an error message. + * + * @param path the file path for which the error message should be created + * @return a MessageBuilder for constructing the error message + */ + MessageBuilder error(Path path); + + /** + * Creates a builder for a warning message. + * + * @param path the file path for which the warning message should be created + * @return a MessageBuilder for constructing the warning message + */ + MessageBuilder warning(Path path); + + /** + * Creates a builder for an informational message. + * + * @param path the file path for which the info message should be created + * @return a MessageBuilder for constructing the info message + */ + MessageBuilder info(Path path); + + /** + * Creates a builder for a message of a specific type. + * This is the generic method that the other build methods delegate to. + * + * @param type the type of message to build + * @param path the file path for which the message should be created + * @return a MessageBuilder for constructing the message + */ + MessageBuilder build(MessageType type, Path path); +}