org.sakaiproject.kernel.authz.simple.SimpleJcrUserEnvironmentResolverService.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.kernel.authz.simple.SimpleJcrUserEnvironmentResolverService.java

Source

/*
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF 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.sakaiproject.kernel.authz.simple;

import com.google.inject.Inject;
import com.google.inject.name.Named;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.kernel.KernelConstants;
import org.sakaiproject.kernel.api.Registry;
import org.sakaiproject.kernel.api.RegistryService;
import org.sakaiproject.kernel.api.UpdateFailedException;
import org.sakaiproject.kernel.api.authz.AuthzResolverService;
import org.sakaiproject.kernel.api.authz.SubjectPermissionService;
import org.sakaiproject.kernel.api.jcr.support.JCRNodeFactoryService;
import org.sakaiproject.kernel.api.jcr.support.JCRNodeFactoryServiceException;
import org.sakaiproject.kernel.api.memory.Cache;
import org.sakaiproject.kernel.api.memory.CacheManagerService;
import org.sakaiproject.kernel.api.memory.CacheScope;
import org.sakaiproject.kernel.api.rest.RestProvider;
import org.sakaiproject.kernel.api.serialization.BeanConverter;
import org.sakaiproject.kernel.api.session.Session;
import org.sakaiproject.kernel.api.user.User;
import org.sakaiproject.kernel.api.user.UserFactoryService;
import org.sakaiproject.kernel.api.user.UserProvisionAgent;
import org.sakaiproject.kernel.api.userenv.UserEnvironment;
import org.sakaiproject.kernel.api.userenv.UserEnvironmentResolverService;
import org.sakaiproject.kernel.model.UserEnvironmentBean;
import org.sakaiproject.kernel.user.jcr.JcrAuthenticationResolverProvider;
import org.sakaiproject.kernel.util.IOUtils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.jcr.Node;
import javax.jcr.RepositoryException;

/**
 *
 */
public class SimpleJcrUserEnvironmentResolverService implements UserEnvironmentResolverService {

    protected String LOCALE_SESSION_KEY = "sakai.locale.";

    private static final Log LOG = LogFactory.getLog(SimpleJcrUserEnvironmentResolverService.class);

    private static final boolean debug = LOG.isDebugEnabled();
    private JCRNodeFactoryService jcrNodeFactoryService;
    private BeanConverter beanConverter;
    private UserEnvironment nullUserEnv;
    private Cache<UserEnvironment> cache;
    private UserFactoryService userFactoryService;

    private AuthzResolverService authzResolverService;

    private SubjectPermissionService subjectPermissionService;

    private RegistryService registryService;

    /**
    *
    */
    @Inject
    public SimpleJcrUserEnvironmentResolverService(JCRNodeFactoryService jcrNodeFactoryService,
            CacheManagerService cacheManagerService, BeanConverter beanConverter,
            @Named(KernelConstants.NULLUSERENV) UserEnvironment nullUserEnv, UserFactoryService userFactoryService,
            AuthzResolverService authzResolverService, SubjectPermissionService subjectPermissionService,
            RegistryService registryService) {
        this.jcrNodeFactoryService = jcrNodeFactoryService;
        this.nullUserEnv = nullUserEnv;
        this.beanConverter = beanConverter;
        this.userFactoryService = userFactoryService;
        this.authzResolverService = authzResolverService;
        this.subjectPermissionService = subjectPermissionService;
        this.registryService = registryService;
        cache = cacheManagerService.getCache("userenv", CacheScope.CLUSTERINVALIDATED);
        cache.put("test", null);
        cache.remove("test");
    }

    /**
     * {@inheritDoc}
     *
     * @see org.sakaiproject.kernel.api.userenv.UserEnvironmentResolverService#resolve(org.sakaiproject.kernel.api.user.User)
     */
    public UserEnvironment resolve(String userId) {
        if (userId != null) {
            if (cache.containsKey(userId)) {
                UserEnvironment ue = cache.get(userId);
                if (ue != null && !ue.hasExpired()) {
                    if (debug) {
                        LOG.debug("Loaded from Cache");
                    }
                    return ue;
                }
            }
            if (userId != null) {
                String userEnv = userFactoryService.getUserEnvPath(userId);
                UserEnvironment ue = loadUserEnvironmentBean(userEnv);
                if (ue != null) {
                    cache.put(userId, ue);
                    return ue;
                }
            }
        }
        return nullUserEnv;
    }

    /**
     * {@inheritDoc}
     *
     * @see org.sakaiproject.kernel.api.userenv.UserEnvironmentResolverService#resolve(org.sakaiproject.kernel.api.session.Session)
     */
    public UserEnvironment resolve(Session currentSession) {
        return resolve(currentSession.getUser());
    }

    /**
     * {@inheritDoc}
     *
     * @see org.sakaiproject.kernel.api.userenv.UserEnvironmentResolverService#resolve(org.sakaiproject.kernel.api.user.User)
     */
    public UserEnvironment resolve(User user) {
        if (user == null) {
            return resolve((String) null);
        } else {
            return resolve(user.getUuid());
        }
    }

    public void expire(String userId) {
        cache.remove(userId);
    }

    /**
     * @param userEnv2
     * @return
     * @throws JCRNodeFactoryServiceException
     * @throws RepositoryException
     * @throws IOException
     * @throws UnsupportedEncodingException
     */
    private UserEnvironment loadUserEnvironmentBean(String userEnvPath) {
        authzResolverService.setRequestGrant("Loading UserEnvironment");
        InputStream in = null;
        try {
            in = jcrNodeFactoryService.getInputStream(userEnvPath);
            String userEnvBody = IOUtils.readFully(in, "UTF-8");
            LOG.info(" Loaded User Env from JCR for " + userEnvPath);
            // convert to a bean, the
            UserEnvironment ue = beanConverter.convertToObject(userEnvBody, UserEnvironment.class);
            // seal the bean to prevent modification.
            ue.seal();
            return ue;
        } catch (UnsupportedEncodingException e) {
            LOG.error(e);
        } catch (IOException e) {
            LOG.warn("Failed to read userenv " + userEnvPath + " cause :" + e.getMessage());
            if (debug) {
                LOG.debug(e);
            }
        } catch (RepositoryException e) {
            LOG.warn("Failed to read userenv for " + userEnvPath + " cause :" + e.getMessage());
            if (debug) {
                LOG.debug(e);
            }
        } catch (JCRNodeFactoryServiceException e) {
            LOG.warn("Failed to read userenv for " + userEnvPath + " cause :" + e.getMessage());
            if (debug) {
                LOG.debug(e);
            }
        } finally {
            try {
                in.close();
            } catch (Exception ex) {
            }
            authzResolverService.clearRequestGrant();
        }
        return null;
    }

    private Map<String, Object> loadUserMap(String userEnvPath) {
        authzResolverService.setRequestGrant("Loading User Map");
        try {
            String userEnvBody = IOUtils.readFully(jcrNodeFactoryService.getInputStream(userEnvPath), "UTF-8");
            // convert to a bean, the
            Map<String, Object> ue = beanConverter.convertToObject(userEnvBody, Map.class);
            return ue;
        } catch (UnsupportedEncodingException e) {
            LOG.error(e);
        } catch (IOException e) {
            LOG.warn("Failed to read userenv " + userEnvPath + " cause :" + e.getMessage());
            if (debug) {
                LOG.debug(e);
            }
        } catch (RepositoryException e) {
            LOG.warn("Failed to read userenv for " + userEnvPath + " cause :" + e.getMessage());
            if (debug) {
                LOG.debug(e);
            }
        } catch (JCRNodeFactoryServiceException e) {
            LOG.warn("Failed to read userenv for " + userEnvPath + " cause :" + e.getMessage());
            if (debug) {
                LOG.debug(e);
            }
        } finally {
            authzResolverService.clearRequestGrant();
        }
        return null;
    }

