You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by gp...@apache.org on 2011/04/06 00:00:00 UTC

svn commit: r1089260 - in /myfaces/extensions/cdi/trunk: core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/config/ core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/ core/api/src/main/java/org/apache/myfaces/ext...

Author: gpetracek
Date: Tue Apr  5 22:00:00 2011
New Revision: 1089260

URL: http://svn.apache.org/viewvc?rev=1089260&view=rev
Log:
EXTCDI-164 InvalidBeanCreationEvent (intermediate result)

Added:
    myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/BeanCreationDecisionVoter.java
    myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/event/
    myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/event/InvalidBeanCreationEvent.java
Modified:
    myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/config/CodiCoreConfig.java
    myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/AbstractGroupedConversationContext.java
    myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/ConversationContextAdapter.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/GroupedConversationContext.java
    myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/GroupedConversationContextExtension.java

Modified: myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/config/CodiCoreConfig.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/config/CodiCoreConfig.java?rev=1089260&r1=1089259&r2=1089260&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/config/CodiCoreConfig.java (original)
+++ myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/config/CodiCoreConfig.java Tue Apr  5 22:00:00 2011
@@ -56,4 +56,18 @@ public class CodiCoreConfig extends Abst
     {
         return true;
     }
+
+    /**
+     * Specifies if the
+     * {@link org.apache.myfaces.extensions.cdi.core.api.security.event.InvalidBeanCreationEvent}
+     * will be fired if a {@link org.apache.myfaces.extensions.cdi.core.api.security.BeanCreationDecisionVoter}
+     * detects a violation. This feature is deactivated per default to avoid side-effects.
+     *
+     * @return true if the event should be fired, false otherwise
+     */
+    @ConfigEntry
+    public boolean isInvalidBeanCreationEventEnabled()
+    {
+        return false;
+    }
 }

Added: myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/BeanCreationDecisionVoter.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/BeanCreationDecisionVoter.java?rev=1089260&view=auto
==============================================================================
--- myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/BeanCreationDecisionVoter.java (added)
+++ myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/BeanCreationDecisionVoter.java Tue Apr  5 22:00:00 2011
@@ -0,0 +1,36 @@
+/*
+ * 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.myfaces.extensions.cdi.core.api.security;
+
+import javax.enterprise.inject.spi.Bean;
+import java.util.Set;
+
+/**
+ * @author Gerhard Petracek
+ */
+public interface BeanCreationDecisionVoter
+{
+    /**
+     * Checks the permission to the given bean
+     * @param beanToCheck bean which should be checked
+     * @param <T> current type
+     * @return found violations, an empty set otherwise
+     */
+    <T> Set<SecurityViolation> checkPermission(Bean<T> beanToCheck);
+}

Added: myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/event/InvalidBeanCreationEvent.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/event/InvalidBeanCreationEvent.java?rev=1089260&view=auto
==============================================================================
--- myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/event/InvalidBeanCreationEvent.java (added)
+++ myfaces/extensions/cdi/trunk/core/api/src/main/java/org/apache/myfaces/extensions/cdi/core/api/security/event/InvalidBeanCreationEvent.java Tue Apr  5 22:00:00 2011
@@ -0,0 +1,47 @@
+/*
+ * 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.myfaces.extensions.cdi.core.api.security.event;
+
+import org.apache.myfaces.extensions.cdi.core.api.security.SecurityViolation;
+
+/**
+ * @author Gerhard Petracek
+ */
+public class InvalidBeanCreationEvent
+{
+    private final SecurityViolation securityViolation;
+
+    /**
+     * Constructor which is required to create the event for the given {@link SecurityViolation}
+     * @param securityViolation current security-violation
+     */
+    public InvalidBeanCreationEvent(SecurityViolation securityViolation)
+    {
+        this.securityViolation = securityViolation;
+    }
+
+    /**
+     * Exposes the current {@link SecurityViolation}
+     * @return the current security-violation
+     */
+    public SecurityViolation getSecurityViolation()
+    {
+        return securityViolation;
+    }
+}

Modified: myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/AbstractGroupedConversationContext.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/AbstractGroupedConversationContext.java?rev=1089260&r1=1089259&r2=1089260&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/AbstractGroupedConversationContext.java (original)
+++ myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/AbstractGroupedConversationContext.java Tue Apr  5 22:00:00 2011
@@ -19,6 +19,7 @@
 package org.apache.myfaces.extensions.cdi.core.impl.scope.conversation;
 
 import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.config.ConversationConfig;
+import org.apache.myfaces.extensions.cdi.core.api.security.SecurityViolation;
 import org.apache.myfaces.extensions.cdi.core.impl.scope.conversation.spi.BeanEntry;
 import org.apache.myfaces.extensions.cdi.core.impl.scope.conversation.spi.WindowContextManager;
 import org.apache.myfaces.extensions.cdi.core.impl.scope.conversation.spi.BeanEntryFactory;
