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

org.apache.commons.jexl3.introspection.JexlSandbox Maven / Gradle / Ivy

Go to download

The Apache Commons JEXL library is an implementation of the JSTL Expression Language with extensions.

There is a newer version: 3.4.0
Show newest version
/*
 * 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.commons.jexl3.introspection;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * A sandbox describes permissions on a class by explicitly allowing or forbidding access to methods and properties
 * through "whitelists" and "blacklists".
 *
 * 

A whitelist explicitly allows methods/properties for a class;

* *
    *
  • If a whitelist is empty and thus does not contain any names, * all properties/methods are allowed for its class.
  • *
  • If it is not empty, the only allowed properties/methods are the ones contained.
  • *
* *

A blacklist explicitly forbids methods/properties for a class;

* *
    *
  • If a blacklist is empty and thus does not contain any names, * all properties/methods are forbidden for its class.
  • *
  • If it is not empty, the only forbidden properties/methods are the ones contained.
  • *
* *

Permissions are composed of three lists, read, write, execute, each being "white" or "black":

* *
    *
  • read controls readable properties
  • *
  • write controls writable properties
  • *
  • execute controls executable methods and constructor
  • *
* *

Note that a JexlUberspect always uses a copy of the JexlSandbox used to built it to avoid synchronization and/or * concurrent modifications at runtime.

* * @since 3.0 */ public final class JexlSandbox { /** * The map from class names to permissions. */ private final Map sandbox; /** * Default behavior, black or white. */ private final boolean white; /** * Creates a new default sandbox. *

In the absence of explicit permissions on a class, the * sandbox is a white-box, white-listing that class for all permissions (read, write and execute). */ public JexlSandbox() { this(true, new HashMap()); } /** * Creates a new default sandbox. *

A white-box considers no permissions as "everything is allowed" when * a black-box considers no permissions as "nothing is allowed". * @param wb whether this sandbox is white (true) or black (false) * if no permission is explicitly defined for a class. * @since 3.1 */ public JexlSandbox(boolean wb) { this(wb, new HashMap()); } /** * Creates a sandbox based on an existing permissions map. * @param map the permissions map */ protected JexlSandbox(Map map) { this(true, map); } /** * Creates a sandbox based on an existing permissions map. * @param wb whether this sandbox is white (true) or black (false) * @param map the permissions map * @since 3.1 */ protected JexlSandbox(boolean wb, Map map) { white = wb; sandbox = map; } /** * @return a copy of this sandbox */ public JexlSandbox copy() { Map map = new HashMap(); for (Map.Entry entry : sandbox.entrySet()) { map.put(entry.getKey(), entry.getValue().copy()); } return new JexlSandbox(white, map); } /** * Gets the read permission value for a given property of a class. * * @param clazz the class * @param name the property name * @return null if not allowed, the name of the property to use otherwise */ public String read(Class clazz, String name) { return read(clazz.getName(), name); } /** * Gets the read permission value for a given property of a class. * * @param clazz the class name * @param name the property name * @return null if not allowed, the name of the property to use otherwise */ public String read(String clazz, String name) { Permissions permissions = sandbox.get(clazz); if (permissions == null) { return white? name : null; } else { return permissions.read().get(name); } } /** * Gets the write permission value for a given property of a class. * * @param clazz the class * @param name the property name * @return null if not allowed, the name of the property to use otherwise */ public String write(Class clazz, String name) { return write(clazz.getName(), name); } /** * Gets the write permission value for a given property of a class. * * @param clazz the class name * @param name the property name * @return null if not allowed, the name of the property to use otherwise */ public String write(String clazz, String name) { Permissions permissions = sandbox.get(clazz); if (permissions == null) { return white ? name : null; } else { return permissions.write().get(name); } } /** * Gets the execute permission value for a given method of a class. * * @param clazz the class * @param name the method name * @return null if not allowed, the name of the method to use otherwise */ public String execute(Class clazz, String name) { return execute(clazz.getName(), name); } /** * Gets the execute permission value for a given method of a class. * * @param clazz the class name * @param name the method name * @return null if not allowed, the name of the method to use otherwise */ public String execute(String clazz, String name) { Permissions permissions = sandbox.get(clazz); if (permissions == null) { return white ? name : null; } else { return permissions.execute().get(name); } } /** * A base set of names. */ public abstract static class Names { /** * Adds a name to this set. * * @param name the name to add * @return true if the name was really added, false if not */ public abstract boolean add(String name); /** * Adds an alias to a name to this set. *

This only has an effect on white lists.

* * @param name the name to alias * @param alias the alias * @return true if the alias was added, false if it was already present */ public boolean alias(String name, String alias) { return false; } /** * Whether a given name is allowed or not. * * @param name the method/property name to check * @return null if not allowed, the actual name to use otherwise */ public String get(String name) { return name; } /** * @return a copy of these Names */ protected Names copy() { return this; } } /** * The pass-thru name set. */ private static final Names WHITE_NAMES = new Names() { @Override public boolean add(String name) { return false; } @Override protected Names copy() { return this; } }; /** * A white set of names. */ public static final class WhiteSet extends Names { /** The map of controlled names and aliases. */ private Map names = null; @Override protected Names copy() { WhiteSet copy = new WhiteSet(); copy.names = names == null ? null : new HashMap(names); return copy; } @Override public boolean add(String name) { if (names == null) { names = new HashMap(); } return names.put(name, name) == null; } @Override public boolean alias(String name, String alias) { if (names == null) { names = new HashMap(); } return names.put(alias, name) == null; } @Override public String get(String name) { if (names == null) { return name; } else { return names.get(name); } } } /** * A black set of names. */ public static final class BlackSet extends Names { /** The set of controlled names. */ private Set names = null; @Override protected Names copy() { BlackSet copy = new BlackSet(); copy.names = names == null ? null : new HashSet(names); return copy; } @Override public boolean add(String name) { if (names == null) { names = new HashSet(); } return names.add(name); } @Override public String get(String name) { return names != null && !names.contains(name) ? name : null; } } /** * Contains the white or black lists for properties and methods for a given class. */ public static final class Permissions { /** The controlled readable properties. */ private final Names read; /** The controlled writable properties. */ private final Names write; /** The controlled methods. */ private final Names execute; /** * Creates a new permissions instance. * * @param readFlag whether the read property list is white or black * @param writeFlag whether the write property list is white or black * @param executeFlag whether the method list is white of black */ Permissions(boolean readFlag, boolean writeFlag, boolean executeFlag) { this(readFlag ? new WhiteSet() : new BlackSet(), writeFlag ? new WhiteSet() : new BlackSet(), executeFlag ? new WhiteSet() : new BlackSet()); } /** * Creates a new permissions instance. * * @param nread the read set * @param nwrite the write set * @param nexecute the method set */ Permissions(Names nread, Names nwrite, Names nexecute) { this.read = nread != null ? nread : WHITE_NAMES; this.write = nwrite != null ? nwrite : WHITE_NAMES; this.execute = nexecute != null ? nexecute : WHITE_NAMES; } /** * @return a copy of these permissions */ Permissions copy() { return new Permissions(read.copy(), write.copy(), execute.copy()); } /** * Adds a list of readable property names to these permissions. * * @param pnames the property names * @return this instance of permissions */ public Permissions read(String... pnames) { for (String pname : pnames) { read.add(pname); } return this; } /** * Adds a list of writable property names to these permissions. * * @param pnames the property names * @return this instance of permissions */ public Permissions write(String... pnames) { for (String pname : pnames) { write.add(pname); } return this; } /** * Adds a list of executable methods names to these permissions. *

The constructor is denoted as the empty-string, all other methods by their names.

* * @param mnames the method names * @return this instance of permissions */ public Permissions execute(String... mnames) { for (String mname : mnames) { execute.add(mname); } return this; } /** * Gets the set of readable property names in these permissions. * * @return the set of property names */ public Names read() { return read; } /** * Gets the set of writable property names in these permissions. * * @return the set of property names */ public Names write() { return write; } /** * Gets the set of method names in these permissions. * * @return the set of method names */ public Names execute() { return execute; } } /** * The pass-thru permissions. */ private static final Permissions ALL_WHITE = new Permissions(WHITE_NAMES, WHITE_NAMES, WHITE_NAMES); /** * Creates the set of permissions for a given class. * * @param clazz the class for which these permissions apply * @param readFlag whether the readable property list is white - true - or black - false - * @param writeFlag whether the writable property list is white - true - or black - false - * @param executeFlag whether the executable method list is white white - true - or black - false - * @return the set of permissions */ public Permissions permissions(String clazz, boolean readFlag, boolean writeFlag, boolean executeFlag) { Permissions box = new Permissions(readFlag, writeFlag, executeFlag); sandbox.put(clazz, box); return box; } /** * Creates a new set of permissions based on white lists for methods and properties for a given class. * * @param clazz the whitened class name * @return the permissions instance */ public Permissions white(String clazz) { return permissions(clazz, true, true, true); } /** * Creates a new set of permissions based on black lists for methods and properties for a given class. * * @param clazz the blackened class name * @return the permissions instance */ public Permissions black(String clazz) { return permissions(clazz, false, false, false); } /** * Gets the set of permissions associated to a class. * * @param clazz the class name * @return the defined permissions or an all-white permission instance if none were defined */ public Permissions get(String clazz) { Permissions permissions = sandbox.get(clazz); if (permissions == null) { return ALL_WHITE; } else { return permissions; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy