NIFI-9211: Fixed NPE when non-existing variable configured for a property with dynamicallyModifiesClasspath (#5382)

diff --git a/nifi-api/src/main/java/org/apache/nifi/components/PropertyValue.java b/nifi-api/src/main/java/org/apache/nifi/components/PropertyValue.java
index 4e291e9..5389262 100644
--- a/nifi-api/src/main/java/org/apache/nifi/components/PropertyValue.java
+++ b/nifi-api/src/main/java/org/apache/nifi/components/PropertyValue.java
@@ -122,7 +122,7 @@
     ResourceReference asResource();
 
     /**
-     * @return a ResourceReferences for the configured property value. If no property value is set, a ResourceRferences will be returned that references no resources.
+     * @return a ResourceReferences for the configured property value. If no property value is set, a ResourceReferences will be returned that references no resources.
      * I.e., this method will never return <code>null</code>.
      */
     ResourceReferences asResources();
diff --git a/nifi-api/src/main/java/org/apache/nifi/components/resource/StandardResourceReferenceFactory.java b/nifi-api/src/main/java/org/apache/nifi/components/resource/StandardResourceReferenceFactory.java
index acc85e5..5384961 100644
--- a/nifi-api/src/main/java/org/apache/nifi/components/resource/StandardResourceReferenceFactory.java
+++ b/nifi-api/src/main/java/org/apache/nifi/components/resource/StandardResourceReferenceFactory.java
@@ -27,18 +27,20 @@
 
 public class StandardResourceReferenceFactory implements ResourceReferenceFactory {
 
+    private static final ResourceReferences EMPTY_RESOURCE_REFERENCES = new StandardResourceReferences(Collections.emptyList());
+
     public ResourceReferences createResourceReferences(final String value, final ResourceDefinition resourceDefinition) {
         if (value == null) {
-            return new StandardResourceReferences(Collections.emptyList());
+            return EMPTY_RESOURCE_REFERENCES;
         }
 
         final String trimmed = value.trim();
         if (trimmed.isEmpty()) {
-            return null;
+            return EMPTY_RESOURCE_REFERENCES;
         }
 
         if (resourceDefinition == null) {
-            return null;
+            return EMPTY_RESOURCE_REFERENCES;
         }
 
         final List<ResourceReference> references;
diff --git a/nifi-api/src/main/java/org/apache/nifi/components/resource/StandardResourceReferences.java b/nifi-api/src/main/java/org/apache/nifi/components/resource/StandardResourceReferences.java
index 0b240be..11ce057 100644
--- a/nifi-api/src/main/java/org/apache/nifi/components/resource/StandardResourceReferences.java
+++ b/nifi-api/src/main/java/org/apache/nifi/components/resource/StandardResourceReferences.java
@@ -25,10 +25,10 @@
 import java.util.Objects;
 
 public class StandardResourceReferences implements ResourceReferences {
-    public List<ResourceReference> resourceReferences;
+    public final List<ResourceReference> resourceReferences;
 
     public StandardResourceReferences(final List<ResourceReference> resourceReferences) {
-        this.resourceReferences = Objects.requireNonNull(resourceReferences);
+        this.resourceReferences = new ArrayList<>(Objects.requireNonNull(resourceReferences));
     }
 
     @Override
diff --git a/nifi-api/src/test/java/org/apache/nifi/components/resource/TestStandardResourceReferenceFactory.java b/nifi-api/src/test/java/org/apache/nifi/components/resource/TestStandardResourceReferenceFactory.java
new file mode 100644
index 0000000..35a274f
--- /dev/null
+++ b/nifi-api/src/test/java/org/apache/nifi/components/resource/TestStandardResourceReferenceFactory.java
@@ -0,0 +1,93 @@
+/*
+ * 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.nifi.components.resource;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class TestStandardResourceReferenceFactory {
+
+    private final StandardResourceReferenceFactory subject = new StandardResourceReferenceFactory();
+
+    @Test
+    public void testCreateResourceReferences() {
+        String value = "/dir1/test1.jar,/dir2/test2.jar";
+        ResourceDefinition resourceDefinition = createResourceDefinition();
+
+        ResourceReferences resourceReferences = subject.createResourceReferences(value, resourceDefinition);
+
+        assertNotNull(resourceReferences);
+
+        List<ResourceReference> resourceReferencesList = resourceReferences.asList();
+        assertNotNull(resourceReferencesList);
+        assertEquals(2, resourceReferencesList.size());
+
+        assertResourceReference(resourceReferencesList.get(0), "/dir1/test1.jar");
+        assertResourceReference(resourceReferencesList.get(1), "/dir2/test2.jar");
+    }
+
+    @Test
+    public void testCreateResourceReferencesWhenValueIsNull() {
+        String value = null;
+        ResourceDefinition resourceDefinition = createResourceDefinition();
+
+        ResourceReferences resourceReferences = subject.createResourceReferences(value, resourceDefinition);
+
+        assertEmptyResourceReferences(resourceReferences);
+    }
+
+    @Test
+    public void testCreateResourceReferencesWhenValueIsEmpty() {
+        String value = "";
+        ResourceDefinition resourceDefinition = createResourceDefinition();
+
+        ResourceReferences resourceReferences = subject.createResourceReferences(value, resourceDefinition);
+
+        assertEmptyResourceReferences(resourceReferences);
+    }
+    @Test
+    public void testCreateResourceReferencesWhenResourceDefinitionIsNull() {
+        String value = "/dir1/test1.jar";
+        ResourceDefinition resourceDefinition = null;
+
+        ResourceReferences resourceReferences = subject.createResourceReferences(value, resourceDefinition);
+
+        assertEmptyResourceReferences(resourceReferences);
+    }
+
+    private StandardResourceDefinition createResourceDefinition() {
+        return new StandardResourceDefinition(ResourceCardinality.SINGLE, Collections.singleton(ResourceType.FILE));
+    }
+
+    private void assertResourceReference(ResourceReference resourceReference, String location) {
+        assertEquals(location, resourceReference.getLocation());
+        assertEquals(ResourceType.FILE, resourceReference.getResourceType());
+    }
+
+    private void assertEmptyResourceReferences(ResourceReferences resourceReferences) {
+        assertNotNull(resourceReferences);
+        assertNotNull(resourceReferences.asList());
+        assertTrue(resourceReferences.asList().isEmpty());
+    }
+}