You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by sb...@apache.org on 2012/07/24 03:32:29 UTC

[13/20] git commit: added ACL permission storage annotations, copied reflections utils from Solder (to be merged with DS core later), minor fixes

added ACL permission storage annotations, copied reflections utils from Solder (to be merged with DS core later), minor fixes


Project: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/commit/426e3724
Tree: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/tree/426e3724
Diff: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/diff/426e3724

Branch: refs/heads/master
Commit: 426e37241fa55a6d916165034fff9baf32023c59
Parents: 7fbb5d7
Author: Shane Bryzak <sb...@gmail.com>
Authored: Thu Jun 7 19:14:27 2012 +1000
Committer: Shane Bryzak <sb...@gmail.com>
Committed: Tue Jul 24 10:05:15 2012 +1000

----------------------------------------------------------------------
 .../api/permission/annotations/ACLIdentifier.java  |   40 +
 .../api/permission/annotations/ACLPermission.java  |   40 +
 .../api/permission/annotations/ACLRecipient.java   |   39 +
 .../permission/annotations/ACLResourceClass.java   |   40 +
 .../api/permission/annotations/ACLStore.java       |   42 +
 .../security/spi/permission/ACLStore.java          |   42 -
 .../deltaspike/security/impl/DefaultIdentity.java  |   12 +
 .../impl/permission/JPAPermissionStore.java        |   19 +-
 .../impl/util/properties/FieldProperty.java        |   27 +
 .../impl/util/properties/FieldPropertyImpl.java    |  104 ++
 .../impl/util/properties/MethodProperty.java       |   29 +
 .../impl/util/properties/MethodPropertyImpl.java   |  252 +++
 .../security/impl/util/properties/Properties.java  |  103 ++
 .../security/impl/util/properties/Property.java    |  112 ++
 .../query/AnnotatedPropertyCriteria.java           |   45 +
 .../properties/query/NamedPropertyCriteria.java    |   52 +
 .../util/properties/query/PropertyCriteria.java    |   59 +
 .../util/properties/query/PropertyQueries.java     |   42 +
 .../impl/util/properties/query/PropertyQuery.java  |  249 +++
 .../properties/query/TypedPropertyCriteria.java    |   47 +
 .../impl/util/reflection/HierarchyDiscovery.java   |  182 ++
 .../util/reflection/ParameterizedTypeImpl.java     |   82 +
 .../security/impl/util/reflection/Reflections.java | 1391 +++++++++++++++
 .../reflection/SetAccessiblePriviligedAction.java  |   41 +
 .../security/impl/util/reflection/Types.java       |  100 +
 25 files changed, 3145 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLIdentifier.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLIdentifier.java b/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLIdentifier.java
new file mode 100644
index 0000000..6f5dc6f
--- /dev/null
+++ b/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLIdentifier.java
@@ -0,0 +1,40 @@
+/*
+ * 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.deltaspike.security.api.permission.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marks the field of an @ACLStore annotated entity bean as containing the identifier value for the
+ * resource.
+ *
+ */
+@Target({ METHOD, FIELD })
+@Retention(RUNTIME)
+@Documented
+public @interface ACLIdentifier
+{
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLPermission.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLPermission.java b/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLPermission.java
new file mode 100644
index 0000000..1812187
--- /dev/null
+++ b/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLPermission.java
@@ -0,0 +1,40 @@
+/*
+ * 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.deltaspike.security.api.permission.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marker annotation.  Denotes the field of an @ACLStore annotated entity bean as containing the 
+ * granted ACL permissions.
+ *
+ */
+@Target({ METHOD, FIELD })
+@Retention(RUNTIME)
+@Documented
+public @interface ACLPermission
+{
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLRecipient.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLRecipient.java b/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLRecipient.java
new file mode 100644
index 0000000..47e56d0
--- /dev/null
+++ b/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLRecipient.java
@@ -0,0 +1,39 @@
+/*
+ * 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.deltaspike.security.api.permission.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marks the field of an @ACLStore annotated entity bean as containing the recipient of the ACL permissions
+ *
+ */
+@Target({ METHOD, FIELD })
+@Retention(RUNTIME)
+@Documented
+public @interface ACLRecipient
+{
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLResourceClass.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLResourceClass.java b/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLResourceClass.java
new file mode 100644
index 0000000..2e13a5d
--- /dev/null
+++ b/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLResourceClass.java
@@ -0,0 +1,40 @@
+/*
+ * 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.deltaspike.security.api.permission.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marker annotation.  Denotes the field of an @ACLStore annotated entity bean as containing the 
+ * fully qualified class name of the resource being secured
+ *
+ */
+@Target({ METHOD, FIELD })
+@Retention(RUNTIME)
+@Documented
+public @interface ACLResourceClass
+{
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLStore.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLStore.java b/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLStore.java
new file mode 100644
index 0000000..9891e8b
--- /dev/null
+++ b/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/permission/annotations/ACLStore.java
@@ -0,0 +1,42 @@
+/*
+ * 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.deltaspike.security.api.permission.annotations;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes an entity bean (i.e. a class annotated with @Entity) as being a storage container
+ * for object permissions.  If the value member is set, then the annotated entity will be used
+ * to lookup object permissions for objects of that class only, otherwise if it is not set the
+ * entity will be used to store general object permissions (only one entity may be used for
+ * general permissions, if more than one entity is defined then a deployment exception will be
+ * thrown).
+ */
+@Target({ TYPE })
+@Retention(RUNTIME)
+@Documented
+public @interface ACLStore
+{
+    Class<?> value();
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/spi/permission/ACLStore.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/spi/permission/ACLStore.java b/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/spi/permission/ACLStore.java
deleted file mode 100644
index 892aac5..0000000
--- a/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/spi/permission/ACLStore.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.deltaspike.security.spi.permission;
-
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Denotes an entity bean (i.e. a class annotated with @Entity) as being a storage container
- * for object permissions.  If the value member is set, then the annotated entity will be used
- * to lookup object permissions for objects of that class only, otherwise if it is not set the
- * entity will be used to store general object permissions (only one entity may be used for
- * general permissions, if more than one entity is defined then a deployment exception will be
- * thrown).
- */
-@Target({ TYPE })
-@Retention(RUNTIME)
-@Documented
-public @interface ACLStore
-{
-    Class<?> value();
-}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/DefaultIdentity.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/DefaultIdentity.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/DefaultIdentity.java
index 1cb7b1b..a791b94 100644
--- a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/DefaultIdentity.java
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/DefaultIdentity.java
@@ -23,9 +23,12 @@ import java.io.Serializable;
 import org.apache.deltaspike.core.util.ExceptionUtils;
 import org.apache.deltaspike.security.api.Identity;
 <<<<<<< HEAD
+<<<<<<< HEAD
 =======
 import org.apache.deltaspike.security.api.User;
 >>>>>>> added missing files
+=======
+>>>>>>> added ACL permission storage annotations, copied reflections utils from Solder (to be merged with DS core later), minor fixes
 import org.apache.deltaspike.security.api.authentication.AuthenticationException;
 import org.apache.deltaspike.security.api.authentication.UnexpectedCredentialException;
 import org.apache.deltaspike.security.api.authentication.event.AlreadyLoggedInEvent;
@@ -36,11 +39,16 @@ import org.apache.deltaspike.security.api.authentication.event.PostLoggedOutEven
 import org.apache.deltaspike.security.api.authentication.event.PreAuthenticateEvent;
 import org.apache.deltaspike.security.api.authentication.event.PreLoggedOutEvent;
 <<<<<<< HEAD
+<<<<<<< HEAD
 import org.apache.deltaspike.security.api.credential.LoginCredentials;
 import org.apache.deltaspike.security.api.idm.User;
 =======
 import org.apache.deltaspike.security.api.credential.LoginCredential;
 >>>>>>> added missing files
+=======
+import org.apache.deltaspike.security.api.credential.LoginCredentials;
+import org.apache.deltaspike.security.api.idm.User;
+>>>>>>> added ACL permission storage annotations, copied reflections utils from Solder (to be merged with DS core later), minor fixes
 import org.apache.deltaspike.security.spi.authentication.Authenticator;
 import org.apache.deltaspike.security.spi.authentication.Authenticator.AuthenticationStatus;
 import org.apache.deltaspike.security.spi.authentication.AuthenticatorSelector;
@@ -71,10 +79,14 @@ public class DefaultIdentity implements Identity
     @Inject
     @SuppressWarnings("NonSerializableFieldInSerializableClass")
 <<<<<<< HEAD
+<<<<<<< HEAD
     private LoginCredentials loginCredential;
 =======
     private LoginCredential loginCredential;
 >>>>>>> added missing files
+=======
+    private LoginCredentials loginCredential;
+>>>>>>> added ACL permission storage annotations, copied reflections utils from Solder (to be merged with DS core later), minor fixes
 
     /**
      * Flag indicating whether we are currently authenticating

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/permission/JPAPermissionStore.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/permission/JPAPermissionStore.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/permission/JPAPermissionStore.java
index 6417fba..74f94b6 100644
--- a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/permission/JPAPermissionStore.java
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/permission/JPAPermissionStore.java
@@ -24,31 +24,40 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.enterprise.context.ApplicationScoped;
 import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Instance;
 import javax.enterprise.inject.spi.AnnotatedType;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.inject.spi.Extension;
 import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.inject.Inject;
 import javax.persistence.Entity;
+import javax.persistence.EntityManager;
 
 import org.apache.deltaspike.security.api.SecurityConfigurationException;
 import org.apache.deltaspike.security.api.permission.Permission;
 import org.apache.deltaspike.security.api.permission.PermissionQuery;
-import org.apache.deltaspike.security.spi.permission.ACLStore;
+import org.apache.deltaspike.security.api.permission.annotations.ACLStore;
 import org.apache.deltaspike.security.spi.permission.PermissionStore;
 
 /**
  * A PermissionStore implementation backed by a JPA datasource
  *
  */
+@ApplicationScoped
 public class JPAPermissionStore implements PermissionStore, Extension
 {
-    Class<?> generalPermissionStore = null;
+    private Class<?> generalPermissionStore = null;
     
-    Map<Class<?>, Class<?>> permissionStoreMap = new HashMap<Class<?>, Class<?>>();)
+    private Map<Class<?>, Class<?>> permissionStoreMap = new HashMap<Class<?>, Class<?>>();
+    
+    @Inject 
+    private Instance<EntityManager> entityManagerInstance;
     
     public <X> void processAnnotatedType(@Observes ProcessAnnotatedType<X> event,
-            final BeanManager beanManager) {
+            final BeanManager beanManager) 
+    {
         
         if (event.getAnnotatedType().isAnnotationPresent(Entity.class)) {
             AnnotatedType<X> type = event.getAnnotatedType();
@@ -92,6 +101,8 @@ public class JPAPermissionStore implements PermissionStore, Extension
     @Override
     public List<Permission> getPermissions(PermissionQuery query)
     {
+        EntityManager em = entityManagerInstance.get();
+        
         // TODO Auto-generated method stub
         return null;
     }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/FieldProperty.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/FieldProperty.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/FieldProperty.java
new file mode 100644
index 0000000..7ef022e
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/FieldProperty.java
@@ -0,0 +1,27 @@
+/*
+ * 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.deltaspike.security.impl.util.properties;
+
+import java.lang.reflect.Field;
+
+
+public interface FieldProperty<V> extends Property<V> 
+{
+    Field getAnnotatedElement();
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/FieldPropertyImpl.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/FieldPropertyImpl.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/FieldPropertyImpl.java
new file mode 100644
index 0000000..95b6511
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/FieldPropertyImpl.java
@@ -0,0 +1,104 @@
+/*
+ * 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.deltaspike.security.impl.util.properties;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Type;
+
+import org.apache.deltaspike.security.impl.util.reflection.Reflections;
+import static org.apache.deltaspike.security.impl.util.reflection.Reflections.getFieldValue;
+import static org.apache.deltaspike.security.impl.util.reflection.Reflections.setFieldValue;
+
+/**
+ * A bean property based on the value contained in a field
+ *
+ */
+class FieldPropertyImpl<V> implements FieldProperty<V> 
+{
+    private final Field field;
+
+    FieldPropertyImpl(Field field) 
+    {
+        this.field = field;
+    }
+
+    public String getName() 
+    {
+        return field.getName();
+    }
+
+    public Type getBaseType() 
+    {
+        return field.getGenericType();
+    }
+
+    public Field getAnnotatedElement() 
+    {
+        return field;
+    }
+
+    public Member getMember() 
+    {
+        return field;
+    }
+
+    @SuppressWarnings("unchecked")
+    public Class<V> getJavaClass() {
+        return (Class<V>) field.getType();
+    }
+
+    public V getValue(Object instance) 
+    {
+        setAccessible();
+        return getFieldValue(field, instance, getJavaClass());
+    }
+
+    public void setValue(Object instance, V value) {
+        setAccessible();
+        setFieldValue(true, field, instance, value);
+    }
+
+    public Class<?> getDeclaringClass() {
+        return field.getDeclaringClass();
+    }
+
+    public boolean isReadOnly() {
+        return false;
+    }
+
+    public void setAccessible() {
+        Reflections.setAccessible(field);
+    }
+
+    @Override
+    public String toString() {
+        return field.toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return field.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return field.equals(obj);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/MethodProperty.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/MethodProperty.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/MethodProperty.java
new file mode 100644
index 0000000..6b415e4
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/MethodProperty.java
@@ -0,0 +1,29 @@
+/*
+ * 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.deltaspike.security.impl.util.properties;
+
+import java.lang.reflect.Method;
+
+
+public interface MethodProperty<V> extends Property<V> 
+{
+
+    public Method getAnnotatedElement();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/MethodPropertyImpl.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/MethodPropertyImpl.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/MethodPropertyImpl.java
new file mode 100644
index 0000000..c15fea7
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/MethodPropertyImpl.java
@@ -0,0 +1,252 @@
+/*
+ * 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.deltaspike.security.impl.util.properties;
+
+import java.beans.Introspector;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+import org.apache.deltaspike.security.impl.util.reflection.Reflections;
+
+import static org.apache.deltaspike.security.impl.util.reflection.Reflections.invokeMethod;
+
+/**
+ * A bean property based on the value represented by a getter/setter method pair
+ *
+ */
+class MethodPropertyImpl<V> implements MethodProperty<V> 
+{
+    private static final String GETTER_METHOD_PREFIX = "get";
+    private static final String SETTER_METHOD_PREFIX = "set";
+    private static final String BOOLEAN_GETTER_METHOD_PREFIX = "is";
+
+    private static final int GETTER_METHOD_PREFIX_LENGTH = GETTER_METHOD_PREFIX.length();
+    private static final int SETTER_METHOD_PREFIX_LENGTH = SETTER_METHOD_PREFIX.length();
+    private static final int BOOLEAN_GETTER_METHOD_PREFIX_LENGTH = BOOLEAN_GETTER_METHOD_PREFIX.length();
+
+    private final Method getterMethod;
+    private final String propertyName;
+    private final Method setterMethod;
+
+    public MethodPropertyImpl(Method method) 
+    {
+        final String accessorMethodPrefix;
+        final String propertyNameInAccessorMethod;
+        
+        if (method.getName().startsWith(GETTER_METHOD_PREFIX)) 
+        {
+            if (method.getReturnType() == Void.TYPE) 
+            {
+                throw new IllegalArgumentException("Invalid accessor method, must have return value if starts with 'get'. Method: " + method);
+            } 
+            else if (method.getParameterTypes().length > 0) 
+            {
+                throw new IllegalArgumentException("Invalid accessor method, must have zero arguments if starts with 'get'. Method: " + method);
+            }
+            propertyNameInAccessorMethod = method.getName().substring(GETTER_METHOD_PREFIX_LENGTH);
+            accessorMethodPrefix = GETTER_METHOD_PREFIX;
+        } 
+        else if (method.getName().startsWith(SETTER_METHOD_PREFIX)) 
+        {
+            if (method.getReturnType() != Void.TYPE) 
+            {
+                throw new IllegalArgumentException("Invalid accessor method, must not have return value if starts with 'set'. Method: " + method);
+            } 
+            else if (method.getParameterTypes().length != 1) 
+            {
+                throw new IllegalArgumentException("Invalid accessor method, must have one argument if starts with 'set'. Method: " + method);
+            }
+            propertyNameInAccessorMethod = method.getName().substring(SETTER_METHOD_PREFIX_LENGTH);
+            accessorMethodPrefix = SETTER_METHOD_PREFIX;
+        } 
+        else if (method.getName().startsWith(BOOLEAN_GETTER_METHOD_PREFIX)) 
+        {
+            if (method.getReturnType() != Boolean.TYPE || !method.getReturnType().isPrimitive()) 
+            {
+                throw new IllegalArgumentException("Invalid accessor method, must return boolean primitive if starts with 'is'. Method: " + method);
+            }
+            propertyNameInAccessorMethod = method.getName().substring(BOOLEAN_GETTER_METHOD_PREFIX_LENGTH);
+            accessorMethodPrefix = BOOLEAN_GETTER_METHOD_PREFIX;
+        } 
+        else 
+        {
+            throw new IllegalArgumentException("Invalid accessor method, must start with 'get', 'set' or 'is'.  " + "Method: " + method);
+        }
+        
+        if (propertyNameInAccessorMethod.length() == 0 || !Character.isUpperCase(propertyNameInAccessorMethod.charAt(0))) 
+        {
+            throw new IllegalArgumentException("Invalid accessor method, prefix '" + accessorMethodPrefix +
+                    "' must be followed a non-empty property name, capitalized. Method: " + method);
+        }
+        
+        this.propertyName = Introspector.decapitalize(propertyNameInAccessorMethod);
+        this.getterMethod = getGetterMethod(method.getDeclaringClass(), propertyName);
+        this.setterMethod = getSetterMethod(method.getDeclaringClass(), propertyName);
+    }
+
+    public String getName() 
+    {
+        return propertyName;
+    }
+
+    @SuppressWarnings("unchecked")
+    public Class<V> getJavaClass() 
+    {
+        return (Class<V>) getterMethod.getReturnType();
+    }
+
+    public Type getBaseType() 
+    {
+        return getterMethod.getGenericReturnType();
+    }
+
+    public Method getAnnotatedElement() 
+    {
+        return getterMethod;
+    }
+
+    public Member getMember() 
+    {
+        return getterMethod;
+    }
+
+	public V getValue(Object instance) 
+	{
+        if (getterMethod == null) {
+            throw new UnsupportedOperationException("Property " + this.setterMethod.getDeclaringClass() + "." + propertyName + " cannot be read, as there is no getter method.");
+        }
+        return Reflections.cast(invokeMethod(getterMethod, instance));
+    }
+
+    public void setValue(Object instance, V value) 
+    {
+        if (setterMethod == null) {
+            throw new UnsupportedOperationException("Property " + this.getterMethod.getDeclaringClass() + "." + propertyName + " is read only, as there is no setter method.");
+        }
+        invokeMethod(setterMethod, instance, value);
+    }
+
+    private static Method getSetterMethod(Class<?> clazz, String name) 
+    {
+        Method[] methods = clazz.getMethods();
+        for (Method method : methods) 
+        {
+            String methodName = method.getName();
+            if (methodName.startsWith(SETTER_METHOD_PREFIX) && method.getParameterTypes().length == 1) 
+            {
+                if (Introspector.decapitalize(methodName.substring(SETTER_METHOD_PREFIX_LENGTH)).equals(name)) 
+                {
+                    return method;
+                }
+            }
+        }
+        return null;
+    }
+
+    private static Method getGetterMethod(Class<?> clazz, String name) 
+    {
+        for (Method method : clazz.getDeclaredMethods()) 
+        {
+            String methodName = method.getName();
+            if (method.getParameterTypes().length == 0) 
+            {
+                if (methodName.startsWith(GETTER_METHOD_PREFIX)) 
+                {
+                    if (Introspector.decapitalize(methodName.substring(GETTER_METHOD_PREFIX_LENGTH)).equals(name)) 
+                    {
+                        return method;
+                    }
+                } 
+                else if (methodName.startsWith(BOOLEAN_GETTER_METHOD_PREFIX)) 
+                {
+                    if (Introspector.decapitalize(methodName.substring(BOOLEAN_GETTER_METHOD_PREFIX_LENGTH)).equals(name)) 
+                    {
+                        return method;
+                    }
+                }
+            }
+        }
+        throw new IllegalArgumentException("no such getter method: " + clazz.getName() + '.' + name);
+    }
+
+    public Class<?> getDeclaringClass() 
+    {
+        return getterMethod.getDeclaringClass();
+    }
+
+    public boolean isReadOnly() 
+    {
+        return setterMethod == null;
+    }
+
+    public void setAccessible() 
+    {
+        if (setterMethod != null) 
+        {
+            Reflections.setAccessible(setterMethod);
+        }
+        if (getterMethod != null) 
+        {
+            Reflections.setAccessible(getterMethod);
+        }
+    }
+
+    @Override
+    public String toString() 
+    {
+        StringBuilder builder = new StringBuilder();
+        if (isReadOnly()) 
+        {
+            builder.append("read-only ").append(setterMethod.toString()).append("; ");
+        }
+        builder.append(getterMethod.toString());
+        return builder.toString();
+    }
+
+    @Override
+    public int hashCode() 
+    {
+        int hash = 1;
+        hash = hash * 31 + (setterMethod == null ? 0 : setterMethod.hashCode());
+        hash = hash * 31 + getterMethod.hashCode();
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) 
+    {
+        if (obj instanceof MethodPropertyImpl<?>) 
+        {
+            MethodPropertyImpl<?> that = (MethodPropertyImpl<?>) obj;
+            if (this.setterMethod == null) 
+            {
+                return that.setterMethod == null && this.getterMethod.equals(that.getterMethod);
+            } else 
+            {
+                return this.setterMethod.equals(that.setterMethod) && this.getterMethod.equals(that.getterMethod);
+            }
+        } 
+        else 
+        {
+            return false;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/Properties.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/Properties.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/Properties.java
new file mode 100644
index 0000000..fea6049
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/Properties.java
@@ -0,0 +1,103 @@
+/*
+ * 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.deltaspike.security.impl.util.properties;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
+/**
+ * Utility class for working with JavaBean style properties
+ *
+ * @see Property
+ */
+public class Properties 
+{
+
+    private Properties() 
+    {
+    }
+
+    /**
+     * Create a JavaBean style property from the field
+     *
+     * @param <V>
+     * @param field
+     * @return
+     */
+    public static <V> FieldProperty<V> createProperty(Field field) 
+    {
+        return new FieldPropertyImpl<V>(field);
+    }
+
+    /**
+     * Create a JavaBean style property from the specified method
+     *
+     * @param <V>
+     * @param method
+     * @return
+     * @throws IllegalArgumentException if the method does not match JavaBean conventions
+     * @see http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html
+     */
+    public static <V> MethodProperty<V> createProperty(Method method) 
+    {
+        return new MethodPropertyImpl<V>(method);
+    }
+
+    /**
+     * Create a JavaBean style property from the specified member
+     *
+     * @param <V>
+     * @param member
+     * @return
+     * @throws IllegalArgumentException if the method does not match JavaBean conventions
+     * @see http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html
+     */
+    public static <V> Property<V> createProperty(Member member) 
+    {
+        if (member instanceof Method) 
+        {
+            return new MethodPropertyImpl<V>(Method.class.cast(member));
+        } 
+        else if (member instanceof Field) 
+        {
+            return new FieldPropertyImpl<V>(Field.class.cast(member));
+        } 
+        else 
+        {
+            throw new IllegalArgumentException("Cannot make a property of " + member + " - it is neither a method or a field");
+        }
+    }
+
+    /**
+     * Indicates whether this method is a valid property method.
+     */
+    public static <V> boolean isProperty(Method method) 
+    {
+        try 
+        {
+            new MethodPropertyImpl<V>(method);
+            return true;
+        } 
+        catch (IllegalArgumentException e) 
+        {
+            return false;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/Property.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/Property.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/Property.java
new file mode 100644
index 0000000..e2d5fab
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/Property.java
@@ -0,0 +1,112 @@
+/*
+ * 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.deltaspike.security.impl.util.properties;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Member;
+import java.lang.reflect.Type;
+import java.security.PrivilegedAction;
+
+/**
+ * A representation of a JavaBean style property
+ *
+ * @param <V> the type of the properties value
+
+ * @see Properties
+ */
+public interface Property<V> 
+{
+    /**
+     * Returns the name of the property. If the property is a field, then the
+     * field name is returned. Otherwise, if the property is a method, then the
+     * name that is returned is the getter method name without the "get" or "is"
+     * prefix, and a lower case first letter.
+     *
+     * @return The name of the property
+     */
+    String getName();
+
+    /**
+     * Returns the property type
+     *
+     * @return The property type
+     */
+    Type getBaseType();
+
+    /**
+     * Returns the property type
+     *
+     * @return The property type
+     */
+    Class<V> getJavaClass();
+
+    /**
+     * Get the element responsible for retrieving the property value
+     *
+     * @return
+     */
+    AnnotatedElement getAnnotatedElement();
+
+    /**
+     * Get the member responsible for retrieving the property value
+     *
+     * @return
+     */
+    Member getMember();
+
+    /**
+     * Returns the property value for the specified bean. The property to be
+     * returned is either a field or getter method.
+     *
+     * @param bean The bean to read the property from
+     * @return The property value
+     * @throws ClassCastException if the value is not of the type V
+     */
+    V getValue(Object instance);
+
+    /**
+     * This method sets the property value for a specified bean to the specified
+     * value. The property to be set is either a field or setter method.
+     *
+     * @param bean  The bean containing the property to set
+     * @param value The new property value
+     */
+    void setValue(Object instance, V value);
+
+    /**
+     * Returns the class that declares the property
+     *
+     * @return
+     */
+    Class<?> getDeclaringClass();
+
+    /**
+     * Indicates whether this is a read-only property
+     *
+     * @return
+     */
+    boolean isReadOnly();
+
+    /**
+     * Calls the setAccessible method on the underlying member(s).
+     * <p/>
+     * The operation should be performed within a {@link PrivilegedAction}
+     */
+    void setAccessible();
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/AnnotatedPropertyCriteria.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/AnnotatedPropertyCriteria.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/AnnotatedPropertyCriteria.java
new file mode 100644
index 0000000..0157c3b
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/AnnotatedPropertyCriteria.java
@@ -0,0 +1,45 @@
+/*
+ * 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.deltaspike.security.impl.util.properties.query;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * A criteria that matches a property based on its annotations
+ *
+ * @see PropertyCriteria
+ */
+public class AnnotatedPropertyCriteria implements PropertyCriteria {
+    private final Class<? extends Annotation> annotationClass;
+
+    public AnnotatedPropertyCriteria(Class<? extends Annotation> annotationClass) {
+        this.annotationClass = annotationClass;
+    }
+
+    public boolean fieldMatches(Field f) {
+        return f.isAnnotationPresent(annotationClass);
+    }
+
+    public boolean methodMatches(Method m) {
+        return m.isAnnotationPresent(annotationClass);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/NamedPropertyCriteria.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/NamedPropertyCriteria.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/NamedPropertyCriteria.java
new file mode 100644
index 0000000..c7b73b1
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/NamedPropertyCriteria.java
@@ -0,0 +1,52 @@
+/*
+ * 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.deltaspike.security.impl.util.properties.query;
+
+import java.beans.Introspector;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * A criteria that matches a property based on name
+ *
+ * @see PropertyCriteria
+ */
+public class NamedPropertyCriteria implements PropertyCriteria {
+    private final String[] propertyNames;
+
+    public NamedPropertyCriteria(String... propertyNames) {
+        this.propertyNames = propertyNames;
+    }
+
+    public boolean fieldMatches(Field f) {
+        for (String propertyName : propertyNames) {
+            if (propertyName.equals(f.getName())) return true;
+        }
+        return false;
+    }
+
+    public boolean methodMatches(Method m) {
+        for (String propertyName : propertyNames) {
+            if (m.getName().startsWith("get") &&
+                    Introspector.decapitalize(m.getName().substring(3)).equals(propertyName)) return true;
+
+        }
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/PropertyCriteria.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/PropertyCriteria.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/PropertyCriteria.java
new file mode 100644
index 0000000..4d8b589
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/PropertyCriteria.java
@@ -0,0 +1,59 @@
+/*
+ * 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.deltaspike.security.impl.util.properties.query;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * <p>
+ * A property criteria can be used to filter the properties found by a
+ * {@link PropertyQuery}
+ * </p>
+ * <p/>
+ * <p>
+ * DeltaSpike provides a number of property queries (
+ * {@link TypedPropertyCriteria}, {@link NamedPropertyCriteria} and
+ * {@link AnnotatedPropertyCriteria}), or you can create a custom query by
+ * implementing this interface.
+ * </p>
+ *
+ * @see PropertyQuery#addCriteria(PropertyCriteria)
+ * @see PropertyQueries
+ * @see TypedPropertyCriteria
+ * @see AnnotatedPropertyCriteria
+ * @see NamedPropertyCriteria
+ */
+public interface PropertyCriteria {
+    /**
+     * Tests whether the specified field matches the criteria
+     *
+     * @param f
+     * @return true if the field matches
+     */
+    boolean fieldMatches(Field f);
+
+    /**
+     * Tests whether the specified method matches the criteria
+     *
+     * @param m
+     * @return true if the method matches
+     */
+    boolean methodMatches(Method m);
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/PropertyQueries.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/PropertyQueries.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/PropertyQueries.java
new file mode 100644
index 0000000..4a4c77d
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/PropertyQueries.java
@@ -0,0 +1,42 @@
+/*
+ * 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.deltaspike.security.impl.util.properties.query;
+
+/**
+ * Utilities for working with property queries
+ *
+ * @see PropertyQuery
+ */
+public class PropertyQueries {
+
+    private PropertyQueries() {
+    }
+
+    /**
+     * Create a new {@link PropertyQuery}
+     *
+     * @param <V>
+     * @param targetClass
+     * @return
+     */
+    public static <V> PropertyQuery<V> createQuery(Class<?> targetClass) {
+        return new PropertyQuery<V>(targetClass);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/PropertyQuery.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/PropertyQuery.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/PropertyQuery.java
new file mode 100644
index 0000000..a8f9a94
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/PropertyQuery.java
@@ -0,0 +1,249 @@
+/*
+ * 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.deltaspike.security.impl.util.properties.query;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.deltaspike.security.impl.util.properties.MethodProperty;
+import org.apache.deltaspike.security.impl.util.properties.Properties;
+import org.apache.deltaspike.security.impl.util.properties.Property;
+
+/**
+ * <p>
+ * Queries a target class for properties that match certain criteria. A property
+ * may either be a private or public field, declared by the target class or
+ * inherited from a superclass, or a public method declared by the target class
+ * or inherited from any of its superclasses. For properties that are exposed
+ * via a method, the property must be a JavaBean style property, i.e. it must
+ * provide both an accessor and mutator method according to the JavaBean
+ * specification.
+ * </p>
+ * <p/>
+ * <p>
+ * This class is not thread-safe, however the result returned by the
+ * getResultList() method is.
+ * </p>
+ *
+ * @see PropertyQueries
+ * @see PropertyCriteria
+ */
+public class PropertyQuery<V> 
+{
+    private final Class<?> targetClass;
+    private final List<PropertyCriteria> criteria;
+
+    PropertyQuery(Class<?> targetClass) 
+    {
+        if (targetClass == null) 
+        {
+            throw new IllegalArgumentException("targetClass parameter may not be null");
+        }
+
+        this.targetClass = targetClass;
+        this.criteria = new ArrayList<PropertyCriteria>();
+    }
+
+    /**
+     * Add a criteria to query
+     *
+     * @param criteria the criteria to add
+     */
+    public PropertyQuery<V> addCriteria(PropertyCriteria criteria) 
+    {
+        this.criteria.add(criteria);
+        return this;
+    }
+
+    /**
+     * Get the first result from the query, causing the query to be run.
+     *
+     * @return the first result, or null if there are no results
+     */
+    public Property<V> getFirstResult() 
+    {
+        List<Property<V>> results = getResultList();
+        return results.isEmpty() ? null : results.get(0);
+    }
+
+    /**
+     * Get the first result from the query that is not marked as read only,
+     * causing the query to be run.
+     *
+     * @return the first writable result, or null if there are no results
+     */
+    public Property<V> getFirstWritableResult() 
+    {
+        List<Property<V>> results = getWritableResultList();
+        return results.isEmpty() ? null : results.get(0);
+    }
+
+    /**
+     * Get a single result from the query, causing the query to be run. An
+     * exception is thrown if the query does not return exactly one result.
+     *
+     * @return the single result
+     * @throws RuntimeException if the query does not return exactly one result
+     */
+    public Property<V> getSingleResult() 
+    {
+        List<Property<V>> results = getResultList();
+        if (results.size() == 1) 
+        {
+            return results.get(0);
+        } 
+        else if (results.isEmpty()) 
+        {
+            throw new RuntimeException("Expected one property match, but the criteria did not match any properties on " + targetClass.getName());
+        } 
+        else 
+        {
+            throw new RuntimeException("Expected one property match, but the criteria matched " + results.size() + " properties on " + targetClass.getName());
+        }
+    }
+
+    /**
+     * Get a single result from the query that is not marked as read only,
+     * causing the query to be run. An exception is thrown if the query does not
+     * return exactly one result.
+     *
+     * @return the single writable result
+     * @throws RuntimeException if the query does not return exactly one result
+     */
+    public Property<V> getWritableSingleResult() 
+    {
+        List<Property<V>> results = getWritableResultList();
+        if (results.size() == 1) 
+        {
+            return results.get(0);
+        } 
+        else if (results.isEmpty()) 
+        {
+            throw new RuntimeException("Expected one property match, but the criteria did not match any properties on " + targetClass.getName());
+        } 
+        else 
+        {
+            throw new RuntimeException("Expected one property match, but the criteria matched " + results.size() + " properties on " + targetClass.getName());
+        }
+    }
+
+    /**
+     * Get the result from the query, causing the query to be run.
+     *
+     * @return the results, or an empty list if there are no results
+     */
+    public List<Property<V>> getResultList() 
+    {
+        return getResultList(false);
+    }
+
+    /**
+     * Get the non read only results from the query, causing the query to be run.
+     *
+     * @return the results, or an empty list if there are no results
+     */
+    public List<Property<V>> getWritableResultList() 
+    {
+        return getResultList(true);
+    }
+
+    /**
+     * Get the result from the query, causing the query to be run.
+     *
+     * @param writable if this query should only return properties that are not
+     *                 read only
+     * @return the results, or an empty list if there are no results
+     */
+    private List<Property<V>> getResultList(boolean writable) 
+    {
+        List<Property<V>> results = new ArrayList<Property<V>>();
+
+        // First check public accessor methods (we ignore private methods)
+        for (Method method : targetClass.getMethods()) 
+        {
+            if (!(method.getName().startsWith("is") || method.getName().startsWith("get")))
+            {
+                continue;
+            }
+
+            boolean match = true;
+            for (PropertyCriteria c : criteria) 
+            {
+                if (!c.methodMatches(method)) 
+                {
+                    match = false;
+                    break;
+                }
+            }
+            if (match) 
+            {
+                MethodProperty<V> property = Properties.<V>createProperty(method);
+                if (!writable || !property.isReadOnly()) 
+                {
+                    results.add(property);
+                }
+            }
+        }
+
+        Class<?> cls = targetClass;
+        while (cls != null && !cls.equals(Object.class)) 
+        {
+            // Now check declared fields
+            for (Field field : cls.getDeclaredFields()) 
+            {
+                boolean match = true;
+                for (PropertyCriteria c : criteria) 
+                {
+                    if (!c.fieldMatches(field)) 
+                    {
+                        match = false;
+                        break;
+                    }
+                }
+                Property<V> prop = Properties.<V>createProperty(field);
+
+                if (match && !resultsContainsProperty(results, prop.getName())) 
+                {
+                    if (!writable || !prop.isReadOnly()) 
+                    {
+                        results.add(prop);
+                    }
+                }
+            }
+
+            cls = cls.getSuperclass();
+        }
+
+        return results;
+    }
+
+    private boolean resultsContainsProperty(List<Property<V>> results, String propertyName) 
+    {
+        for (Property<V> p : results) 
+        {
+            if (propertyName.equals(p.getName()))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/TypedPropertyCriteria.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/TypedPropertyCriteria.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/TypedPropertyCriteria.java
new file mode 100644
index 0000000..2938170
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/properties/query/TypedPropertyCriteria.java
@@ -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.deltaspike.security.impl.util.properties.query;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * A criteria that matches a property based on its type
+ *
+ * @see PropertyCriteria
+ */
+public class TypedPropertyCriteria implements PropertyCriteria 
+{
+    private final Class<?> propertyClass;
+
+    public TypedPropertyCriteria(Class<?> propertyClass) 
+    {
+        this.propertyClass = propertyClass;
+    }
+
+    public boolean fieldMatches(Field f) 
+    {
+        return propertyClass.equals(f.getType());
+    }
+
+    public boolean methodMatches(Method m) 
+    {
+        return propertyClass.equals(m.getReturnType());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/reflection/HierarchyDiscovery.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/reflection/HierarchyDiscovery.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/reflection/HierarchyDiscovery.java
new file mode 100644
index 0000000..404f6c3
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/reflection/HierarchyDiscovery.java
@@ -0,0 +1,182 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed 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.deltaspike.security.impl.util.reflection;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Utility class for resolving all bean types from a given type.
+ */
+public class HierarchyDiscovery {
+
+    private final Type type;
+
+    private Map<Type, Class<?>> types;
+
+    public HierarchyDiscovery(Type type) {
+        this.type = type;
+    }
+
+    protected void add(Class<?> clazz, Type type) {
+        types.put(type, clazz);
+    }
+
+    public Set<Type> getTypeClosure() {
+        if (types == null) {
+            init();
+        }
+        // Return an independent set with no ties to the BiMap used
+        return new HashSet<Type>(types.keySet());
+    }
+
+    private void init() {
+        this.types = new HashMap<Type, Class<?>>();
+        try {
+            discoverTypes(type);
+        } catch (StackOverflowError e) {
+            System.out.println("type" + type);
+            Thread.dumpStack();
+            throw e;
+        }
+    }
+
+    public Type getResolvedType() {
+        if (type instanceof Class<?>) {
+            Class<?> clazz = (Class<?>) type;
+            return resolveType(clazz);
+        }
+        return type;
+    }
+
+    private void discoverTypes(Type type) {
+        if (type != null) {
+            if (type instanceof Class<?>) {
+                Class<?> clazz = (Class<?>) type;
+                add(clazz, resolveType(clazz));
+                discoverFromClass(clazz);
+            } else {
+                Class<?> clazz = null;
+                if (type instanceof ParameterizedType) {
+                    Type rawType = ((ParameterizedType) type).getRawType();
+                    if (rawType instanceof Class<?>) {
+                        discoverFromClass((Class<?>) rawType);
+                        clazz = (Class<?>) rawType;
+                    }
+                }
+                add(clazz, type);
+            }
+        }
+    }
+
+    private Type resolveType(Class<?> clazz) {
+        if (clazz.getTypeParameters().length > 0) {
+            TypeVariable<?>[] actualTypeParameters = clazz.getTypeParameters();
+            ParameterizedType parameterizedType = new ParameterizedTypeImpl(clazz, actualTypeParameters, clazz.getDeclaringClass());
+            return parameterizedType;
+        } else {
+            return clazz;
+        }
+    }
+
+    private void discoverFromClass(Class<?> clazz) {
+        discoverTypes(resolveType(type, type, clazz.getGenericSuperclass()));
+        for (Type c : clazz.getGenericInterfaces()) {
+            discoverTypes(resolveType(type, type, c));
+        }
+    }
+
+    /**
+     * Gets the actual types by resolving TypeParameters.
+     *
+     * @param beanType
+     * @param type
+     * @return actual type
+     */
+    private Type resolveType(Type beanType, Type beanType2, Type type) {
+        if (type instanceof ParameterizedType) {
+            if (beanType instanceof ParameterizedType) {
+                return resolveParameterizedType((ParameterizedType) beanType, (ParameterizedType) type);
+            }
+            if (beanType instanceof Class<?>) {
+                return resolveType(((Class<?>) beanType).getGenericSuperclass(), beanType2, type);
+            }
+        }
+
+        if (type instanceof TypeVariable<?>) {
+            if (beanType instanceof ParameterizedType) {
+                return resolveTypeParameter((ParameterizedType) beanType, beanType2, (TypeVariable<?>) type);
+            }
+            if (beanType instanceof Class<?>) {
+                return resolveType(((Class<?>) beanType).getGenericSuperclass(), beanType2, type);
+            }
+        }
+        return type;
+    }
+
+    private Type resolveParameterizedType(ParameterizedType beanType, ParameterizedType parameterizedType) {
+        Type rawType = parameterizedType.getRawType();
+        Type[] actualTypes = parameterizedType.getActualTypeArguments();
+
+        Type resolvedRawType = resolveType(beanType, beanType, rawType);
+        Type[] resolvedActualTypes = new Type[actualTypes.length];
+
+        for (int i = 0; i < actualTypes.length; i++) {
+            resolvedActualTypes[i] = resolveType(beanType, beanType, actualTypes[i]);
+        }
+        // reconstruct ParameterizedType by types resolved TypeVariable.
+        return new ParameterizedTypeImpl(resolvedRawType, resolvedActualTypes, parameterizedType.getOwnerType());
+    }
+
+    private Type resolveTypeParameter(ParameterizedType type, Type beanType, TypeVariable<?> typeVariable) {
+        // step1. raw type
+        Class<?> actualType = (Class<?>) type.getRawType();
+        TypeVariable<?>[] typeVariables = actualType.getTypeParameters();
+        Type[] actualTypes = type.getActualTypeArguments();
+        for (int i = 0; i < typeVariables.length; i++) {
+            if (typeVariables[i].equals(typeVariable) && !actualTypes[i].equals(typeVariable)) {
+                return resolveType(this.type, beanType, actualTypes[i]);
+            }
+        }
+
+        // step2. generic super class
+        Type genericSuperType = actualType.getGenericSuperclass();
+        Type resolvedGenericSuperType = resolveType(genericSuperType, beanType, typeVariable);
+        if (!(resolvedGenericSuperType instanceof TypeVariable<?>)) {
+            return resolvedGenericSuperType;
+        }
+
+        // step3. generic interfaces
+        if (beanType instanceof ParameterizedType) {
+            for (Type interfaceType : ((Class<?>) ((ParameterizedType) beanType).getRawType()).getGenericInterfaces()) {
+                Type resolvedType = resolveType(interfaceType, interfaceType, typeVariable);
+                if (!(resolvedType instanceof TypeVariable<?>)) {
+                    return resolvedType;
+                }
+            }
+        }
+
+        // don't resolve type variable
+        return typeVariable;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/426e3724/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/reflection/ParameterizedTypeImpl.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/reflection/ParameterizedTypeImpl.java b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/reflection/ParameterizedTypeImpl.java
new file mode 100644
index 0000000..8e45e0d
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/reflection/ParameterizedTypeImpl.java
@@ -0,0 +1,82 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed 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.deltaspike.security.impl.util.reflection;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+
+
+public class ParameterizedTypeImpl implements ParameterizedType {
+    private final Type[] actualTypeArguments;
+    private final Type rawType;
+    private final Type ownerType;
+
+    public ParameterizedTypeImpl(Type rawType, Type[] actualTypeArguments, Type ownerType) {
+        this.actualTypeArguments = actualTypeArguments;
+        this.rawType = rawType;
+        this.ownerType = ownerType;
+    }
+
+    public Type[] getActualTypeArguments() {
+        return Arrays.copyOf(actualTypeArguments, actualTypeArguments.length);
+    }
+
+    public Type getOwnerType() {
+        return ownerType;
+    }
+
+    public Type getRawType() {
+        return rawType;
+    }
+
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(actualTypeArguments) ^ (ownerType == null ? 0 : ownerType.hashCode()) ^ (rawType == null ? 0 : rawType.hashCode());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        } else if (obj instanceof ParameterizedType) {
+            ParameterizedType that = (ParameterizedType) obj;
+            Type thatOwnerType = that.getOwnerType();
+            Type thatRawType = that.getRawType();
+            return (ownerType == null ? thatOwnerType == null : ownerType.equals(thatOwnerType)) && (rawType == null ? thatRawType == null : rawType.equals(thatRawType)) && Arrays.equals(actualTypeArguments, that.getActualTypeArguments());
+        } else {
+            return false;
+        }
+
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(rawType);
+        if (actualTypeArguments.length > 0) {
+            sb.append("<");
+            for (Type actualType : actualTypeArguments) {
+                sb.append(actualType);
+                sb.append(",");
+            }
+            sb.delete(sb.length() - 1, sb.length());
+            sb.append(">");
+        }
+        return sb.toString();
+    }
+}