Skip to content

Commit b17ea7c

Browse files
Copilotlaeubi
andcommitted
Implement Messages API with builder pattern
Co-authored-by: laeubi <[email protected]>
1 parent 07aabd9 commit b17ea7c

File tree

6 files changed

+522
-0
lines changed

6 files changed

+522
-0
lines changed

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,47 @@ The project was relocated from <https://github.com/sonatype/sisu-build-api>. Als
3232

3333
## Provided APIs
3434

35+
### Messages API
36+
37+
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.
38+
39+
**Key Features:**
40+
- Builder pattern for flexible message construction
41+
- Clear separation of concerns from resource operations
42+
- Support for error, warning, and info messages
43+
- File path-based message management
44+
- Optional line and column information
45+
- Optional exception cause association
46+
47+
**Example Usage:**
48+
49+
```java
50+
@Inject
51+
private Messages messages;
52+
53+
public void execute() {
54+
// Create an error message
55+
messages.buildError(Paths.get("/path/to/file.java"))
56+
.line(42)
57+
.column(10)
58+
.message("Syntax error")
59+
.cause(exception)
60+
.create();
61+
62+
// Create a warning message
63+
messages.buildWarning(Paths.get("/path/to/file.java"))
64+
.line(15)
65+
.message("Deprecated method used")
66+
.create();
67+
68+
// Clear messages for a specific file
69+
messages.clear(Paths.get("/path/to/file.java"));
70+
71+
// Clear all messages
72+
messages.clearAll();
73+
}
74+
```
75+
3576
### Progress
3677

