001 /*
002 * Copyright (C) 2014 XStream Committers.
003 * All rights reserved.
004 *
005 * Created on 08. January 2014 by Joerg Schaible
006 */
007 package com.thoughtworks.xstream.mapper;
008
009 import java.util.ArrayList;
010 import java.util.Arrays;
011 import java.util.List;
012
013 import com.thoughtworks.xstream.security.AnyTypePermission;
014 import com.thoughtworks.xstream.security.ForbiddenClassException;
015 import com.thoughtworks.xstream.security.NoTypePermission;
016 import com.thoughtworks.xstream.security.TypePermission;
017
018
019 /**
020 * A Mapper implementation injecting a security layer based on permission rules for any type required in the
021 * unmarshalling process.
022 *
023 * @author Jörg Schaible
024 * @since 1.4.7
025 */
026 public class SecurityMapper extends MapperWrapper {
027
028 private final List permissions;
029
030 /**
031 * Construct a SecurityMapper.
032 *
033 * @param wrapped the mapper chain
034 * @since 1.4.7
035 */
036 public SecurityMapper(final Mapper wrapped) {
037 this(wrapped, (TypePermission[])null);
038 }
039
040 /**
041 * Construct a SecurityMapper.
042 *
043 * @param wrapped the mapper chain
044 * @param permissions the predefined permissions
045 * @since 1.4.7
046 */
047 public SecurityMapper(final Mapper wrapped, final TypePermission[] permissions) {
048 super(wrapped);
049 this.permissions = permissions == null //
050 ? new ArrayList()
051 : new ArrayList(Arrays.asList(permissions));
052 }
053
054 /**
055 * Add a new permission.
056 * <p>
057 * Permissions are evaluated in the added sequence. An instance of {@link NoTypePermission} or
058 * {@link AnyTypePermission} will implicitly wipe any existing permission.
059 * </p>
060 *
061 * @param permission the permission to add.
062 * @since 1.4.7
063 */
064 public void addPermission(final TypePermission permission) {
065 if (permission.equals(NoTypePermission.NONE) || permission.equals(AnyTypePermission.ANY))
066 permissions.clear();
067 permissions.add(0, permission);
068 }
069
070 public Class realClass(final String elementName) {
071 final Class type = super.realClass(elementName);
072 for (int i = 0; i < permissions.size(); ++i) {
073 final TypePermission permission = (TypePermission)permissions.get(i);
074 if (permission.allows(type))
075 return type;
076 }
077 throw new ForbiddenClassException(type);
078 }
079 }