@@ -26,6 +27,7 @@ import org.apache.myfaces.extensions.cdi
 import javax.enterprise.context.spi.CreationalContext;
 import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
+import java.util.Set;
 
 /**
  * @author Gerhard Petracek
@@ -154,6 +156,8 @@ public abstract class AbstractGroupedCon
      */
     public abstract boolean isActive();
 
+    protected abstract <T> Set<SecurityViolation> checkPermission(Bean<T> bean);
+
     private void lazyInitConversationConfig()
     {
         if(this.conversationConfig == null)

Modified: myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/ConversationContextAdapter.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/ConversationContextAdapter.java?rev=1089260&r1=1089259&r2=1089260&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/ConversationContextAdapter.java (original)
+++ myfaces/extensions/cdi/trunk/core/impl/src/main/java/org/apache/myfaces/extensions/cdi/core/impl/scope/conversation/ConversationContextAdapter.java Tue Apr  5 22:00:00 2011
@@ -18,11 +18,17 @@
  */
 package org.apache.myfaces.extensions.cdi.core.impl.scope.conversation;
 
+import org.apache.myfaces.extensions.cdi.core.api.config.CodiCoreConfig;
+import org.apache.myfaces.extensions.cdi.core.api.security.event.InvalidBeanCreationEvent;
+import org.apache.myfaces.extensions.cdi.core.api.security.SecurityViolation;
+import org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils;
 import javax.enterprise.context.spi.Context;
 import javax.enterprise.context.spi.Contextual;
 import javax.enterprise.context.spi.CreationalContext;
 import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
 import java.lang.annotation.Annotation;
+import java.util.Set;
 
 /**
  * @author Gerhard Petracek
@@ -31,17 +37,22 @@ public class ConversationContextAdapter 
 {
     private final Class<? extends Annotation> scopeType;
     private final AbstractGroupedConversationContext conversationContext;
+    private BeanManager beanManager;
+    private Boolean invalidBeanCreationEventEnabled;
 
     /**
      * Constructor which allows to build a context for conversations for the given scope-type and scope-implementation
      * @param scope type of the scope
      * @param conversationContext implementation of the conversation scope
+     * @param beanManager current bean-manager
      */
     public ConversationContextAdapter(Class<? extends Annotation> scope,
-                                      AbstractGroupedConversationContext conversationContext)
+                                      AbstractGroupedConversationContext conversationContext,
+                                      BeanManager beanManager)
     {
         this.scopeType = scope;
         this.conversationContext = conversationContext;
+        this.beanManager = beanManager;
     }
 
     /** {@inheritDoc} */
@@ -59,6 +70,11 @@ public class ConversationContextAdapter 
     {
         if (component instanceof Bean)
         {
+            //since the basic use-case is related to topics like security,
+            //we only have to check it at the very first access - everything else would have a major performance impact
+            checkForInvalidBeanAccess((Bean<T>)component);
+
+            //cdi doesn't support to throw an exception -> create the bean in any case - codi has to handle the rest
             return this.conversationContext.create((Bean<T>)component, creationalContext);
         }
 
@@ -86,4 +102,41 @@ public class ConversationContextAdapter 
     {
         return this.conversationContext.isActive();
     }
+
+    private <T> void checkForInvalidBeanAccess(Bean<T> bean)
+    {
+        lazyInit();
+
+        if(!this.invalidBeanCreationEventEnabled)
+        {
+            return;
+        }
+        
+        Set<SecurityViolation> violations = this.conversationContext.checkPermission(bean);
+
+        for(SecurityViolation securityViolation : violations)
+        {
+            this.beanManager.fireEvent(new InvalidBeanCreationEvent(securityViolation));
+        }
+    }
+
+    private void lazyInit()
+    {
+        if(this.invalidBeanCreationEventEnabled == null)
+        {
+            init();
+        }
+    }
+
+    private synchronized void init()
+    {
+        // switch into paranoia mode
+        if(this.invalidBeanCreationEventEnabled == null)
+        {
+            CodiCoreConfig codiCoreConfig =
+                    CodiUtils.getContextualReferenceByClass(this.beanManager, CodiCoreConfig.class);
+
+            this.invalidBeanCreationEventEnabled = codiCoreConfig.isInvalidBeanCreationEventEnabled();
+        }
+    }
 }

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/GroupedConversationContext.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/GroupedConversationContext.java?rev=1089260&r1=1089259&r2=1089260&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/GroupedConversationContext.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/GroupedConversationContext.java Tue Apr  5 22:00:00 2011
@@ -19,12 +19,15 @@
 package org.apache.myfaces.extensions.cdi.jsf.impl.scope.conversation;
 
 import org.apache.myfaces.extensions.cdi.core.api.scope.conversation.config.ConversationConfig;
+import org.apache.myfaces.extensions.cdi.core.api.security.SecurityViolation;
 import org.apache.myfaces.extensions.cdi.core.impl.scope.conversation.AbstractGroupedConversationContext;
 import org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils;
