All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.amazonaws.auth.policy.internal.JsonPolicyWriter Maven / Gradle / Ivy

Go to download

The AWS SDK for Java - Core module holds the classes that are used by the individual service clients to interact with Amazon Web Services. Users need to depend on aws-java-sdk artifact for accessing individual client classes.

There is a newer version: 1.12.778
Show newest version
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 com.amazonaws.auth.policy.internal;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.amazonaws.util.PolicyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.amazonaws.SdkClientException;
import com.amazonaws.auth.policy.Action;
import com.amazonaws.auth.policy.Condition;
import com.amazonaws.auth.policy.Policy;
import com.amazonaws.auth.policy.Principal;
import com.amazonaws.auth.policy.Resource;
import com.amazonaws.auth.policy.Statement;
import com.amazonaws.util.json.Jackson;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;

/**
 * Serializes an AWS policy object to a JSON string, suitable for sending to an
 * AWS service.
 */
public class JsonPolicyWriter {

    /** The JSON Generator to generator a JSON string.*/
    private JsonGenerator generator = null;

    /** The output writer to which the JSON String is written.*/
    private Writer writer;

    /** Logger used to log exceptions that occurs while writing the Json policy.*/
    private static final Log log = LogFactory.getLog("com.amazonaws.auth.policy");

    /**
     * Constructs a new instance of JSONPolicyWriter.
     */
    public JsonPolicyWriter() {
        writer = new StringWriter();
        try {
            generator = Jackson.jsonGeneratorOf(writer);
        } catch (IOException ioe) {
            throw new SdkClientException(
                    "Unable to instantiate JsonGenerator.", ioe);
        }

    }

    /**
     * Converts the specified AWS policy object to a JSON string, suitable for
     * passing to an AWS service.
     *
     * @param policy
     *            The AWS policy object to convert to a JSON string.
     *
     * @return The JSON string representation of the specified policy object.
     *
     * @throws IllegalArgumentException
     *             If the specified policy is null or invalid and cannot be
     *             serialized to a JSON string.
     */
    public String writePolicyToString(Policy policy) {

        if(!isNotNull(policy))
            throw new IllegalArgumentException("Policy cannot be null");

        try {
            return jsonStringOf(policy);
        } catch (Exception e) {
            String message = "Unable to serialize policy to JSON string: "
                    + e.getMessage();
            throw new IllegalArgumentException(message, e);
        } finally {
            try { writer.close(); } catch (Exception e) { }
        }
    }

    /**
     * Converts the given Policy into a JSON String.
     *
     * @param policy
     *            the policy to be converted.
     * @return a JSON String of the specified policy object.
     */
    private String jsonStringOf(Policy policy) throws JsonGenerationException,
            IOException {
        generator.writeStartObject();

        writeJsonKeyValue(JsonDocumentFields.VERSION, policy.getVersion());

        if (isNotNull(policy.getId()))
            writeJsonKeyValue(JsonDocumentFields.POLICY_ID, policy.getId());

        writeJsonArrayStart(JsonDocumentFields.STATEMENT);

        for (Statement statement : policy.getStatements()) {
            generator.writeStartObject();

            if (isNotNull(statement.getId())) {
                writeJsonKeyValue(JsonDocumentFields.STATEMENT_ID, statement.getId());
            }
            writeJsonKeyValue(JsonDocumentFields.STATEMENT_EFFECT, statement
                    .getEffect().toString());

            List principals = statement.getPrincipals();
            if (isNotNull(principals) && !principals.isEmpty())
                writePrincipals(principals);

            List actions = statement.getActions();
            if (isNotNull(actions) && !actions.isEmpty())
                writeActions(actions);

            List resources = statement.getResources();
            if (isNotNull(resources) && !resources.isEmpty())
                writeResources(resources);

            List conditions = statement.getConditions();
            if (isNotNull(conditions) && !conditions.isEmpty())
                writeConditions(conditions);

            generator.writeEndObject();
        }

        writeJsonArrayEnd();

        generator.writeEndObject();

        generator.flush();

        return writer.toString();

    }

    /**
     * Writes the list of conditions to the JSONGenerator.
     *
     * @param conditions
     *            the conditions to be written.
     */
    private void writeConditions(List conditions)
            throws JsonGenerationException, IOException {
        Map conditionsByType = groupConditionsByTypeAndKey(conditions);

        writeJsonObjectStart(JsonDocumentFields.CONDITION);

        ConditionsByKey conditionsByKey;
        for (Map.Entry entry : conditionsByType
                .entrySet()) {
            conditionsByKey = conditionsByType.get(entry.getKey());

            writeJsonObjectStart(entry.getKey());
            for (String key : conditionsByKey.keySet()) {
                writeJsonArray(key, conditionsByKey.getConditionsByKey(key));
            }
            writeJsonObjectEnd();
        }
        writeJsonObjectEnd();
    }

    /**
     * Writes the list of Resources to the JSONGenerator.
     *
     * @param resources
     *            the list of resources to be written.
     */
    private void writeResources(List resources)
            throws JsonGenerationException, IOException {

        PolicyUtils.validateResourceList(resources);
        List resourceStrings = new ArrayList();

        for (Resource resource : resources) {
            resourceStrings.add(resource.getId());
        }

        // all resources are validated to be of the same type, so it is safe to take the type of the first one
        if (resources.get(0).isNotType()) {
            writeJsonArray(JsonDocumentFields.NOT_RESOURCE, resourceStrings);
        } else {
            writeJsonArray(JsonDocumentFields.RESOURCE, resourceStrings);
        }
    }

