diff --git a/src/main/java/org/codehaus/plexus/build/BuildContext.java b/src/main/java/org/codehaus/plexus/build/BuildContext.java
index f132223..ffefd24 100644
--- a/src/main/java/org/codehaus/plexus/build/BuildContext.java
+++ b/src/main/java/org/codehaus/plexus/build/BuildContext.java
@@ -167,10 +167,16 @@ public interface BuildContext {
*
* @see #setValue(String, Object)
* @see #isIncremental()
+ *
+ * The return type is inferred from the assignment target and is not checked here: a value of another type
+ * than the one the caller expects fails with a {@link ClassCastException} at the call site.
+ *
+ *
+ * @param the expected type of the value
* @param key a {@link java.lang.String} object.
- * @return a {@link java.lang.Object} object.
+ * @return the value, or {@code null} if there is none
*/
- Object getValue(String key);
+ T getValue(String key);
/**
* addWarning.
diff --git a/src/main/java/org/codehaus/plexus/build/DefaultBuildContext.java b/src/main/java/org/codehaus/plexus/build/DefaultBuildContext.java
index 5cde79a..5257358 100644
--- a/src/main/java/org/codehaus/plexus/build/DefaultBuildContext.java
+++ b/src/main/java/org/codehaus/plexus/build/DefaultBuildContext.java
@@ -152,11 +152,12 @@ public boolean isIncremental() {
}
/** {@inheritDoc} */
- public Object getValue(String key) {
+ @SuppressWarnings("unchecked")
+ public T getValue(String key) {
if (isDefaultImplementation()) {
- return contextMap.get(key);
+ return (T) contextMap.get(key);
}
- return legacy.getValue(key);
+ return (T) legacy.getValue(key);
}
/** {@inheritDoc} */
diff --git a/src/test/java/org/codehaus/plexus/build/BuildContextGetValueTypingTest.java b/src/test/java/org/codehaus/plexus/build/BuildContextGetValueTypingTest.java
new file mode 100644
index 0000000..305df03
--- /dev/null
+++ b/src/test/java/org/codehaus/plexus/build/BuildContextGetValueTypingTest.java
@@ -0,0 +1,29 @@
+package org.codehaus.plexus.build;
+
+/**
+ * Compile-time check that {@link BuildContext#getValue(String)} infers its result type from the assignment target, and
+ * that an implementation declaring the pre-generic {@code Object getValue(String)} still compiles. The module skips
+ * test execution, so this fails the build by not compiling.
+ */
+final class BuildContextGetValueTypingTest {
+
+ private BuildContextGetValueTypingTest() {}
+
+ static String inferredFromAssignment(BuildContext context) {
+ String value = context.getValue("key");
+ return value;
+ }
+
+ static Object plainObjectStillWorks(BuildContext context) {
+ Object value = context.getValue("key");
+ return value;
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ abstract static class PreGenericImplementation implements BuildContext {
+ @Override
+ public Object getValue(String key) {
+ return null;
+ }
+ }
+}