3778
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.
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/*
2+
Copyright (c) 2008 Sonatype, Inc. All rights reserved.
3+
4+
This program is licensed to you under the Apache License Version 2.0,
5+
and you may not use this file except in compliance with the Apache License Version 2.0.
6+
You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
7+
8+
Unless required by applicable law or agreed to in writing,
9+
software distributed under the Apache License Version 2.0 is distributed on an
10+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
12+
*/
13+
package org.codehaus.plexus.build.messages;
14+
15+
import javax.inject.Inject;
16+
import javax.inject.Named;
17+
import javax.inject.Singleton;
18+
19+
import java.nio.file.Path;
20+
21+
import org.codehaus.plexus.build.BuildContext;
22+
import org.slf4j.Logger;
23+
import org.slf4j.LoggerFactory;
24+
25+
/**
26+
* Default implementation of the Messages interface.
27+
* <p>
28+
* This implementation delegates to the BuildContext for compatibility with existing
29+
* message handling infrastructure. It logs messages and calls the legacy BuildContext
30+
* message API.
31+
* </p>
32+
*/
33+
@Named("default")
34+
@Singleton
35+
public class DefaultMessages implements Messages {
36+
37+
private static final Logger logger = LoggerFactory.getLogger(DefaultMessages.class);
38+
39+
private final BuildContext buildContext;
40+
41+
/**
42+
* Creates a new DefaultMessages instance.
43+
*
44+
* @param buildContext the BuildContext to which messages will be delegated
45+
*/
46+
@Inject
47+
public DefaultMessages(BuildContext buildContext) {
48+
this.buildContext = buildContext;
49+
}
50+
51+
@Override
52+
public void clearAll() {
53+
// This is a no-op in the default implementation
54+
// Custom implementations may provide actual clearing functionality
55+
}
56+
57+
@Override
58+
public void clear(Path path) {
59+
if (path != null) {
60+
buildContext.removeMessages(path.toFile());
61+
}
62+
}
63+
64+
@Override
65+
public MessageBuilder buildError(Path path) {
66+
return build(MessageType.ERROR, path);
67+
}
68+
69+
@Override
70+
public MessageBuilder buildWarning(Path path) {
71+
return build(MessageType.WARNING, path);
72+
}
73+
74+
@Override
75+
public MessageBuilder buildInfo(Path path) {
76+
return build(MessageType.INFO, path);
77+
}
78+
79+
@Override
80+
public MessageBuilder build(MessageType type, Path path) {
81+
return new MessageBuilder(type, path, this::handleMessage);
82+
}
83+
84+
/**
85+
* Handles a message by logging it and delegating to the BuildContext.
86+
*
87+
* @param message the message to handle
88+
*/
89+
private void handleMessage(Message message) {
90+
// Log the message
91+
String logMessage = formatLogMessage(message);
92+
93+
switch (message.getType()) {
94+
case ERROR:
95+
logger.error(logMessage, message.getCause());
96+
break;
97+
case WARNING:
98+
logger.warn(logMessage, message.getCause());
99+
break;
100+
case INFO:
101+
logger.info(logMessage, message.getCause());
102+
break;
103+
}
104+
105+
// Delegate to BuildContext for compatibility
106+
if (message.getPath() != null) {
107+
int severity = mapTypeToSeverity(message.getType());
108+
buildContext.addMessage(
109+
message.getPath().toFile(),
110+
message.getLine(),
111+
message.getColumn(),
112+
message.getMessage(),
113+
severity,
114+
message.getCause());
115+
}
116+
}
117+
118+
/**
119+
* Formats a message for logging.
120+
*
121+
* @param message the message to format
122+
* @return the formatted log message
123+
*/
124+
private String formatLogMessage(Message message) {
125+
StringBuilder sb = new StringBuilder();
126+
127+
if (message.getPath() != null) {
128+
sb.append(message.getPath().toAbsolutePath());
129+
}
130+
131+
if (message.getLine() > 0 || message.getColumn() > 0) {
132+
sb.append(" [");
133+
if (message.getLine() > 0) {
134+
sb.append(message.getLine());
135+
}
136+
if (message.getColumn() > 0) {
137+
sb.append(':').append(message.getColumn());
138+
}
139+
sb.append("]");
140+
}
141+
142+
if (message.getMessage() != null) {
143+
if (sb.length() > 0) {
144+
sb.append(": ");
145+
}
146+
sb.append(message.getMessage());
147+
}
148+
149+
return sb.toString();
150+
}
151+
152+
/**
153+
* Maps a MessageType to a BuildContext severity level.
154+
*
155+
* @param type the message type
156+
* @return the corresponding BuildContext severity
157+
*/
158+
private int mapTypeToSeverity(MessageType type) {
159+
switch (type) {
160+
case ERROR:
161+
return BuildContext.SEVERITY_ERROR;
162+
case WARNING:
163+
return BuildContext.SEVERITY_WARNING;
164+
case INFO:
165+
default:
166+
// There's no INFO severity in BuildContext, use WARNING as fallback
167+
return BuildContext.SEVERITY_WARNING;
168+
}
169+
}
170+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
Copyright (c) 2008 Sonatype, Inc. All rights reserved.
3+
4+
This program is licensed to you under the Apache License Version 2.0,
5+
and you may not use this file except in compliance with the Apache License Version 2.0.
6+
You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
7+
8+
Unless required by applicable law or agreed to in writing,
9+
software distributed under the Apache License Version 2.0 is distributed on an
10+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
12+
*/
13+
package org.codehaus.plexus.build.messages;
14+
15+
import java.nio.file.Path;
16+
17+
/**
18+
* Represents a message with all its parameters.
19+
* This class holds the collected parameters for a message that can be created through the MessageBuilder.
20+
*/
21+
public class Message {
22+
private final MessageType type;
23+
private final Path path;
24+
private final int line;
25+
private final int column;
26+
private final String message;
27+
private final Throwable cause;
28+
29+
/**
30+
* Creates a new message with the specified parameters.
31+
*
32+
* @param type the message type
33+
* @param path the file path associated with this message
34+
* @param line the line number (1-based, 0 for unknown)
35+
* @param column the column number (1-based, 0 for unknown)
36+
* @param message the message text
37+
* @param cause the exception cause, can be null
38+
*/
39+
public Message(MessageType type, Path path, int line, int column, String message, Throwable cause) {
40+
this.type = type;
41+
this.path = path;
42+
this.line = line;
43+
this.column = column;
44+
this.message = message;
45+
this.cause = cause;
46+
}
47+
48+
/**
49+
* @return the message type
50+
*/
51+
public MessageType getType() {
52+
return type;
53+
}
54+
55+
/**
56+
* @return the file path
57+
*/
58+
public Path getPath() {
59+
return path;
60+
}
61+
62+
/**
63+
* @return the line number (1-based, 0 for unknown)
64+
*/
65+
public int getLine() {
66+
return line;
67+
}
68+
69+
/**
70+
* @return the column number (1-based, 0 for unknown)
71+
*/
72+
public int getColumn() {
73+
return column;
74+
}
75+
76+
/**
77+
* @return the message text
78+
*/
79+
public String getMessage() {
80+
return message;
81+
}
82+
83+
/**
84+
* @return the exception cause, or null if none
85+
*/
86+
public Throwable getCause() {
87+
return cause;
88+
}
89+
}

0 commit comments

Comments
 (0)