001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.xbean.naming.context;
018
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.List;
022
023import javax.naming.Name;
024import javax.naming.NamingException;
025
026/**
027 * @version $Rev$ $Date$
028 */
029public class ContextAccessControlList implements ContextAccess {
030    private final boolean defaultAllow;
031    private final List<Name> allow;
032    private final List<Name> deny;
033
034    public ContextAccessControlList(boolean defaultAllow, List allow, List deny) {
035        this.defaultAllow = defaultAllow;
036        this.allow = toACL(allow);
037        this.deny = toACL(deny);
038    }
039
040    private List<Name> toACL(List input) {
041        if (input == null) return Collections.emptyList();
042        
043        ArrayList<Name> list = new ArrayList<Name>(input.size());
044        for (Object value : input) {
045            if (value instanceof Name) {
046                list.add((Name) value);
047            } else if (value instanceof String) {
048                String string = (String) value;
049                Name name;
050                try {
051                    name = ContextUtil.NAME_PARSER.parse(string);
052                } catch (NamingException e) {
053                    throw new IllegalArgumentException("error while parsing name: " + value);
054                }
055                list.add(name);
056            } else {
057                throw new IllegalArgumentException("name is not an instance of Name or String: " + value);
058            }
059        }
060        return Collections.unmodifiableList(list);
061    }
062
063    public boolean isModifiable(Name name) {
064        if (name == null) throw new NullPointerException("name is null");
065        if (defaultAllow) {
066            // allow by default, so allow if it wasn't explicitly denied or was explicitly allowed
067            return !isDenied(name) || isAllowed(name);
068        } else {
069            // deny by default, so allow if it was explicitly allowed or wasn't explicitly denied
070            return isAllowed(name) && !isDenied(name);
071        }
072    }
073
074    protected boolean isAllowed(Name name) {
075        if (name == null) throw new NullPointerException("name is null");
076        for (Name prefix : allow) {
077            if (name.startsWith(prefix)) {
078                return true;
079            }
080        }
081
082        return false;
083    }
084
085    protected boolean isDenied(Name name) {
086        if (name == null) throw new NullPointerException("name is null");
087        for (Name prefix : deny) {
088            if (name.startsWith(prefix)) {
089                return true;
090            }
091        }
092
093        return false;
094    }
095}