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    
018    
019    package org.apache.geronimo.javamail.store.imap;
020    import java.util.Comparator;
021    import java.util.HashMap;
022    import java.util.HashSet;
023    import java.util.Iterator;
024    import java.util.Map;
025    import java.util.Set;
026    import java.util.SortedSet;
027    import java.util.TreeSet;
028    
029    /**
030     * Represents a set of rights associated with a user to manipulate the 
031     * IMAP Store.
032     */
033    public class Rights implements Cloneable {
034        
035        /**
036         * An individual right for IMAP Store manipulation.
037         */
038        public static final class Right {
039            // The set of created stores.  The getInstance() method ensures 
040            // that each right is a singleton object. 
041            static private Map rights = new HashMap();
042            
043            /**
044             * lookup (mailbox is visible to LIST/LSUB commands)
045             */
046            public static final Right LOOKUP = getInstance('l'); 
047            /**
048             * read (SELECT the mailbox, perform CHECK, FETCH, PARTIAL,
049             *        SEARCH, COPY from mailbox)
050             */
051            public static final Right READ = getInstance('r'); 
052            /**
053             * keep seen/unseen information across sessions (STORE SEEN flag)
054             */
055            public static final Right KEEP_SEEN = getInstance('s'); 
056            /**
057             * write (STORE flags other than SEEN and DELETED)
058             */
059            public static final Right WRITE = getInstance('w'); 
060            /**
061             * insert (perform APPEND, COPY into mailbox)
062             */
063            public static final Right INSERT = getInstance('i'); 
064            /**
065             * post (send mail to submission address for mailbox,
066             *        not enforced by IMAP4 itself)
067             */
068            public static final Right POST = getInstance('p'); 
069            /**
070             * create (CREATE new sub-mailboxes in any implementation-defined
071             *        hierarchy)
072             */
073            public static final Right CREATE = getInstance('c'); 
074            /**
075             * delete (STORE DELETED flag, perform EXPUNGE)
076             */
077            public static final Right DELETE = getInstance('d'); 
078            /**
079             * administer (perform SETACL)
080             */
081            public static final Right ADMINISTER = getInstance('a'); 
082            
083            // the actual right definition 
084            String right; 
085            
086            /**
087             * Private constructor for an individual Right.  Used by getInstance().
088             * 
089             * @param right  The String name of the right (a single character).
090             */
091            private Right(String right) {
092                this.right = right; 
093            }
094            
095            /**
096             * Get an instance for a right from the single character right value.  The
097             * returned instance will be a singleton for that character value.
098             * 
099             * @param right  The right character value.
100             * 
101             * @return A Right instance that's the mapping for the character value.
102             */
103            public static synchronized Right getInstance(char right) {
104                String name = String.valueOf(right); 
105                Right instance = (Right)rights.get(name); 
106                if (instance == null) {
107                    instance = new Right(name); 
108                    rights.put(name, instance); 
109                }
110                return instance; 
111            }
112            
113            /**
114             * Return the string value of the Right.  The string value is the character 
115             * used to create the Right with newInstance().
116             * 
117             * @return The string representation of the Right.
118             */
119            public String toString() {
120                return right; 
121            }
122        }
123        
124        /**
125         * The set of Rights contained in this instance.  This is a TreeSet so that
126         * we can create the string value more consistently.
127         */
128        private SortedSet rights = new TreeSet(new RightComparator()); 
129        
130        /**
131         * Construct an empty set of Rights.
132         */
133        public Rights() {
134        }
135        
136        /**
137         * Construct a Rights set from a single Right instance.
138         * 
139         * @param right  The source Right.
140         */
141        public Rights(Right right) {
142            rights.add(right); 
143        }
144        
145        /**
146         * Construct a set of rights from an existing Rights set.  This will copy 
147         * the rights values.
148         * 
149         * @param list   The source Rights instance.
150         */
151        public Rights(Rights list) {
152            add(list); 
153            Rights[] otherRights = list.getRights(); 
154            for (int i = 0; i < otherRights.length; i++) {
155                rights.add(otherRights[i]); 
156            }
157        }
158        
159        /**
160         * Construct a Rights et from a character string.  Each character in the
161         * string represents an individual Right.
162         * 
163         * @param list   The source set of rights.
164         */
165        public Rights(String list) {
166            for (int i = 0; i < list.length(); i++) {
167                rights.add(Right.getInstance(list.charAt(i))); 
168            }
169        }
170        
171        /**
172         * Add a single Right to the set.
173         * 
174         * @param right  The new Right.  If the Rigtht is already part of the Set, this is a nop.
175         */
176        public void add(Right right) {
177            rights.add(right); 
178        }
179        
180        /**
181         * Merge a Rights set with this set.  Duplicates are eliminated.
182         * 
183         * @param list   The source for the added Rights.
184         */
185        public void add(Rights list) {
186            Rights[] otherRights = list.getRights(); 
187            for (int i = 0; i < otherRights.length; i++) {
188                rights.add(otherRights[i]); 
189            }
190        }
191        
192        /**
193         * Clone a set of Rights.
194         */
195        public Object clone() {
196            return new Rights(this); 
197        }
198        
199        /**
200         * Test if a Rights set contains a given Right.
201         * 
202         * @param right  The Right instance to test.
203         * 
204         * @return true if the Right exists in the Set, false otherwise.
205         */
206        public boolean contains(Right right) {
207            return rights.contains(right); 
208        }
209        
210        /**
211         * Test if this Rights set contains all of the Rights contained in another
212         * set.
213         * 
214         * @param list   The source Rights set for the test.
215         * 
216         * @return true if all of the Rights in the source set exist in the target set.
217         */
218        public boolean contains(Rights list) {
219            return rights.containsAll(list.rights); 
220        }
221        
222        /**
223         * Test if two Rights sets are equivalent.
224         * 
225         * @param list   The source rights set.
226         * 
227         * @return true if both Rigths sets contain the same Rights values.
228         */
229        public boolean equals(Rights list) {
230            return rights.equals(list.rights); 
231        }
232        
233        /**
234         * Get an array of Rights contained in the set.
235         * 
236         * @return An array of Rights[] values.
237         */
238        public Rights[] getRights() {
239            Rights[] list = new Rights[rights.size()]; 
240            return (Rights[])rights.toArray(list); 
241        }
242        
243        /**
244         * Compute a hashCode for the Rights set.
245         * 
246         * @return The computed hashCode.
247         */
248        public int hashCode() {
249            return rights.hashCode(); 
250        }
251        
252        /**
253         * Remove a Right from the set.
254         * 
255         * @param right  The single Right to remove.
256         */
257        public void remove(Right right) {
258            rights.remove(right); 
259        }
260        
261        /**
262         * Remove a set of rights from the set.
263         * 
264         * @param list   The list of rights to be removed.
265         */
266        public void remove(Rights list) {
267            rights.removeAll(list.rights); 
268        }
269        
270        /**
271         * Return a string value for the Rights set.  The string value is the 
272         * concatenation of the single-character Rights names. 
273         * 
274         * @return The string representation of this Rights set. 
275         */
276        public String toString() {
277            StringBuffer buff = new StringBuffer(); 
278            Iterator i = rights.iterator(); 
279            while (i.hasNext()) {
280                buff.append(i.next().toString()); 
281            }
282            return buff.toString(); 
283        }
284        
285        class RightComparator implements Comparator {
286            /**
287             * Perform a sort comparison to order two Right objects.
288             * The sort is performed using the string value. 
289             * 
290             * @param o1     The left comparator
291             * @param o2     The right comparator.
292             * 
293             * @return 0 if the two items have equal ordering, -1 if the 
294             *         left item is lower, 1 if the left item is greater.
295             */
296            public int compare(Object o1, Object o2) {
297                // compare on the string value 
298                String left = o1.toString(); 
299                return left.compareTo(o2.toString()); 
300            }
301        }
302        
303    }