Class ModuleScanDiagnostics
ComponentScanner and PluginManager both catch ClassNotFoundException |
LinkageError per class during a module's scan and skip-and-continue — the module still loads,
every other command still registers, and the one stale command silently does not exist. This
class does not change that shape; it only makes it loud. Its API is deliberately small: recordSkippedClass(String, String, Throwable) accumulates one skipped class for the module
currently being scanned, and emitSummary(String) — called once, after that module's
scan loop finishes — turns the accumulated list into exactly ONE Level.SEVERE record
naming the module, every skipped class, and pointing at COMPATIBILITY.md. A module that
skips nothing never calls the emitter at all, so a healthy startup produces no output from this
class whatsoever.
Never routes through the root logger. DIAGNOSTICS_LOGGER disables parent
handlers, exactly as RemoteActionLog does and for the same measured reason:
SystemLogHandler attaches only to the root (empty-name) logger and
auto-reports any Level.SEVERE record carrying a Throwable into
ErrorReportCollector — which would turn this per-module summary into an error report
and risk the circular logging both classes' javadoc already warns about. The summary emitted by
emitSummary(String) deliberately carries no Throwable for the same reason; the
individual causes live only on the per-class Level.FINE detail recorded by recordSkippedClass(String, String, Throwable). Disabling parent handlers also disconnects this
logger from the console/logs/latest.log sink the server installs on the root logger, so a
PluginLoggerBridge forwards the records to the plugin's own logger (#557) -- the summary
then reaches the console at its real level and in the server's normal log format. (A private
console handler used here before wrote to the standard error stream, which Paper prints as two
WARN lines per record.)
- Since:
- 6.3.0
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringThe pointer to the compatibility record that followsOLDER_API_CAUSEin both places.private static final Loggerstatic final StringThe cause phrase shared by this class's scan summary andPluginManager's refusal of a module whose declared main class fails to link against this framework, so an operator reads one wording for one cause.One accumulator entry per module currently being scanned; cleared as each is emitted. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic voidemitSummary(String moduleName) Emits ONELevel.SEVEREsummary formoduleNameif, and only if, at least one class was recorded for it since the last call — then resets the accumulator for that module, so a subsequent, cleanly-skip-free re-scan of the same module never repeats it.private static booleanstatic voidrecordSkippedClass(String moduleName, String className, Throwable cause) Records one class that failed to load duringmoduleName's scan, and immediately logs the per-class detail atLevel.FINEwithcauseattached — matching the shape the GEN-07 audit evaluator (D-14) also uses, so the two diagnostics read as one pattern.
-
Field Details
-
DIAGNOSTICS_LOGGER
-
OLDER_API_CAUSE
The cause phrase shared by this class's scan summary andPluginManager's refusal of a module whose declared main class fails to link against this framework, so an operator reads one wording for one cause.- See Also:
-
COMPATIBILITY_POINTER
The pointer to the compatibility record that followsOLDER_API_CAUSEin both places.- See Also:
-
SKIPPED_CLASSES_BY_MODULE
One accumulator entry per module currently being scanned; cleared as each is emitted.
-
-
Constructor Details
-
ModuleScanDiagnostics
private ModuleScanDiagnostics()
-
-
Method Details
-
recordSkippedClass
Records one class that failed to load duringmoduleName's scan, and immediately logs the per-class detail atLevel.FINEwithcauseattached — matching the shape the GEN-07 audit evaluator (D-14) also uses, so the two diagnostics read as one pattern.A
nullor blankmoduleNameorclassNameis ignored entirely — neither the accumulator nor the FINE detail record it — rather than producing a summary entry reading the literal text"null".- Parameters:
moduleName- the module (or, fromComponentScanner, the base package) whose scan is in progressclassName- the class that failed to loadcause- the exception the scan caught; may benull
-
emitSummary
Emits ONELevel.SEVEREsummary formoduleNameif, and only if, at least one class was recorded for it since the last call — then resets the accumulator for that module, so a subsequent, cleanly-skip-free re-scan of the same module never repeats it. A module with nothing recorded is a silent no-op: the emitter is never invoked at all.- Parameters:
moduleName- the module whose scan just finished
-
isBlank
-