@@ -120,13 +120,23 @@ public static PainlessLookup buildFromWhitelists(List<Whitelist> whitelists) {
120120 return painlessLookupBuilder .build ();
121121 }
122122
123+ // javaClassNamesToClasses is all the classes that need to be available to the custom classloader
124+ // including classes used as part of imported methods and class bindings but not necessarily whitelisted
125+ // individually. The values of javaClassNamesToClasses are a superset of the values of
126+ // canonicalClassNamesToClasses.
127+ private final Map <String , Class <?>> javaClassNamesToClasses ;
128+ // canonicalClassNamesToClasses is all the whitelisted classes available in a Painless script including
129+ // classes with imported canonical names but does not include classes from imported methods or class
130+ // bindings unless also whitelisted separately. The values of canonicalClassNamesToClasses are a subset
131+ // of the values of javaClassNamesToClasses.
123132 private final Map <String , Class <?>> canonicalClassNamesToClasses ;
124133 private final Map <Class <?>, PainlessClassBuilder > classesToPainlessClassBuilders ;
125134
126135 private final Map <String , PainlessMethod > painlessMethodKeysToImportedPainlessMethods ;
127136 private final Map <String , PainlessClassBinding > painlessMethodKeysToPainlessClassBindings ;
128137
129138 public PainlessLookupBuilder () {
139+ javaClassNamesToClasses = new HashMap <>();
130140 canonicalClassNamesToClasses = new HashMap <>();
131141 classesToPainlessClassBuilders = new HashMap <>();
132142
@@ -189,7 +199,16 @@ public void addPainlessClass(Class<?> clazz, boolean importClassName) {
189199 throw new IllegalArgumentException ("invalid class name [" + canonicalClassName + "]" );
190200 }
191201
192- Class <?> existingClass = canonicalClassNamesToClasses .get (canonicalClassName );
202+ Class <?> existingClass = javaClassNamesToClasses .get (clazz .getName ());
203+
204+ if (existingClass == null ) {
205+ javaClassNamesToClasses .put (clazz .getName (), clazz );
206+ } else if (existingClass != clazz ) {
207+ throw new IllegalArgumentException ("class [" + canonicalClassName + "] " +
208+ "cannot represent multiple java classes with the same name from different class loaders" );
209+ }
210+
211+ existingClass = canonicalClassNamesToClasses .get (canonicalClassName );
193212
194213 if (existingClass != null && existingClass != clazz ) {
195214 throw new IllegalArgumentException ("class [" + canonicalClassName + "] " +
@@ -685,6 +704,14 @@ public void addImportedPainlessMethod(Class<?> targetClass, String methodName, C
685704 }
686705
687706 String targetCanonicalClassName = typeToCanonicalTypeName (targetClass );
707+ Class <?> existingTargetClass = javaClassNamesToClasses .get (targetClass .getName ());
708+
709+ if (existingTargetClass == null ) {
710+ javaClassNamesToClasses .put (targetClass .getName (), targetClass );
711+ } else if (existingTargetClass != targetClass ) {
712+ throw new IllegalArgumentException ("class [" + targetCanonicalClassName + "] " +
713+ "cannot represent multiple java classes with the same name from different class loaders" );
714+ }
688715
689716 if (METHOD_NAME_PATTERN .matcher (methodName ).matches () == false ) {
690717 throw new IllegalArgumentException (
@@ -818,6 +845,14 @@ public void addPainlessClassBinding(Class<?> targetClass, String methodName, Cla
818845 }
819846
820847 String targetCanonicalClassName = typeToCanonicalTypeName (targetClass );
848+ Class <?> existingTargetClass = javaClassNamesToClasses .get (targetClass .getName ());
849+
850+ if (existingTargetClass == null ) {
851+ javaClassNamesToClasses .put (targetClass .getName (), targetClass );
852+ } else if (existingTargetClass != targetClass ) {
853+ throw new IllegalArgumentException ("class [" + targetCanonicalClassName + "] " +
854+ "cannot represent multiple java classes with the same name from different class loaders" );
855+ }
821856
822857 Constructor <?>[] javaConstructors = targetClass .getConstructors ();
823858 Constructor <?> javaConstructor = null ;
@@ -952,7 +987,23 @@ public PainlessLookup build() {
952987 classesToPainlessClasses .put (painlessClassBuilderEntry .getKey (), painlessClassBuilderEntry .getValue ().build ());
953988 }
954989
955- return new PainlessLookup (canonicalClassNamesToClasses , classesToPainlessClasses ,
990+ if (javaClassNamesToClasses .values ().containsAll (canonicalClassNamesToClasses .values ()) == false ) {
991+ throw new IllegalArgumentException ("the values of java class names to classes " +
992+ "must be a superset of the values of canonical class names to classes" );
993+ }
994+
995+ if (javaClassNamesToClasses .values ().containsAll (classesToPainlessClasses .keySet ()) == false ) {
996+ throw new IllegalArgumentException ("the values of java class names to classes " +
997+ "must be a superset of the keys of classes to painless classes" );
998+ }
999+
1000+ if (canonicalClassNamesToClasses .values ().containsAll (classesToPainlessClasses .keySet ()) == false ||
1001+ classesToPainlessClasses .keySet ().containsAll (canonicalClassNamesToClasses .values ()) == false ) {
1002+ throw new IllegalArgumentException ("the values of canonical class names to classes " +
1003+ "must have the same classes as the keys of classes to painless classes" );
1004+ }
1005+
1006+ return new PainlessLookup (javaClassNamesToClasses , canonicalClassNamesToClasses , classesToPainlessClasses ,
9561007 painlessMethodKeysToImportedPainlessMethods , painlessMethodKeysToPainlessClassBindings );
9571008 }
9581009
0 commit comments