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

org.opencastproject.security.api.AccessControlParser Maven / Gradle / Ivy

There is a newer version: 16.7
Show newest version
/*
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 *
 * The Apereo Foundation licenses this file to you under the Educational
 * Community 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://opensource.org/licenses/ecl2.txt
 *
 * 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.opencastproject.security.api;

import static org.opencastproject.util.data.functions.Misc.chuck;

import org.opencastproject.util.XmlSafeParser;

import org.apache.commons.io.IOUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.Writer;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

/**
 * Marshals and unmarshals {@link AccessControlList}s to/from XML.
 */
public final class AccessControlParser {
  /** Role constant used in JSON formatted access control entries */
  public static final String ROLE = "role";

  /** Action constant used in JSON formatted access control entries */
  public static final String ACTION = "action";

  /** Allow constant used in JSON formatted access control entries */
  public static final String ALLOW = "allow";

  /** ACL constant used in JSON formatted access control entries */
  public static final String ACL = "acl";

  /** ACE constant used in JSON formatted access control entries */
  public static final String ACE = "ace";

  /** Encoding expected from all inputs */
  public static final String ENCODING = "UTF-8";

  private static final JAXBContext jaxbContext;

  static {
    try {
      jaxbContext = JAXBContext.newInstance("org.opencastproject.security.api",
              AccessControlParser.class.getClassLoader());
    } catch (JAXBException e) {
      throw new IllegalStateException(e);
    }
  }

  /**
   * Disallow construction of this utility class.
   */
  private AccessControlParser() {
  }

  /**
   * Parses a string into an ACL.
   *
   * @param serializedForm
   *          the string containing the xml or json formatted access control list.
   * @return the access control list
   * @throws IOException
   *           if the encoding is invalid
   * @throws AccessControlParsingException
   *           if the format is invalid
   */
  public static AccessControlList parseAcl(String serializedForm) throws IOException, AccessControlParsingException {
    // Determine whether to parse this as XML or JSON
    if (serializedForm.startsWith("{")) {
      return parseJson(serializedForm);
    } else {
      return parseXml(IOUtils.toInputStream(serializedForm, ENCODING));
    }
  }

  /** Same like {@link #parseAcl(String)} but throws runtime exceptions in case of an error. */
  public static AccessControlList parseAclSilent(String serializedForm) {
    try {
      return parseAcl(serializedForm);
    } catch (Exception e) {
      return chuck(e);
    }
  }

  /**
   * Unmarshals an ACL from an xml input stream.
   *
   * @param in
   *          the xml input stream
   * @return the acl
   * @throws IOException
   *           if there is a problem unmarshaling the stream
   * @throws AccessControlParsingException
   *           if the format is invalid
   */
  public static AccessControlList parseAcl(InputStream in) throws IOException, AccessControlParsingException {
    return parseAcl(IOUtils.toString(in, ENCODING));
  }

  /**
   * Parses a JSON stream to an ACL.
   *
   * @param content
   *          the JSON stream
   * @return the access control list
   * @throws AccessControlParsingException
   *           if the json is not properly formatted
   */
  private static AccessControlList parseJson(String content) throws AccessControlParsingException {
    try {
      JSONObject json = (JSONObject) new JSONParser().parse(content);
      JSONObject jsonAcl = (JSONObject) json.get(ACL);
      Object jsonAceObj = jsonAcl.get(ACE);

      AccessControlList acl = new AccessControlList();
      if (jsonAceObj == null)
        return acl;

      if (jsonAceObj instanceof JSONObject) {
        JSONObject jsonAce = (JSONObject) jsonAceObj;
        acl.getEntries().add(getAce(jsonAce));
      } else {
        JSONArray jsonAceArray = (JSONArray) jsonAceObj;
        for (Object element : jsonAceArray) {
          JSONObject jsonAce = (JSONObject) element;
          acl.getEntries().add(getAce(jsonAce));
        }
      }
      return acl;
    } catch (ParseException e) {
      throw new AccessControlParsingException(e);
    }
  }

  /**
   * Converts a JSON representation of an access control entry to an {@link AccessControlEntry}.
   *
   * @param jsonAce
   *          the json object
   * @return the access control entry
   */
  private static AccessControlEntry getAce(JSONObject jsonAce) {
    String role = (String) jsonAce.get(ROLE);
    String action = (String) jsonAce.get(ACTION);
    Boolean allow = (Boolean) jsonAce.getOrDefault(ALLOW, Boolean.TRUE);
    return new AccessControlEntry(role, action, allow);
  }

  /**
   * Parses an XML stream to an ACL.
   *
   * @param in
   *          the XML stream
   * @throws IOException
   *           if there is a problem unmarshaling the stream
   */
  private static AccessControlList parseXml(InputStream in) throws IOException, AccessControlParsingException {
    Unmarshaller unmarshaller;
    try {
      unmarshaller = jaxbContext.createUnmarshaller();
      return unmarshaller.unmarshal(XmlSafeParser.parse(in), AccessControlList.class).getValue();
    } catch (Exception e) {
      if (e instanceof IOException) {
        throw (IOException) e;
      } else {
        throw new AccessControlParsingException(e);
      }
    } finally {
      IOUtils.closeQuietly(in);
    }
  }

  /**
   * Serializes an AccessControlList to its XML form.
   *
   * @param acl
   *          the access control list
   * @return the xml as a string
   * @throws IOException
   *           if there is a problem marshaling the xml
   */
  public static String toXml(AccessControlList acl) throws IOException {
    try {
      Marshaller marshaller = jaxbContext.createMarshaller();
      Writer writer = new StringWriter();
      marshaller.marshal(acl, writer);
      return writer.toString();
    } catch (JAXBException e) {
      throw new IOException(e);
    }
  }

  @SuppressWarnings("unchecked")
  public static String toJson(AccessControlList acl) throws IOException {
    JSONObject json = new JSONObject();
    JSONObject jsonAcl = new JSONObject();
    List entries = acl.getEntries();
    if (entries.size() > 0) {
      JSONArray jsonEntryArray = new JSONArray();
      jsonAcl.put(ACE, jsonEntryArray);
      for (AccessControlEntry entry : entries) {
        JSONObject jsonEntry = new JSONObject();
        jsonEntry.put(ACTION, entry.getAction());
        jsonEntry.put(ROLE, entry.getRole());
        jsonEntry.put(ALLOW, entry.isAllow());
        jsonEntryArray.add(jsonEntry);
      }
    }
    json.put(ACL, jsonAcl);
    return json.toJSONString();
  }

  public static String toJsonSilent(AccessControlList acl) {
    try {
      return toJson(acl);
    } catch (IOException e) {
      return chuck(e);
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy