[java-identity-provider] branch master updated: IDP-1640 - Override Spring WebFlow's ApplicationContext creation logic

Scott Cantor cantor.2 at osu.edu
Thu Jul 16 18:57:54 UTC 2020


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch master
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=b84c1493388cdba5820bea2bdaa80a82a781123c

The following commit(s) were added to refs/heads/master by this push:
       new  b84c14933 IDP-1640 - Override Spring WebFlow's ApplicationContext creation logic
b84c14933 is described below

commit b84c1493388cdba5820bea2bdaa80a82a781123c
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Jul 16 14:58:22 2020 -0400

    IDP-1640 - Override Spring WebFlow's ApplicationContext creation logic
    
    https://issues.shibboleth.net/jira/browse/IDP-1640
    
    Inject our ApplicationContext and BeanDefinitionReader classes
---
 .../spring/factory/FlowModelFlowBuilder.java       | 29 +++++--
 .../spring/factory/FlowRelativeResourceLoader.java | 98 +++++++++++++++-------
 2 files changed, 91 insertions(+), 36 deletions(-)

diff --git a/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/factory/FlowModelFlowBuilder.java b/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/factory/FlowModelFlowBuilder.java
index 28420d5bc..290b0a06d 100644
--- a/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/factory/FlowModelFlowBuilder.java
+++ b/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/factory/FlowModelFlowBuilder.java
@@ -24,7 +24,6 @@ import java.util.List;
 
 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
 import org.springframework.binding.convert.ConversionExecutionException;
 import org.springframework.binding.convert.ConversionExecutor;
 import org.springframework.binding.convert.service.RuntimeBindingConversionExecutor;
@@ -114,13 +113,22 @@ import org.springframework.webflow.scope.FlowScope;
 import org.springframework.webflow.scope.ViewScope;
 import org.springframework.webflow.security.SecurityRule;
 
+import net.shibboleth.ext.spring.context.FilesystemGenericApplicationContext;
+import net.shibboleth.ext.spring.context.FilesystemGenericWebApplicationContext;
+import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
+
 /**
  * 
- * This code is copied verbatim from org.springframework.webflow.engine.builder.model.FlowModelFlowBuilder
+ * This code is extended from org.springframework.webflow.engine.builder.model.FlowModelFlowBuilder
+ * in order to customize the Spring {@link ApplicationContext} used for flow configuration.
+ * 
+ * The only method changed is {@link #createFlowApplicationContext(Resource[])}, but it's private
+ * and there are too many threads pulled by anything but a wholesale duplication of this class.
  * 
  * Builds a runtime {@link Flow} definition object from a {@link FlowModel}.
  *
  * @author Keith Donald
+ * @author Scott Cantor
  */
 public class FlowModelFlowBuilder extends AbstractFlowBuilder {
 
@@ -338,11 +346,13 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
         ApplicationContext parent = getContext().getApplicationContext();
         GenericApplicationContext flowContext;
         if (parent instanceof WebApplicationContext) {
-            GenericWebApplicationContext webContext = new GenericWebApplicationContext();
+            // Shibboleth change - Use our override of GenericWebApplicationContext.
+            GenericWebApplicationContext webContext = new FilesystemGenericWebApplicationContext();
             webContext.setServletContext(((WebApplicationContext) parent).getServletContext());
             flowContext = webContext;
         } else {
-            flowContext = new GenericApplicationContext();
+            // Shibboleth change - Use our override of GenericApplicationContext.
+            flowContext = new FilesystemGenericApplicationContext();
         }
         flowContext.setDisplayName("Flow ApplicationContext [" + getContext().getFlowId() + "]");
         flowContext.setParent(parent);
@@ -351,7 +361,7 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
         flowContext.getBeanFactory().registerScope("view", new ViewScope());
         flowContext.getBeanFactory().registerScope("flow", new FlowScope());
         flowContext.getBeanFactory().registerScope("conversation", new ConversationScope());
-
+        
         // Ensure the current ClassLoader is used, or otherwise setting the ResourceLoader would suppress it
         ClassLoader classLoaderToUse = flowContext.getClassLoader();
         flowContext.setClassLoader(classLoaderToUse);
@@ -359,8 +369,15 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
         Resource flowResource = flowModelHolder.getFlowModelResource();
         flowContext.setResourceLoader(new FlowRelativeResourceLoader(flowResource));
 
+        // Shibboleth change - override the property placeholder syntax.
+        flowContext.getEnvironment().setPlaceholderPrefix("%{");
+        flowContext.getEnvironment().setPlaceholderSuffix("}");
+
         AnnotationConfigUtils.registerAnnotationConfigProcessors(flowContext);
-        new XmlBeanDefinitionReader(flowContext).loadBeanDefinitions(resources);
+        
+        // Shibboleth change - Use our document reader instead, which fixes import resolution.
+        new SchemaTypeAwareXMLBeanDefinitionReader(flowContext).loadBeanDefinitions(resources);
+        
         registerFlowBeans(flowContext.getBeanFactory());
         registerMessageSource(flowContext, flowResource);
 
diff --git a/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/factory/FlowRelativeResourceLoader.java b/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/factory/FlowRelativeResourceLoader.java
index e4c1c90d0..704c3744a 100644
--- a/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/factory/FlowRelativeResourceLoader.java
+++ b/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/factory/FlowRelativeResourceLoader.java
@@ -20,45 +20,83 @@ package net.shibboleth.idp.profile.spring.factory;
 import java.io.IOException;
 
 import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.FileSystemResource;
 import org.springframework.core.io.Resource;
 import org.springframework.core.io.ResourceLoader;
 
+import net.shibboleth.ext.spring.resource.ConditionalResourceResolver;
+
 /**
- * This code is copied verbatim from org.springframework.webflow.engine.builder.model.FlowRelativeResourceLoader
- * 
- * A resource loader that loads other resources relative to a Flow definition resource. Allows for easy loading of
- * flow-relative resources using the standard {@link ResourceLoader} interface.
+ * This code is extended from org.springframework.webflow.engine.builder.model.FlowRelativeResourceLoader
+ * with modifications to support proper lookup of resources via both filesystem and classpath along with
+ * custom protocol-specific loaders.
  * 
- * @author Keith Donald
+ * This fills a gap for cases where the Spring {@link ResourceLoader} itself is fully replaced, versus
+ * relying solely on customized behavior in the Spring contexts themselves.
  */
-class FlowRelativeResourceLoader implements ResourceLoader {
+class FlowRelativeResourceLoader extends DefaultResourceLoader {
+
+    /** Flow resource for relative lookup. */
+    private Resource flowResource;
 
-	private Resource flowResource;
+    /**
+     * Constructor.
+     *
+     * @param resource flow resource for relative lookup
+     */
+    public FlowRelativeResourceLoader(final Resource resource) {
+        flowResource = resource;
+        getProtocolResolvers().add(new ConditionalResourceResolver());
+    }
 
-	public FlowRelativeResourceLoader(Resource resource) {
-		this.flowResource = resource;
-	}
+    public ClassLoader getClassLoader() {
+        return flowResource.getClass().getClassLoader();
+    }
 
-	public ClassLoader getClassLoader() {
-		return flowResource.getClass().getClassLoader();
-	}
+    /** {@inheritDoc} */
+    @Override
+    public Resource getResource(final String location) {
+        
+        final Resource r = super.getResource(location);
+        if (r.exists()) {
+            return r;
+        }
+        
+        if (location.startsWith(CLASSPATH_URL_PREFIX)) {
+            return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()),
+                    getClassLoader());
+        }
+        return createFlowRelativeResource(location);
+    }
 
-	public Resource getResource(String location) {
-		if (location.startsWith(CLASSPATH_URL_PREFIX)) {
-			return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
-		} else {
-			return createFlowRelativeResource(location);
-		}
-	}
+    private Resource createFlowRelativeResource(final String location) {
+        try {
+            return flowResource.createRelative(location);
+        } catch (final IOException e) {
+            final IllegalArgumentException iae = new IllegalArgumentException(
+                    "Unable to access a flow relative resource at location '" + location + "'");
+            iae.initCause(e);
+            throw iae;
+        }
+    }
 
-	private Resource createFlowRelativeResource(String location) {
-		try {
-			return flowResource.createRelative(location);
-		} catch (IOException e) {
-			IllegalArgumentException iae = new IllegalArgumentException(
-					"Unable to access a flow relative resource at location '" + location + "'");
-			iae.initCause(e);
-			throw iae;
-		}
-	}
+    /**
+     * {@inheritDoc}
+     * 
+     * <p>
+     * Overrides the standard behavior of path-only resources and treats them as file paths if the path exists. Note
+     * that this differs from the ordinary Spring contexts that default to file paths because paths are treated as
+     * absolute if they are in fact absolute.
+     * </p>
+     */
+    @Override
+    protected Resource getResourceByPath(final String path) {
+        final Resource r = new FileSystemResource(path);
+        if (r.exists()) {
+            return r;
+        }
+        return super.getResourceByPath(path);
+    }
+    
 }
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list