This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit 6f0cafcaff9aa9ad2a8d9df6598d5725dcaa8838
Author: Andrus Adamchik <[email protected]>
AuthorDate: Mon Jul 20 18:31:10 2026 +0200

    Fixing missed validations
---
 .../project/validation/DataMapValidator.java       |  4 ++
 .../cayenne/project/validation/NameValidator.java  | 10 ++-
 .../project/validation/ObjEntityValidator.java     |  6 +-
 .../project/validation/NameValidatorTest.java      | 72 ++++++++++++++++++++++
 4 files changed, 87 insertions(+), 5 deletions(-)

diff --git 
a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DataMapValidator.java
 
b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DataMapValidator.java
index c4931a8ae..4b617c777 100644
--- 
a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DataMapValidator.java
+++ 
b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/DataMapValidator.java
@@ -103,6 +103,10 @@ class DataMapValidator extends 
ConfigurationNodeValidator<DataMap> {
         if (invalidChars != null) {
             addFailure(validationResult, map, "DataMap '%s' Java package '%s' 
contains invalid characters: %s",
                     map.getName(), javaPackage, invalidChars);
+        } else if (NameValidator.invalidJavaClassComponents(javaPackage)) {
+            addFailure(validationResult, map,
+                    "DataMap '%s' Java package '%s' contains a reserved word 
or an empty name component",
+                    map.getName(), javaPackage);
         }
     }
 }
diff --git 
a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/NameValidator.java
 
b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/NameValidator.java
index 581e7c5e1..706ad6c46 100644
--- 
a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/NameValidator.java
+++ 
b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/NameValidator.java
@@ -128,14 +128,18 @@ public class NameValidator {
         return !invalidChars.isEmpty() ? invalidChars : null;
     }
 
+    /**
+     * Returns whether a "."-separated class or package name contains invalid 
components: reserved Java
+     * keywords or empty segments ("com.default.Foo", "com..Foo", ".Foo", 
"Foo.").
+     */
     public static boolean invalidJavaClassComponents(String classFQN) {
         if (classFQN == null) {
             return true;
         }
 
-        StringTokenizer toks = new StringTokenizer(classFQN, ".");
-        while (toks.hasMoreTokens()) {
-            if (RESERVED_JAVA_KEYWORDS.contains(toks.nextToken())) {
+        // the -1 limit keeps trailing empty segments that StringTokenizer 
would silently skip
+        for (String component : classFQN.split("\\.", -1)) {
+            if (component.isEmpty() || 
RESERVED_JAVA_KEYWORDS.contains(component)) {
                 return true;
             }
         }
diff --git 
a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ObjEntityValidator.java
 
b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ObjEntityValidator.java
index 2b33de354..b08fa2647 100644
--- 
a/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ObjEntityValidator.java
+++ 
b/cayenne-project/src/main/java/org/apache/cayenne/project/validation/ObjEntityValidator.java
@@ -115,7 +115,8 @@ class ObjEntityValidator extends 
ConfigurationNodeValidator<ObjEntity> {
             addFailure(validationResult, entity, "ObjEntity '%s' Java class 
'%s' contains invalid characters: %s",
                     entity.getName(), className, invalidChars);
         } else if (NameValidator.invalidJavaClassComponents(className)) {
-            addFailure(validationResult, entity, "Java class '%s' of ObjEntity 
'%s' is a reserved word",
+            addFailure(validationResult, entity,
+                    "Java class '%s' of ObjEntity '%s' contains a reserved 
word or an empty name component",
                     className, entity.getName());
         } else if (className.indexOf('.') < 0) {
             addFailure(validationResult, entity, "Java class '%s' of ObjEntity 
'%s' is in a default package",
@@ -136,7 +137,8 @@ class ObjEntityValidator extends 
ConfigurationNodeValidator<ObjEntity> {
             addFailure(validationResult, entity, "ObjEntity '%s' Java 
superclass '%s' contains invalid characters: %s",
                     entity.getName(), superClassName, invalidChars);
         } else if (NameValidator.invalidJavaClassComponents(superClassName)) {
-            addFailure(validationResult, entity, "ObjEntity '%s' Java 
superclass '%s' is a reserved word",
+            addFailure(validationResult, entity,
+                    "ObjEntity '%s' Java superclass '%s' contains a reserved 
word or an empty name component",
                     entity.getName(), superClassName);
         }
 
diff --git 
a/cayenne-project/src/test/java/org/apache/cayenne/project/validation/NameValidatorTest.java
 
b/cayenne-project/src/test/java/org/apache/cayenne/project/validation/NameValidatorTest.java
new file mode 100644
index 000000000..e58d0df1a
--- /dev/null
+++ 
b/cayenne-project/src/test/java/org/apache/cayenne/project/validation/NameValidatorTest.java
@@ -0,0 +1,72 @@
+/*****************************************************************
+ *   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
+ *
+ *    https://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.cayenne.project.validation;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class NameValidatorTest {
+
+    @Test
+    public void invalidJavaClassComponents_Valid() {
+        assertFalse(NameValidator.invalidJavaClassComponents("Artist"));
+        
assertFalse(NameValidator.invalidJavaClassComponents("org.example.model.Artist"));
+        
assertFalse(NameValidator.invalidJavaClassComponents("org.example.model"));
+    }
+
+    @Test
+    public void invalidJavaClassComponents_ReservedWords() {
+        assertTrue(NameValidator.invalidJavaClassComponents("class"));
+        
assertTrue(NameValidator.invalidJavaClassComponents("com.default.Foo"));
+        
assertTrue(NameValidator.invalidJavaClassComponents("org.example.switch"));
+    }
+
+    @Test
+    public void invalidJavaClassComponents_EmptyComponents() {
+        assertTrue(NameValidator.invalidJavaClassComponents(""));
+        assertTrue(NameValidator.invalidJavaClassComponents("com..Foo"));
+        assertTrue(NameValidator.invalidJavaClassComponents(".Foo"));
+        assertTrue(NameValidator.invalidJavaClassComponents("Foo."));
+        assertTrue(NameValidator.invalidJavaClassComponents(null));
+    }
+
+    @Test
+    public void invalidCharsInJavaClassName() {
+        
assertNull(NameValidator.invalidCharsInJavaClassName("org.example.Artist"));
+        assertEquals("-", 
NameValidator.invalidCharsInJavaClassName("org.example.My-Class"));
+        assertEquals(" ", NameValidator.invalidCharsInJavaClassName("My 
Class"));
+    }
+
+    @Test
+    public void invalidPersistentProperty() {
+        assertTrue(NameValidator.invalidPersistentProperty("class"));
+        assertTrue(NameValidator.invalidPersistentProperty("objectId"));
+        assertTrue(NameValidator.invalidPersistentProperty("objectContext"));
+        
assertTrue(NameValidator.invalidPersistentProperty("persistenceState"));
+        assertTrue(NameValidator.invalidPersistentProperty("snapshotVersion"));
+        assertTrue(NameValidator.invalidPersistentProperty(null));
+
+        assertFalse(NameValidator.invalidPersistentProperty("name"));
+        assertFalse(NameValidator.invalidPersistentProperty("classRoom"));
+    }
+}

Reply via email to