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     */
017    package org.apache.xbean.naming.context;
018    
019    import java.util.ArrayList;
020    import java.util.Collections;
021    import java.util.List;
022    
023    import javax.naming.Name;
024    import javax.naming.NamingException;
025    
026    /**
027     * @version $Rev$ $Date$
028     */
029    public 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    }