    /**
     * Writes the list of Actions to the JSONGenerator.
     *
     * @param actions
     *            the list of the actions to be written.
     */
    private void writeActions(List actions)
            throws JsonGenerationException, IOException {
        List actionStrings = new ArrayList();

        for (Action action : actions) {
            actionStrings.add(action.getActionName());
        }
        writeJsonArray(JsonDocumentFields.ACTION, actionStrings);
    }

    /**
     * Writes the list of Principals to the JSONGenerator.
     *
     * @param principals
     *            the list of principals to be written.
     */
    private void writePrincipals(List principals)
            throws JsonGenerationException, IOException {
        if (principals.size() == 1 && principals.get(0).equals(Principal.All)) {
            writeJsonKeyValue(JsonDocumentFields.PRINCIPAL, Principal.All.getId());
        } else {
            writeJsonObjectStart(JsonDocumentFields.PRINCIPAL);

            Map> principalsByScheme = groupPrincipalByScheme(principals);

            List principalValues;
            for (Map.Entry> entry : principalsByScheme.entrySet()) {
                principalValues = principalsByScheme.get(entry.getKey());

                if (principalValues.size() == 1) {
                    writeJsonKeyValue(entry.getKey(), principalValues.get(0));
                } else {
                    writeJsonArray(entry.getKey(), principalValues);
                }

            }
            writeJsonObjectEnd();
        }
    }

    /**
     * Groups the list of Principals by the Scheme.
     *
     * @param principals
     *            the list of Principals
     * @return a map grouped by scheme of the principal.
     */
    private Map> groupPrincipalByScheme(
            List principals) {
        Map> principalsByScheme = new LinkedHashMap>();

        String provider;
        List principalValues;
        for (Principal principal : principals) {
            provider = principal.getProvider();
            if (!principalsByScheme.containsKey(provider)) {
                principalsByScheme.put(provider, new ArrayList());
            }
            principalValues = principalsByScheme.get(provider);
            principalValues.add(principal.getId());
        }

        return principalsByScheme;
    }

    /**
     * Inner class to hold condition values for each key under a condition type.
     */
    static class ConditionsByKey {
        private Map> conditionsByKey;

        public ConditionsByKey(){
            conditionsByKey = new LinkedHashMap>();
        }

        public Map> getConditionsByKey() {
            return conditionsByKey;
        }

        public void setConditionsByKey(Map> conditionsByKey) {
            this.conditionsByKey = conditionsByKey;
        }

        public boolean containsKey(String key){
            return conditionsByKey.containsKey(key);
        }

        public List getConditionsByKey(String key){
            return conditionsByKey.get(key);
        }

        public Set keySet(){
            return conditionsByKey.keySet();
        }

        public void addValuesToKey(String key, List values) {

            List conditionValues = getConditionsByKey(key);
            if (conditionValues == null)
                conditionsByKey.put(key, new ArrayList(values));
            else
                conditionValues.addAll(values);
        }
    }

    /**
     * Groups the list of Conditions by the condition type and
     * condition key.
     *
     * @param conditions
     *            the list of conditions to be grouped
     * @return a map of conditions grouped by type and then key.
     */
    private Map groupConditionsByTypeAndKey(
            List conditions) {
        Map conditionsByType = new LinkedHashMap();

        String type;
        String key;
        ConditionsByKey conditionsByKey;
        for (Condition condition : conditions) {
            type = condition.getType();
            key = condition.getConditionKey();

            if (!(conditionsByType.containsKey(type))) {
                conditionsByType.put(type, new ConditionsByKey());
            }

            conditionsByKey = conditionsByType.get(type);
            conditionsByKey.addValuesToKey(key, condition.getValues());
        }
        return conditionsByType;
    }

    /**
     * Writes an array along with its values to the JSONGenerator.
     *
     * @param arrayName
     *            name of the JSON array.
     * @param values
     *            values of the JSON array.
     */
    private void writeJsonArray(String arrayName, List values)
            throws JsonGenerationException, IOException {
        writeJsonArrayStart(arrayName);
        for (String value : values)
            generator.writeString(value);
        writeJsonArrayEnd();
    }

    /**
     * Writes the Start of Object String to the JSONGenerator along with Object
     * Name.
     *
     * @param fieldName
     *            name of the JSON Object.
     */
    private void writeJsonObjectStart(String fieldName)
            throws JsonGenerationException, IOException {
        generator.writeObjectFieldStart(fieldName);
    }

    /**
     * Writes the End of Object String to the JSONGenerator.
     */
    private void writeJsonObjectEnd() throws JsonGenerationException, IOException {
        generator.writeEndObject();
    }

    /**
     * Writes the Start of Array String to the JSONGenerator along with Array
     * Name.
     *
     * @param fieldName
     *            name of the JSON array
     */
    private void writeJsonArrayStart(String fieldName)
            throws JsonGenerationException, IOException {
        generator.writeArrayFieldStart(fieldName);
    }

    /**
     * Writes the End of Array String to the JSONGenerator.
     */
    private void writeJsonArrayEnd() throws JsonGenerationException, IOException {
        generator.writeEndArray();
    }

    /**
     * Writes the given field and the value to the JsonGenerator
     *
     * @param fieldName
     *            the JSON field name
     * @param value
     *            value for the field
     */
    private void writeJsonKeyValue(String fieldName, String value)
            throws JsonGenerationException, IOException {
        generator.writeStringField(fieldName, value);
    }

    /**
     * Checks if the given object is not null.
     *
     * @param object
     *            the object compared to null.
     * @return true if the object is not null else false
     */
    private boolean isNotNull(Object object) {
        return null != object;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy