You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by rw...@apache.org on 2009/02/08 22:28:38 UTC

svn commit: r742172 [5/7] - in /portals/jetspeed-2/portal/branches/JPA_BRANCH: ./ components/jetspeed-page-manager/ components/jetspeed-page-manager/src/main/java/org/apache/jetspeed/page/jpa/ components/jetspeed-profiler/ components/jetspeed-profiler/...

Added: portals/jetspeed-2/portal/branches/JPA_BRANCH/components/jetspeed-security/src/main/java/org/apache/jetspeed/security/spi/jpa/JetspeedSecurityPersistenceManager.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JPA_BRANCH/components/jetspeed-security/src/main/java/org/apache/jetspeed/security/spi/jpa/JetspeedSecurityPersistenceManager.java?rev=742172&view=auto
==============================================================================
--- portals/jetspeed-2/portal/branches/JPA_BRANCH/components/jetspeed-security/src/main/java/org/apache/jetspeed/security/spi/jpa/JetspeedSecurityPersistenceManager.java (added)
+++ portals/jetspeed-2/portal/branches/JPA_BRANCH/components/jetspeed-security/src/main/java/org/apache/jetspeed/security/spi/jpa/JetspeedSecurityPersistenceManager.java Sun Feb  8 21:28:35 2009
@@ -0,0 +1,1446 @@
+/*
+ * 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.jetspeed.security.spi.jpa;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.PersistenceContext;
+import javax.persistence.PersistenceContextType;
+import javax.persistence.Query;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jetspeed.i18n.KeyedMessage;
+import org.apache.jetspeed.security.JetspeedPermission;
+import org.apache.jetspeed.security.JetspeedPrincipal;
+import org.apache.jetspeed.security.JetspeedPrincipalAssociationReference;
+import org.apache.jetspeed.security.JetspeedPrincipalType;
+import org.apache.jetspeed.security.PasswordCredential;
+import org.apache.jetspeed.security.SecurityDomain;
+import org.apache.jetspeed.security.SecurityException;
+import org.apache.jetspeed.security.User;
+import org.apache.jetspeed.security.impl.AbstractTransientJetspeedPrincipal;
+import org.apache.jetspeed.security.jpa.PersistentJetspeedPrincipal;
+import org.apache.jetspeed.security.jpa.SecurityDomainImpl;
+import org.apache.jetspeed.security.spi.JetspeedDomainPrincipalAccessManager;
+import org.apache.jetspeed.security.spi.JetspeedPermissionAccessManager;
+import org.apache.jetspeed.security.spi.JetspeedPermissionStorageManager;
+import org.apache.jetspeed.security.spi.JetspeedPrincipalAccessManager;
+import org.apache.jetspeed.security.spi.JetspeedPrincipalAssociationStorageManager;
+import org.apache.jetspeed.security.spi.JetspeedPrincipalStorageManager;
+import org.apache.jetspeed.security.spi.PersistentJetspeedPermission;
+import org.apache.jetspeed.security.spi.SecurityDomainAccessManager;
+import org.apache.jetspeed.security.spi.SecurityDomainStorageManager;
+import org.apache.jetspeed.security.spi.UserPasswordCredentialAccessManager;
+import org.apache.jetspeed.security.spi.UserPasswordCredentialStorageManager;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @version $Id: JetspeedSecurityPersistenceManager.java 736729 2009-01-22 18:02:23Z rwatler $
+ */
+@Repository
+public class JetspeedSecurityPersistenceManager implements Serializable, SecurityManager, JetspeedPrincipalAccessManager,
+                                                           JetspeedPrincipalStorageManager, JetspeedDomainPrincipalAccessManager,
+                                                           UserPasswordCredentialStorageManager, UserPasswordCredentialAccessManager,
+                                                           JetspeedPrincipalAssociationStorageManager, JetspeedPermissionAccessManager,
+                                                           JetspeedPermissionStorageManager, SecurityDomainStorageManager,
+                                                           SecurityDomainAccessManager
+{
+    private static final long serialVersionUID = -2689340557699526023L;
+    private static final Log logger = LogFactory.getLog(JetspeedSecurityPersistenceManager.class);
+	
+    private EntityManager entityManager;
+    private ThreadLocal<SecurityManagerContext> contexts;
+    private Long defaultSecurityDomainId;
+    
+    /**
+     * Default constructor.
+     */
+    public JetspeedSecurityPersistenceManager()
+    {
+        this.contexts = new ThreadLocal<SecurityManagerContext>();        
+    }
+    
+    /**
+     * Inject shared entity manager from assembly; this entity
+     * manager is expected to honor existing entity manager
+     * context attached to current thread, (otherwise, a new
+     * temporary entity manager is created).
+     * 
+     * @param entityManager injected shared entity manager
+     */
+    @PersistenceContext (type=PersistenceContextType.TRANSACTION, unitName="jetspeed-security")
+    public void setEntityManager(EntityManager entityManager) 
+    {
+        this.entityManager = entityManager;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.jetspeed.security.spi.jpa.SecurityManager#registerContext(java.lang.Object)
+     */
+    public void registerContext(Object context)
+    {
+        SecurityManagerContext registeredContext = (SecurityManagerContext)contexts.get();
+        if ((registeredContext == null) && (context instanceof SecurityManagerContext))
+        {
+            contexts.set((SecurityManagerContext)context);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.jetspeed.security.spi.jpa.SecurityManager#getContext()
+     */
+    public Object getContext()
+    {
+        return (SecurityManagerContext)contexts.get();
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.jetspeed.security.spi.jpa.SecurityManager#unregisterContext(java.lang.Object)
+     */
+    public void unregisterContext(Object context)
+    {
+        SecurityManagerContext registeredContext = (SecurityManagerContext)contexts.get();
+        if (context == registeredContext)
+        {
+            contexts.remove();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.jetspeed.security.spi.jpa.SecurityManager#getEntityManager()
+     */
+    public EntityManager getEntityManager()
+    {
+        SecurityManagerContext context = (SecurityManagerContext)getContext();
+        return ((context != null) ? context.getExtendedEntityManager() : entityManager);
+    }    
+    
+    //
+    // JetspeedPrincipalAccessManager interface implementation
+    //
+    
+    @Transactional (readOnly=true)
+	public boolean principalExists(JetspeedPrincipal principal)
+    {
+        if (principal.getId() == null)
+        {
+            if (principal.getDomainId() != null)
+            {
+                return principalExists(principal.getName(), principal.getType(), principal.getDomainId());    
+            }
+            else
+            {
+                return principalExists(principal.getName(), principal.getType());
+            }            
+        }
+
+        // query for principal by id, type, and domain
+        EntityManager entityManager = getEntityManager();
+        Query principalQuery = entityManager.createNamedQuery("PRINCIPAL");
+        principalQuery.setParameter("id", principal.getId());
+        principalQuery.setParameter("type", principal.getType().getName());
+        principalQuery.setParameter("domainId", principal.getDomainId());
+        try
+        {
+            principalQuery.getSingleResult();
+            return true;
+        }
+        catch (NoResultException nre)
+        {            
+        }
+        return false;
+    }
+
+    @Transactional (readOnly=true)
+	public List<JetspeedPrincipal> getAssociatedFrom(String principalFromName, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName)
+	{
+	    Long defaultDomainId = getDefaultSecurityDomainId();
+	    return getAssociatedFrom(principalFromName, from, to, associationName, defaultDomainId, defaultDomainId);
+	}
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<JetspeedPrincipal> getAssociatedFrom(String principalFromName, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName, Long fromSecurityDomain, Long toSecurityDomain)
+    {
+        // query for principals associated from other principal by name
+        EntityManager entityManager = getEntityManager();
+        Query principalsAssociatedFromQuery = entityManager.createNamedQuery("PRINCIPALS_ASSOCIATED_FROM_NAME");
+        principalsAssociatedFromQuery.setParameter("associationName", associationName);
+        principalsAssociatedFromQuery.setParameter("principalFromName", principalFromName);
+        principalsAssociatedFromQuery.setParameter("type", to.getName());
+        principalsAssociatedFromQuery.setParameter("fromSecurityDomain", fromSecurityDomain);
+        principalsAssociatedFromQuery.setParameter("toSecurityDomain", toSecurityDomain);
+        return principalsAssociatedFromQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public List<JetspeedPrincipal> getAssociatedTo(String principalToName, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName)
+    {
+        Long defaultDomainId = getDefaultSecurityDomainId();
+        return getAssociatedTo(principalToName, from, to, associationName, defaultDomainId, defaultDomainId);
+    }
+
+    @SuppressWarnings("unchecked") 
+    public List<JetspeedPrincipal> getAssociatedTo(String principalToName, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName, Long fromSecurityDomain, Long toSecurityDomain)
+    {
+        // query for principals associated to other principal by name
+        EntityManager entityManager = getEntityManager();
+        Query principalsAssociatedToQuery = entityManager.createNamedQuery("PRINCIPALS_ASSOCIATED_TO_NAME");
+        principalsAssociatedToQuery.setParameter("associationName", associationName);
+        principalsAssociatedToQuery.setParameter("principalToName", principalToName);
+        principalsAssociatedToQuery.setParameter("type", from.getName());
+        principalsAssociatedToQuery.setParameter("fromSecurityDomain", fromSecurityDomain);
+        principalsAssociatedToQuery.setParameter("toSecurityDomain", toSecurityDomain);
+        return principalsAssociatedToQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public List<JetspeedPrincipal> getAssociatedFrom(Long principalFromId, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName)
+    {
+        Long defaultDomainId = getDefaultSecurityDomainId();
+        return getAssociatedFrom(principalFromId, from, to, associationName, defaultDomainId, defaultDomainId);
+    }
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<JetspeedPrincipal> getAssociatedFrom(Long principalFromId, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName, Long fromSecurityDomain, Long toSecurityDomain)
+    {
+        // query for principals associated from other principal by id
+        EntityManager entityManager = getEntityManager();
+        Query principalsAssociatedFromQuery = entityManager.createNamedQuery("PRINCIPALS_ASSOCIATED_FROM_ID");
+        principalsAssociatedFromQuery.setParameter("associationName", associationName);
+        principalsAssociatedFromQuery.setParameter("principalFromId", principalFromId);
+        principalsAssociatedFromQuery.setParameter("type", to.getName());
+        principalsAssociatedFromQuery.setParameter("fromSecurityDomain", fromSecurityDomain);
+        principalsAssociatedFromQuery.setParameter("toSecurityDomain", toSecurityDomain);
+        return principalsAssociatedFromQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public List<JetspeedPrincipal> getAssociatedTo(Long principalToId, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName)
+    {
+        Long defaultDomainId = getDefaultSecurityDomainId();
+        return getAssociatedTo(principalToId, from, to, associationName, defaultDomainId, defaultDomainId);
+    }
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<JetspeedPrincipal> getAssociatedTo(Long principalToId, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName, Long fromSecurityDomain, Long toSecurityDomain)
+    {
+        // query for principals associated to other principal by id
+        EntityManager entityManager = getEntityManager();
+        Query principalsAssociatedToQuery = entityManager.createNamedQuery("PRINCIPALS_ASSOCIATED_TO_ID");
+        principalsAssociatedToQuery.setParameter("associationName", associationName);
+        principalsAssociatedToQuery.setParameter("principalToId", principalToId);
+        principalsAssociatedToQuery.setParameter("type", from.getName());
+        principalsAssociatedToQuery.setParameter("fromSecurityDomain", fromSecurityDomain);
+        principalsAssociatedToQuery.setParameter("toSecurityDomain", toSecurityDomain);
+        return principalsAssociatedToQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public List<String> getAssociatedNamesFrom(String principalFromName, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName)
+    {
+        Long defaultDomainId = getDefaultSecurityDomainId();
+        return getAssociatedNamesFrom(principalFromName, from, to, associationName, defaultDomainId, defaultDomainId);
+    }
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<String> getAssociatedNamesFrom(String principalFromName, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName, Long fromSecurityDomain, Long toSecurityDomain)
+    {
+        // query for principal names associated from other principal by name
+        EntityManager entityManager = getEntityManager();
+        Query principalNamesAssociatedFromQuery = entityManager.createNamedQuery("PRINCIPAL_NAMES_ASSOCIATED_FROM_NAME");
+        principalNamesAssociatedFromQuery.setParameter("associationName", associationName);
+        principalNamesAssociatedFromQuery.setParameter("principalFromName", principalFromName);
+        principalNamesAssociatedFromQuery.setParameter("type", to.getName());
+        principalNamesAssociatedFromQuery.setParameter("fromSecurityDomain", fromSecurityDomain);
+        principalNamesAssociatedFromQuery.setParameter("toSecurityDomain", toSecurityDomain);
+        return principalNamesAssociatedFromQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public List<String> getAssociatedNamesFrom(Long principalFromId, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName)
+    {
+        Long defaultDomainId = getDefaultSecurityDomainId();
+        return getAssociatedNamesFrom(principalFromId, from, to, associationName, defaultDomainId, defaultDomainId);
+    }
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<String> getAssociatedNamesFrom(Long principalFromId, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName, Long fromSecurityDomain, Long toSecurityDomain)
+    {
+        // query for principal names associated from other principal by id
+        EntityManager entityManager = getEntityManager();
+        Query principalNamesAssociatedFromQuery = entityManager.createNamedQuery("PRINCIPAL_NAMES_ASSOCIATED_FROM_ID");
+        principalNamesAssociatedFromQuery.setParameter("associationName", associationName);
+        principalNamesAssociatedFromQuery.setParameter("principalFromId", principalFromId);
+        principalNamesAssociatedFromQuery.setParameter("type", to.getName());
+        principalNamesAssociatedFromQuery.setParameter("fromSecurityDomain", fromSecurityDomain);
+        principalNamesAssociatedFromQuery.setParameter("toSecurityDomain", toSecurityDomain);
+        return principalNamesAssociatedFromQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public List<String> getAssociatedNamesTo(String principalToName, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName)
+    {
+        Long defaultDomainId = getDefaultSecurityDomainId();
+        return getAssociatedNamesTo(principalToName, from, to, associationName, defaultDomainId, defaultDomainId);
+    }
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<String> getAssociatedNamesTo(String principalToName, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName, Long fromSecurityDomain, Long toSecurityDomain)
+    {
+        // query for principal names associated to other principal by name
+        EntityManager entityManager = getEntityManager();
+        Query principalNamesAssociatedToQuery = entityManager.createNamedQuery("PRINCIPAL_NAMES_ASSOCIATED_TO_NAME");
+        principalNamesAssociatedToQuery.setParameter("associationName", associationName);
+        principalNamesAssociatedToQuery.setParameter("principalToName", principalToName);
+        principalNamesAssociatedToQuery.setParameter("type", from.getName());
+        principalNamesAssociatedToQuery.setParameter("fromSecurityDomain", fromSecurityDomain);
+        principalNamesAssociatedToQuery.setParameter("toSecurityDomain", toSecurityDomain);
+        return principalNamesAssociatedToQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public List<String> getAssociatedNamesTo(Long principalToId, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName)
+    {
+        Long defaultDomainId = getDefaultSecurityDomainId();
+        return getAssociatedNamesTo(principalToId, from, to, associationName, defaultDomainId, defaultDomainId);
+    }
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<String> getAssociatedNamesTo(Long principalToId, JetspeedPrincipalType from, JetspeedPrincipalType to, String associationName, Long fromSecurityDomain, Long toSecurityDomain)
+    {
+        // query for principal names associated to other principal by id
+        EntityManager entityManager = getEntityManager();
+        Query principalNamesAssociatedToQuery = entityManager.createNamedQuery("PRINCIPAL_NAMES_ASSOCIATED_TO_ID");
+        principalNamesAssociatedToQuery.setParameter("associationName", associationName);
+        principalNamesAssociatedToQuery.setParameter("principalToId", principalToId);
+        principalNamesAssociatedToQuery.setParameter("type", from.getName());
+        principalNamesAssociatedToQuery.setParameter("fromSecurityDomain", fromSecurityDomain);
+        principalNamesAssociatedToQuery.setParameter("toSecurityDomain", toSecurityDomain);
+        return principalNamesAssociatedToQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public JetspeedPrincipal getPrincipal(Long id)
+    {
+        // query for principal by id
+        EntityManager entityManager = getEntityManager();
+        Query principalQuery = entityManager.createNamedQuery("PRINCIPAL_ID");
+        principalQuery.setParameter("id", id);
+        try
+        {
+            return (JetspeedPrincipal)principalQuery.getSingleResult();
+        }
+        catch (NoResultException nre)
+        {            
+        }
+        return null;
+    }
+
+    @Transactional (readOnly=true)
+    public JetspeedPrincipal getPrincipal(String principalName, JetspeedPrincipalType type)
+    {
+        return getPrincipal(principalName, type, getDefaultSecurityDomainId());
+    }
+    
+    @Transactional (readOnly=true)
+    public JetspeedPrincipal getPrincipal(String principalName, JetspeedPrincipalType type, Long securityDomain)
+    {
+        // query for principal by name, type, and domain
+        EntityManager entityManager = getEntityManager();
+        Query principalQuery = entityManager.createNamedQuery("PRINCIPAL_NAME");
+        principalQuery.setParameter("name", principalName);
+        principalQuery.setParameter("type", type.getName());
+        principalQuery.setParameter("domainId", securityDomain);
+        try
+        {
+            return (JetspeedPrincipal)principalQuery.getSingleResult();
+        }
+        catch (NoResultException nre)
+        {            
+        }
+        return null;
+    }
+
+    @Transactional (readOnly=true)
+    public List<String> getPrincipalNames(String nameFilter, JetspeedPrincipalType type)
+    {
+        return getPrincipalNames(nameFilter, type, getDefaultSecurityDomainId());
+    }
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<String> getPrincipalNames(String nameFilter, JetspeedPrincipalType type, Long securityDomain)
+    {
+        // query for principal names by name like filter, type, and domain
+        EntityManager entityManager = getEntityManager();
+        Query principalNamesQuery = entityManager.createNamedQuery("PRINCIPAL_NAMES_LIKE_NAME");
+        principalNamesQuery.setParameter("nameFilter", ((nameFilter != null) ? nameFilter : "")+"%");
+        principalNamesQuery.setParameter("type", type.getName());
+        principalNamesQuery.setParameter("domainId", securityDomain);
+        return principalNamesQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public List<JetspeedPrincipal> getPrincipals(String nameFilter, JetspeedPrincipalType type)
+    {
+        return getPrincipals(nameFilter, type, getDefaultSecurityDomainId());
+    }
+    
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<JetspeedPrincipal> getPrincipals(String nameFilter, JetspeedPrincipalType type, Long securityDomain)
+    {
+        // query for principals by name like filter, type, and domain
+        EntityManager entityManager = getEntityManager();
+        Query principalsQuery = entityManager.createNamedQuery("PRINCIPALS_LIKE_NAME");
+        principalsQuery.setParameter("nameFilter", ((nameFilter != null) ? nameFilter : "")+"%");
+        principalsQuery.setParameter("type", type.getName());
+        principalsQuery.setParameter("domainId", securityDomain);
+        return principalsQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public List<JetspeedPrincipal> getPrincipalsByAttribute(String attributeName, String attributeValue, JetspeedPrincipalType type)
+    {
+        return getPrincipalsByAttribute(attributeName, attributeValue, type, getDefaultSecurityDomainId());
+    }
+    
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<JetspeedPrincipal> getPrincipalsByAttribute(String attributeName, String attributeValue, JetspeedPrincipalType type, Long securityDomain)
+    {
+        // query for principals by type, domain, and attributes
+        EntityManager entityManager = getEntityManager();
+        Query principalsQuery = entityManager.createNamedQuery("PRINCIPALS_ATTRIBUTE");
+        principalsQuery.setParameter("type", type.getName());
+        principalsQuery.setParameter("domainId", securityDomain);
+        principalsQuery.setParameter("attributeName", attributeName);
+        principalsQuery.setParameter("attributeValue", attributeValue);
+        return principalsQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public boolean principalExists(String principalName, JetspeedPrincipalType type)
+    {
+        return principalExists(principalName, type, getDefaultSecurityDomainId());
+    }
+    
+    @Transactional (readOnly=true)
+    public boolean principalExists(String principalName, JetspeedPrincipalType type, Long securityDomain)
+    {
+        // query for principal by name, type, and domain
+        EntityManager entityManager = getEntityManager();
+        Query principalQuery = entityManager.createNamedQuery("PRINCIPAL_NAME");
+        principalQuery.setParameter("name", principalName);
+        principalQuery.setParameter("type", type.getName());
+        principalQuery.setParameter("domainId", securityDomain);
+        try
+        {
+            principalQuery.getSingleResult();
+            return true;
+        }
+        catch (NoResultException nre)
+        {            
+        }
+        return false;
+    }
+
+    //
+    // JetspeedPrincipalStorageManager interface implementation
+    //
+    
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void addPrincipal(JetspeedPrincipal principal, Set<JetspeedPrincipalAssociationReference> associations) throws SecurityException
+    {
+        if (principal.getDomainId() == null && principal instanceof AbstractTransientJetspeedPrincipal)
+        {
+            ((AbstractTransientJetspeedPrincipal)principal).setDomainId(getDefaultSecurityDomainId());
+        }
+        if (principalExists(principal))
+        {
+            throw new SecurityException(SecurityException.PRINCIPAL_ALREADY_EXISTS.createScoped(principal.getType().getName(), principal.getName()));
+        }
+        try
+        {
+            // persist, (potentially detached), principal
+            EntityManager entityManager = getEntityManager();
+            if (!((PersistentJetspeedPrincipal)principal).isNew())
+            {
+                principal = entityManager.merge(principal);
+            }
+            entityManager.persist(principal);
+            // explicitly flush entity manager after update
+            entityManager.flush();            
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager","addPrincipal", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);            
+        }
+        // Note: the (optional) required associations are expected to be stored by the calling JetspeedPrincipalManager
+    }
+
+    public boolean isMapped()
+    {
+        return false;
+    }
+
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void removePrincipal(JetspeedPrincipal principal) throws SecurityException
+    {
+        if (!principalExists(principal))
+        {
+            throw new SecurityException(SecurityException.PRINCIPAL_DOES_NOT_EXIST.createScoped(principal.getType().getName(), principal.getName()));
+        }
+        try
+        {
+            // remove, (potentially detached), principal
+            EntityManager entityManager = getEntityManager();
+            if (!((PersistentJetspeedPrincipal)principal).isNew())
+            {
+                principal = entityManager.merge(principal);
+            }
+            entityManager.remove(principal);
+            // explicitly flush entity manager after remove
+            entityManager.flush();
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "removePrincipal", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);            
+        }
+    }
+
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void updatePrincipal(JetspeedPrincipal principal) throws SecurityException
+    {
+        if (!principalExists(principal))
+        {
+            throw new SecurityException(SecurityException.PRINCIPAL_DOES_NOT_EXIST.createScoped(principal.getType().getName(), principal.getName()));
+        }
+        try
+        {
+            // persist, (potentially detached), principal
+            EntityManager entityManager = getEntityManager();
+            if (!((PersistentJetspeedPrincipal)principal).isNew())
+            {
+                principal = entityManager.merge(principal);
+            }
+            entityManager.persist(principal);
+            // explicitly flush entity manager after update
+            entityManager.flush();
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "updatePrincipal", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);            
+        }
+    }
+
+    //
+    // UserPasswordCredentialStorageManager interface implementation
+    //
+
+    @Transactional (readOnly=true)
+    public PasswordCredential getPasswordCredential(User user)
+    {
+        // query for password credential by user id and type
+        EntityManager entityManager = getEntityManager();
+        Query passwordCredentialQuery = entityManager.createNamedQuery("PASSWORD_CREDENTIAL");
+        passwordCredentialQuery.setParameter("principalId", user.getId());
+        passwordCredentialQuery.setParameter("type", PasswordCredential.TYPE_CURRENT);
+        PasswordCredentialImpl passwordCredential;
+        try
+        {
+            passwordCredential = (PasswordCredentialImpl)passwordCredentialQuery.getSingleResult();
+        }
+        catch (NoResultException nre)
+        {            
+            passwordCredential = new PasswordCredentialImpl();
+        }
+        // set the credential user explicitly
+        passwordCredential.setUser(user);
+        return passwordCredential;
+    }
+
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void storePasswordCredential(PasswordCredential credential) throws SecurityException
+    {
+        if (credential.isNewPasswordSet())
+        {
+            if (credential.getNewPassword() != null)
+            {
+                credential.setPassword(credential.getNewPassword(), credential.isEncoded());                
+            }
+        }
+        try
+        {
+            // persist, (potentially detached), password credential
+            EntityManager entityManager = getEntityManager();
+            if (!((PasswordCredentialImpl)credential).isNew())
+            {
+                credential = entityManager.merge(credential);
+            }
+            entityManager.persist(credential);
+            // explicitly flush entity manager after update
+            entityManager.flush();
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "storePasswordCredential", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);            
+        }
+    }
+
+    @Transactional (readOnly=true)
+    public PasswordCredential getPasswordCredential(String userName)
+    {
+        return getPasswordCredential(userName,getDefaultSecurityDomainId());
+    }
+    
+    //
+    // UserPasswordCredentialAccessManager interface implementation
+    //
+
+    /**
+     * <p>
+     * Retrieves the current PasswordCredential by userName
+     * </p>
+     * <p>
+     * Warning: the User reference is transient. This is intentionally done to
+     * allow retrieving the credential for authentication purposes only so no
+     * User is loaded when authentication fails. The user reference can be materialized
+     * by calling {@link #loadPasswordCredentialUser(PasswordCredential)}.
+     * </p>
+     */
+    @Transactional (readOnly=true)
+    public PasswordCredential getPasswordCredential(String userName, Long securityDomain)
+    {
+        // query for password credential by user name, type
+        EntityManager entityManager = getEntityManager();
+        Query passwordCredentialQuery = entityManager.createNamedQuery("PASSWORD_CREDENTIAL_PRINCIPAL_NAME");
+        passwordCredentialQuery.setParameter("name", userName);
+        passwordCredentialQuery.setParameter("enabled", true);
+        passwordCredentialQuery.setParameter("domainId", securityDomain);
+        passwordCredentialQuery.setParameter("type", PasswordCredential.TYPE_CURRENT);
+        try
+        {
+            PasswordCredentialImpl passwordCredential = (PasswordCredentialImpl)passwordCredentialQuery.getSingleResult();
+            // set the user name explicitly
+            passwordCredential.setUserName(userName);
+            return passwordCredential;
+        }
+        catch (NoResultException nre)
+        {            
+        }
+        return null;
+    }
+    
+    @Transactional (readOnly=true)
+    public void loadPasswordCredentialUser(final PasswordCredential credential)
+    {
+        // query for and set credential user
+        PasswordCredentialImpl credentialImpl = (PasswordCredentialImpl)credential;
+        Long userPrincipalId = credentialImpl.getPrincipalId();
+        if ((credential.getUser() == null) && (userPrincipalId != null))
+        {
+            credentialImpl.setUser((User)getPrincipal(userPrincipalId));
+        }
+    }
+
+    @Transactional (readOnly=true)
+    public List<PasswordCredential> getHistoricPasswordCredentials(User user)
+    {
+        return getHistoricPasswordCredentials(user,getDefaultSecurityDomainId());
+    }
+    
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<PasswordCredential> getHistoricPasswordCredentials(User user, Long securityDomain)
+    {
+        // query for password credential by user id and type
+        EntityManager entityManager = getEntityManager();
+        Query passwordCredentialQuery = entityManager.createNamedQuery("PASSWORD_CREDENTIAL");
+        passwordCredentialQuery.setParameter("principalId", user.getId());
+        passwordCredentialQuery.setParameter("type", PasswordCredential.TYPE_HISTORICAL);
+        List<PasswordCredential> list = passwordCredentialQuery.getResultList();
+        // set the credential users explicitly
+        for (PasswordCredential passwordCredential : list)
+        {
+            ((PasswordCredentialImpl)passwordCredential).setUser(user);
+        }
+        return list;
+    }
+
+    //
+    // JetspeedPrincipalAssociationStorageManager interface implementation
+    //
+
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void addAssociation(JetspeedPrincipal from, JetspeedPrincipal to, String associationName) throws SecurityException
+    {
+        // query for principal association using from, to, and name
+        EntityManager entityManager = getEntityManager();
+        Query principalAssociationsQuery = entityManager.createNamedQuery("PRINCIPAL_ASSOCIATION");
+        principalAssociationsQuery.setParameter("fromPrincipalId", from.getId());
+        principalAssociationsQuery.setParameter("toPrincipalId", to.getId());
+        principalAssociationsQuery.setParameter("associationName", associationName);
+        try
+        {
+            if (principalAssociationsQuery.getResultList().isEmpty())
+            {
+                // persist new principal association
+                entityManager.persist(new JetspeedPrincipalAssociation(from, to, associationName));
+                // explicitly flush entity manager after update
+                entityManager.flush();
+                // evict all principal object instances and related queries
+                // from cache since the relationships between the associations
+                // and the principals is not modeled explicitly in JPA metadata
+                evictFromCache(PersistentJetspeedPrincipal.class);
+            }
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "addAssociation", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);
+        }
+    }
+
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    @SuppressWarnings("unchecked") 
+    public void removeAssociation(JetspeedPrincipal from, JetspeedPrincipal to, String associationName) throws SecurityException
+    {
+        // query for principal association using from, to, and name
+        EntityManager entityManager = getEntityManager();
+        Query principalAssociationsQuery = entityManager.createNamedQuery("PRINCIPAL_ASSOCIATION");
+        principalAssociationsQuery.setParameter("fromPrincipalId", from.getId());
+        principalAssociationsQuery.setParameter("toPrincipalId", to.getId());
+        principalAssociationsQuery.setParameter("associationName", associationName);
+        try
+        {
+            // remove principal associations
+            for (JetspeedPrincipalAssociation principalAssociation : (List<JetspeedPrincipalAssociation>)principalAssociationsQuery.getResultList())
+            {
+                entityManager.remove(principalAssociation);
+            }
+            // explicitly flush entity manager after removes
+            entityManager.flush();
+            // evict all principal object instances and related queries
+            // from cache since the relationships between the associations
+            // and the principals is not modeled explicitly in JPA metadata
+            evictFromCache(PersistentJetspeedPrincipal.class);
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "removeAssociation", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);
+        }
+    }
+
+    //
+    // JetspeedPermissionAccessManager interface implementation
+    //
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<PersistentJetspeedPermission> getPermissions()
+    {
+        // query for all permissions ordered by type and name
+        EntityManager entityManager = getEntityManager();
+        Query permissionsQuery = entityManager.createNamedQuery("PERMISSIONS");
+        return permissionsQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public List<PersistentJetspeedPermission> getPermissions(String type)
+    {
+        return getPermissions(type, null);
+    }
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<PersistentJetspeedPermission> getPermissions(String type, String nameFilter)
+    {
+        // query for all permissions with type and name like filter ordered name
+        EntityManager entityManager = getEntityManager();
+        Query permissionsQuery = entityManager.createNamedQuery("PERMISSIONS_LIKE_NAME");
+        permissionsQuery.setParameter("type", type);
+        permissionsQuery.setParameter("nameFilter", ((nameFilter != null) ? nameFilter : "")+"%");
+        return permissionsQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    public boolean permissionExists(JetspeedPermission permission)
+    {
+        // query for permission with type and name
+        EntityManager entityManager = getEntityManager();
+        Query permissionQuery = entityManager.createNamedQuery("PERMISSION_TYPE_NAME");
+        permissionQuery.setParameter("type", permission.getType());
+        permissionQuery.setParameter("name", permission.getName());
+        try
+        {
+            permissionQuery.getSingleResult();
+            return true;
+        }
+        catch (NoResultException nre)
+        {            
+        }
+        return false;
+    }
+    
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public List<PersistentJetspeedPermission> getPermissions(JetspeedPrincipal principal)
+    {
+        EntityManager entityManager = getEntityManager();
+        Query permissionsPrincipalQuery = entityManager.createNamedQuery("PERMISSIONS_PRINCIPAL");
+        permissionsPrincipalQuery.setParameter("principalId", principal.getId());
+        return permissionsPrincipalQuery.getResultList();
+    }
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked")
+    public List<JetspeedPrincipal> getPrincipals(PersistentJetspeedPermission permission, String principalType)
+    {
+        // query for principals that have permission
+        EntityManager entityManager = getEntityManager();
+        Query principalsPermissionQuery;
+        if (principalType != null)
+        {
+            if (permission.getId() != null)
+            {
+                // query for principals that have permission with id
+                principalsPermissionQuery = entityManager.createNamedQuery("PRINCIPALS_TYPE_PERMISSION");
+                principalsPermissionQuery.setParameter("permissionId", permission.getId());
+            }
+            else
+            {
+                // query for principals that have permission with name and type
+                principalsPermissionQuery = entityManager.createNamedQuery("PRINCIPALS_TYPE_PERMISSION_TYPE_NAME");
+                principalsPermissionQuery.setParameter("type", permission.getType());
+                principalsPermissionQuery.setParameter("name", permission.getName());
+            }
+            // constrain principals by type
+            principalsPermissionQuery.setParameter("principalType", principalType);
+        }
+        else
+        {
+            if (permission.getId() != null)
+            {
+                // query for principals that have permission with id
+                principalsPermissionQuery = entityManager.createNamedQuery("PRINCIPALS_PERMISSION");
+                principalsPermissionQuery.setParameter("permissionId", permission.getId());
+            }
+            else
+            {
+                // query for principals that have permission with name and type
+                principalsPermissionQuery = entityManager.createNamedQuery("PRINCIPALS_PERMISSION_TYPE_NAME");
+                principalsPermissionQuery.setParameter("type", permission.getType());
+                principalsPermissionQuery.setParameter("name", permission.getName());
+            }            
+        }
+        // constrain principals by default domain
+        principalsPermissionQuery.setParameter("domainId", getDefaultSecurityDomainId());
+        return principalsPermissionQuery.getResultList();
+    }
+
+    //
+    // JetspeedPermissionStorageManager interface implementation
+    //
+
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void addPermission(PersistentJetspeedPermission permission) throws SecurityException
+    {
+        if (permission.getId() != null || permissionExists(permission))
+        {
+            throw new SecurityException(SecurityException.PERMISSION_ALREADY_EXISTS.create(permission.getName()));
+        }
+        try
+        {
+            // persist new permission
+            EntityManager entityManager = getEntityManager();
+            entityManager.persist(permission);
+            // explicitly flush entity manager after update
+            entityManager.flush();
+            // evict all principal and persistence object instances and
+            // related queries from cache since the relationships between
+            // the principals and permissions are not modeled explicitly
+            // in JPA metadata
+            evictFromCache(PersistentJetspeedPrincipal.class);
+            evictFromCache(PersistentJetspeedPermissionImpl.class);
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "addPermission", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);            
+        }
+    }
+
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void updatePermission(PersistentJetspeedPermission permission) throws SecurityException
+    {
+        // query for current permission
+        EntityManager entityManager = getEntityManager();
+        Query permissionQuery;
+        if (permission.getId() != null)
+        {
+            // query for permission with id
+            permissionQuery = entityManager.createNamedQuery("PERMISSION");
+            permissionQuery.setParameter("id", permission.getId());
+        }
+        else
+        {
+            // query for permission with type and name
+            permissionQuery = entityManager.createNamedQuery("PERMISSION_TYPE_NAME");            
+            permissionQuery.setParameter("type", permission.getType());
+            permissionQuery.setParameter("name", permission.getName());
+        }
+        PersistentJetspeedPermission current;
+        try
+        {
+            current = (PersistentJetspeedPermission)permissionQuery.getSingleResult();
+        }
+        catch (NoResultException nre)
+        {            
+            throw new SecurityException(SecurityException.PERMISSION_DOES_NOT_EXIST.create(permission.getName()));
+        }
+        // update current permission with actions from specified permission
+        if (!current.getActions().equals(permission.getActions()))
+        {
+            current.setActions(permission.getActions());
+            try
+            {
+                // persist permission
+                entityManager.persist(current);
+                // explicitly flush entity manager after update
+                entityManager.flush();
+                // evict all principal and persistence object instances and
+                // related queries from cache since the relationships between
+                // the principals and permissions are not modeled explicitly
+                // in JPA metadata
+                evictFromCache(PersistentJetspeedPrincipal.class);
+                evictFromCache(PersistentJetspeedPermissionImpl.class);
+            }
+            catch (Exception e)
+            {
+                KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "updatePermission", e.getMessage());
+                logger.error(msg, e);
+                throw new SecurityException(msg, e);
+            }
+        }
+    }    
+    
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void removePermission(PersistentJetspeedPermission permission) throws SecurityException
+    {
+        // query for current permission
+        EntityManager entityManager = getEntityManager();
+        Query permissionQuery;
+        if (permission.getId() != null)
+        {
+            // query for permission with id
+            permissionQuery = entityManager.createNamedQuery("PERMISSION");
+            permissionQuery.setParameter("id", permission.getId());
+        }
+        else
+        {
+            // query for permission with type and name
+            permissionQuery = entityManager.createNamedQuery("PERMISSION_TYPE_NAME");            
+            permissionQuery.setParameter("type", permission.getType());
+            permissionQuery.setParameter("name", permission.getName());
+        }
+        PersistentJetspeedPermission current;
+        try
+        {
+            current = (PersistentJetspeedPermission)permissionQuery.getSingleResult();
+        }
+        catch (NoResultException nre)
+        {            
+            throw new SecurityException(SecurityException.PERMISSION_DOES_NOT_EXIST.create(permission.getName()));
+        }
+        try
+        {
+            // remove permission
+            entityManager.remove(current);
+            // explicitly flush entity manager after remove
+            entityManager.flush();
+            // evict all principal and persistence object instances and
+            // related queries from cache since the relationships between
+            // the principals and permissions are not modeled explicitly
+            // in JPA metadata
+            evictFromCache(PersistentJetspeedPrincipal.class);
+            evictFromCache(PersistentJetspeedPermissionImpl.class);
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "removePermission", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);            
+        }
+    }    
+
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void grantPermission(PersistentJetspeedPermission permission, JetspeedPrincipal principal) throws SecurityException
+    {
+        if (permission.getId() == null)
+        {
+            // query for current permission with type and name
+            EntityManager entityManager = getEntityManager();
+            Query permissionQuery = entityManager.createNamedQuery("PERMISSION_TYPE_NAME");            
+            permissionQuery.setParameter("type", permission.getType());
+            permissionQuery.setParameter("name", permission.getName());
+            try
+            {
+                permission = (PersistentJetspeedPermission)permissionQuery.getSingleResult();
+            }
+            catch (NoResultException nre)
+            {            
+                throw new SecurityException(SecurityException.PERMISSION_DOES_NOT_EXIST.create(permission.getName()));
+            }
+        }
+        grantPermission(permission, principal, true);
+    }
+
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    protected void grantPermission(PersistentJetspeedPermission permission, JetspeedPrincipal principal, boolean checkExists) throws SecurityException
+    {
+        if (principal.isTransient() || principal.getId() == null)
+        {
+            JetspeedPrincipal p = getPrincipal(principal.getName(), principal.getType());
+            if (p == null)
+            {
+                throw new SecurityException(SecurityException.PRINCIPAL_DOES_NOT_EXIST.createScoped(principal.getType().getName(), principal.getName()));
+            }
+            principal = p;
+        }
+        EntityManager entityManager = getEntityManager();
+        if (checkExists)
+        {
+            // query for principal permission with principal id and permission id
+            Query principalPermissionsQuery = entityManager.createNamedQuery("PRINCIPAL_PERMISSION");            
+            principalPermissionsQuery.setParameter("principalId", principal.getId());
+            principalPermissionsQuery.setParameter("permissionId", permission.getId());
+            if (!principalPermissionsQuery.getResultList().isEmpty())
+            {
+                return;
+            }
+        }
+        try
+        {
+            // persist new principal permission
+            entityManager.persist(new JetspeedPrincipalPermission(principal, permission));
+            // explicitly flush entity manager after update
+            entityManager.flush();
+            // evict all principal and persistence object instances and
+            // related queries from cache since the relationships between
+            // the principals and permissions are not modeled explicitly
+            // in JPA metadata
+            evictFromCache(PersistentJetspeedPrincipal.class);
+            evictFromCache(PersistentJetspeedPermissionImpl.class);
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "grantPermission", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);
+        }
+    }
+
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    @SuppressWarnings("unchecked") 
+    public void grantPermissionOnlyTo(PersistentJetspeedPermission permission, String principalType, List<JetspeedPrincipal> principals) throws SecurityException
+    {
+        if (permission.getId() == null)
+        {
+            // query for current permission with type and name
+            EntityManager entityManager = getEntityManager();
+            Query permissionQuery = entityManager.createNamedQuery("PERMISSION_TYPE_NAME");            
+            permissionQuery.setParameter("type", permission.getType());
+            permissionQuery.setParameter("name", permission.getName());
+            try
+            {
+                permission = (PersistentJetspeedPermission)permissionQuery.getSingleResult();
+            }
+            catch (NoResultException nre)
+            {            
+                throw new SecurityException(SecurityException.PERMISSION_DOES_NOT_EXIST.create(permission.getName()));
+            }
+        }
+        // query for current principals that have permission
+        EntityManager entityManager = getEntityManager();
+        Query principalsPermissionQuery; 
+        if (principalType != null)
+        {
+            // query for principals by type that have permission with id
+            principalsPermissionQuery = entityManager.createNamedQuery("PRINCIPALS_TYPE_PERMISSION");
+            principalsPermissionQuery.setParameter("permissionId", permission.getId());
+            principalsPermissionQuery.setParameter("principalType", principalType);
+        }
+        else
+        {
+            // query for principals that have permission with id
+            principalsPermissionQuery = entityManager.createNamedQuery("PRINCIPALS_PERMISSION");
+            principalsPermissionQuery.setParameter("permissionId", permission.getId());
+        }
+        // constrain principals by default domain
+        principalsPermissionQuery.setParameter("domainId", getDefaultSecurityDomainId());
+        // get current principals in a mutable list
+        List<JetspeedPrincipal> currentList = new ArrayList<JetspeedPrincipal>(principalsPermissionQuery.getResultList());
+        // grant/revoke permissions to update from current to specified target principals
+        List<JetspeedPrincipal> targetList = new ArrayList<JetspeedPrincipal>(principals);
+        for (Iterator<JetspeedPrincipal> i = currentList.iterator(); i.hasNext(); )
+        {
+            JetspeedPrincipal current = i.next();
+            for (Iterator<JetspeedPrincipal> j = targetList.iterator(); j.hasNext(); )
+            {
+                JetspeedPrincipal target = j.next();                
+                if (principalType != null && !target.getType().getName().equals(principalType))
+                {
+                    throw new SecurityException(SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "grantPermissionOnlyTo", "Specified "+target.getType().getName()+" principal: "+target.getName()+" is not of type: "+principalType));
+                }
+                if (current.getType().getName().equals(target.getType().getName()) && current.getName().equals(target.getName()))
+                {
+                    j.remove();
+                    current = null;
+                    break;
+                }
+            }
+            if (current == null)
+            {
+                i.remove();
+            }
+        }
+        for (Iterator<JetspeedPrincipal> i = currentList.iterator(); i.hasNext(); )
+        {
+            revokePermission(permission, i.next());
+        }
+        for (Iterator<JetspeedPrincipal> i = targetList.iterator(); i.hasNext(); )
+        {
+            grantPermission(permission, i.next(), false);
+        }
+    }
+
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void revokePermission(PersistentJetspeedPermission permission, JetspeedPrincipal principal) throws SecurityException
+    {
+        // perform principal permission delete
+        EntityManager entityManager = getEntityManager();
+        Query principalPermissionDelete;
+        if (principal.isTransient() || principal.getId() == null)
+        {
+            if (permission.getId() == null)
+            {
+                // delete by principal type, name, and domain and permission type and name
+                principalPermissionDelete = entityManager.createNamedQuery("DELETE_PRINCIPAL_TYPE_NAME_PERMISSION_TYPE_NAME");
+                principalPermissionDelete.setParameter("permissionType", permission.getType());
+                principalPermissionDelete.setParameter("permissionName", permission.getName());
+            }
+            else
+            {
+                // delete by principal type, name, and domain and permission id
+                principalPermissionDelete = entityManager.createNamedQuery("DELETE_PRINCIPAL_TYPE_NAME_PERMISSION");
+                principalPermissionDelete.setParameter("permissionId", permission.getId());
+            }
+            principalPermissionDelete.setParameter("principalType", principal.getType());
+            principalPermissionDelete.setParameter("principalName", principal.getName());
+            principalPermissionDelete.setParameter("principalDomainId", getDefaultSecurityDomainId());
+        }
+        else
+        {
+            if (permission.getId() == null)
+            {
+                // delete by principal id and permission type and name
+                principalPermissionDelete = entityManager.createNamedQuery("DELETE_PRINCIPAL_PERMISSION_TYPE_NAME");
+                principalPermissionDelete.setParameter("permissionType", permission.getType());
+                principalPermissionDelete.setParameter("permissionName", permission.getName());
+            }
+            else
+            {
+                // delete by principal id and permission id
+                principalPermissionDelete = entityManager.createNamedQuery("DELETE_PRINCIPAL_PERMISSION");
+                principalPermissionDelete.setParameter("permissionId", permission.getId());
+            }
+            principalPermissionDelete.setParameter("principalId", principal.getId());
+        }
+        try
+        {
+            principalPermissionDelete.executeUpdate();
+            // evict all principal and persistence object instances and
+            // related queries from cache since the relationships between
+            // the principals and permissions are not modeled explicitly
+            // in JPA metadata
+            evictFromCache(PersistentJetspeedPrincipal.class);
+            evictFromCache(PersistentJetspeedPermissionImpl.class);
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "revokePermission", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);
+        }
+    }
+    
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void revokeAllPermissions(JetspeedPrincipal principal) throws SecurityException
+    {
+        // perform principal permissions delete
+        EntityManager entityManager = getEntityManager();
+        Query principalPermissionsDelete;
+        if (principal.isTransient() || principal.getId() == null)
+        {
+            // delete by principal type, name, and domain
+            principalPermissionsDelete = entityManager.createNamedQuery("DELETE_PRINCIPAL_TYPE_NAME_PERMISSIONS");
+            principalPermissionsDelete.setParameter("principalType", principal.getType());
+            principalPermissionsDelete.setParameter("principalName", principal.getName());
+            principalPermissionsDelete.setParameter("principalDomainId", getDefaultSecurityDomainId());
+        }
+        else
+        {
+            // delete by principal id
+            principalPermissionsDelete = entityManager.createNamedQuery("DELETE_PRINCIPAL_PERMISSIONS");
+            principalPermissionsDelete.setParameter("principalId", principal.getId());
+        }
+        try
+        {
+            principalPermissionsDelete.executeUpdate();
+            // evict all principal and persistence object instances and
+            // related queries from cache since the relationships between
+            // the principals and permissions are not modeled explicitly
+            // in JPA metadata
+            evictFromCache(PersistentJetspeedPrincipal.class);
+            evictFromCache(PersistentJetspeedPermissionImpl.class);
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "revokeAllPermissions", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);
+        }
+    }
+
+    @Transactional (readOnly=true)
+    protected boolean domainExists(SecurityDomain domain)
+    {        
+        if (domain.getDomainId() != null)
+        {
+            return getDomain(domain.getDomainId()) != null;
+        }
+        else
+        {
+            return getDomainByName(domain.getName()) != null; 
+        }
+    }
+    
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void addDomain(SecurityDomain domain) throws SecurityException 
+    {
+        if (domainExists(domain))
+        {
+            throw new SecurityException(SecurityException.SECURITY_DOMAIN_EXISTS.create(domain.getName()));
+        }
+        try
+        {
+            // persist, (potentially detached), domain
+            EntityManager entityManager = getEntityManager();
+            if (!((SecurityDomainImpl)domain).isNew())
+            {
+                domain = entityManager.merge(domain);
+            }
+            entityManager.persist(domain);
+            // explicitly flush entity manager after update
+            entityManager.flush();            
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "addDomain", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);            
+        }
+    }
+
+    @Transactional (readOnly=true)
+    public SecurityDomain getDomain(Long domainId)
+    {
+        // query for security domain with id
+        EntityManager entityManager = getEntityManager();
+        Query domainQuery = entityManager.createNamedQuery("SECURITY_DOMAIN");            
+        domainQuery.setParameter("domainId", domainId);
+        try
+        {
+            return (SecurityDomain)domainQuery.getSingleResult();
+        }
+        catch (NoResultException nre)
+        {            
+        }
+        return null;
+    }
+
+    protected Long getDefaultSecurityDomainId()
+    {
+        if (defaultSecurityDomainId == null)
+        {
+            SecurityDomain d = getDomainByName(SecurityDomain.DEFAULT_NAME);
+            if (d != null)
+            {
+                // cache real default security domain id
+                defaultSecurityDomainId = d.getDomainId();
+            }
+            else
+            {
+                // return fake id that should not exist
+                return new Long(-1);
+            }
+        }   
+        return defaultSecurityDomainId;
+    }
+    
+    @Transactional (readOnly=true)
+    public SecurityDomain getDomainByName(String domainName)
+    {
+        // query for security domain with name
+        EntityManager entityManager = getEntityManager();
+        Query domainQuery = entityManager.createNamedQuery("SECURITY_DOMAIN_NAME");            
+        domainQuery.setParameter("name", domainName);
+        try
+        {
+            return (SecurityDomain)domainQuery.getSingleResult();
+        }
+        catch (NoResultException nre)
+        {            
+        }
+        return null;
+    }
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public Collection<SecurityDomain> getAllDomains()
+    {
+        // query for security domains ordered by name
+        EntityManager entityManager = getEntityManager();
+        Query domainsQuery = entityManager.createNamedQuery("SECURITY_DOMAINS");            
+        return domainsQuery.getResultList();
+    }
+    
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void removeDomain(SecurityDomain domain) throws SecurityException
+    {
+        if (!domainExists(domain))
+        {
+            throw new SecurityException(SecurityException.PRINCIPAL_DOES_NOT_EXIST.create(domain.getName()));
+        }
+        try
+        {
+            // remove, (potentially detached), domain
+            EntityManager entityManager = getEntityManager();
+            if (!((SecurityDomainImpl)domain).isNew())
+            {
+                domain = entityManager.merge(domain);
+            }
+            entityManager.remove(domain);
+            // explicitly flush entity manager after remove
+            entityManager.flush();            
+            // evict all principal object instances and related queries
+            // from cache since the relationships between principals and
+            // and domains is not modeled explicitly in JPA metadata
+            evictFromCache(PersistentJetspeedPrincipal.class);
+        }
+        catch (Exception e)
+        {
+            KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "removeDomain", e.getMessage());
+            logger.error(msg, e);
+            throw new SecurityException(msg, e);            
+        }
+    }
+    
+    @Transactional (readOnly=false, rollbackFor=SecurityException.class)
+    public void updateDomain(SecurityDomain domain) throws SecurityException
+    {
+         if (!domainExists(domain))
+         {
+             throw new SecurityException(SecurityException.SECURITY_DOMAIN_DOES_NOT_EXIST.create(domain.getName()));
+         }
+         try
+         {
+             // persist, (potentially detached), domain
+             EntityManager entityManager = getEntityManager();
+             if (!((SecurityDomainImpl)domain).isNew())
+             {
+                 domain = entityManager.merge(domain);
+             }
+             entityManager.persist(domain);
+             // explicitly flush entity manager after update
+             entityManager.flush();            
+             // evict all principal object instances and related queries
+             // from cache since the relationships between principals and
+             // and domains is not modeled explicitly in JPA metadata
+             evictFromCache(PersistentJetspeedPrincipal.class);
+         }
+         catch (Exception e)
+         {
+             KeyedMessage msg = SecurityException.UNEXPECTED.create("JetspeedSecurityPersistenceManager", "updateDomain", e.getMessage());
+             logger.error(msg, e);
+             throw new SecurityException(msg, e);            
+         }
+    }
+
+    @Transactional (readOnly=true)
+    @SuppressWarnings("unchecked") 
+    public Collection<SecurityDomain> getDomainsOwnedBy(Long ownerDomainId)
+    {
+        // query for security domain with owner domain ordered by name
+        EntityManager entityManager = getEntityManager();
+        Query domainsQuery = entityManager.createNamedQuery("SECURITY_DOMAINS_OWNER");            
+        domainsQuery.setParameter("ownerDomainId", ownerDomainId);
+        return domainsQuery.getResultList();
+    }
+    
+    /**
+     * Evict all object instances of specified type from cache
+     * along with related cached query results. This capability
+     * is required to support flushing of related objects where
+     * associations are not explicitly modeled in JPA metadata.
+     * 
+     * @param evictClass class of objects to evict from cache.
+     */
+    protected void evictFromCache(Class<?> evictClass)
+    {
+        // no default JPA implementation        
+    }
+}

Added: portals/jetspeed-2/portal/branches/JPA_BRANCH/components/jetspeed-security/src/main/java/org/apache/jetspeed/security/spi/jpa/OpenJPAJetspeedSecurityPersistenceManager.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JPA_BRANCH/components/jetspeed-security/src/main/java/org/apache/jetspeed/security/spi/jpa/OpenJPAJetspeedSecurityPersistenceManager.java?rev=742172&view=auto
==============================================================================
--- portals/jetspeed-2/portal/branches/JPA_BRANCH/components/jetspeed-security/src/main/java/org/apache/jetspeed/security/spi/jpa/OpenJPAJetspeedSecurityPersistenceManager.java (added)
+++ portals/jetspeed-2/portal/branches/JPA_BRANCH/components/jetspeed-security/src/main/java/org/apache/jetspeed/security/spi/jpa/OpenJPAJetspeedSecurityPersistenceManager.java Sun Feb  8 21:28:35 2009
@@ -0,0 +1,105 @@
+/*
+ * 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.jetspeed.security.spi.jpa;
+
+import java.util.Arrays;
+
+import javax.persistence.EntityManager;
+
+import org.apache.openjpa.conf.OpenJPAConfiguration;
+import org.apache.openjpa.event.RemoteCommitEvent;
+import org.apache.openjpa.event.RemoteCommitEventManager;
+import org.apache.openjpa.event.RemoteCommitProvider;
+import org.apache.openjpa.event.SingleJVMRemoteCommitProvider;
+import org.apache.openjpa.persistence.EntityManagerImpl;
+import org.apache.openjpa.persistence.QueryResultCache;
+import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;
+
+/**
+ * OpenJPAJetspeedSecurityPersistenceManager
+ * 
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id: $
+ */
+public class OpenJPAJetspeedSecurityPersistenceManager extends JetspeedSecurityPersistenceManager
+{
+    private static final long serialVersionUID = 1958254980350768940L;
+
+    // Members
+    
+    private RemoteCommitEventManager openJPAEventManager;
+    private QueryResultCache openJPAQueryResultCache;
+    private boolean distributed;
+
+    // Lifecycle
+    
+    /**
+     * Initialize by accessing OpenJPA components.
+     */
+    public void initialize()
+    {
+        // get OpenJPA entity manager and event manager
+        EntityManager entityManager = getEntityManager();
+        EntityManagerImpl openJPAEntityManager = (EntityManagerImpl)entityManager.getDelegate();
+        if (openJPAEntityManager != null)
+        {
+            // check OpenJPA configuration for distributed operation
+            OpenJPAConfiguration configuration = openJPAEntityManager.getConfiguration();
+            openJPAEventManager = configuration.getRemoteCommitEventManager();
+            if (openJPAEventManager.areRemoteEventsEnabled())
+            {
+                RemoteCommitProvider provider = openJPAEventManager.getRemoteCommitProvider();
+                distributed = ((provider != null) && !(provider instanceof SingleJVMRemoteCommitProvider));
+            }
+            // access system wide query results cache
+            OpenJPAEntityManagerFactory openJPAEntityManagerFactory = openJPAEntityManager.getEntityManagerFactory();
+            openJPAQueryResultCache = openJPAEntityManagerFactory.getQueryResultCache();
+        }
+        entityManager.close();
+    }
+
+    /**
+     * Terminate access to OpenJPA components.
+     */
+    public void terminate()
+    {
+        // terminate access to OpenJPA components
+        openJPAEventManager = null;
+        openJPAQueryResultCache = null;
+    }    
+
+    // Implementation
+    
+    /* (non-Javadoc)
+     * @see org.apache.jetspeed.security.spi.jpa.JetspeedSecurityPersistenceManager#evictFromCache(java.lang.Class)
+     */
+    protected void evictFromCache(Class<?> evictClass)
+    {
+        // evict query results that contain specified class object instances
+        if (openJPAQueryResultCache != null)
+        {
+            openJPAQueryResultCache.evictAll(evictClass);
+        }
+        // send eviction/update notification to distributed caches
+        if ((openJPAEventManager != null) && distributed)
+        {
+            RemoteCommitEvent evictEvent = new RemoteCommitEvent(RemoteCommitEvent.PAYLOAD_EXTENTS, null, null, Arrays.asList(new Class<?>[]{evictClass}), null);
+            RemoteCommitProvider provider = openJPAEventManager.getRemoteCommitProvider();
+            provider.broadcast(evictEvent);
+        }
+    }
+}

Added: portals/jetspeed-2/portal/branches/JPA_BRANCH/components/jetspeed-security/src/main/java/org/apache/jetspeed/security/spi/jpa/PasswordCredentialImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JPA_BRANCH/components/jetspeed-security/src/main/java/org/apache/jetspeed/security/spi/jpa/PasswordCredentialImpl.java?rev=742172&view=auto
==============================================================================
--- portals/jetspeed-2/portal/branches/JPA_BRANCH/components/jetspeed-security/src/main/java/org/apache/jetspeed/security/spi/jpa/PasswordCredentialImpl.java (added)
+++ portals/jetspeed-2/portal/branches/JPA_BRANCH/components/jetspeed-security/src/main/java/org/apache/jetspeed/security/spi/jpa/PasswordCredentialImpl.java Sun Feb  8 21:28:35 2009
@@ -0,0 +1,458 @@
+/* 
+ * 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.jetspeed.security.spi.jpa;
+
+import java.sql.Date;
+import java.sql.Timestamp;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQuery;
+import javax.persistence.NamedQueries;
+import javax.persistence.PrePersist;
+import javax.persistence.PostRemove;
+import javax.persistence.PostLoad;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.Transient;
+import javax.persistence.Version;
+
+import org.apache.jetspeed.security.PasswordCredential;
+import org.apache.jetspeed.security.User;
+import org.apache.jetspeed.security.UserCredential;
+
+/**
+ * <p>
+ * Default Password credential implementation
+ * </p>
+ * 
+ * @version $Id: PasswordCredentialImpl.java 708045 2008-10-26 21:22:00Z ate $
+ */
+@Entity (name="PasswordCredential")
+@Table (name="SECURITY_CREDENTIAL")
+@NamedQueries ({@NamedQuery(name="PASSWORD_CREDENTIAL", query="select pc from PasswordCredential pc where pc.principalId = :principalId and pc.type = :type"),
+                @NamedQuery(name="PASSWORD_CREDENTIAL_PRINCIPAL_NAME", query="select pc from PasswordCredential pc, Principal p where pc.type = :type and pc.principalId = p.id and p.name = :name and p.domainId = :domainId and p.enabled = :enabled")})
+public class PasswordCredentialImpl implements PasswordCredential
+{
+    private static final long serialVersionUID = -4975305752376365096L;
+    
+    // Members
+    
+    @Id
+    @GeneratedValue (strategy=GenerationType.AUTO)
+    @Column (name="CREDENTIAL_ID")
+    @SuppressWarnings("unused")
+    private Long id;
+    @Version
+    @Column (name="JPA_VERSION")
+    @SuppressWarnings("unused")
+    private int jpaVersion;
+    @Basic
+    @Column (name="PRINCIPAL_ID")
+    private Long principalId;
+    /** The "raw" password value */
+    @Basic
+    @Column (name="CREDENTIAL_VALUE")
+    private String password;
+    /** The type mapping field */
+    @Basic
+    @Column (name="TYPE")
+    private short type;
+    /** flag (default true) indicating if the credential password is updatable (e.g. by the user itself). */
+    @Basic
+    @Column (name="UPDATE_ALLOWED")
+    private boolean updateAllowed;    
+    /** flag (default false) indicating if the credential password state is read only. */
+    @Basic
+    @Column (name="IS_STATE_READONLY")
+    private boolean stateReadOnly;
+    /** The update required state */
+    @Basic
+    @Column (name="UPDATE_REQUIRED")
+    private boolean updateRequired;
+    /** flag indicating if the current password is encoded */
+    @Basic
+    @Column (name="IS_ENCODED")
+    private boolean encoded;
+    /** The enabled state. */
+    @Basic
+    @Column (name="IS_ENABLED")
+    private boolean enabled;
+    /** The number of authentication failures */
+    @Basic
+    @Column (name="AUTH_FAILURES")
+    private int authenticationFailures;
+    /** The expired state. */
+    @Basic
+    @Column (name="IS_EXPIRED")
+    private boolean expired;
+    /** The creation date. */
+    @Temporal (value=TemporalType.TIMESTAMP)
+    @Column (name="CREATION_DATE")
+    private Timestamp creationDate;
+    /** The modified date. */
+    @Temporal (value=TemporalType.TIMESTAMP)
+    @Column (name="MODIFIED_DATE")
+    private Timestamp modifiedDate;        
+    /** The previous authentication in date */
+    @Temporal (value=TemporalType.TIMESTAMP)
+    @Column (name="PREV_AUTH_DATE")
+    private Timestamp previousAuthenticationDate;
+    /** The last authentication in date */
+    @Temporal (value=TemporalType.TIMESTAMP)
+    @Column (name="LAST_AUTH_DATE")
+    private Timestamp lastAuthenticationDate;
+    /** The expiration date. */
+    @Temporal (value=TemporalType.DATE)
+    @Column (name="EXPIRATION_DATE")
+    private Date expirationDate;
+    
+    @PrePersist
+    @SuppressWarnings("unused")
+    private void prePersist()
+    {
+        if (creationDate == null)
+        {
+            creationDate = new Timestamp(System.currentTimeMillis());
+            modifiedDate = creationDate;
+        }
+        else
+        {
+            modifiedDate = new Timestamp(System.currentTimeMillis());
+        }
+    }
+    @PostLoad
+    @SuppressWarnings("unused")
+    private void postLoad()
+    {
+        persistent = true;
+    }
+    @PostRemove
+    @SuppressWarnings("unused")
+    private void postRemove()
+    {
+        persistent = false;
+    }
+
+    @Transient
+    private boolean persistent;
+    @Transient
+    private User user;    
+    @Transient
+    private String userName;
+    /** The saved current "raw" password value */
+    @Transient
+    private String currentPassword;
+    /** the "old" password for authenticating password change (if set) */
+    @Transient
+    private String oldPassword;
+    /** the "new" password to be used for changing the real password */
+    @Transient
+    private String newPassword;    
+    /** flag indicating a new password value is set to be processed */
+    @Transient
+    private boolean newPasswordSet;
+
+    // Implementation
+    
+    public PasswordCredentialImpl()
+    {
+        this.updateAllowed = true;
+        this.enabled = true;
+        this.type = TYPE_CURRENT;
+    }
+    
+    public PasswordCredentialImpl(User user, String password)
+    {
+        this();
+        setUser(user);
+        this.password = password;
+    }
+    
+    public void synchronize(UserCredential pwc)
+    {
+        throw new UnsupportedOperationException();
+    }
+    
+    public boolean isNew()
+    {
+        return !persistent;
+    }
+    
+    private void checkUpdatePassword()
+    {
+        if (!updateAllowed)
+        {
+            throw new IllegalStateException();
+        }
+    }
+    
+    private void checkUpdateState()
+    {
+        if (stateReadOnly)
+        {
+            throw new IllegalStateException();
+        }
+    }
+    
+    public void setUser(User user)
+    {
+        this.user = user;
+        if (user != null && user.getId() != null)
+        {
+            this.principalId = user.getId();
+        }
+    }
+    
+    public void setUserName(String userName)
+    {
+        this.userName = userName;
+    }
+    
+    /**
+     * @return The username.
+     */
+    public String getUserName()
+    {
+        return user != null ? user.getName() : userName;
+    }
+    
+    public User getUser()
+    {
+        return user;
+    }
+    
+    public Long getPrincipalId()
+    {
+        return principalId;
+    }
+    
+    public Short getType()
+    {
+        return type;
+    }
+    
+    /**
+     * @return The password.
+     */
+    public String getPassword()
+    {
+        return currentPassword != null ? currentPassword : password;
+    }
+    
+    public void setPassword(String password, boolean encoded)
+    {
+        checkUpdatePassword();
+        if (password != null && (this.password == null || encoded != this.encoded || !password.equals(this.password)))
+        {
+            if (!newPasswordSet && currentPassword == null)
+            {
+                currentPassword = password;
+            }
+            this.password = password;
+            this.encoded = encoded;
+            oldPassword = null;
+            newPassword = null;
+            newPasswordSet = true;
+        }
+    }
+    
+    public void setPassword(String oldPassword, String newPassword)
+    {
+        checkUpdatePassword();
+        if (newPassword != null && (oldPassword == null || !newPassword.equals(oldPassword)))
+        {
+            if (!newPasswordSet && currentPassword == null)
+            {
+                currentPassword = password;
+            }
+            this.newPassword = newPassword;
+            this.oldPassword = oldPassword;
+            newPasswordSet = true;
+        }
+    }
+    
+    public void clearNewPasswordSet()
+    {
+        currentPassword = null;
+        oldPassword = null;
+        newPassword = null;
+        newPasswordSet = false;
+    }
+    
+    public void revertNewPasswordSet()
+    {
+        if (newPasswordSet)
+        {
+            newPassword = currentPassword;
+            currentPassword = null;
+            oldPassword = null;
+            newPassword = null;
+            newPasswordSet = false;
+        }
+    }
+    
+    public String getOldPassword()
+    {
+        return oldPassword;
+    }
+    
+    public String getNewPassword()
+    {
+        return newPassword;
+    }
+    
+    public boolean isNewPasswordSet()
+    {
+        return newPasswordSet;
+    }
+    
+    public boolean isEncoded()
+    {
+        return encoded;
+    }
+    
+    public void setEncoded(boolean encoded)
+    {
+        checkUpdatePassword();
+        this.encoded = encoded;
+    }
+    
+    public boolean isUpdateAllowed()
+    {
+        return updateAllowed;
+    }
+    
+    public void setUpdateAllowed(boolean updateAllowed)
+    {
+        this.updateAllowed = true;
+    }
+    
+    public boolean isStateReadOnly()
+    {
+        return stateReadOnly;
+    }
+    
+    public void setStateReadOnly(boolean stateReadOnly)
+    {
+        this.stateReadOnly = stateReadOnly; 
+    }
+    
+    public boolean isUpdateRequired()
+    {
+        return updateRequired;
+    }
+    
+    public void setUpdateRequired(boolean updateRequired)
+    {
+        checkUpdateState();
+        this.updateRequired = updateRequired;
+    }
+
+    public boolean isEnabled()
+    {
+        return enabled;
+    }
+    
+    public void setEnabled(boolean enabled)
+    {
+        checkUpdateState();
+        this.enabled = enabled;
+        if (enabled)
+        {
+            setAuthenticationFailures(0);
+        }
+    }
+
+    public boolean isExpired()
+    {
+        return expired;
+    }
+    
+    public void setExpired(boolean expired)
+    {
+        checkUpdateState();
+        this.expired = expired;
+    }
+
+    public Timestamp getCreationDate()
+    {
+        return creationDate;
+    }
+
+    public Timestamp getModifiedDate()
+    {
+        return modifiedDate;
+    }
+
+    public Date getExpirationDate()
+    {
+        return expirationDate;
+    }
+    
+    public void setExpirationDate(Date expirationDate)
+    {
+        checkUpdateState();
+        this.expirationDate = expirationDate;
+        if (expirationDate != null && new Date(new java.util.Date().getTime()).after(expirationDate))
+        {
+            setExpired(true);
+        }
+        else
+        {
+            setExpired(false);
+        }
+    }
+    
+    public Timestamp getPreviousAuthenticationDate()
+    {
+        return previousAuthenticationDate;
+    }
+    
+    public void setPreviousAuthenticationDate(Timestamp previousAuthenticationDate)
+    {
+        checkUpdateState();
+        this.previousAuthenticationDate = previousAuthenticationDate;
+    }
+
+    public Timestamp getLastAuthenticationDate()
+    {
+        return lastAuthenticationDate;
+    }
+
+    public void setLastAuthenticationDate(Timestamp lastAuthenticationDate)
+    {
+        checkUpdateState();
+        this.lastAuthenticationDate = lastAuthenticationDate;
+    }
+
+    public int getAuthenticationFailures()
+    {
+        return authenticationFailures;
+    }
+
+    public void setAuthenticationFailures(int authenticationFailures)
+    {
+        checkUpdateState();
+        this.authenticationFailures = authenticationFailures;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org