View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.vfs2.util;
19  
20  import java.util.EnumMap;
21  import java.util.Map;
22  
23  /**
24   * UNIX permissions.
25   *
26   * @since 2.1
27   */
28  public class PosixPermissions {
29  
30      /**
31       * Permission types.
32       */
33      public enum Type {
34          /**
35           * User right readable.
36           */
37          UserReadable(00400),
38  
39          /**
40           * User right writable.
41           */
42          UserWritable(00200),
43  
44          /**
45           * User right executable.
46           */
47          UserExecutable(00100),
48  
49          /**
50           * Group right readable.
51           */
52          GroupReadable(00040),
53  
54          /**
55           * Group right writable.
56           */
57          GroupWritable(00020),
58  
59          /**
60           * Group right executable.
61           */
62          GroupExecutable(00010),
63  
64          /**
65           * Other right readable.
66           */
67          OtherReadable(00004),
68  
69          /**
70           * Other right writable.
71           */
72          OtherWritable(00002),
73  
74          /**
75           * Other right executable.
76           */
77          OtherExecutable(00001);
78  
79          private final int mask;
80  
81          /**
82           * Initialize with the mask
83           */
84          Type(final int mask) {
85              this.mask = mask;
86          }
87  
88          /**
89           * Return the mask for this permission.
90           *
91           * @return the mask for this permission.
92           */
93          public int getMask() {
94              return this.mask;
95          }
96  
97      }
98  
99      /**
100      * Current permissions.
101      */
102     private final int permissions;
103 
104     /**
105      * If the user is the owner of the file.
106      */
107     private final boolean isOwner;
108 
109     /**
110      * If one user group is the group of the file.
111      */
112     private final boolean isInGroup;
113 
114     /**
115      * Creates a new PosixPermissions object.
116      *
117      * @param permissions The permissions
118      * @param isOwner true if the user is the owner of the file
119      * @param isInGroup true if the user is a group owner of the file
120      */
121     public PosixPermissions(final int permissions, final boolean isOwner, final boolean isInGroup) {
122         this.permissions = permissions;
123         this.isOwner = isOwner;
124         this.isInGroup = isInGroup;
125     }
126 
127     /**
128      * Computes new permission from old ones.
129      *
130      * @param values The permissions to set.
131      * @return The new permissions.
132      */
133     private int computeNewPermissions(final Map<Type, Boolean> values) {
134         int newPerms = this.permissions;
135         for (final Map.Entry<Type, Boolean> entry : values.entrySet()) {
136             final Type type = entry.getKey();
137             if (entry.getValue()) {
138                 newPerms |= type.getMask();
139             } else {
140                 newPerms &= ~type.getMask();
141             }
142         }
143         return newPerms;
144     }
145 
146     /**
147      * Tests whether the bit corresponding to the permission is set.
148      *
149      * @return whether the bit corresponding to the permission is set.
150      */
151     private boolean get(final Type type) {
152         return (type.getMask() & this.permissions) != 0;
153     }
154 
155     /**
156      * Gets permissions.
157      *
158      * @return permissions.
159      */
160     public int getPermissions() {
161         return this.permissions;
162     }
163 
164     /**
165      * Gets whether the permissions are executable.
166      *
167      * @return whether the permissions are executable.
168      */
169     public boolean isExecutable() {
170         if (this.isOwner) {
171             return this.get(Type.UserExecutable);
172         }
173         if (this.isInGroup) {
174             return this.get(Type.GroupExecutable);
175         }
176         return this.get(Type.OtherExecutable);
177     }
178 
179     /**
180      * Gets whether the permissions are readable.
181      *
182      * @return whether the permissions are readable.
183      */
184     public boolean isReadable() {
185         if (this.isOwner) {
186             return this.get(Type.UserReadable);
187         }
188         if (this.isInGroup) {
189             return this.get(Type.GroupReadable);
190         }
191         return this.get(Type.OtherReadable);
192     }
193 
194     /**
195      * Gets whether the permissions are writable.
196      *
197      * @return whether the permissions are writable.
198      */
199     public boolean isWritable() {
200         if (this.isOwner) {
201             return this.get(Type.UserWritable);
202         }
203         if (this.isInGroup) {
204             return this.get(Type.GroupWritable);
205         }
206         return this.get(Type.OtherWritable);
207     }
208 
209     /**
210      * Creates new permissions based on these permissions.
211      *
212      * @param executable Whether the new permissions should be readable.
213      * @param ownerOnly Whether the new permissions are only for the owner.
214      * @return the new permissions.
215      */
216     public int makeExecutable(final boolean executable, final boolean ownerOnly) {
217         final EnumMap<Type, Boolean> map = new EnumMap<>(Type.class);
218         map.put(Type.UserExecutable, executable);
219         if (!ownerOnly) {
220             map.put(Type.GroupExecutable, executable);
221             map.put(Type.OtherExecutable, executable);
222         }
223         return this.computeNewPermissions(map);
224     }
225 
226     /**
227      * Creates new permissions based on these permissions.
228      *
229      * @param readable Whether the new permissions should be readable.
230      * @param ownerOnly Whether the new permissions are only for the owner.
231      * @return the new permissions.
232      */
233     public Integer makeReadable(final boolean readable, final boolean ownerOnly) {
234         final EnumMap<Type, Boolean> map = new EnumMap<>(Type.class);
235         map.put(Type.UserReadable, readable);
236         if (!ownerOnly) {
237             map.put(Type.GroupReadable, readable);
238             map.put(Type.OtherReadable, readable);
239         }
240         return this.computeNewPermissions(map);
241     }
242 
243     /**
244      * Creates new permissions based on these permissions.
245      *
246      * @param writable Whether the new permissions should be readable.
247      * @param ownerOnly Whether the new permissions are only for the owner.
248      * @return the new permissions.
249      */
250     public Integer makeWritable(final boolean writable, final boolean ownerOnly) {
251         final EnumMap<Type, Boolean> map = new EnumMap<>(Type.class);
252         map.put(Type.UserWritable, writable);
253         if (!ownerOnly) {
254             map.put(Type.GroupWritable, writable);
255             map.put(Type.OtherWritable, writable);
256         }
257         return this.computeNewPermissions(map);
258     }
259 }