    /**
     * {@inheritDoc}
     *
     * @see org.sakaiproject.kernel.api.userenv.UserEnvironmentResolverService#getUserEnvironmentBasePath(java.lang.String)
     */
    public String getUserEnvironmentBasePath(String userId) {
        return userFactoryService.getUserEnvironmentBasePath(userId);
    }

    /**
     * * Return user's prefered locale * First: return locale from Sakai user preferences,
     * if available * Second: return locale from user session, if available * Last: return
     * system default locale
     *
     * @param locale * *
     * @return user's Locale object
     */
    public Locale getUserLocale(Locale browserLocale, Session session) {
        Locale loc = null;

        User user = session.getUser();
        UserEnvironment userEnvironment = null;
        if (user != null && user.getUuid() != null) {
            userEnvironment = resolve(user.getUuid());
        }
        String localeKey = (String) session.getAttribute(LOCALE_SESSION_KEY);
        if (userEnvironment != null && localeKey == null) {
            localeKey = userEnvironment.getLocale();
        }
        String[] locValues = StringUtils.split(localeKey, '_');
        if (locValues != null && locValues.length > 1) {
            loc = new Locale(locValues[0], locValues[1]);
        } else if (locValues != null && locValues.length == 1) {
            loc = new Locale(locValues[0]);
        } else if (browserLocale != null) {
            loc = browserLocale;
        } else {
            loc = Locale.getDefault();
        }
        return loc;
    }

    /**
     * {@inheritDoc}
     *
     * @throws RepositoryException
     * @throws JCRNodeFactoryServiceException
     *
     * @see org.sakaiproject.kernel.api.userenv.UserEnvironmentResolverService#save(org.sakaiproject.kernel.api.userenv.UserEnvironment)
     */
    public void save(UserEnvironment userEnvironment) throws UpdateFailedException {
        authzResolverService.setRequestGrant("Saving User Environment");
        InputStream bais = null;

        try {
            String userEnvironmentPath = userFactoryService.getUserEnvPath(userEnvironment.getUser().getUuid());
            Map<String, Object> userMap = loadUserMap(userEnvironmentPath);

            userMap.put("locale", userEnvironment.getLocale());
            userMap.put("subjects", userEnvironment.getSubjects());

            // save the template
            String userEnvironmentJson = beanConverter.convertToString(userMap);
            System.err.println("New User at " + userEnvironmentPath + " Is " + userEnvironmentJson);
            bais = new ByteArrayInputStream(userEnvironmentJson.getBytes("UTF-8"));
            Node userEnvNode = jcrNodeFactoryService.setInputStream(userEnvironmentPath, bais,
                    RestProvider.CONTENT_TYPE);

            expire(userEnvironment.getUser().getUuid());

            Node n = userEnvNode;
            while (n.isNew()) {
                n = n.getParent();
            }
            n.save();

        } catch (Exception ex) {
            throw new UpdateFailedException(ex.getMessage(), ex);
        } finally {
            try {
                bais.close();
            } catch (Exception ex) {
            }
            authzResolverService.clearRequestGrant();
        }

    }

    /**
     * {@inheritDoc}
     *
     * @see org.sakaiproject.kernel.api.userenv.UserEnvironmentResolverService#create(org.sakaiproject.kernel.api.user.User,
     *      java.lang.String)
     */
    public UserEnvironment create(User u, String externalId, String password, String userType) {
        String userEnvironmentPath = userFactoryService.getUserEnvPath(u.getUuid());

        ByteArrayInputStream bais = null;
        InputStream templateInputStream = null;
        try {

            String userEnvironmentTemplate = userFactoryService.getUserEnvTemplate(userType);

            // load the template
            templateInputStream = jcrNodeFactoryService.getInputStream(userEnvironmentTemplate);
            String template = IOUtils.readFully(templateInputStream, "UTF-8");
            System.err.println("Loading UE from " + userEnvironmentTemplate + " as " + template);
            UserEnvironmentBean userEnvironmentBean = beanConverter.convertToObject(template,
                    UserEnvironmentBean.class);

            // make the template this user
            userEnvironmentBean.setEid(externalId);
            userEnvironmentBean.setUuid(u.getUuid());
            Map<String, String> p = new HashMap<String, String>();
            p.put("userType", userType);
            userEnvironmentBean.setProperties(p);

            // save the template
            String userEnv = beanConverter.convertToString(userEnvironmentBean);
            System.err.println("Saving UE to " + userEnvironmentPath + " as " + userEnv);
            bais = new ByteArrayInputStream(userEnv.getBytes("UTF-8"));
            Node userEnvNode = jcrNodeFactoryService.setInputStream(userEnvironmentPath, bais,
                    RestProvider.CONTENT_TYPE);

            // set the password
            userEnvNode.setProperty(JcrAuthenticationResolverProvider.JCRPASSWORDHASH,
                    org.sakaiproject.kernel.util.StringUtils.sha1Hash(password));

            // make the private and shares spaces for the user owned by this used.
            jcrNodeFactoryService.setOwner(userFactoryService.getUserPrivatePath(u.getUuid()), u.getUuid());
            jcrNodeFactoryService.setOwner(userFactoryService.getUserSharedPrivatePath(u.getUuid()), u.getUuid());

            // allow other provisioning agents to perform
            Registry<String, UserProvisionAgent> registry = registryService
                    .getRegistry(UserProvisionAgent.REGISTRY);
            for (UserProvisionAgent agent : registry.getList()) {
                agent.provision(userEnvironmentBean);
            }

            userEnvironmentBean.seal();
            return userEnvironmentBean;

        } catch (RepositoryException e) {
            LOG.error(e.getMessage(), e);
        } catch (JCRNodeFactoryServiceException e) {
            LOG.error(e.getMessage(), e);
        } catch (UnsupportedEncodingException e) {
            LOG.error(e.getMessage(), e);
        } catch (NoSuchAlgorithmException e) {
            LOG.error(e.getMessage(), e);
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        } finally {
            try {
                bais.close();
            } catch (Exception ex) {
                // not interested
            }
            try {
                templateInputStream.close();
            } catch (Exception ex) {
                // not interested
            }
        }
        return null;

    }

    /**
     * {@inheritDoc}
     * @see org.sakaiproject.kernel.api.userenv.UserEnvironmentResolverService#addMembership(java.lang.String, java.lang.String, java.lang.String)
     */
    public void addMembership(String userId, String siteId, String membershipType) {
        UserEnvironmentBean userEnv = (UserEnvironmentBean) resolve(userId);
        UserEnvironmentBean newUserEnvironment = new UserEnvironmentBean(subjectPermissionService, 0,
                registryService);
        newUserEnvironment.copyFrom(userEnv);

        String newSubject = siteId + ":" + membershipType;
        String[] subjects = newUserEnvironment.getSubjects();
        subjects = org.sakaiproject.kernel.util.StringUtils.addString(subjects, newSubject);
        newUserEnvironment.setSubjects(subjects);

        save(newUserEnvironment);
    }

    /**
     * {@inheritDoc}
     * @see org.sakaiproject.kernel.api.userenv.UserEnvironmentResolverService#removeMembership(java.lang.String, java.lang.String, java.lang.String)
     */
    public void removeMembership(String userId, String siteId, String membershipType) {
        UserEnvironmentBean userEnv = (UserEnvironmentBean) resolve(userId);
        UserEnvironmentBean newUserEnvironment = new UserEnvironmentBean(subjectPermissionService, 0,
                registryService);
        newUserEnvironment.copyFrom(userEnv);

        String newSubject = siteId + ":" + membershipType;
        String[] subjects = newUserEnvironment.getSubjects();
        subjects = org.sakaiproject.kernel.util.StringUtils.removeString(subjects, newSubject);
        newUserEnvironment.setSubjects(subjects);

        save(newUserEnvironment);
    }

}