Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
###############################################################################
# Copyright (c) 2010, 2020 IBM Corporation and others.
# Copyright (c) 2010, 2025 IBM Corporation and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License 2.0
# which accompanies this distribution, and is available at
Expand Down Expand Up @@ -498,5 +498,9 @@ error.config.root.deleted=CWWKG0110E: A configuration update was detected, but t
error.config.root.deleted.explanation=The server.xml file was deleted. To cause no disruptions to running apps, no configuration changes are made.
error.config.root.deleted.useraction=Add the server.xml file back to the server.

error.potential.malformed.element=CWWKG0111E: Potential malformed XML element detected in configuration: [{0}] at line {1} in {2}. This text appears to be an XML element but is missing the opening angle bracket (<). Verify that the syntax is correct.
error.potential.malformed.element.explanation=The configuration parser detected text that might be a malformed XML element. This error typically occurs when an element is missing its opening angle bracket (<).
error.potential.malformed.element.useraction=Check the configuration file at the specified line and ensure that all XML elements start with an opening angle bracket (<).

# Non-TR message
error.invalidOCDRef=ERROR: Metatype PID [{0}] specifies non-existent object class definition ID [{1}]
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ private boolean parseServerConfiguration(DepthAwareXMLStreamReader parser, Strin
}
// If we get here, there is a single element in the file and it is not <server> or <client>
logError(ThrowBehavior.ALWAYS_THROW_EXCEPTION, "error.root.must.be.server", docLocation, processType);
return false; // Dead code because of the always-throw above, but we must please the compiler.
return false; // Unreachable: ALWAYS_THROW_EXCEPTION guarantees an exception, but we must please the compiler.

} catch (XMLStreamException e) {
throw new ConfigParserException(e);
Expand Down Expand Up @@ -329,7 +329,35 @@ private void parseServer(DepthAwareXMLStreamReader parser, String docLocation, B
Tr.debug(tc, "parseServer: event=" + eventName + " (" + event + "), depth=" + depth + ", location=" + parser.getLocation().getLineNumber());
}

if (event == XMLStreamConstants.START_ELEMENT) {
if (event == XMLStreamConstants.CHARACTERS) {
// Check for potential malformed XML elements
String text = parser.getText();

// Debug logging - log ALL CHARACTERS events
if (tc.isDebugEnabled()) {
String displayText = text != null ? text.replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t") : "null";
Tr.debug(tc, "CHARACTERS event, text length=" + (text != null ? text.length() : 0) +
", trimmed length=" + (text != null ? text.trim().length() : 0) +
", text=[" + displayText + "]");
}

if (text != null && text.trim().length() > 0) {
String trimmed = text.trim();

// Skip invisible Unicode whitespace characters.
if (isOnlyInvisibleWhitespace(trimmed)) {
if (tc.isDebugEnabled()) {
Tr.debug(tc, "Ignoring invisible Unicode whitespace at line " + parser.getLocation().getLineNumber());
}
} else {
// At the server level (between top-level elements), there should be NO text content.
// Any non-whitespace text is a malformed element.
Location l = parser.getLocation();
String preview = trimmed.length() > 60 ? trimmed.substring(0, 60) + "..." : trimmed;
logError(ThrowBehavior.SOMETIMES_THROW_EXCEPTION, "error.potential.malformed.element", preview, l.getLineNumber(), docLocation);
}
}
} else if (event == XMLStreamConstants.START_ELEMENT) {
String name = parser.getLocalName();

// Debug: Log element name
Expand Down Expand Up @@ -392,6 +420,38 @@ private void parseServer(DepthAwareXMLStreamReader parser, String docLocation, B
}
}

/**
* Checks if a string contains only invisible Unicode whitespace characters.
* These characters are commonly inserted during copy/paste operations from
* web browsers or rich text editors, but they don't affect XML parsing or
* configuration functionality.
*
* @param text The text to check
* @return true if the text contains only invisible whitespace characters, false otherwise
*/
@Trivial
private boolean isOnlyInvisibleWhitespace(String text) {
if (text == null || text.isEmpty()) {
return false;
}

// Check if string contains only invisible Unicode characters:
// U+200B: Zero Width Space
// U+200C: Zero Width Non-Joiner
// U+200D: Zero Width Joiner
// U+FEFF: Zero Width No-Break Space (BOM)
// U+2060: Word Joiner
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c != '\u200B' && c != '\u200C' && c != '\u200D' &&
c != '\uFEFF' && c != '\u2060') {
return false;
}
}

return true;
}

public enum MergeBehavior {
MERGE,
REPLACE,
Expand Down Expand Up @@ -925,18 +985,32 @@ private void logError(ThrowBehavior throwBehavior, String msgKey, Object... args
throw new ConfigParserTolerableException();
}
}


/**
* Helper method to get a human-readable name for XML stream event types.
* Used for debug logging.
*
* @param eventType The XMLStreamConstants event type
* @return A string representation of the event type
*/
@Trivial
private String getEventName(int eventType) {
switch (eventType) {
case XMLStreamConstants.START_ELEMENT: return "START_ELEMENT";
case XMLStreamConstants.END_ELEMENT: return "END_ELEMENT";
case XMLStreamConstants.CHARACTERS: return "CHARACTERS";
case XMLStreamConstants.CHARACTERS: return "CHARACTERS";
case XMLStreamConstants.COMMENT: return "COMMENT";
case XMLStreamConstants.START_DOCUMENT: return "START_DOCUMENT";
case XMLStreamConstants.END_DOCUMENT: return "END_DOCUMENT";
case XMLStreamConstants.PROCESSING_INSTRUCTION: return "PROCESSING_INSTRUCTION";
case XMLStreamConstants.CDATA: return "CDATA";
case XMLStreamConstants.SPACE: return "SPACE";
case XMLStreamConstants.START_DOCUMENT: return "START_DOCUMENT";
case XMLStreamConstants.END_DOCUMENT: return "END_DOCUMENT";
case XMLStreamConstants.ENTITY_REFERENCE: return "ENTITY_REFERENCE";
case XMLStreamConstants.ATTRIBUTE: return "ATTRIBUTE";
case XMLStreamConstants.DTD: return "DTD";
case XMLStreamConstants.NAMESPACE: return "NAMESPACE";
case XMLStreamConstants.NOTATION_DECLARATION: return "NOTATION_DECLARATION";
case XMLStreamConstants.ENTITY_DECLARATION: return "ENTITY_DECLARATION";
default: return "UNKNOWN(" + eventType + ")";
}
}
Expand Down