com.quartercode.disconnected.sim.comp.file.FileRights.java Source code

Java tutorial

Introduction

Here is the source code for com.quartercode.disconnected.sim.comp.file.FileRights.java

Source

/*
 * This file is part of Disconnected.
 * Copyright (c) 2013 QuarterCode <http://www.quartercode.com/>
 *
 * Disconnected is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Disconnected is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Disconnected. If not, see <http://www.gnu.org/licenses/>.
 */

package com.quartercode.disconnected.sim.comp.file;

import java.util.Arrays;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.apache.commons.lang.Validate;

/**
 * File rights control the access to files by users.
 * You can set if a given user/group is allowed to read, write, execute or delete.
 */
@XmlJavaTypeAdapter(FileRights.FileRightsAdapter.class)
public class FileRights {

    /**
     * The file accessor represents the type of person who accesses a file in its context.
     */
    public static enum FileAccessor {

        /**
         * The owner of the file is the user who created it (the owner can be changed).
         */
        OWNER,
        /**
         * By default, this is the primary group of the creator of the file (the group can be changed).
         */
        GROUP,
        /**
         * Everyone else (not owner or group).
         */
        OTHERS;

    }

    /**
     * This enum stores all types of file rights which can be assigned.
     */
    public static enum FileRight {

        /**
         * The read-right determinates if a user is allowed to read the contents from a file or directory (letter 'r').
         */
        READ('r'),
        /**
         * The write-right determinates if a user is allowed to write contents into files or create new files in a directory (letter 'w').
         */
        WRITE('w'),
        /**
         * The delete-right determinates if a user is allowed to delete a file or a directory (letter 'e').
         * In the case of a directory, the user also needs the delete-right on every file or folder in it.
         */
        DELETE('d'),
        /**
         * The execute-right determinates if a user is allowed to execute a file (letter 'x').
         * It cannot be applied to directories.
         */
        EXECUTE('x'),
        /**
         * The execute-extended-right is equally to the setuid/setgid-flag on UNIX-systems.
         * It allows to execute files as the owner or the group of the file.
         */
        EXECUTE_EXTENDED('s');

        private char letter;

        private FileRight(char letter) {

            this.letter = letter;
        }

        /**
         * Returns the letter which can be used as an acronym for the right.
         * 
         * @return The letter which can be used as an acronym for the right.
         */
        public char getLetter() {

            return letter;
        }

    }

    private FileRight[] ownerRights;
    private FileRight[] groupRights;
    private FileRight[] othersRights;

    /**
     * Creates a new empty file rights storage.
     * This is only recommended for direct field access (e.g. for serialization).
     */
    protected FileRights() {

    }

    public FileRights(FileRight[] ownerRights, FileRight[] groupRights, FileRight[] othersRights) {

        Validate.isTrue(ownerRights.length == 4, "Owner right array must contain 4 elements");
        Validate.isTrue(groupRights.length == 4, "Group right array must contain 4 elements");
        Validate.isTrue(othersRights.length == 4, "Others right array must contain 4 elements");

        this.ownerRights = othersRights;
        this.groupRights = groupRights;
        this.othersRights = othersRights;
    }

    /**
     * Creates a new file rights storage using the given file right string.
     * This is using the typcial UNIX-format with some changes. Examples:
     * 
     * <pre>
     * rwdsr--xr--x
     * rwdxrwdx----
     * </pre>
     * 
     * You can split the string into 3 segments.
     * 
     * <pre>
     * rwds | r--x | r--x
     * rwdx | rwdx | ----
     * </pre>
     * 
     * The first segment defines the rights for the owner, the second for the group and the third for everyone else.
     * 
     * A "r" means that you can read from the file or directory.
     * A "w" means that you can write content into the file or create new files inside a directory.
     * A "d" means that you can delete the file or directory (if it's empty).
     * A "x" means that you can execute the file.
     * A "s" (replaces "x") meands that you can execute the file as the owner or the group of the file.
     * 
     * @param rights The right information to parse.
     */
    public FileRights(String rights) {

        Validate.isTrue(rights.length() == 4 * 3, "The right string must contain 4 * 3 = 12 characters");

        ownerRights = parseCharRights(rights.substring(0, 4).toCharArray());
        groupRights = parseCharRights(rights.substring(4, 8).toCharArray());
        othersRights = parseCharRights(rights.substring(8, 12).toCharArray());
    }

