001    /*
002     * Jpkg - Java library and tools for operating system package creation.
003     *
004     * Copyright (c) 2007-2008 Three Rings Design, Inc.
005     * All rights reserved.
006     *
007     * Redistribution and use in source and binary forms, with or without
008     * modification, are permitted provided that the following conditions
009     * are met:
010     * 1. Redistributions of source code must retain the above copyright
011     *    notice, this list of conditions and the following disclaimer.
012     * 2. Redistributions in binary form must reproduce the above copyright
013     *    notice, this list of conditions and the following disclaimer in the
014     *    documentation and/or other materials provided with the distribution.
015     * 3. Neither the name of the copyright owner nor the names of contributors
016     *    may be used to endorse or promote products derived from this software
017     *    without specific prior written permission.
018     *
019     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
023     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
024     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
025     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
026     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
027     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
029     * POSSIBILITY OF SUCH DAMAGE.
030     */
031    package com.threerings.jpkg.ant.dpkg.permissions;
032    
033    import java.util.List;
034    
035    import com.threerings.antidote.SetStatus;
036    import com.threerings.antidote.field.ListField;
037    import com.threerings.antidote.property.BooleanProperty;
038    import com.threerings.antidote.property.IntegerProperty;
039    import com.threerings.antidote.property.StringProperty;
040    import com.threerings.jpkg.PathPermissions;
041    
042    import static com.threerings.antidote.MutabilityHelper.areMutablesSet;
043    import static com.threerings.antidote.MutabilityHelper.objectIsNotSet;
044    import static com.threerings.antidote.MutabilityHelper.requiresValidation;
045    
046    
047    /**
048     * The <permission> child field type for the <dpkg> <permissions> field. Describes permissions
049     * for the permissions map.
050     * @see PathPermissions
051     */
052    public class Permission extends ListField<Path>
053    {
054        // from Field
055        public String getFieldName ()
056        {
057            return "permission";
058        }
059    
060        @Override // from ListField
061        public String getChildFieldName ()
062        {
063            return "path";
064        }
065    
066        /**
067         * Ant setter field: user.
068         */
069        public void setUser (String value)
070        {
071            _user.setValue(value);
072        }
073    
074        /**
075         * Ant setter field: group.
076         */
077        public void setGroup (String value)
078        {
079            _group.setValue(value);
080        }
081    
082        /**
083         * Ant setter field: userId.
084         */
085        public void setUserId (String value)
086        {
087            _userId.setValue(value);
088        }
089    
090        /**
091         * Ant setter field: groupId.
092         */
093        public void setGroupId (String value)
094        {
095            _groupId.setValue(value);
096        }
097    
098        /**
099         * Ant setter field: mode.
100         */
101        public void setMode (String value)
102        {
103            _mode.setValue(value);
104        }
105    
106        /**
107         * Ant setter field: recursive.
108         */
109        public void setRecursive (String value)
110        {
111            _recursive.setValue(value);
112        }
113    
114        /**
115         * Ant adder field: Add a {@link Path}.
116         */
117        public void addPath (Path path)
118        {
119            appendRequiresValidation(path);
120        }
121    
122        /**
123         * Return the user supplied fields as a {@link PathPermissions} object.
124         */
125        public PathPermissions getPathPermissions ()
126        {
127            requiresValidation(_pathPermissions);
128            return _pathPermissions;
129        }
130    
131        /**
132         * Return the list of Paths declared for this Permission.
133         */
134        public List<Path> getPaths ()
135        {
136            requiresValidation(_validatedPaths);
137            return _validatedPaths;
138        }
139    
140        @Override // from BaseComponent
141        protected void validateField ()
142        {
143            // validate the required properties. recursive defaults to false if not set.
144            switch (validateProperties(_mode, _recursive)) {
145                case ALL_INVALID:
146                case SOME_INVALID:
147                    // fail now if required properties are not valid otherwise broken PathPermissions
148                    // objects will be constructed
149                    return;
150    
151                case ALL_VALID:
152                    break;
153            }
154    
155            // if none of the user/group/userId/groupId fields have been set, then construct
156            // a mode only permission object.
157            if (areMutablesSet(_user, _group, _userId, _groupId) == SetStatus.ALL_UNSET) {
158                _pathPermissions = new PathPermissions(_mode.getValue(), _recursive.getValue());
159    
160            } else {
161                // attempt to set the path permission object from the permission name fields
162                switch (areMutablesSet(_user, _group)) {
163                case ALL_UNSET:
164                    // none of the name fields were set, attempt to set the PathPermissions object
165                    // from the id fields
166                    _pathPermissions = validateIdFields(_mode.getValue(), _recursive.getValue());
167                    break;
168    
169                case SOME_UNSET:
170                    // only some of the name fields were set, validate but we will not get a path
171                    // permissions object so fail now
172                    validateNameFields(_mode.getValue(), _recursive.getValue());
173                    return;
174    
175                case ALL_SET:
176                    // all of the name fields were set, we should have a PathPermissions object now.
177                    _pathPermissions = validateNameFields(_mode.getValue(), _recursive.getValue());
178                    break;
179                }
180            }
181    
182            // if we still don't have a PathPermissions object, fail now
183            if (objectIsNotSet(_pathPermissions)) {
184                return;
185            }
186    
187            // if we have no <path> child fields defined, fail now
188            if (noChildFieldsDefined()) {
189                return;
190            }
191    
192            // validate the child <path> fields
193            switch(validateFieldList()) {
194                case ALL_INVALID:
195                case SOME_INVALID:
196                    return;
197    
198                case ALL_VALID:
199                     _validatedPaths = getValidatedFieldList();
200                    break;
201            }
202        }
203    
204        /**
205         * Validate the user and group fields. Returns a PathPermissions object if one was able
206         * to be created, null otherwise..
207         */
208        private PathPermissions validateNameFields (Integer mode, Boolean recursive)
209        {
210            switch (areMutablesSet(_user, _group)) {
211                case ALL_UNSET:
212                    return null;
213    
214                case SOME_UNSET:
215                    reportUnsetDependentProperties(_user, _group);
216                    reportUnsetDependentProperties(_group, _user);
217                    return null;
218    
219                case ALL_SET:
220                    // report violations if any of the id fields are set
221                    reportConflictingProperties(_userId, _user, _group);
222                    reportConflictingProperties(_groupId, _user, _group);
223    
224                    // continue to validation
225                    break;
226            }
227    
228            switch (validateProperties(_user, _group)) {
229                case ALL_INVALID:
230                case SOME_INVALID:
231                    return null;
232    
233                case ALL_VALID:
234                    return new PathPermissions(_user.getValue(), _group.getValue(), mode, recursive);
235            }
236    
237            // required catch all for switch statement fall-through which should be full enumerated
238            return null;
239        }
240    
241        /**
242         * Validate the userId and groupId fields. Returns a PathPermissions object if one was able
243         * to be created, null otherwise.
244         */
245        private PathPermissions validateIdFields (Integer mode, Boolean recursive)
246        {
247            switch (areMutablesSet(_userId, _groupId)) {
248                case ALL_UNSET:
249                    return null;
250    
251                case SOME_UNSET:
252                    reportUnsetDependentProperties(_userId, _groupId);
253                    reportUnsetDependentProperties(_groupId, _userId);
254                    return null;
255    
256                case ALL_SET:
257                    // report violations if any of the name fields are set
258                    reportConflictingProperties(_user, _userId, _groupId);
259                    reportConflictingProperties(_group, _userId, _groupId);
260    
261                    // continue to validation
262                    break;
263            }
264    
265            switch (validateProperties(_userId, _groupId)) {
266                case ALL_INVALID:
267                case SOME_INVALID:
268                    return null;
269    
270                case ALL_VALID:
271                    return new PathPermissions(_userId.getValue(), _groupId.getValue(), mode, recursive);
272            }
273    
274            // required catch all for switch statement fall-through which should be full enumerated
275            return null;
276        }
277    
278        /** The user supplied fields as a PathPermissions object. */
279        private PathPermissions _pathPermissions;
280    
281        /** The list containing all the paths defined for this Permission after they have been validated. */
282        private List<Path> _validatedPaths;
283    
284        /** Ant adder/setter fields. */
285        private final StringProperty _user = new StringProperty("user", this);
286        private final StringProperty _group = new StringProperty("group", this);
287        private final IntegerProperty _userId = new IntegerProperty("userid", this);
288        private final IntegerProperty _groupId = new IntegerProperty("groupid", this);
289        private final BooleanProperty _recursive = new BooleanProperty("recursive", this, false);
290        private final ModeProperty _mode = new ModeProperty("mode", this);
291    }