001/* 002 * Copyright (C) 2014 XStream Committers. 003 * All rights reserved. 004 * 005 * Created on 08. January 2014 by Joerg Schaible 006 */ 007package com.thoughtworks.xstream.mapper; 008 009import java.util.ArrayList; 010import java.util.Arrays; 011import java.util.List; 012 013import com.thoughtworks.xstream.security.AnyTypePermission; 014import com.thoughtworks.xstream.security.ForbiddenClassException; 015import com.thoughtworks.xstream.security.NoTypePermission; 016import 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 */ 026public 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}