001    /*
002     * Copyright (c) OSGi Alliance (2004, 2009). All Rights Reserved.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.osgi.service.cm;
018    
019    import java.security.BasicPermission;
020    import java.security.Permission;
021    import java.security.PermissionCollection;
022    import java.util.Enumeration;
023    import java.util.NoSuchElementException;
024    
025    /**
026     * Indicates a bundle's authority to configure bundles.
027     * 
028     * This permission has only a single action: CONFIGURE.
029     * 
030     * @ThreadSafe
031     * @version $Revision: 6381 $
032     * @since 1.2
033     */
034    
035    public final class ConfigurationPermission extends BasicPermission {
036            static final long                       serialVersionUID        = 5716868734811965383L;
037            /**
038             * The action string <code>configure</code>.
039             */
040            public final static String      CONFIGURE                       = "configure";
041    
042            /**
043             * Create a new ConfigurationPermission.
044             * 
045             * @param name Name must be &quot;*&quot;.
046             * @param actions <code>configure</code> (canonical order).
047             */
048    
049            public ConfigurationPermission(String name, String actions) {
050                    super(name);
051                    if (!name.equals("*")) {
052                            throw new IllegalArgumentException("name must be *");
053                    }
054                    actions = actions.trim();
055                    if (actions.equalsIgnoreCase(CONFIGURE)||actions.equals("*"))
056                            return;
057                    
058                    throw new IllegalArgumentException("actions must be " + CONFIGURE);
059            }
060    
061            /**
062             * Determines if a <code>ConfigurationPermission</code> object "implies"
063             * the specified permission.
064             * 
065             * @param p The target permission to check.
066             * @return <code>true</code> if the specified permission is implied by
067             *         this object; <code>false</code> otherwise.
068             */
069    
070            public boolean implies(Permission p) {
071                    return p instanceof ConfigurationPermission;
072            }
073    
074            /**
075             * Determines the equality of two <code>ConfigurationPermission</code>
076             * objects.
077             * <p>
078             * Two <code>ConfigurationPermission</code> objects are equal.
079             * 
080             * @param obj The object being compared for equality with this object.
081             * @return <code>true</code> if <code>obj</code> is equivalent to this
082             *         <code>ConfigurationPermission</code>; <code>false</code>
083             *         otherwise.
084             */
085            public boolean equals(Object obj) {
086                    return obj instanceof ConfigurationPermission;
087            }
088    
089            /**
090             * Returns the hash code value for this object.
091             * 
092             * @return Hash code value for this object.
093             */
094    
095            public int hashCode() {
096                    int h = 31 * 17 + getName().hashCode();
097                    h = 31 * h + getActions().hashCode();
098                    return h;
099            }
100    
101            /**
102             * Returns the canonical string representation of the
103             * <code>ConfigurationPermission</code> actions.
104             * 
105             * <p>
106             * Always returns present <code>ConfigurationPermission</code> actions in
107             * the following order: <code>CONFIGURE</code>
108             * 
109             * @return Canonical string representation of the
110             *         <code>ConfigurationPermission</code> actions.
111             */
112            public String getActions() {
113                    return CONFIGURE;
114            }
115    
116            /**
117             * Returns a new <code>PermissionCollection</code> object suitable for
118             * storing <code>ConfigurationPermission</code>s.
119             * 
120             * @return A new <code>PermissionCollection</code> object.
121             */
122            public PermissionCollection newPermissionCollection() {
123                    return new ConfigurationPermissionCollection();
124            }
125    }
126    
127    /**
128     * Stores a set of <code>ConfigurationPermission</code> permissions.
129     * 
130     * @see java.security.Permission
131     * @see java.security.Permissions
132     * @see java.security.PermissionCollection
133     */
134    final class ConfigurationPermissionCollection extends PermissionCollection {
135            static final long       serialVersionUID        = -6917638867081695839L;
136            /**
137             * True if collection is non-empty.
138             * 
139             * @serial
140             */
141            private volatile boolean        hasElement;
142    
143            /**
144             * Creates an empty <tt>ConfigurationPermissionCollection</tt> object.
145             * 
146             */
147            public ConfigurationPermissionCollection() {
148                    hasElement = false;
149            }
150    
151            /**
152             * Adds the specified permission to the
153             * <tt>ConfigurationPermissionCollection</tt>. The key for the hash is
154             * the interface name of the service.
155             * 
156             * @param permission The <tt>Permission</tt> object to add.
157             * 
158             * @exception IllegalArgumentException If the permission is not an
159             *            <tt>ConfigurationPermission</tt>.
160             * 
161             * @exception SecurityException If this ConfigurationPermissionCollection
162             *            object has been marked read-only.
163             */
164    
165            public void add(Permission permission) {
166                    if (!(permission instanceof ConfigurationPermission)) {
167                            throw new IllegalArgumentException("invalid permission: "
168                                            + permission);
169                    }
170    
171                    if (isReadOnly())
172                            throw new SecurityException("attempt to add a Permission to a "
173                                            + "readonly PermissionCollection");
174    
175                    hasElement = true;
176            }
177    
178            /**
179             * Determines if the specified set of permissions implies the permissions
180             * expressed in the parameter <tt>permission</tt>.
181             * 
182             * @param p The Permission object to compare.
183             * 
184             * @return true if permission is a proper subset of a permission in the set;
185             *         false otherwise.
186             */
187    
188            public boolean implies(Permission p) {
189                    return hasElement && (p instanceof ConfigurationPermission);
190            }
191    
192            /**
193             * Returns an enumeration of an <tt>ConfigurationPermission</tt> object.
194             * 
195             * @return Enumeration of an <tt>ConfigurationPermission</tt> object.
196             */
197    
198            public Enumeration elements() {
199                    final boolean nonEmpty = hasElement;
200                    return new Enumeration() {
201                            private boolean more = nonEmpty;
202    
203                            public boolean hasMoreElements() {
204                                    return more;
205                            }
206    
207                            public Object nextElement() {
208                                    if (more) {
209                                            more = false;
210    
211                                            return new ConfigurationPermission("*",
212                                                            ConfigurationPermission.CONFIGURE);
213                                    }
214                                    else {
215                                            throw new NoSuchElementException();
216                                    }
217                            }
218                    };
219            }
220    }