org.iavante.sling.initialconfig.services.impl.JCROperations.java Source code

Java tutorial

Introduction

Here is the source code for org.iavante.sling.initialconfig.services.impl.JCROperations.java

Source

/*
 * Digital Assets Management
 * =========================
 * 
 * Copyright 2009 Fundacin Iavante
 * 
 * Authors: 
 *   Francisco Jos Moreno Llorca <packo@assamita.net>
 *   Francisco Jess Gonzlez Mata <chuspb@gmail.com>
 *   Juan Antonio Guzmn Hidalgo <juan@guzmanhidalgo.com>
 *   Daniel de la Cuesta Navarrete <cues7a@gmail.com>
 *   Manuel Jos Cobo Fernndez <ranrrias@gmail.com>
 *
 * Licensed under the EUPL, Version 1.1 or  as soon they will be approved by
 * the European Commission - subsequent versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://ec.europa.eu/idabc/eupl
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the Licence is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing permissions and 
 * limitations under the Licence.
 * 
 */
package org.iavante.sling.initialconfig.services.impl;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.http.HttpServletResponse;

import junit.framework.AssertionFailedError;

import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Some operations about JCR Initialization.
 */
public class JCROperations extends AbstractHttpOperation implements Serializable {
    private static final long serialVersionUID = 1L;

    /** Default Logger */
    private final Logger log = LoggerFactory.getLogger(getClass());

    /** Admin user name. */
    private String adminUser;

    /** Admin user password. */
    private String adminPasswd;

    /** Default admin user name */
    private String defaultAdminUser = "admin";

    /** Default admin user password. */
    private String defaultAdminPasswd = "admin";

    /** Anonymous user name. */
    private String anonymousUser = "anonymous";

    /** GAD user name. */
    private String gadUser = "gaduser";

    /** JCR root node. */
    private Node rootNode;

    /** Authentication properties. */
    private Map<String, String> authProperties = null;

    public JCROperations(Map properties, Node rootNode) {
        this.rootNode = rootNode;
        authProperties = properties;
        try {
            init();
        } catch (IOException e) {
            log.error("activate, error creating user " + gadUser);
            e.printStackTrace();
        }
    }

    private void init() throws IOException {

        if (log.isInfoEnabled())
            log.info("init, ini");

        // Getting admin username and password from global configuration service
        try {
            adminUser = authProperties.get("sling_user");
            adminPasswd = authProperties.get("sling_pass");
            if (log.isInfoEnabled())
                log.info("init, auth_properties gotten from config node");
        } catch (Exception e) {
            log.error("init, error getting admin username and password, " + e.getMessage());
            adminUser = defaultAdminUser;
            adminPasswd = defaultAdminPasswd;
            log.error("init, using default admin username and password");
        }

        // Setting privileges to 'anonymous' user
        try {
            setAnonymousPrivileges();
        } catch (IOException e) {
            log.error("activate, error assigning permissions to " + anonymousUser);
            e.printStackTrace();
        } catch (JSONException e) {
            log.error(
                    "activate, could not check if permissions to " + anonymousUser + " were stablished correctly");
            e.printStackTrace();
        } catch (AssertionFailedError e) {
            log.error("activate, error assigning permissions to " + anonymousUser);
            e.printStackTrace();
        }

        // Creating the gaduser
        createUserInJCR(gadUser);

        // Setting privileges to gaduser
        try {
            setGADUserPrivileges();
        } catch (IOException e) {
            log.error("activate, error assigning permissions to " + gadUser);
            e.printStackTrace();
        } catch (JSONException e) {
            log.error("activate, could not check if permissions to " + gadUser + " were stablished correctly");
            e.printStackTrace();
        } catch (AssertionFailedError e) {
            log.error("activate, error assigning permissions to " + gadUser);
            e.printStackTrace();
        }

        if (log.isInfoEnabled())
            log.info("init, end");
    }

    // -------------------- Internal -------------------------

    /**
     * Set privileges to anonymous user in JCR.
     * 
     * @throws IOException
     * @throws JSONException
     */
    public void setAnonymousPrivileges() throws IOException, JSONException {

        if (log.isInfoEnabled())
            log.info("setAnonymousPrivileges, ini");

        // Root nodes will be applied priveleges from
        List<String> rootNodes = new ArrayList<String>();
        rootNodes.add("/content");

        Credentials creds = new UsernamePasswordCredentials(adminUser, adminPasswd);

        // Assigning privileges in every node
        for (String node : rootNodes) {

            String postUrl = HTTP_BASE_URL + node + ".modifyAce.html";
            if (log.isInfoEnabled())
                log.info("postUrl: " + postUrl);
            List<NameValuePair> postParams = new ArrayList<NameValuePair>();
            postParams.add(new NameValuePair("principalId", anonymousUser));
            postParams.add(new NameValuePair("privilege@jcr:all", "granted"));

            assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);

            // fetch the JSON for the acl to verify the settings:
            // {"anonymous":{"granted":["jcr:all"]}}
            String getUrl = HTTP_BASE_URL + node + ".acl.json";
            String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null,
                    HttpServletResponse.SC_OK);
            assertNotNull(json);
            JSONObject jsonObj = new JSONObject(json);
            String aceString = jsonObj.getString(anonymousUser);
            assertNotNull(aceString);

            JSONObject aceObject = new JSONObject(aceString);
            assertNotNull(aceObject);

            JSONArray grantedArray = aceObject.getJSONArray("granted");
            assertNotNull(grantedArray);
            assertEquals("jcr:all", grantedArray.getString(0));

            if (log.isInfoEnabled())
                log.info("setAnonymousPrivileges, permissions assigned to " + anonymousUser);
        }

        if (log.isInfoEnabled())
            log.info("setAnonymousPrivileges, end");
    }

    /**
     * Set privileges to anonymous user in JCR.
     * 
     * @throws IOException
     * @throws JSONException
     */
    private void setGADUserPrivileges() throws IOException, JSONException {

        if (log.isInfoEnabled())
            log.info("setGADUserPrivileges, ini");

        // Root nodes will be applied priveleges from
        List<String> rootNodes = new ArrayList<String>();
        rootNodes.add("/content");

        Credentials creds = new UsernamePasswordCredentials(adminUser, adminPasswd);

        // Assigning privileges in every node
        for (String node : rootNodes) {

            String postUrl = HTTP_BASE_URL + node + ".modifyAce.html";
            List<NameValuePair> postParams = new ArrayList<NameValuePair>();
            postParams.add(new NameValuePair("principalId", gadUser));
            postParams.add(new NameValuePair("privilege@jcr:all", "granted"));

            assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);

            // fetch the JSON for the acl to verify the settings:
            // {"anonymous":{"granted":["jcr:all"]}}
            String getUrl = HTTP_BASE_URL + node + ".acl.json";
            String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, null,
                    HttpServletResponse.SC_OK);
            assertNotNull(json);
            JSONObject jsonObj = new JSONObject(json);
            String aceString = jsonObj.getString(gadUser);
            assertNotNull(aceString);

            JSONObject aceObject = new JSONObject(aceString);
            assertNotNull(aceObject);

            JSONArray grantedArray = aceObject.getJSONArray("granted");
            assertNotNull(grantedArray);
            assertEquals("jcr:all", grantedArray.getString(0));

            if (log.isInfoEnabled())
                log.info("setGADUserPrivileges, permissions assigned to " + gadUser);
        }

        if (log.isInfoEnabled())
            log.info("setGADUserPrivileges, end");
    }

    /**
     * Check if the user already exists. If doesn't, tries to create it with a
     * generated password. If error, throws IOException.
     * 
     * @param user
     * @throws IOException
     */
    private void createUserInJCR(String user) throws IOException {

        if (log.isInfoEnabled())
            log.info("createUserInJCR, ini");

        boolean createUser = false;

        Credentials creds = new UsernamePasswordCredentials(adminUser, adminPasswd);
        String postUrl = HTTP_BASE_URL + "/system/userManager/user/" + user + ".html";

        Node slingConf = null;
        try {
            if (log.isInfoEnabled())
                log.info("rootNode=" + rootNode);
            slingConf = rootNode.getNode("content/config/sling");
            if (log.isInfoEnabled())
                log.info("slingConf=" + slingConf.getPath());
        } catch (PathNotFoundException e2) {
            e2.printStackTrace();
        } catch (RepositoryException e2) {
            e2.printStackTrace();
        }

        try { // Checking if user already exists
            assertAuthenticatedHttpStatus(creds, postUrl, HttpServletResponse.SC_OK, null);
            if (log.isInfoEnabled())
                log.info("createUserInJCR, " + user + " already exists");

            //if 'gaduser' property doesn't exits in '/content/config/sling' node, then
            // generate a new password

            if (!slingConf.hasProperty("gaduser")) {
                if (log.isInfoEnabled())
                    log.info("createUserInJCR, " + user + " already exists, but prop '" + user
                            + "' doesn't exits in " + slingConf.getPath());

                //In order to update pwd, we need to delete and create 'gaduser'
                postUrl = HTTP_BASE_URL + "/system/userManager/user/" + user + ".delete.html";
                List<NameValuePair> postParams = new ArrayList<NameValuePair>();
                postParams.add(new NameValuePair("go", "" + 1));
                assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);
                if (log.isInfoEnabled())
                    log.info("createUserInJCR, user deleted: " + user);

                createUser = true;
            }

        } catch (AssertionFailedError e) { // Not exists, needs to create the user

            createUser = true;

        } catch (RepositoryException e) {
            e.printStackTrace();
        }

        if (createUser) {
            postUrl = HTTP_BASE_URL + "/system/userManager/user.create.html";
            String pwd = generatePassword(10);

            List<NameValuePair> postParams = new ArrayList<NameValuePair>();
            postParams.add(new NameValuePair(":name", user));
            postParams.add(new NameValuePair("pwd", pwd));
            postParams.add(new NameValuePair("pwdConfirm", pwd));

            assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, null);

            if (log.isInfoEnabled())
                log.info("createUserInJCR, user created " + user + ":" + pwd);

            // Setting gaduser and gaduserpwd in /content/config/sling node
            try {
                if (log.isInfoEnabled())
                    log.info("saving...");
                slingConf.setProperty("gad_user", user);
                slingConf.setProperty("gad_pass", pwd);
                slingConf.save();
                if (log.isInfoEnabled())
                    log.info("saved");
            } catch (PathNotFoundException e1) {
                e1.printStackTrace();
            } catch (RepositoryException e1) {
                e1.printStackTrace();
            }
        }

        if (log.isInfoEnabled())
            log.info("createUserInJCR, end");
    }

    /**
     * Generate a low security password.
     * 
     * @param length
     *          Minimum length for a password
     * @return
     */
    private String generatePassword(int length) {

        /** The random number generator. */
        Random r = new java.util.Random();

        char[] goodChar = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't',
                'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q',
                'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-',
                '@', };
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            sb.append(goodChar[r.nextInt(goodChar.length)]);
        }
        return sb.toString();
    }

}