    private FileRight[] parseCharRights(char[] rights) {

        FileRight[] enumRights = new FileRight[4];
        for (int index = 0; index < rights.length; index++) {
            for (FileRight enumRight : FileRight.values()) {
                if (enumRight.getLetter() == rights[index]) {
                    enumRights[index] = enumRight;
                }
            }
        }
        return enumRights;
    }

    private FileRight[] getRightArray(FileAccessor accessor) {

        if (accessor == FileAccessor.OWNER) {
            return ownerRights;
        } else if (accessor == FileAccessor.GROUP) {
            return groupRights;
        } else if (accessor == FileAccessor.OTHERS) {
            return othersRights;
        } else {
            return null;
        }
    }

    /**
     * Returns if the given right is set for the given file accessor.
     * 
     * @param accessor The accessor who wants to access the file.
     * @param right The file right to test on.
     * @return If the given right is set for the given file accessor.
     */
    public boolean getRight(FileAccessor accessor, FileRight right) {

        for (FileRight setRight : getRightArray(accessor)) {
            if (setRight != null && setRight == right) {
                return true;
            }
        }
        return false;
    }

    /**
     * Sets or unsets the given right for the given file accessor.
     * If a right is set, the given file accessor use functions related to the right.
     * 
     * @param accessor The accessor who wants to access the file.
     * @param right The file right to set or unset.
     * @param set If the given right should be set (true) or unset (false).
     */
    public void setRight(FileAccessor accessor, FileRight right, boolean set) {

        int index = 0;
        if (right == FileRight.READ) {
            index = 0;
        } else if (right == FileRight.WRITE) {
            index = 1;
        } else if (right == FileRight.DELETE) {
            index = 2;
        } else if (right == FileRight.EXECUTE) {
            index = 3;
        } else if (right == FileRight.EXECUTE_EXTENDED) {
            index = 3;
        }

        getRightArray(accessor)[index] = set ? right : null;
    }

    @Override
    public int hashCode() {

        final int prime = 31;
        int result = 1;
        result = prime * result + Arrays.hashCode(groupRights);
        result = prime * result + Arrays.hashCode(othersRights);
        result = prime * result + Arrays.hashCode(ownerRights);
        return result;
    }

    @Override
    public boolean equals(Object obj) {

        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        FileRights other = (FileRights) obj;
        if (!Arrays.equals(groupRights, other.groupRights)) {
            return false;
        }
        if (!Arrays.equals(othersRights, other.othersRights)) {
            return false;
        }
        if (!Arrays.equals(ownerRights, other.ownerRights)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {

        return generateRightString(ownerRights) + generateRightString(groupRights)
                + generateRightString(othersRights);
    }

    private String generateRightString(FileRight[] rights) {

        String rightString = "";
        for (FileRight right : rights) {
            rightString += right.getLetter();
        }
        return rightString;
    }

    /**
     * This file rights adapter is for storing a file rights object as a simple string.
     * This is using the typcial UNIX-format with some changes. Examples:
     * 
     * <pre>
     * rwdsr--xr--x
     * rwdxrwdx----
     * </pre>
     * 
     * You can split the string into 3 segments.
     * 
     * <pre>
     * rwds | r--x | r--x
     * rwdx | rwdx | ----
     * </pre>
     * 
     * The first segment defines the rights for the owner, the second for the group and the third for everyone else.
     * 
     * A "r" means that you can read from the file or directory.
     * A "w" means that you can write content into the file or create new files inside a directory.
     * A "d" means that you can delete the file or directory (if it's empty).
     * A "x" means that you can execute the file.
     * A "s" (replaces "x") meands that you can execute the file as the owner or the group of the file.
     */
    public static class FileRightsAdapter extends XmlAdapter<String, FileRights> {

        /**
         * Creates a new file rights adapter.
         */
        public FileRightsAdapter() {

        }

        @Override
        public FileRights unmarshal(String v) {

            return new FileRights(v);
        }

        @Override
        public String marshal(FileRights v) {

            return v.toString();
        }

    }

}