/*
 * 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.sling.jcr.jackrabbit.accessmanager.it;

import static org.apache.sling.testing.paxexam.SlingOptions.slingCommonsCompiler;
import static org.apache.sling.testing.paxexam.SlingOptions.slingJcrJackrabbitSecurity;
import static org.apache.sling.testing.paxexam.SlingOptions.slingScriptingJavascript;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.ops4j.pax.exam.CoreOptions.when;
import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.factoryConfiguration;

import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.List;

import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.junit.After;
import org.junit.Before;
import org.ops4j.pax.exam.Option;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;

/**
 * base class for tests doing http requests to verify calls to the accessmanager
 * servlets
 */
public abstract class AccessManagerClientTestSupport extends AccessManagerTestSupport {
    protected static final int SC_UNPROCESSABLE_ENTITY = 422; // http status code for 422 Unprocessable Entity

    protected static final String TEST_FOLDER_JSON = "{'jcr:primaryType': 'nt:unstructured'}";

    protected static final String CONTENT_TYPE_JSON = "application/json";
    protected static final String CONTENT_TYPE_HTML = "text/html";

    protected static long randomId = System.currentTimeMillis();

    protected static synchronized long getNextInt() {
        final long val = randomId;
        randomId++;
        return val;
    }

    @Inject
    protected ConfigurationAdmin cm;

    protected static final String COOKIE_SLING_FORMAUTH = "sling.formauth";
    protected static final String COOKIE_SLING_FORMAUTH_DOMAIN = "sling.formauth.cookie.domain";
    protected static final String HEADER_SET_COOKIE = "Set-Cookie";

    protected URI baseServerUri;
    protected HttpClientContext httpContext;
    protected CloseableHttpClient httpClient;

    protected String testUserId = null;
    protected String testUserId2 = null;
    protected String testGroupId = null;
    protected String testFolderUrl = null;

    @Override
    protected Option[] additionalOptions() throws IOException {
        // optionally create a tinybundle that contains a test script
        final Option bundle = buildBundleResourcesBundle();

        return new Option[]{
            // for usermanager support
            slingJcrJackrabbitSecurity(),
            // add javascript support for the test script
            slingCommonsCompiler(),
            when(bundle != null).useOptions(slingScriptingJavascript()),

            // add the test script tinybundle
            when(bundle != null).useOptions(bundle),

            // enable the healthcheck configuration for checking when the server is ready to
            //  receive http requests.  (adapted from the starter healthcheck.json configuration)
            factoryConfiguration("org.apache.felix.hc.generalchecks.FrameworkStartCheck")
                .put("hc.tags", new String[] {"systemalive"})
                .put("targetStartLevel", 5)
                .asOption(),
            factoryConfiguration("org.apache.felix.hc.generalchecks.ServicesCheck")
                .put("hc.tags", new String[] {"systemalive"})
                .put("services.list", new String[] {
                        "org.apache.sling.jcr.api.SlingRepository",
                        "org.apache.sling.engine.auth.Authenticator",
                        "org.apache.sling.api.resource.ResourceResolverFactory",
                        "org.apache.sling.api.servlets.ServletResolver",
                        "javax.script.ScriptEngineManager"
                })
                .asOption(),
            factoryConfiguration("org.apache.felix.hc.generalchecks.BundlesStartedCheck")
                .put("hc.tags", new String[] {"bundles"})
                .asOption(),
            factoryConfiguration("org.apache.sling.jcr.contentloader.hc.BundleContentLoadedCheck")
                .put("hc.tags", new String[] {"bundles"})
                .asOption(),
        };
    }

    @Before
    public void before() throws Exception {
        // wait for the health checks to be OK
        waitForServerReady(Duration.ofMinutes(1).toMillis(), 500);

        // calculate the address of the http server
        baseServerUri = getBaseServerUri();
        assertNotNull(baseServerUri);

        HttpHost targetHost = new HttpHost(baseServerUri.getHost(), baseServerUri.getPort(), baseServerUri.getScheme());
        AuthCache authCache = new BasicAuthCache();
        authCache.put(targetHost, new BasicScheme());

        // prepare the http client for the test user
        httpContext = HttpClientContext.create();
        httpContext.setCookieStore(new BasicCookieStore());
        httpContext.setCredentialsProvider(new BasicCredentialsProvider());
        httpContext.setAuthCache(authCache);
        RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT).build();
        httpContext.setRequestConfig(requestConfig);
        httpClient = HttpClients.custom()
                .disableRedirectHandling()
                .build();
    }

    @After
    public void after() throws Exception {
        Credentials creds = new UsernamePasswordCredentials("admin", "admin");

        if (testFolderUrl != null) {
            //remove the test user if it exists.
            List<NameValuePair> postParams = new ArrayList<>();
            postParams.add(new BasicNameValuePair(":operation", "delete"));
            assertAuthenticatedPostStatus(creds, testFolderUrl, HttpServletResponse.SC_OK, postParams, null);
        }
        if (testGroupId != null) {
            //remove the test user if it exists.
            String postUrl = String.format("%s/system/userManager/group/%s.delete.html", baseServerUri, testGroupId);
            assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, Collections.emptyList(), null);
        }
        if (testUserId != null) {
            //remove the test user if it exists.
            String postUrl = String.format("%s/system/userManager/user/%s.delete.html", baseServerUri, testUserId);
            assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, Collections.emptyList(), null);
        }
        if (testUserId2 != null) {
            //remove the test user if it exists.
            String postUrl = String.format("%s/system/userManager/user/%s.delete.html", baseServerUri, testUserId2);
            assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, Collections.emptyList(), null);
        }

        // close/cleanup the test user http client
        if (httpClient != null) {
            httpClient.close();
            httpClient = null;
        }

        // clear out other state
        httpContext = null;
        baseServerUri = null;
    }

    /**
     * Calculate the base server URI from the current configuration of the
     * httpservice
     */
    protected URI getBaseServerUri() throws IOException, URISyntaxException {
        assertNotNull(cm);
        Configuration httpServiceConfiguration = cm.getConfiguration("org.apache.felix.http");
        Dictionary<String, Object> properties = httpServiceConfiguration.getProperties();

        String host;
        Object hostObj = properties.get("org.apache.felix.http.host");
        if (hostObj == null) {
            host = "localhost";
        } else {
            assertTrue(hostObj instanceof String);
            host = (String)hostObj;
        }
        assertNotNull(host);

        String scheme = null;
        Object portObj = null;
        Object httpsEnableObj = properties.get("org.apache.felix.https.enable");
        if ("true".equals(httpsEnableObj)) {
            scheme = "https";
            portObj = properties.get("org.osgi.service.http.port.secure");
        } else {
            Object httpEnableObj = properties.get("org.apache.felix.http.enable");
            if (httpEnableObj == null || "true".equals(httpEnableObj)) {
                scheme = "http";
                portObj = properties.get("org.osgi.service.http.port");
            } else {
                fail("Expected either http or https to be enabled");
            }
        }
        int port = -1;
        if (portObj instanceof Number) {
            port = ((Number)portObj).intValue();
        }
        assertTrue(port > 0);

        return new URI(String.format("%s://%s:%d", scheme, host, port));
    }

    protected void assertPrivilege(Collection<String> privileges, boolean expected, String privilegeName) {
        if(expected != privileges.contains(privilegeName)) {
            fail("Expected privilege " + privilegeName + " to be "
                    + (expected ? "included" : "NOT INCLUDED")
                    + " in supplied list: " + privileges + ")");
        }
    }

    protected void assertPrivilege(JsonObject privilegesObject, boolean expectedPrivilege, PrivilegeValues privilegeState, String privilegeName) {
        assertPrivilege(privilegesObject, expectedPrivilege, privilegeState, privilegeName, null);
    }
    protected void assertPrivilege(JsonObject privilegesObject, boolean expectedPrivilege, PrivilegeValues privilegeState, String privilegeName,
            VerifyAce verifyAce) {
        assertPrivilege(privilegesObject, expectedPrivilege, privilegeState, privilegeName, true, verifyAce);
    }
    protected void assertPrivilege(JsonObject privilegesObject, boolean expectedPrivilege, PrivilegeValues privilegeState, String privilegeName,
            boolean expectedForAllow,
            VerifyAce verifyAce) {
        assertNotNull(privilegesObject);
        if (expectedPrivilege != privilegesObject.containsKey(privilegeName)) {
            fail("Expected privilege " + privilegeName + " to be "
                    + (expectedPrivilege ? "included" : "NOT INCLUDED")
                    + " in supplied object)");
        }
        JsonObject privilegeObj = privilegesObject.getJsonObject(privilegeName);
        if (!expectedPrivilege) {
            assertNull(privilegeObj);
        } else {
            assertNotNull(privilegeObj);
            String key = privilegeState.toString();;
            if (expectedForAllow) {
                assertTrue("Expected privilege " + privilegeName + " to have key: " + key,
                        privilegeObj.containsKey(key));
                JsonValue jsonValue = privilegeObj.get(key);
                if (verifyAce != null) {
                    verifyAce.verify(jsonValue);
                }
            } else {
                assertFalse("Did not expect privilege " + privilegeName + " to have key: " + key,
                        privilegeObj.containsKey(key));
            }
        }
    }

    protected Object doAuthenticatedWork(Credentials creds, AuthenticatedWorker worker) throws IOException {
        Object result = null;
        AuthScope authScope = new AuthScope(baseServerUri.getHost(), baseServerUri.getPort(), baseServerUri.getScheme());
        CredentialsProvider oldCredentialsProvider = httpContext.getCredentialsProvider();
        try {
            BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            httpContext.setCredentialsProvider(credentialsProvider);
            credentialsProvider.setCredentials(authScope, creds);

            result = worker.doWork();
        } finally {
            httpContext.setCredentialsProvider(oldCredentialsProvider);
        }
        return result;
    }

    protected void assertAuthenticatedPostStatus(Credentials creds, String url, int expectedStatusCode, List<NameValuePair> postParams, String assertMessage) throws IOException {
        doAuthenticatedWork(creds, () -> {
            HttpPost postRequest = new HttpPost(url);
            postRequest.setEntity(new UrlEncodedFormEntity(postParams));
            try (CloseableHttpResponse response = httpClient.execute(postRequest, httpContext)) {
                assertEquals(assertMessage, expectedStatusCode, response.getStatusLine().getStatusCode());
            }
            return null;
        });
    }

    protected void assertAuthenticatedHttpStatus(Credentials creds, String urlString, int expectedStatusCode, String assertMessage) throws IOException {
        doAuthenticatedWork(creds, () -> {
            HttpGet getRequest = new HttpGet(urlString);
            try (CloseableHttpResponse response = httpClient.execute(getRequest, httpContext)) {
                assertEquals(assertMessage, expectedStatusCode, response.getStatusLine().getStatusCode());
                return null;
            }
        });
    }

    protected String getAuthenticatedContent(Credentials creds, String url, String expectedContentType, int expectedStatusCode) throws IOException {
        return (String)doAuthenticatedWork(creds, () -> {
            HttpGet getRequest = new HttpGet(url);
            try (CloseableHttpResponse response = httpClient.execute(getRequest, httpContext)) {
                assertEquals(expectedStatusCode, response.getStatusLine().getStatusCode());
                final Header h = response.getFirstHeader("Content-Type");
                if (expectedContentType == null) {
                    if (h != null) {
                        fail("Expected null Content-Type, got " + h.getValue());
                    }
                } else if (h == null) {
                    fail(
                            "Expected Content-Type that starts with '" + expectedContentType
                            +" but got no Content-Type header at " + url
                    );
                } else {
                    assertTrue(
                        "Expected Content-Type that starts with '" + expectedContentType
                        + "' for " + url + ", got '" + h.getValue() + "'",
                        h.getValue().startsWith(expectedContentType)
                    );
                }
                return EntityUtils.toString(response.getEntity());
            }
        });
    }

    protected String getAuthenticatedPostContent(Credentials creds, String url, String expectedContentType, List<NameValuePair> postParams, int expectedStatusCode) throws IOException {
        return (String)doAuthenticatedWork(creds, () -> {
            HttpPost postRequest = new HttpPost(url);
            postRequest.setEntity(new UrlEncodedFormEntity(postParams));
            try (CloseableHttpResponse response = httpClient.execute(postRequest, httpContext)) {
                assertEquals(expectedStatusCode, response.getStatusLine().getStatusCode());
                final Header h = response.getFirstHeader("Content-Type");
                if (expectedContentType == null) {
                    if (h != null) {
                        fail("Expected null Content-Type, got " + h.getValue());
                    }
                } else if (h == null) {
                    fail(
                            "Expected Content-Type that starts with '" + expectedContentType
                            +" but got no Content-Type header at " + url
                    );
                } else {
                    assertTrue(
                        "Expected Content-Type that starts with '" + expectedContentType
                        + "' for " + url + ", got '" + h.getValue() + "'",
                        h.getValue().startsWith(expectedContentType)
                    );
                }
                return EntityUtils.toString(response.getEntity());
            }
        });
    }

    protected String createTestUser() throws IOException {
        String postUrl = String.format("%s/system/userManager/user.create.html", baseServerUri);

        String userId = "testUser" + getNextInt();
        List<NameValuePair> postParams = new ArrayList<>();
        postParams.add(new BasicNameValuePair(":name", userId));
        postParams.add(new BasicNameValuePair("pwd", "testPwd"));
        postParams.add(new BasicNameValuePair("pwdConfirm", "testPwd"));
        Credentials creds = new UsernamePasswordCredentials("admin", "admin");
        final String msg = "Unexpected status while attempting to create test user at " + postUrl;
        assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, msg);

        final String sessionInfoUrl = String.format("%s/system/sling/info.sessionInfo.json", baseServerUri);
        assertAuthenticatedHttpStatus(creds, sessionInfoUrl, HttpServletResponse.SC_OK,
                "session info failed for user " + userId);

        return userId;
    }

    protected String createTestGroup() throws IOException {
        String postUrl = String.format("%s/system/userManager/group.create.html", baseServerUri);

        String groupId = "testGroup" + getNextInt();
        List<NameValuePair> postParams = new ArrayList<>();
        postParams.add(new BasicNameValuePair(":name", groupId));

        Credentials creds = new UsernamePasswordCredentials("admin", "admin");
        final String msg = "Unexpected status while attempting to create test group at " + postUrl;
        assertAuthenticatedPostStatus(creds, postUrl, HttpServletResponse.SC_OK, postParams, msg);

        return groupId;
    }

    protected String createTestFolder() throws IOException {
        return createTestFolder(null, "sling-tests");
    }

    protected String createTestFolder(String parentPath, String nameHint) throws IOException {
        return createTestFolder(parentPath, nameHint, TEST_FOLDER_JSON);
    }
    protected String createTestFolder(String parentPath, String nameHint, String jsonImport) throws IOException {
        JsonObject json = importJSON(parentPath, nameHint, jsonImport);
        return String.format("%s%s", baseServerUri, json.getString("path"));
    }

    protected JsonObject importJSON(String nameHint, String jsonImport) throws IOException {
        return importJSON(null, nameHint, jsonImport);
    }

    protected JsonObject importJSON(String parentPath, String nameHint, String jsonImport) throws IOException {
        JsonObject result = null;
        Credentials creds = new UsernamePasswordCredentials("admin", "admin");
        result = (JsonObject)doAuthenticatedWork(creds, () -> {
            List<NameValuePair> parameters = new ArrayList<>();
            parameters.add(new BasicNameValuePair(":operation", "import"));
            if (nameHint != null) {
                parameters.add(new BasicNameValuePair(":nameHint", nameHint));
            }
            parameters.add(new BasicNameValuePair(":content", jsonImport));
            parameters.add(new BasicNameValuePair(":contentType", "json"));
            parameters.add(new BasicNameValuePair(":replaceProperties", "true"));

            String postUrl = String.format("%s%s", baseServerUri, parentPath != null ? parentPath : "/content");
            HttpPost postRequest = new HttpPost(postUrl);
            postRequest.setEntity(new UrlEncodedFormEntity(parameters));
            postRequest.addHeader(new BasicHeader("Accept", "application/json,*/*;q=0.9"));
            JsonObject jsonObj = null;
            try (CloseableHttpResponse response = httpClient.execute(postRequest, httpContext)) {
                assertEquals(HttpServletResponse.SC_CREATED, response.getStatusLine().getStatusCode());
                jsonObj = parseJson(EntityUtils.toString(response.getEntity()));
            }
            return jsonObj;
        });
        return result;
    }

    /**
     * @param json the json string to parse
     * @return the parsed JsonObject
     */
    protected JsonObject parseJson(String json) {
        JsonObject jsonObj = null;
        try (JsonReader reader = Json.createReader(new StringReader(json))) {
            jsonObj = reader.readObject();
        }
        return jsonObj;
    }

    protected static interface AuthenticatedWorker {
        public Object doWork() throws IOException;
    }

    protected static interface VerifyAce {
        public void verify(JsonValue jsonValue);
    }

    protected enum PrivilegeValues {
        ALLOW("allow"),
        DENY("deny"),
        NONE("none"),
        BOGUS("bogus"); //to simulate invalid value

        private String paramValue;

        private PrivilegeValues(String paramValue) {
            this.paramValue = paramValue;
        }

        @Override
        public String toString() {
            return paramValue;
        }
    }

    protected enum DeleteValues {
        ALL("all"),
        ALLOW("allow"),
        DENY("deny"),

        // some invalid values for testing
        TRUE("true"),
        VALUE_DOES_NOT("value does not"),
        MATTER("matter");

        private String paramValue;

        private DeleteValues(String paramValue) {
            this.paramValue = paramValue;
        }

        @Override
        public String toString() {
            return paramValue;
        }
    }

    protected static class AcePostParamsBuilder {
        List<NameValuePair> list = new ArrayList<>();

        public AcePostParamsBuilder(String principalId) {
            with("principalId", principalId);
        }

        public AcePostParamsBuilder withPrivilege(String privilegeName, PrivilegeValues value) {
            return with("privilege@" + privilegeName, value.toString());
        }

        public AcePostParamsBuilder withDeletePrivilege(String privilegeName, DeleteValues value) {
            return with(String.format("privilege@%s@Delete", privilegeName), value.toString());
        }

        public AcePostParamsBuilder withRestriction(String restrictionName, String restrictionValue) {
            return with(String.format("restriction@%s", restrictionName), restrictionValue);
        }
        public AcePostParamsBuilder withRestriction(String restrictionName, String[] restrictionValues) {
            return with(String.format("restriction@%s", restrictionName), restrictionValues);
        }

        public AcePostParamsBuilder withDeleteRestriction(String restrictionName, DeleteValues value) {
            return with(String.format("restriction@%s@Delete", restrictionName), "true");
        }

        public AcePostParamsBuilder withPrivilegeRestriction(PrivilegeValues value, String privilegeName, String restrictionName, String restrictionValue) {
            switch (value) {
            case ALLOW:
                with(String.format("restriction@%s@%s@Allow", privilegeName, restrictionName), restrictionValue);
                break;
            case DENY:
                with(String.format("restriction@%s@%s@Deny", privilegeName, restrictionName), restrictionValue);
                break;
            default:
                break;
            }
            return this;
        }
        public AcePostParamsBuilder withPrivilegeRestriction(PrivilegeValues value, String privilegeName, String restrictionName, String[] restrictionValues) {
            for (String restrictionValue : restrictionValues) {
                withPrivilegeRestriction(value, privilegeName, restrictionName, restrictionValue);
            }
            return this;
        }

        public AcePostParamsBuilder withDeletePrivilegeRestriction(String privilegeName, String restrictionName, DeleteValues value) {
            return with(String.format("restriction@%s@%s@Delete", privilegeName, restrictionName), value.toString());
        }

        public AcePostParamsBuilder withOrder(String order) {
            return with("order", order);
        }

        public AcePostParamsBuilder withRedirect(String redirectTo) {
            return with(":redirect", redirectTo);
        }

        public AcePostParamsBuilder with(String key, String value) {
            list.add(new BasicNameValuePair(key, value));
            return this;
        }

        public AcePostParamsBuilder with(String key, String[] values) {
            for (String value : values) {
                list.add(new BasicNameValuePair(key, value));
            }
            return this;
        }

        public List<NameValuePair> build() {
            return list;
        }

    }

    protected void addOrUpdateAce(String folderUrl, List<NameValuePair> postParams) throws IOException, JsonException {
        addOrUpdateAce(folderUrl, postParams, HttpServletResponse.SC_OK);
    }
    protected void addOrUpdateAce(String folderUrl, List<NameValuePair> postParams, int expectedStatus) throws IOException, JsonException {
        String postUrl = folderUrl + ".modifyAce.html";

        Credentials creds = new UsernamePasswordCredentials("admin", "admin");
        assertAuthenticatedPostStatus(creds, postUrl, expectedStatus, postParams, null);
    }

    protected String addOrUpdateAce(String folderUrl, List<NameValuePair> postParams, String contentType) throws IOException, JsonException {
        return addOrUpdateAce(folderUrl, postParams, contentType, HttpServletResponse.SC_OK);
    }

    protected String addOrUpdateAce(String folderUrl, List<NameValuePair> postParams, String contentType, int expectedStatus) throws IOException, JsonException {
        String postUrl = folderUrl + ".modifyAce." + (CONTENT_TYPE_JSON.equals(contentType) ? "json" : "html");

        Credentials creds = new UsernamePasswordCredentials("admin", "admin");
        return getAuthenticatedPostContent(creds, postUrl, contentType, postParams, expectedStatus);
    }

    protected JsonObject getAcl(String folderUrl) throws IOException, JsonException {
        String getUrl = folderUrl + ".acl.json";

        Credentials creds = new UsernamePasswordCredentials("admin", "admin");
        String json = getAuthenticatedContent(creds, getUrl, CONTENT_TYPE_JSON, HttpServletResponse.SC_OK);
        assertNotNull(json);

        JsonObject aclObject = parseJson(json);
        return aclObject;
    }

    protected JsonObject getPrincipalAce(String folderUrl, String principalId) throws IOException, JsonException {
        return getPrincipalAce(folderUrl, principalId, CONTENT_TYPE_JSON, HttpServletResponse.SC_OK);
    }
    protected JsonObject getPrincipalAce(String folderUrl, String principalId, String expectedContentType, int expectedStatus) throws IOException, JsonException {
        String getUrl = folderUrl + ".pace.json?pid=" + principalId;

        Credentials creds = new UsernamePasswordCredentials("admin", "admin");
        String json = getAuthenticatedContent(creds, getUrl, expectedContentType, expectedStatus);
        JsonObject aceObject = null;
        if (expectedStatus == HttpServletResponse.SC_OK) {
            assertNotNull(json);

            aceObject = parseJson(json);
        }
        return aceObject;
    }

    protected JsonObject getAce(String folderUrl, String principalId) throws IOException, JsonException {
        JsonObject aclObject = getAcl(folderUrl);
        assertNotNull(aclObject);

        JsonObject aceObj = aclObject.getJsonObject(principalId);
        assertNotNull(aceObj);
        assertEquals(principalId, aceObj.getString("principal"));
        return aceObj;
    }

    protected JsonObject getAcePrivleges(String folderUrl, String principalId) throws IOException, JsonException {
        JsonObject ace = getAce(folderUrl, principalId);
        JsonObject privilegesObject = ace.getJsonObject("privileges");
        assertNotNull(privilegesObject);
        return privilegesObject;
    }

}
