/* Copyright (c) 2008 Health Market Science, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA You can contact Health Market Science at info@healthmarketscience.com or at the following address: Health Market Science 2700 Horizon Drive Suite 200 King of Prussia, PA 19406 */ package com.healthmarketscience.sqlbuilder; import java.io.IOException; import com.healthmarketscience.common.util.AppendableExt; import com.healthmarketscience.sqlbuilder.dbspec.Column; import com.healthmarketscience.sqlbuilder.dbspec.Table; /** * Base of a query which generates a query for manipulating privileges. Keeps * track of the privileges, grantees, and target object. * * @author James Ahlborn */ public abstract class BaseGrantQuery<ThisType extends BaseGrantQuery<ThisType>> extends Query<ThisType> { /** grantee object which represents PUBLIC access */ public static final SqlObject PUBLIC_GRANTEE = new CustomSql("PUBLIC"); private static final Privilege PRIVILEGE_ALL = new Privilege(Privilege.Type.ALL); private static final Privilege PRIVILEGE_SELECT = new Privilege(Privilege.Type.SELECT); private static final Privilege PRIVILEGE_DELETE = new Privilege(Privilege.Type.DELETE); private static final Privilege PRIVILEGE_USAGE = new Privilege(Privilege.Type.USAGE); protected SqlObjectList<SqlObject> _grantees = SqlObjectList.create(); protected SqlObjectList<SqlObject> _privileges = SqlObjectList.create(); protected SqlObject _targetObj; protected BaseGrantQuery() { } /** * Adds the given custom grantees to the query * <p> * {@code Object} -> {@code SqlObject} conversions handled by * {@link Converter#CUSTOM_TO_OBJ}. */ public ThisType addCustomGrantees(Object... grantees) { _grantees.addObjects(Converter.CUSTOM_TO_OBJ, grantees); return getThisType(); } /** Adds the given grantees to the query */ public ThisType addGrantees(String... grantees) { return addCustomGrantees((Object[])grantees); } /** * Adds the given privileges to the query. Generally this should be an * instance of a {@link Privilege} object, created by one of the static * <code>privilege*</code> methods. * <p> * {@code Object} -> {@code SqlObject} conversions handled by * {@link Converter#CUSTOM_TO_OBJ}. */ public ThisType addCustomPrivileges(Object... privileges) { _privileges.addObjects(Converter.CUSTOM_TO_OBJ, privileges); return getThisType(); } /** Adds the given privileges to the query. Generally this should be an instance of a {@link Privilege} object, created by one of the static <code>privilege*</code> methods. */ public ThisType addPrivileges(Privilege... privileges) { return addCustomPrivileges((Object[])privileges); } /** * Sets the target for the query. Generally this should be an * instance of a {@link TargetObject} object, created by one of the static * <code>target*</code> methods. * <p> * {@code Object} -> {@code SqlObject} conversions handled by * {@link Converter#toCustomSqlObject(Object)}. */ public ThisType setCustomTarget(Object target) { _targetObj = Converter.toCustomSqlObject(target); return getThisType(); } /** Sets the target for the query. Generally this should be an instance of a {@link TargetObject} object, created by one of the static <code>target*</code> methods. */ public ThisType setTarget(TargetObject target) { return setCustomTarget(target); } /** @return a Privilege with the type of ALL */ public static Privilege privilegeAll() { return PRIVILEGE_ALL; } /** @return a Privilege with the type of SELECT */ public static Privilege privilegeSelect() { return PRIVILEGE_SELECT; } /** @return a Privilege with the type of DELETE */ public static Privilege privilegeDelete() { return PRIVILEGE_DELETE; } /** @return a Privilege with the type of INSERT and the given (optional) columns */ public static Privilege privilegeInsert(Column... columns) { return new Privilege(Privilege.Type.INSERT, columns); } /** @return a Privilege with the type of UPDATE and the given (optional) columns */ public static Privilege privilegeUpdate(Column... columns) { return new Privilege(Privilege.Type.UPDATE, columns); } /** @return a Privilege with the type of REFERENCES and the given (optional) columns */ public static Privilege privilegeReferences(Column... columns) { return new Privilege(Privilege.Type.REFERENCES, columns); } /** @return a Privilege with the type of USAGE */ public static Privilege privilegeUsage() { return PRIVILEGE_USAGE; } /** @return a TargetObject with the type of TABLE and the given table */ public static TargetObject targetTable(Table table) { return new TargetObject(TargetObject.Type.TABLE, new TableObject(table)); } @Override protected void collectSchemaObjects(ValidationContext vContext) { super.collectSchemaObjects(vContext); _grantees.collectSchemaObjects(vContext); _privileges.collectSchemaObjects(vContext); _targetObj.collectSchemaObjects(vContext); } @Override public void validate(ValidationContext vContext) throws ValidationException { // validate super class super.validate(vContext); // must have privileges if(_privileges.isEmpty()) { throw new ValidationException("Must specify privileges"); } // must have grantees if(_grantees.isEmpty()) { throw new ValidationException("Must specify grantees"); } // if no _targetObj, NPE will be thrown already // cannot have additional privileges with ALL boolean hasAll = false; for(SqlObject privilege : _privileges) { if((privilege instanceof Privilege) && (((Privilege)privilege)._type == Privilege.Type.ALL)) { hasAll = true; break; } } if(hasAll && (_privileges.size() > 1)) { throw new ValidationException("May not have other privileges with ALL"); } } /** * Encapsulation of a database privilege. */ public static class Privilege extends SqlObject { /** Enumeration representing the various database privilege types */ public enum Type { ALL("ALL PRIVILEGES", false), SELECT("SELECT", false), DELETE("DELETE", false), INSERT("INSERT", true), UPDATE("UPDATE", true), REFERENCES("REFERENCES", true), USAGE("USAGE", false); private final String _typeStr; private final boolean _maySpecifyColumns; private Type(String typeStr, boolean maySpecifyColumns) { _typeStr = typeStr; _maySpecifyColumns = maySpecifyColumns; } public boolean maySpecifyColumns() { return _maySpecifyColumns; } @Override public String toString() { return _typeStr; } } private Type _type; private SqlObjectList<SqlObject> _columns = SqlObjectList.create(); public Privilege(Type type, Column... columns) { _type = type; if(_type.maySpecifyColumns()) { _columns.addObjects(Converter.COLUMN_TO_OBJ, columns); } } /** * Adds the given columns to the column list. * <p> * {@code Object} -> {@code SqlObject} conversions handled by * {@link Converter#CUSTOM_COLUMN_TO_OBJ}. */ public Privilege addCustomColumns(Object... columnStrs) { if(_type.maySpecifyColumns()) { _columns.addObjects(Converter.CUSTOM_COLUMN_TO_OBJ, columnStrs); } return this; } /** Adds the given columns to the column list. */ public Privilege addColumns(Column... columns) { return addCustomColumns((Object[])columns); } @Override protected void collectSchemaObjects(ValidationContext vContext) { _columns.collectSchemaObjects(vContext); } @Override public void appendTo(AppendableExt app) throws IOException { app.append(_type); if(!_columns.isEmpty()) { app.append("(").append(_columns).append(")"); } } } /** * Information about the database object upon which a privilege allows (or * disallows) action. */ public static class TargetObject extends SqlObject { /** Enumeration representing the types of database objects which have privileges for interacting with them. */ public enum Type { TABLE("TABLE "), DOMAIN("DOMAIN "), COLLATION("COLLATION "), CHARACTER_SET("CHARACTER SET "), TRANSLATION("TRANSLATION "); private final String _typeStr; private Type(String typeStr) { _typeStr = typeStr; } @Override public String toString() { return _typeStr; } } private Type _type; private SqlObject _name; public TargetObject(Type type, SqlObject name) { _type = type; _name = name; } @Override protected void collectSchemaObjects(ValidationContext vContext) { _name.collectSchemaObjects(vContext); } @Override public void appendTo(AppendableExt app) throws IOException { app.append(_type).append(_name); } } }