This is an automated email from the ASF dual-hosted git repository.
veithen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ws-axiom.git
The following commit(s) were added to refs/heads/master by this push:
new 02d06cc92 Add @StringOrCharacterData annotation and Checker Framework
checker
02d06cc92 is described below
commit 02d06cc92524ee01d3fea33c146e495d31134a1f
Author: Copilot <[email protected]>
AuthorDate: Wed Jun 3 18:27:17 2026 +0200
Add @StringOrCharacterData annotation and Checker Framework checker
Co-authored-by: Andreas Veithen-Knowles <[email protected]>
---
buildutils/pom.xml | 1 +
.../stringorcharacterdata-checker}/pom.xml | 17 ++-
.../StringOrCharacterDataAnnotatedTypeFactory.java | 122 +++++++++++++++++++++
.../checker/StringOrCharacterDataChecker.java | 23 ++--
components/{ => checker-annotations}/pom.xml | 19 ++--
.../stream/annotations/StringOrCharacterData.java | 38 +++++++
.../annotations/UnknownCharacterDataType.java | 28 +++--
components/core-streams/pom.xml | 6 +
.../apache/axiom/core/stream/CharacterData.java | 2 +
.../org/apache/axiom/core/stream/XmlHandler.java | 4 +-
components/pom.xml | 1 +
mixins/core-mixins/pom.xml | 6 +
.../apache/axiom/core/CoreCharacterDataNode.java | 5 +-
.../axiom/core/CoreCharacterDataSinkNode.java | 4 +-
.../axiom/core/CoreCharacterDataSourceNode.java | 3 +
.../axiom/core/CoreMixedContentContainer.java | 3 +
.../java/org/apache/axiom/core/CoreParentNode.java | 4 +-
.../axiom/core/impl/AbstractNodeIterator.java | 1 +
.../org/apache/axiom/core/impl/TreeWalkerImpl.java | 8 +-
.../axiom/core/impl/builder/BuildableContext.java | 5 +-
.../axiom/core/impl/builder/BuilderHandler.java | 3 +-
.../apache/axiom/core/impl/builder/Context.java | 3 +-
.../axiom/core/impl/builder/UnwrappingContext.java | 3 +-
...CoreCharacterDataContainingParentNodeMixin.java | 5 +-
.../impl/mixin/CoreCharacterDataNodeMixin.java | 11 +-
.../impl/mixin/CoreMixedContentContainerMixin.java | 4 +-
.../axiom/core/impl/mixin/CoreParentNodeMixin.java | 22 +++-
pom.xml | 30 +++++
28 files changed, 312 insertions(+), 69 deletions(-)
diff --git a/buildutils/pom.xml b/buildutils/pom.xml
index 8eb899775..7bf8a2081 100644
--- a/buildutils/pom.xml
+++ b/buildutils/pom.xml
@@ -36,6 +36,7 @@
<module>axiom-weaver-maven-plugin</module>
<module>buildutils-maven-plugin</module>
<module>shade-axiom-xml</module>
+ <module>stringorcharacterdata-checker</module>
</modules>
<properties>
diff --git a/mixins/core-mixins/pom.xml
b/buildutils/stringorcharacterdata-checker/pom.xml
similarity index 77%
copy from mixins/core-mixins/pom.xml
copy to buildutils/stringorcharacterdata-checker/pom.xml
index a0710fc17..cac55858b 100644
--- a/mixins/core-mixins/pom.xml
+++ b/buildutils/stringorcharacterdata-checker/pom.xml
@@ -22,30 +22,27 @@
<parent>
<groupId>org.apache.ws.commons.axiom</groupId>
- <artifactId>mixins</artifactId>
+ <artifactId>buildutils</artifactId>
<version>2.1.0-SNAPSHOT</version>
</parent>
- <artifactId>core-mixins</artifactId>
+ <artifactId>stringorcharacterdata-checker</artifactId>
- <name>Core Mixins</name>
<url>http://ws.apache.org/axiom/</url>
<dependencies>
<dependency>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
+ <groupId>org.checkerframework</groupId>
+ <artifactId>checker</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>core-streams</artifactId>
+ <artifactId>checker-annotations</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>axiom-weaver-annotations</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
+ <groupId>com.google.auto.service</groupId>
+ <artifactId>auto-service-annotations</artifactId>
</dependency>
</dependencies>
</project>
diff --git
a/buildutils/stringorcharacterdata-checker/src/main/java/org/apache/axiom/checker/StringOrCharacterDataAnnotatedTypeFactory.java
b/buildutils/stringorcharacterdata-checker/src/main/java/org/apache/axiom/checker/StringOrCharacterDataAnnotatedTypeFactory.java
new file mode 100644
index 000000000..000b89231
--- /dev/null
+++
b/buildutils/stringorcharacterdata-checker/src/main/java/org/apache/axiom/checker/StringOrCharacterDataAnnotatedTypeFactory.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.checker;
+
+import java.lang.annotation.Annotation;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
+import org.apache.axiom.core.stream.annotations.UnknownCharacterDataType;
+import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
+import org.checkerframework.common.basetype.BaseTypeChecker;
+import org.checkerframework.framework.type.AnnotatedTypeMirror;
+import org.checkerframework.framework.type.QualifierHierarchy;
+import org.checkerframework.framework.type.treeannotator.ListTreeAnnotator;
+import org.checkerframework.framework.type.treeannotator.TreeAnnotator;
+import org.checkerframework.framework.type.typeannotator.ListTypeAnnotator;
+import org.checkerframework.framework.type.typeannotator.TypeAnnotator;
+import org.checkerframework.javacutil.AnnotationBuilder;
+import org.checkerframework.javacutil.TypesUtils;
+
+/**
+ * The annotated type factory for the {@link StringOrCharacterDataChecker}.
This factory
+ * automatically adds {@code @StringOrCharacterData} to {@link String} types
and to types that
+ * implement {@link org.apache.axiom.core.stream.CharacterData}.
+ */
+public class StringOrCharacterDataAnnotatedTypeFactory extends
BaseAnnotatedTypeFactory {
+
+ private static final String CHARACTER_DATA_NAME =
"org.apache.axiom.core.stream.CharacterData";
+
+ private final AnnotationMirror STRING_OR_CHARACTER_DATA;
+
+ public StringOrCharacterDataAnnotatedTypeFactory(BaseTypeChecker checker) {
+ super(checker);
+ STRING_OR_CHARACTER_DATA = AnnotationBuilder.fromClass(elements,
StringOrCharacterData.class);
+ postInit();
+ }
+
+ @Override
+ protected Set<Class<? extends Annotation>> createSupportedTypeQualifiers()
{
+ LinkedHashSet<Class<? extends Annotation>> qualifiers = new
LinkedHashSet<>();
+ qualifiers.add(StringOrCharacterData.class);
+ qualifiers.add(UnknownCharacterDataType.class);
+ return qualifiers;
+ }
+
+ @Override
+ protected TreeAnnotator createTreeAnnotator() {
+ return new ListTreeAnnotator(super.createTreeAnnotator());
+ }
+
+ @Override
+ protected TypeAnnotator createTypeAnnotator() {
+ return new ListTypeAnnotator(new
StringOrCharacterDataTypeAnnotator(this), super.createTypeAnnotator());
+ }
+
+ private class StringOrCharacterDataTypeAnnotator extends TypeAnnotator {
+
+
StringOrCharacterDataTypeAnnotator(StringOrCharacterDataAnnotatedTypeFactory
factory) {
+ super(factory);
+ }
+
+ @Override
+ public Void visitDeclared(AnnotatedTypeMirror.AnnotatedDeclaredType
type, Void p) {
+ if (shouldAnnotate(type)) {
+ type.addAnnotation(STRING_OR_CHARACTER_DATA);
+ }
+ return super.visitDeclared(type, null);
+ }
+ }
+
+ private boolean shouldAnnotate(AnnotatedTypeMirror.AnnotatedDeclaredType
type) {
+ QualifierHierarchy hierarchy = getQualifierHierarchy();
+ Set<AnnotationMirror> annotations = type.getAnnotations();
+ // Don't override existing annotations
+ for (AnnotationMirror anno : annotations) {
+ if (hierarchy.isSubtypeQualifiersOnly(anno,
STRING_OR_CHARACTER_DATA)
+ ||
hierarchy.isSubtypeQualifiersOnly(STRING_OR_CHARACTER_DATA, anno)) {
+ return false;
+ }
+ }
+ TypeMirror underlyingType = type.getUnderlyingType();
+ if (TypesUtils.isString(underlyingType)) {
+ return true;
+ }
+ return isCharacterData(underlyingType);
+ }
+
+ private boolean isCharacterData(TypeMirror type) {
+ if (type instanceof DeclaredType declaredType) {
+ String qualifiedName =
TypesUtils.getQualifiedName(declaredType).toString();
+ if (qualifiedName.equals(CHARACTER_DATA_NAME)) {
+ return true;
+ }
+ // Check supertypes
+ for (TypeMirror superType : types.directSupertypes(type)) {
+ if (isCharacterData(superType)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreMixedContentContainerMixin.java
b/buildutils/stringorcharacterdata-checker/src/main/java/org/apache/axiom/checker/StringOrCharacterDataChecker.java
similarity index 60%
copy from
mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreMixedContentContainerMixin.java
copy to
buildutils/stringorcharacterdata-checker/src/main/java/org/apache/axiom/checker/StringOrCharacterDataChecker.java
index 6077327fd..e51466c7c 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreMixedContentContainerMixin.java
+++
b/buildutils/stringorcharacterdata-checker/src/main/java/org/apache/axiom/checker/StringOrCharacterDataChecker.java
@@ -16,17 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.core.impl.mixin;
+package org.apache.axiom.checker;
-import org.apache.axiom.core.CoreMixedContentContainer;
-import org.apache.axiom.core.CoreModelException;
-import org.apache.axiom.core.ElementAction;
-import org.apache.axiom.weaver.annotation.Mixin;
+import com.google.auto.service.AutoService;
+import javax.annotation.processing.Processor;
+import org.checkerframework.common.basetype.BaseTypeChecker;
-@Mixin
-public abstract class CoreMixedContentContainerMixin implements
CoreMixedContentContainer {
- @Override
- public final Object coreGetCharacterData(ElementAction elementAction)
throws CoreModelException {
- return internalGetCharacterData(elementAction);
- }
-}
+/**
+ * A Checker Framework checker that enforces that {@code
@StringOrCharacterData Object} can only be
+ * assigned from {@link String}, {@link
org.apache.axiom.core.stream.CharacterData}, or another
+ * {@code @StringOrCharacterData Object}.
+ */
+@AutoService(Processor.class)
+public class StringOrCharacterDataChecker extends BaseTypeChecker {}
diff --git a/components/pom.xml b/components/checker-annotations/pom.xml
similarity index 78%
copy from components/pom.xml
copy to components/checker-annotations/pom.xml
index 6d945feb7..c4ac604b4 100644
--- a/components/pom.xml
+++ b/components/checker-annotations/pom.xml
@@ -22,21 +22,18 @@
<parent>
<groupId>org.apache.ws.commons.axiom</groupId>
- <artifactId>axiom</artifactId>
+ <artifactId>components</artifactId>
<version>2.1.0-SNAPSHOT</version>
</parent>
- <artifactId>components</artifactId>
- <packaging>pom</packaging>
+ <artifactId>checker-annotations</artifactId>
<url>http://ws.apache.org/axiom/</url>
- <modules>
- <module>base64-utils</module>
- <module>blob</module>
- <module>core-streams</module>
- <module>io</module>
- <module>namespace-utils</module>
- <module>xml-utils</module>
- </modules>
+ <dependencies>
+ <dependency>
+ <groupId>org.checkerframework</groupId>
+ <artifactId>checker-qual</artifactId>
+ </dependency>
+ </dependencies>
</project>
diff --git
a/components/checker-annotations/src/main/java/org/apache/axiom/core/stream/annotations/StringOrCharacterData.java
b/components/checker-annotations/src/main/java/org/apache/axiom/core/stream/annotations/StringOrCharacterData.java
new file mode 100644
index 000000000..a2a34fd95
--- /dev/null
+++
b/components/checker-annotations/src/main/java/org/apache/axiom/core/stream/annotations/StringOrCharacterData.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axiom.core.stream.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.checkerframework.framework.qual.SubtypeOf;
+
+/**
+ * Indicates that the annotated {@link Object} type use holds a value that is
either a {@link
+ * String} or a {@link org.apache.axiom.core.stream.CharacterData} instance.
+ *
+ * <p>This annotation is enforced by the {@code StringOrCharacterDataChecker}
which ensures that
+ * only {@link String}, {@link org.apache.axiom.core.stream.CharacterData}, or
another {@code
+ * @StringOrCharacterData Object} can be assigned to a position annotated with
this qualifier.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE_USE})
+@SubtypeOf(UnknownCharacterDataType.class)
+public @interface StringOrCharacterData {}
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreMixedContentContainerMixin.java
b/components/checker-annotations/src/main/java/org/apache/axiom/core/stream/annotations/UnknownCharacterDataType.java
similarity index 54%
copy from
mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreMixedContentContainerMixin.java
copy to
components/checker-annotations/src/main/java/org/apache/axiom/core/stream/annotations/UnknownCharacterDataType.java
index 6077327fd..33ba01ab0 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreMixedContentContainerMixin.java
+++
b/components/checker-annotations/src/main/java/org/apache/axiom/core/stream/annotations/UnknownCharacterDataType.java
@@ -16,17 +16,21 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.core.impl.mixin;
+package org.apache.axiom.core.stream.annotations;
-import org.apache.axiom.core.CoreMixedContentContainer;
-import org.apache.axiom.core.CoreModelException;
-import org.apache.axiom.core.ElementAction;
-import org.apache.axiom.weaver.annotation.Mixin;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.checkerframework.framework.qual.DefaultQualifierInHierarchy;
+import org.checkerframework.framework.qual.SubtypeOf;
-@Mixin
-public abstract class CoreMixedContentContainerMixin implements
CoreMixedContentContainer {
- @Override
- public final Object coreGetCharacterData(ElementAction elementAction)
throws CoreModelException {
- return internalGetCharacterData(elementAction);
- }
-}
+/**
+ * The top type in the StringOrCharacterData type hierarchy. This is the
default qualifier for
+ * unannotated types and represents an unknown character data type.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE_USE})
+@SubtypeOf({})
+@DefaultQualifierInHierarchy
+public @interface UnknownCharacterDataType {}
diff --git a/components/core-streams/pom.xml b/components/core-streams/pom.xml
index 954b7b926..931aee9d8 100644
--- a/components/core-streams/pom.xml
+++ b/components/core-streams/pom.xml
@@ -35,6 +35,12 @@
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>checker-annotations</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>xml-utils</artifactId>
diff --git
a/components/core-streams/src/main/java/org/apache/axiom/core/stream/CharacterData.java
b/components/core-streams/src/main/java/org/apache/axiom/core/stream/CharacterData.java
index f66906b94..d9c7d2a06 100644
---
a/components/core-streams/src/main/java/org/apache/axiom/core/stream/CharacterData.java
+++
b/components/core-streams/src/main/java/org/apache/axiom/core/stream/CharacterData.java
@@ -19,6 +19,7 @@
package org.apache.axiom.core.stream;
import java.io.IOException;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
// TODO: clean up this Javadoc
/**
@@ -49,5 +50,6 @@ public interface CharacterData {
* @return a {@link String} or {@link CharacterData} representation of
this instance that
* remains valid beyond the current invocation
*/
+ @StringOrCharacterData
Object retain();
}
diff --git
a/components/core-streams/src/main/java/org/apache/axiom/core/stream/XmlHandler.java
b/components/core-streams/src/main/java/org/apache/axiom/core/stream/XmlHandler.java
index 3ce6f42d9..bf66d885c 100644
---
a/components/core-streams/src/main/java/org/apache/axiom/core/stream/XmlHandler.java
+++
b/components/core-streams/src/main/java/org/apache/axiom/core/stream/XmlHandler.java
@@ -18,6 +18,8 @@
*/
package org.apache.axiom.core.stream;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
+
public interface XmlHandler {
void startDocument(String inputEncoding, String xmlVersion, String
xmlEncoding, Boolean standalone)
throws StreamException;
@@ -121,7 +123,7 @@ public interface XmlHandler {
* otherwise
* @throws StreamException if an error occurs when processing the event
*/
- void processCharacterData(Object data, boolean ignorable) throws
StreamException;
+ void processCharacterData(@StringOrCharacterData Object data, boolean
ignorable) throws StreamException;
/**
* Notify the handler of the beginning of a processing instruction.
diff --git a/components/pom.xml b/components/pom.xml
index 6d945feb7..26bd1b9f5 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -34,6 +34,7 @@
<modules>
<module>base64-utils</module>
<module>blob</module>
+ <module>checker-annotations</module>
<module>core-streams</module>
<module>io</module>
<module>namespace-utils</module>
diff --git a/mixins/core-mixins/pom.xml b/mixins/core-mixins/pom.xml
index a0710fc17..7ca286b79 100644
--- a/mixins/core-mixins/pom.xml
+++ b/mixins/core-mixins/pom.xml
@@ -36,6 +36,12 @@
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>checker-annotations</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>core-streams</artifactId>
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreCharacterDataNode.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreCharacterDataNode.java
index 46e0affcf..ce5d9c2c5 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreCharacterDataNode.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreCharacterDataNode.java
@@ -18,11 +18,14 @@
*/
package org.apache.axiom.core;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
+
public interface CoreCharacterDataNode extends CoreLeafNode,
CoreCharacterDataContainer {
@Override
+ @StringOrCharacterData
Object coreGetCharacterData();
- void coreSetCharacterData(Object data);
+ void coreSetCharacterData(@StringOrCharacterData Object data);
/**
* Check whether this text node contains element content whitespace (also
called "ignorable
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreCharacterDataSinkNode.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreCharacterDataSinkNode.java
index c935e7664..26c4efbdc 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreCharacterDataSinkNode.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreCharacterDataSinkNode.java
@@ -18,6 +18,8 @@
*/
package org.apache.axiom.core;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
+
public interface CoreCharacterDataSinkNode {
- void coreSetCharacterData(Object data, Semantics semantics) throws
CoreModelException;
+ void coreSetCharacterData(@StringOrCharacterData Object data, Semantics
semantics) throws CoreModelException;
}
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreCharacterDataSourceNode.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreCharacterDataSourceNode.java
index 2270f2685..9c147e10f 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreCharacterDataSourceNode.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreCharacterDataSourceNode.java
@@ -18,6 +18,9 @@
*/
package org.apache.axiom.core;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
+
public interface CoreCharacterDataSourceNode extends CoreNode {
+ @StringOrCharacterData
Object coreGetCharacterData() throws CoreModelException;
}
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreMixedContentContainer.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreMixedContentContainer.java
index f2c56db13..a68497dda 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreMixedContentContainer.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreMixedContentContainer.java
@@ -18,6 +18,9 @@
*/
package org.apache.axiom.core;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
+
public interface CoreMixedContentContainer extends CoreParentNode,
CoreCharacterDataSinkNode {
+ @StringOrCharacterData
Object coreGetCharacterData(ElementAction elementAction) throws
CoreModelException;
}
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreParentNode.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreParentNode.java
index 73b22cf52..2792de09e 100644
--- a/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreParentNode.java
+++ b/mixins/core-mixins/src/main/java/org/apache/axiom/core/CoreParentNode.java
@@ -21,6 +21,7 @@ package org.apache.axiom.core;
import org.apache.axiom.core.stream.StreamException;
import org.apache.axiom.core.stream.XmlHandler;
import org.apache.axiom.core.stream.XmlReader;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
/** Interface for parent nodes. */
public interface CoreParentNode extends CoreNode {
@@ -101,7 +102,7 @@ public interface CoreParentNode extends CoreNode {
Mapper<S, ? super T> mapper,
Semantics semantics);
- void coreSetCharacterData(Object data, Semantics semantics) throws
CoreModelException;
+ void coreSetCharacterData(@StringOrCharacterData Object data, Semantics
semantics) throws CoreModelException;
void coreRemoveChildren(Semantics semantics) throws CoreModelException;
@@ -117,5 +118,6 @@ public interface CoreParentNode extends CoreNode {
Content internalGetContent(boolean create);
+ @StringOrCharacterData
Object internalGetCharacterData(ElementAction elementAction) throws
CoreModelException;
}
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/AbstractNodeIterator.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/AbstractNodeIterator.java
index d19103cf3..943b20aa1 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/AbstractNodeIterator.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/AbstractNodeIterator.java
@@ -136,6 +136,7 @@ public abstract class AbstractNodeIterator<T extends
CoreNode, S> implements Nod
}
@Override
+ @SuppressWarnings("stringorcharacterdata")
public final S next() {
if (hasNext()) {
currentNode = nextNode;
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/TreeWalkerImpl.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/TreeWalkerImpl.java
index cfcc10815..cfebe91d4 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/TreeWalkerImpl.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/TreeWalkerImpl.java
@@ -257,8 +257,12 @@ public final class TreeWalkerImpl implements XmlReader {
reader = null;
}
}
- case STATE_CONTENT_VISITED ->
- handler.processCharacterData(((CoreParentNode)
nextNode).internalGetContent(), false);
+ case STATE_CONTENT_VISITED -> {
+ @SuppressWarnings("stringorcharacterdata")
+
@org.apache.axiom.core.stream.annotations.StringOrCharacterData
+ Object data = ((CoreParentNode)
nextNode).internalGetContent();
+ handler.processCharacterData(data, false);
+ }
default -> throw new IllegalStateException();
}
node = nextNode;
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/BuildableContext.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/BuildableContext.java
index 8dc58a931..d460fe3b0 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/BuildableContext.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/BuildableContext.java
@@ -40,13 +40,14 @@ import org.apache.axiom.core.stream.CharacterData;
import org.apache.axiom.core.stream.NullXmlHandler;
import org.apache.axiom.core.stream.StreamException;
import org.apache.axiom.core.stream.XmlHandler;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
final class BuildableContext extends Context implements InputContext {
private final Context parentContext;
private CoreParentNode target;
- private Object pendingCharacterData;
+ private @StringOrCharacterData Object pendingCharacterData;
/**
* The {@link XmlHandler} object to send events to if pass-through is
enabled. See {@link
@@ -260,7 +261,7 @@ final class BuildableContext extends Context implements
InputContext {
}
@Override
- void processCharacterData(Object data, boolean ignorable) throws
StreamException {
+ void processCharacterData(@StringOrCharacterData Object data, boolean
ignorable) throws StreamException {
if (passThroughHandler != null) {
passThroughHandler.processCharacterData(data, ignorable);
} else if (!ignorable && pendingCharacterData == null &&
target.coreGetFirstChildIfAvailable() == null) {
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/BuilderHandler.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/BuilderHandler.java
index 2353b61e8..0eacd7772 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/BuilderHandler.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/BuilderHandler.java
@@ -29,6 +29,7 @@ import org.apache.axiom.core.DeferredParsingException;
import org.apache.axiom.core.NodeFactory;
import org.apache.axiom.core.stream.StreamException;
import org.apache.axiom.core.stream.XmlHandler;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
final class BuilderHandler implements XmlHandler {
final NodeFactory nodeFactory;
@@ -176,7 +177,7 @@ final class BuilderHandler implements XmlHandler {
}
@Override
- public void processCharacterData(Object data, boolean ignorable) throws
StreamException {
+ public void processCharacterData(@StringOrCharacterData Object data,
boolean ignorable) throws StreamException {
context.processCharacterData(data, ignorable);
}
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/Context.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/Context.java
index 2063f841b..9efe7fe71 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/Context.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/Context.java
@@ -20,6 +20,7 @@ package org.apache.axiom.core.impl.builder;
import org.apache.axiom.core.CoreParentNode;
import org.apache.axiom.core.stream.StreamException;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
abstract class Context {
protected final BuilderHandler builderHandler;
@@ -62,7 +63,7 @@ abstract class Context {
abstract void attributesCompleted() throws StreamException;
- abstract void processCharacterData(Object data, boolean ignorable) throws
StreamException;
+ abstract void processCharacterData(@StringOrCharacterData Object data,
boolean ignorable) throws StreamException;
abstract Context startProcessingInstruction(String piTarget) throws
StreamException;
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/UnwrappingContext.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/UnwrappingContext.java
index 668cd73e7..7d163dd03 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/UnwrappingContext.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/builder/UnwrappingContext.java
@@ -21,6 +21,7 @@ package org.apache.axiom.core.impl.builder;
import org.apache.axiom.core.CoreNSAwareElement;
import org.apache.axiom.core.CoreParentNode;
import org.apache.axiom.core.stream.StreamException;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
final class UnwrappingContext extends Context {
private final CoreNSAwareElement root;
@@ -87,7 +88,7 @@ final class UnwrappingContext extends Context {
}
@Override
- void processCharacterData(Object data, boolean ignorable) throws
StreamException {
+ void processCharacterData(@StringOrCharacterData Object data, boolean
ignorable) throws StreamException {
// TODO Auto-generated method stub
}
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreCharacterDataContainingParentNodeMixin.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreCharacterDataContainingParentNodeMixin.java
index 717f2b43a..a7796a8bf 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreCharacterDataContainingParentNodeMixin.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreCharacterDataContainingParentNodeMixin.java
@@ -21,13 +21,14 @@ package org.apache.axiom.core.impl.mixin;
import org.apache.axiom.core.CoreCharacterDataContainingParentNode;
import org.apache.axiom.core.CoreModelException;
import org.apache.axiom.core.ElementAction;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
import org.apache.axiom.weaver.annotation.Mixin;
@Mixin
public abstract class CoreCharacterDataContainingParentNodeMixin implements
CoreCharacterDataContainingParentNode {
@Override
- public final Object coreGetCharacterData() throws CoreModelException {
- Object characterData =
internalGetCharacterData(ElementAction.RETURN_NULL);
+ public final @StringOrCharacterData Object coreGetCharacterData() throws
CoreModelException {
+ @StringOrCharacterData Object characterData =
internalGetCharacterData(ElementAction.RETURN_NULL);
if (characterData == null) {
throw new IllegalStateException();
}
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreCharacterDataNodeMixin.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreCharacterDataNodeMixin.java
index f4fa1aebd..f0729e82c 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreCharacterDataNodeMixin.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreCharacterDataNodeMixin.java
@@ -28,12 +28,13 @@ import org.apache.axiom.core.impl.Flags;
import org.apache.axiom.core.stream.CharacterData;
import org.apache.axiom.core.stream.StreamException;
import org.apache.axiom.core.stream.XmlHandler;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
import org.apache.axiom.weaver.annotation.Mixin;
@Mixin
public abstract class CoreCharacterDataNodeMixin implements
CoreCharacterDataNode {
/** Either a {@link String} or a {@link CharacterData} object. */
- private Object data;
+ private @StringOrCharacterData Object data;
@Override
public final NodeType coreGetNodeType() {
@@ -51,24 +52,24 @@ public abstract class CoreCharacterDataNodeMixin implements
CoreCharacterDataNod
}
@Override
- public final Object coreGetCharacterData() {
+ public final @StringOrCharacterData Object coreGetCharacterData() {
return data == null ? "" : data;
}
@Override
- public final void coreSetCharacterData(Object data) {
+ public final void coreSetCharacterData(@StringOrCharacterData Object data)
{
this.data = data;
}
@Override
- public final void coreSetCharacterData(Object data, Semantics semantics) {
+ public final void coreSetCharacterData(@StringOrCharacterData Object data,
Semantics semantics) {
this.data = data;
}
@Override
public final <T> void init(ClonePolicy<T> policy, T options, CoreNode
other) {
CoreCharacterDataNode o = (CoreCharacterDataNode) other;
- Object otherData = o.coreGetCharacterData();
+ @StringOrCharacterData Object otherData = o.coreGetCharacterData();
data = otherData instanceof CloneableCharacterData
cloneableCharacterData
? cloneableCharacterData.clone(policy, options)
: otherData;
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreMixedContentContainerMixin.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreMixedContentContainerMixin.java
index 6077327fd..e3ebd9354 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreMixedContentContainerMixin.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreMixedContentContainerMixin.java
@@ -21,12 +21,14 @@ package org.apache.axiom.core.impl.mixin;
import org.apache.axiom.core.CoreMixedContentContainer;
import org.apache.axiom.core.CoreModelException;
import org.apache.axiom.core.ElementAction;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
import org.apache.axiom.weaver.annotation.Mixin;
@Mixin
public abstract class CoreMixedContentContainerMixin implements
CoreMixedContentContainer {
@Override
- public final Object coreGetCharacterData(ElementAction elementAction)
throws CoreModelException {
+ public final @StringOrCharacterData Object
coreGetCharacterData(ElementAction elementAction)
+ throws CoreModelException {
return internalGetCharacterData(elementAction);
}
}
diff --git
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreParentNodeMixin.java
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreParentNodeMixin.java
index 91aed47e5..cff323f48 100644
---
a/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreParentNodeMixin.java
+++
b/mixins/core-mixins/src/main/java/org/apache/axiom/core/impl/mixin/CoreParentNodeMixin.java
@@ -52,6 +52,7 @@ import org.apache.axiom.core.stream.CharacterData;
import org.apache.axiom.core.stream.StreamException;
import org.apache.axiom.core.stream.XmlHandler;
import org.apache.axiom.core.stream.XmlReader;
+import org.apache.axiom.core.stream.annotations.StringOrCharacterData;
import org.apache.axiom.weaver.annotation.Mixin;
@Mixin
@@ -123,7 +124,10 @@ public abstract class CoreParentNodeMixin implements
CoreParentNode {
Content content = new Content();
CoreCharacterDataNode cdata =
coreGetNodeFactory().createCharacterDataNode();
cdata.internalSetParent(this);
- cdata.coreSetCharacterData(this.content);
+ @SuppressWarnings("stringorcharacterdata")
+ @StringOrCharacterData
+ Object characterData = this.content;
+ cdata.coreSetCharacterData(characterData);
content.firstChild = cdata;
content.lastChild = cdata;
this.content = content;
@@ -342,11 +346,15 @@ public abstract class CoreParentNodeMixin implements
CoreParentNode {
}
@Override
- public final Object internalGetCharacterData(ElementAction elementAction)
throws CoreModelException {
+ public final @StringOrCharacterData Object
internalGetCharacterData(ElementAction elementAction)
+ throws CoreModelException {
if (getState() == COMPACT) {
- return content;
+ @SuppressWarnings("stringorcharacterdata")
+ @StringOrCharacterData
+ Object result = content;
+ return result;
} else {
- Object textContent = null;
+ @StringOrCharacterData Object textContent = null;
StringBuilder buffer = null;
int depth = 0;
CoreChildNode child = coreGetFirstChild();
@@ -371,6 +379,7 @@ public abstract class CoreParentNodeMixin implements
CoreParentNode {
}
} else {
if (child instanceof CoreCharacterDataNode || child
instanceof CoreCDATASection) {
+ @StringOrCharacterData
Object textValue = ((CoreCharacterDataContainer)
child).coreGetCharacterData();
if (textValue instanceof CharacterData || ((String)
textValue).length() != 0) {
if (textContent == null) {
@@ -411,7 +420,8 @@ public abstract class CoreParentNodeMixin implements
CoreParentNode {
}
@Override
- public final void coreSetCharacterData(Object data, Semantics semantics)
throws CoreModelException {
+ public final void coreSetCharacterData(@StringOrCharacterData Object data,
Semantics semantics)
+ throws CoreModelException {
coreRemoveChildren(semantics);
if (data != null && (data instanceof CharacterData || ((String)
data).length() > 0)) {
coreSetState(COMPACT);
@@ -443,6 +453,8 @@ public abstract class CoreParentNodeMixin implements
CoreParentNode {
CoreParentNode targetParent = (CoreParentNode) clone;
if (policy.cloneChildren(options, coreGetNodeType()) &&
targetParent.isExpanded()) {
if (getState() == COMPACT) {
+ @SuppressWarnings("stringorcharacterdata")
+ @StringOrCharacterData
Object content = this.content;
if (content instanceof CloneableCharacterData) {
content = ((CloneableCharacterData) content).clone(policy,
options);
diff --git a/pom.xml b/pom.xml
index 33fab2de4..9ff78e095 100644
--- a/pom.xml
+++ b/pom.xml
@@ -296,6 +296,7 @@
<mime4j.version>0.8.14</mime4j.version>
<surefire.version>3.5.5</surefire.version>
<jaxws-rt.version>4.0.4</jaxws-rt.version>
+ <checkerframework.version>3.48.4</checkerframework.version>
<skipDeploy>false</skipDeploy>
@@ -557,6 +558,16 @@
<artifactId>guice</artifactId>
<version>7.0.0</version>
</dependency>
+ <dependency>
+ <groupId>org.checkerframework</groupId>
+ <artifactId>checker-qual</artifactId>
+ <version>${checkerframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.checkerframework</groupId>
+ <artifactId>checker</artifactId>
+ <version>${checkerframework.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
@@ -1417,5 +1428,24 @@ $${type_declaration}</template></templates>]]></value>
</plugins>
</build>
</profile>
+ <profile>
+ <id>checkerframework</id>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <annotationProcessorPaths
combine.children="append">
+ <annotationProcessorPath>
+ <groupId>${project.groupId}</groupId>
+
<artifactId>stringorcharacterdata-checker</artifactId>
+ <version>${project.version}</version>
+ </annotationProcessorPath>
+ </annotationProcessorPaths>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
</profiles>
</project>