/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/security/admin/URMUsersGate.java,v 1.3 2004/07/30 06:52:02 ozeigermann Exp $
 * $Revision: 1.3 $
 * $Date: 2004/07/30 06:52:02 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * 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.slide.store.tamino.security.admin;

import org.apache.slide.urm.URMException;
import org.apache.slide.urm.URMForbiddenException;
import org.apache.slide.urm.authenticator.userdb.URMUser;
import org.apache.slide.urm.common.URMSetRoleException;
import org.apache.slide.urm.common.URMUpdateException;
import org.apache.slide.store.tamino.common.XForbiddenException;
import org.apache.slide.store.tamino.common.XGlobals;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Vector;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.macro.ConflictException;
import org.apache.slide.macro.ForbiddenException;

/**
 ** URMUsersGate serves the URMUsersStore using the URM API. It represents a user
 **
 ** @author    josef.haiduk@softwareag.com
 ** @version   $Revision: 1.3 $
 **
 **/
public class URMUsersGate extends URMGate
{
    public static String DEFAULT_PASSWORD = "Administrator";
    public static String OLD_PASSWORD = "oldPassword";
    public static String NEW_PASSWORD = "newPassword";
    
    URMUser urmUser = null;
    String user = null;
    private boolean userExists = false;
    
    /**
     * Creates a new gate to the URM API for serving user requests
     *
     * @param    parent              an URMUserDBStore
     * @param    uriStr              a  String
     *
     * @throws   ServiceAccessException
     *
     */
    public URMUsersGate(URMUserDBStore parent, String uriStr)
        throws ServiceAccessException
    {
        super(parent, uriStr);
        init();
    }
    
    /**
     * Method init
     *
     * @throws   ServiceAccessException
     *
     */
    private void init()
        throws ServiceAccessException
    {
        String path = URMUserDBStore.getUsersPath();
        
        if ( uriStr.compareTo(path) == 0 )
            return;
        
        String lastToken = uriStr.substring(path.length()+1);
        if ( lastToken.indexOf("/") != -1 )
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uriStr,
                            new XForbiddenException( "Operations below a user are forbidden!!!" )));
        try {
            user = new String(lastToken);
            
            if ( urmAdm.isUser(lastToken, domain) ) {
                urmUser = urmAdm.getUser(user, domain);
                userExists = true;
            }
        }
        catch (URMForbiddenException e) {
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uri.toString(), e));
        }
        catch (URMException e) {
            throw new ServiceAccessException(parent, e);
        }
    }
    
    /**
     * objectExists returns true if the user referenced by the uri passed to the constructor exists.
     *
     * @return   a boolean
     *
     */
    public boolean objectExists()
    {
        return userExists;
    }
    
    /**
     * getId returns the name of the user
     *
     * @return   a String
     *
     */
    public String getId()
    {
        return user;
    }
    
    /**
     * createObject creates a user referenced by the uri passed to the constructor
     *
     * @throws   ServiceAccessException
     *
     */
    public void createObject()
        throws ServiceAccessException
    {
        try {
            getUrmAdministratorWithAdminRole().createUser(user, DEFAULT_PASSWORD.toCharArray(), domain);
            urmUser = urmAdm.getUser(user, domain);
            userExists = true;
        }

        catch (URMForbiddenException e) {
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uri.toString(), e));
        }
        catch (URMSetRoleException e) {
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uri.toString(), e));
        }
        catch (URMException e) {
            throw new ServiceAccessException(parent, e);
        }
    }
    
    /**
     * deleteObject the user referenced by the uri passed to the constructor
     *
     * @throws   ServiceAccessException
     *
     */
    public void deleteObject()
        throws ServiceAccessException
    {
        try {
            getUrmAdministratorWithAdminRole().deleteUser(user, domain);
            userExists = false;
        }

        catch (URMForbiddenException e) {
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uri.toString(), e));
        }
        catch (URMSetRoleException e) {
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uri.toString(), e));
        }
        catch (URMException e) {
            throw new ServiceAccessException(parent, e);
        }
    }
    
    /**
     * getObject returns the URMUser referenced by the uri passed to the constructor
     *
     * @return   an URMUser
     *
     */
    public URMUser getObject()
    {
        return urmUser;
    }
    
    /**
     * getProperty returns the property value
     *
     * @param    key                 a  String
     *
     * @return   a String
     *
     * @throws   ServiceAccessException
     *
     */
    public String getProperty(String key)
        throws ServiceAccessException
    {
        return getProperty(urmUser, key);
    }
    
    /**
     * insertMappedProperties puts mapped properties into the NodeRevisionDescriptor
     *
     * @param    nrd                 a  NodeRevisionDescriptor
     *
     * @throws   ServiceAccessException
     *
     */
    public void insertMappedProperties(NodeRevisionDescriptor nrd)
        throws ServiceAccessException
    {
        insertMappedProperties(nrd, urmUser);
    }
    
    /**
     * getPropertiesAsBytes return properties as a byte array
     *
     * @return   a byte[]
     *
     * @throws   ServiceAccessException
     *
     */
    public byte[] getPropertiesAsBytes()
        throws ServiceAccessException
    {
        return getProperties(urmUser);
    }
    
    /**
     * getProperties return user properties having a value
     *
     * @return   a Properties
     *
     * @throws   ServiceAccessException
     *
     */
    public Properties getProperties()
        throws ServiceAccessException
    {
        try {
            return urmUser.getProperties();
        }
        catch (URMForbiddenException e) {
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uri.toString(), e));
        }
        catch (URMException e) {
            throw new ServiceAccessException(parent, e);
        }
        
    }
    
    /**
     * getAvailableProperties returns all users properties in a map. The values indicates if the
     * property can be modified (true)
     *
     * @return   a Map
     *
     * @throws   ServiceAccessException
     *
     */
    public Map getAvailableProperties()
        throws ServiceAccessException
    {
        return getAvailableProperties(urmUser);
    }
    
    /**
     * getModifiableProperties returns a set of modifiable user properties
     *
     * @return   a Set
     *
     * @throws   ServiceAccessException
     *
     */
    public Set getModifiableProperties()
        throws ServiceAccessException
    {
        return getModifiableProperties(getAvailableProperties());
    }
    
    /**
     * setProperties sets users properties and the password if the  NodeRevisionDescriptor contains
     * the properties for the old a new password
     *
     * @param    nrd                 a  NodeRevisionDescriptor
     *
     * @throws   ServiceAccessException
     *
     */
    public void setProperties(NodeRevisionDescriptor nrd)
        throws ServiceAccessException
    {
            NodeProperty op = nrd.getProperty(OLD_PASSWORD, XGlobals.TAMINO_NAMESPACE_URI);
            NodeProperty np = nrd.getProperty(NEW_PASSWORD, XGlobals.TAMINO_NAMESPACE_URI);
            
            if ( op != null && np != null ) {
                setPassword((String)op.getValue(),(String)np.getValue());
                return;
            }
            if ( op != null && np == null )
                throw new ServiceAccessException(parent,
                    new ConflictException(uri.toString(),
                            new XForbiddenException( "Old and new password are required!!!" )));

            if ( op == null && np != null )
                throw new ServiceAccessException(parent,
                    new ConflictException(uri.toString(),
                            new XForbiddenException( "Old and new password are required!!!" )));
            
            Properties pr = getPropertiesToModify(nrd);
            Set v = getModifiableProperties();
            Iterator i = v.iterator();
            while (i.hasNext()) {
                String key = (String)i.next();
                NodeProperty p = nrd.getProperty(key, XGlobals.TAMINO_NAMESPACE_URI);
                if ( p != null ) {
                    String value = (String)p.getValue();
                    if ( value.compareTo("") != 0 )
                        pr.put(key, value);
                }
            }
            updateProperties(urmUser, pr);
    }
        
    /**
     * setPassword the password of the user
     *
     * @param    oldPassword         a  String
     * @param    newPassword         a  String
     *
     * @throws   ServiceAccessException
     *
     */
    private void setPassword(String oldPassword, String newPassword)
        throws ServiceAccessException
    {
        try {
            if ( principal.getName().compareTo(user) == 0 ) {
                principal.setPassword(oldPassword.toCharArray(),newPassword.toCharArray());
                // the principal can only change his password. Changing properties will result
                // in an exception. Therefore leave the method here
                return;
            }
            else {
                URMUser urmUserAdmin = getUrmAdministratorWithAdminRole().getUser(user, domain);
                urmUserAdmin.setPassword(oldPassword.toCharArray(),newPassword.toCharArray());
            }
        }
        catch (URMForbiddenException e) {
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uri.toString(), e));
        }
        
        catch (URMSetRoleException e) {
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uri.toString(), e));
        }
        catch (URMUpdateException e) {
            throw new ServiceAccessException(parent,
                    new ConflictException(uri.toString(), e));
        }
        catch (URMException e) {
            throw new ServiceAccessException(parent, e);
        }
    }
            
    /**
     * getRoles returns a set of roles this user has
     *
     * @return   a Set
     *
     * @throws   ServiceAccessException
     *
     */
    public Set getRoles()
        throws ServiceAccessException
    {
        try {
            return urmUser.getRoleMapping();
        }
        catch (URMForbiddenException e) {
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uri.toString(), e));
        }
        catch (URMException e) {
            throw new ServiceAccessException(parent, e);
        }
    }
    
    
    /**
     * getGroups returns a set of groups to which this user belongs
     *
     * @return   a Set
     *
     * @throws   ServiceAccessException
     *
     */
    public Set getGroups()
        throws ServiceAccessException
    {
        if (userExists) {
            try {
                return urmUser.getGroups();
            }
            catch (URMForbiddenException e) {
                throw new ServiceAccessException(parent,
                        new ForbiddenException(uri.toString(), e));
            }
            catch (URMException e) {
                throw new ServiceAccessException(parent, e);
            }
        }
        return null;
    }
    
    /**
     * getAllUsers returns a set of all existing users
     *
     * @return   a Set
     *
     * @throws   ServiceAccessException
     *
     */
    private Set getAllUsers()
        throws ServiceAccessException
    {
        try {
            return urmAdm.getAllUsers(domain);
        }
        catch (URMForbiddenException e) {
            throw new ServiceAccessException(parent,
                    new ForbiddenException(uri.toString(), e));
        }
        catch (URMException e) {
            throw new ServiceAccessException(parent, e);
        }
    }
    
    /**
     * enumerateObject puts existing users into the vector
     *
     * @param    v                   a  Vector
     *
     * @throws   ServiceAccessException
     *
     */
    public void enumerateObject(Vector v)
        throws ServiceAccessException
    {
        enumerateSubjects(getAllUsers(), v);
    }
    
    /**
     * updateParents the members of this role; users, groups and roles
     *
     * @param    nrd                 a  NodeRevisionDescriptor
     *
     * @throws   ServiceAccessException
     *
     */
    public void updateParents(NodeRevisionDescriptor nrd)
        throws ServiceAccessException {
        updateParents(urmUser, nrd);
    }
}






