/* PermEntry.java This class holds the basic per-object / per-field access control bits. Created: 27 June 1997 Module By: Jonathan Abbey, jonabbey@arlut.utexas.edu ----------------------------------------------------------------------- Ganymede Directory Management System Copyright (C) 1996-2014 The University of Texas at Austin Ganymede is a registered trademark of The University of Texas at Austin Contact information Author Email: ganymede_author@arlut.utexas.edu Email mailing list: ganymede@arlut.utexas.edu US Mail: Computer Science Division Applied Research Laboratories The University of Texas at Austin PO Box 8029, Austin TX 78713-8029 Telephone: (512) 835-3200 This program 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 2 of the License, or (at your option) any later version. This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package arlut.csd.ganymede.common; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import arlut.csd.Util.TranslationService; /*------------------------------------------------------------------------------ class PermEntry ------------------------------------------------------------------------------*/ /** * <p>Serializable and immutable permissions entry object, used to * store and transmit permissions for a specific {@link * arlut.csd.ganymede.server.DBObjectBase DBObjectBase} and {@link * arlut.csd.ganymede.server.DBObjectBaseField DBObjectBaseField}.</p> * * <p>Used in conjunction with * {@link arlut.csd.ganymede.server.PermissionMatrixDBField PermissionMatrixDBField} * and {@link arlut.csd.ganymede.common.PermMatrix PermMatrix} to handle Permissions * in a Role object in the Ganymede server.</p> */ public final class PermEntry implements java.io.Serializable { /** * TranslationService object for handling string localization in * the Ganymede server. */ static final TranslationService ts = TranslationService.getTranslationService("arlut.csd.ganymede.common.PermEntry"); static private final PermEntry[] permObs; static public final PermEntry fullPerms; static public final PermEntry noPerms; static public final PermEntry viewPerms; static public final PermEntry createPerms; static { permObs = new PermEntry[16]; permObs[0] = new PermEntry(false, false, false, false); permObs[1] = new PermEntry(true, false, false, false); permObs[2] = new PermEntry(false, true, false, false); permObs[3] = new PermEntry(true, true, false, false); permObs[4] = new PermEntry(false, false, true, false); permObs[5] = new PermEntry(true, false, true, false); permObs[6] = new PermEntry(false, true, true, false); permObs[7] = new PermEntry(true, true, true, false); permObs[8] = new PermEntry(false, false, false, true); permObs[9] = new PermEntry(true, false, false, true); permObs[10] = new PermEntry(false, true, false, true); permObs[11] = new PermEntry(true, true, false, true); permObs[12] = new PermEntry(false, false, true, true); permObs[13] = new PermEntry(true, false, true, true); permObs[14] = new PermEntry(false, true, true, true); permObs[15] = new PermEntry(true, true, true, true); fullPerms = permObs[15]; noPerms = permObs[0]; viewPerms = permObs[1]; createPerms = permObs[4]; // f,f,t,f } static final long serialVersionUID = 1867526089374473743L; public static void main(String argv[]) { PermEntry x = getPermEntry(true, false, false, false); System.err.println(x.union(x)); } /** * <p>This static method returns a reference to an immutable PermEntry * object with the requested privilege bits set.</p> */ public static PermEntry getPermEntry(boolean visible, boolean editable, boolean create, boolean delete) { byte result = 0; /* -- */ if (visible) { result++; } if (editable) { result += 2; } if (create) { result += 4; } if (delete) { result += 8; } return permObs[result]; } /** * <p>This static method returns a reference to an immutable PermEntry * object with the requested privilege bits set.</p> */ public static PermEntry getPermEntry(byte index) { return permObs[index]; } /** * <p>This static method reads a PermEntry object from the given DataInput * stream and returns an immutable PermEntry with the appropriate bits * set.</p> */ public static PermEntry getPermEntry(DataInput in) throws IOException { boolean visible, editable, create, delete; short entrySize; /* -- */ entrySize = in.readShort(); // We use entrySize to support being able to compatibly add extra // perm bits to PermEntry. visible = in.readBoolean(); editable = in.readBoolean(); create = in.readBoolean(); // We added the delete bit after the above three if (entrySize >= 4) { delete = in.readBoolean(); } else { delete = false; } return getPermEntry(visible, editable, create, delete); } // --- private final boolean visible; private final boolean editable; private final boolean create; private final boolean delete; // initialize our transient fields when we're deserialized on the // client. we'll use indexSet to differentiate between index being // zero because we have no permissions and index being zero because // of deserialization private transient byte index = 0; private transient boolean indexSet = false; /* -- */ public PermEntry(boolean visible, boolean editable, boolean create, boolean delete) { this.visible = visible; this.editable = editable; this.create = create; this.delete = delete; calcIndex(); indexSet = true; } public PermEntry(PermEntry orig) { this.visible = orig.visible; this.editable = orig.editable; this.create = orig.create; this.delete = orig.delete; calcIndex(); indexSet = true; } public int hashCode() { return (visible ? 1 : 0) + (editable ? 2 : 0) + (create ? 4: 0) + (delete ? 8 : 0); } public boolean equals(Object obj) { PermEntry pe; /* -- */ if (obj == null) { return false; } if (!(obj.getClass().equals(this.getClass()))) { return false; } pe = (PermEntry) obj; return ((visible == pe.visible) && (editable == pe.editable) && (create == pe.create) && (delete == pe.delete)); } public void emit(DataOutput out) throws IOException { out.writeShort(4); out.writeBoolean(visible); out.writeBoolean(editable); out.writeBoolean(create); out.writeBoolean(delete); } /** * <p>This method returns true if the this entry in a * {@link arlut.csd.ganymede.common.PermMatrix PermMatrix} is granted * visibility privilege.</p> */ public boolean isVisible() { return visible; } /** * <p>This method returns true if the this entry in a * {@link arlut.csd.ganymede.common.PermMatrix PermMatrix} is granted * editing privilege.</p> */ public boolean isEditable() { return editable; } /** * <p>This method returns true if the this entry in a * {@link arlut.csd.ganymede.common.PermMatrix PermMatrix} is granted * creation privilege.</p> */ public boolean isCreatable() { return create; } /** * <p>This method returns true if the this entry in a * {@link arlut.csd.ganymede.common.PermMatrix PermMatrix} is granted * deletion privilege.</p> */ public boolean isDeletable() { return delete; } /** * <p>This method returns a bit coded byte value representing the * permission bits set in this PermEntry object. This byte may * be used to access a pre-allocated PermEntry object using the * static getPermEntry() method.</p> */ public byte indexNum() { if (!indexSet) { calcIndex(); indexSet = true; } return index; } /** * <p>This method returns an immutable PermEntry that allows all * permissions allowed by the logical union of this PermEntry and * p.</p> */ public final PermEntry union(PermEntry p) { if (p == null) { return this; } byte pVal = p.indexNum(); byte myVal = indexNum(); return permObs[pVal | myVal]; } /** * <p>This method returns an immutable PermEntry that allows all * permissions allowed by the logical intersection of this PermEntry and * p.</p> */ public final PermEntry intersection(PermEntry p) { if (p == null) { return PermEntry.noPerms; } byte pVal = p.indexNum(); byte myVal = indexNum(); return permObs[pVal & myVal]; } /** * <p>This method returns a textual description of the changes * between this PermEntry and <p></p> */ public final String difference(PermEntry p) { StringBuilder result = new StringBuilder(); if (visible && (p == null || !p.visible)) { // "+visible" addString(result, ts.l("difference.addVisible")); } if (p != null && p.visible && !visible) { // "-visible" addString(result, ts.l("difference.remVisible")); } if (editable && (p == null || !p.editable)) { // "+editable" addString(result, ts.l("difference.addEditable")); } if (p != null && p.editable && !editable) { // "-editable" addString(result, ts.l("difference.remEditable")); } if (create && (p == null || !p.create)) { // "+create" addString(result, ts.l("difference.addCreate")); } if (p != null && p.create && !create) { // "-create" addString(result, ts.l("difference.remCreate")); } if (delete && (p == null || !p.delete)) { // "+delete" addString(result, ts.l("difference.addDelete")); } if (p != null && p.delete && !delete) { // "-delete" addString(result, ts.l("difference.remDelete")); } return result.toString(); } private void addString(StringBuilder x, String y) { if (x.length() > 0) { x.append(", "); } x.append(y); } /** * * Diagnostic aid. * */ public String toString() { StringBuilder result = new StringBuilder(); if (visible) { // "visible" result.append(ts.l("toString.visible")); result.append(" "); } if (editable) { // "editable" result.append(ts.l("toString.editable")); result.append(" "); } if (create) { // "create" result.append(ts.l("toString.create")); result.append(" "); } if (delete) { // "delete" result.append(ts.l("toString.delete")); } return result.toString().trim(); } public String getXMLCode() { StringBuilder result = new StringBuilder(); if (visible) { result.append("V"); } if (editable) { result.append("E"); } if (create) { result.append("C"); } if (delete) { result.append("D"); } return result.toString(); } private void calcIndex() { index = 0; if (visible) { index++; } if (editable) { index += 2; } if (create) { index += 4; } if (delete) { index += 8; } } }