+import org.apache.myfaces.extensions.cdi.core.impl.util.AnyLiteral;
 import org.apache.myfaces.extensions.cdi.jsf.impl.scope.conversation.spi.EditableConversation;
 import org.apache.myfaces.extensions.cdi.core.impl.scope.conversation.spi.WindowContextManager;
 import org.apache.myfaces.extensions.cdi.core.impl.scope.conversation.spi.BeanEntry;
 import org.apache.myfaces.extensions.cdi.core.impl.scope.conversation.spi.BeanEntryFactory;
+import org.apache.myfaces.extensions.cdi.core.api.security.BeanCreationDecisionVoter;
 import org.apache.myfaces.extensions.cdi.jsf.impl.util.ConversationUtils;
 import org.apache.myfaces.extensions.cdi.jsf.impl.util.ExceptionUtils;
 import org.apache.myfaces.extensions.cdi.jsf.impl.util.RequestCache;
@@ -35,7 +38,10 @@ import javax.enterprise.inject.spi.Bean;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.faces.context.FacesContext;
 import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Set;
+import java.util.HashSet;
 
 /**
  * jsf specific parts for managing grouped conversations
@@ -44,6 +50,8 @@ import java.util.Set;
  */
 class GroupedConversationContext extends AbstractGroupedConversationContext
 {
+    private List<BeanCreationDecisionVoter> beanCreationDecisionVoters;
+
     GroupedConversationContext(BeanManager beanManager)
     {
         super(beanManager);
@@ -59,6 +67,58 @@ class GroupedConversationContext extends
         return FacesContext.getCurrentInstance().getExternalContext().getSession(false) != null;
     }
 
+    protected <T> Set<SecurityViolation> checkPermission(Bean<T> bean)
+    {
+        lazyInit();
+
+        Set<SecurityViolation> violations = new HashSet<SecurityViolation>();
+
+        for(BeanCreationDecisionVoter beanCreationDecisionVoter : this.beanCreationDecisionVoters)
+        {
+            Set<SecurityViolation> currentViolations = beanCreationDecisionVoter.checkPermission(bean);
+
+            if(currentViolations != null)
+            {
+                violations.addAll(currentViolations);
+            }
+        }
+
+        return violations;
+    }
+
+    private void lazyInit()
+    {
+        if(this.beanCreationDecisionVoters == null)
+        {
+            init();
+        }
+    }
+
+    private synchronized void init()
+    {
+        // switch into paranoia mode
+        if(this.beanCreationDecisionVoters == null)
+        {
+            this.beanCreationDecisionVoters = new ArrayList<BeanCreationDecisionVoter>();
+
+            Set<? extends Bean> foundBeans =
+                    this.beanManager.getBeans(BeanCreationDecisionVoter.class, new AnyLiteral());
+
+            Bean<?> foundBean;
+            Set<Bean<?>> beanSet;
+            for(Bean<?> currentBean : foundBeans)
+            {
+                beanSet = new HashSet<Bean<?>>(1);
+                beanSet.add(currentBean);
+                foundBean = this.beanManager.resolve(beanSet);
+                this.beanCreationDecisionVoters.add(
+                        CodiUtils.getContextualReference(this.beanManager,
+                                                         BeanCreationDecisionVoter.class,
+                                                         (Bean<BeanCreationDecisionVoter>)foundBean));
+            }
+        }
+    }
+
     /**
      * {@inheritDoc}
      */

Modified: myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/GroupedConversationContextExtension.java
URL: http://svn.apache.org/viewvc/myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/GroupedConversationContextExtension.java?rev=1089260&r1=1089259&r2=1089260&view=diff
==============================================================================
--- myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/GroupedConversationContextExtension.java (original)
+++ myfaces/extensions/cdi/trunk/jee-modules/jsf-module/impl/src/main/java/org/apache/myfaces/extensions/cdi/jsf/impl/scope/conversation/GroupedConversationContextExtension.java Tue Apr  5 22:00:00 2011
@@ -59,9 +59,9 @@ public class GroupedConversationContextE
         //here we don't need CodiStartupBroadcaster.broadcastStartup(); see #validateScopes
 
         AbstractGroupedConversationContext codiConversationContext = new GroupedConversationContext(manager);
-        event.addContext(new ConversationContextAdapter(WindowScoped.class, codiConversationContext));
-        event.addContext(new ConversationContextAdapter(ConversationScoped.class, codiConversationContext));
-        event.addContext(new ConversationContextAdapter(ViewAccessScoped.class, codiConversationContext));
+        event.addContext(new ConversationContextAdapter(WindowScoped.class, codiConversationContext, manager));
+        event.addContext(new ConversationContextAdapter(ConversationScoped.class, codiConversationContext, manager));
+        event.addContext(new ConversationContextAdapter(ViewAccessScoped.class, codiConversationContext, manager));
     }
 
     /**