/* * eXist Open Source Native XML Database * Copyright (C) 2001-06 The eXist Project * http://exist-db.org * * This program 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 * 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * $Id$ */ package org.exist.client.xacml; import java.net.URI; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.TableModel; import org.apache.log4j.Logger; import org.exist.security.xacml.XACMLConstants; import org.exist.security.xacml.XACMLUtil; import com.sun.xacml.TargetMatch; import com.sun.xacml.UnknownIdentifierException; import com.sun.xacml.attr.AttributeDesignator; import com.sun.xacml.attr.AttributeValue; import com.sun.xacml.cond.Evaluatable; import com.sun.xacml.cond.Function; import com.sun.xacml.cond.FunctionFactory; import com.sun.xacml.cond.FunctionTypeException; public class TargetTableModel implements TableModel { private static final Logger LOG = Logger.getLogger(TargetTableModel.class); private static final String UNSPECIFIED = "[match all]"; private static final AttributeDesignator[] SUBJECT_ATTRIBUTES; private static final AttributeDesignator[] ACTION_ATTRIBUTES; private static final AttributeDesignator[] RESOURCE_ATTRIBUTES; private static final AttributeDesignator[] ENVIRONMENT_ATTRIBUTES; static { SUBJECT_ATTRIBUTES = new AttributeDesignator[4]; SUBJECT_ATTRIBUTES[0] = new AttributeDesignator(AttributeDesignator.SUBJECT_TARGET, XACMLConstants.STRING_TYPE, XACMLConstants.SUBJECT_ID_ATTRIBUTE, false); SUBJECT_ATTRIBUTES[1] = new AttributeDesignator(AttributeDesignator.SUBJECT_TARGET, XACMLConstants.URI_TYPE, XACMLConstants.SUBJECT_NS_ATTRIBUTE, false); SUBJECT_ATTRIBUTES[2] = new AttributeDesignator(AttributeDesignator.SUBJECT_TARGET, XACMLConstants.STRING_TYPE, XACMLConstants.GROUP_ATTRIBUTE, false); SUBJECT_ATTRIBUTES[3] = new AttributeDesignator(AttributeDesignator.SUBJECT_TARGET, XACMLConstants.STRING_TYPE, XACMLConstants.USER_NAME_ATTRIBUTE, false); ACTION_ATTRIBUTES = new AttributeDesignator[2]; ACTION_ATTRIBUTES[0] = new AttributeDesignator(AttributeDesignator.ACTION_TARGET, XACMLConstants.STRING_TYPE, XACMLConstants.ACTION_ID_ATTRIBUTE, false); ACTION_ATTRIBUTES[1] = new AttributeDesignator(AttributeDesignator.ACTION_TARGET, XACMLConstants.URI_TYPE, XACMLConstants.ACTION_NS_ATTRIBUTE, false); RESOURCE_ATTRIBUTES = new AttributeDesignator[6]; RESOURCE_ATTRIBUTES[0] = new AttributeDesignator(AttributeDesignator.RESOURCE_TARGET, XACMLConstants.STRING_TYPE, XACMLConstants.RESOURCE_ID_ATTRIBUTE, false); RESOURCE_ATTRIBUTES[1] = new AttributeDesignator(AttributeDesignator.RESOURCE_TARGET, XACMLConstants.URI_TYPE, XACMLConstants.MODULE_NS_ATTRIBUTE, false); RESOURCE_ATTRIBUTES[2] = new AttributeDesignator(AttributeDesignator.RESOURCE_TARGET, XACMLConstants.STRING_TYPE, XACMLConstants.RESOURCE_CATEGORY_ATTRIBUTE, false); RESOURCE_ATTRIBUTES[3] = new AttributeDesignator(AttributeDesignator.RESOURCE_TARGET, XACMLConstants.STRING_TYPE, XACMLConstants.MODULE_CATEGORY_ATTRIBUTE, false); RESOURCE_ATTRIBUTES[4] = new AttributeDesignator(AttributeDesignator.RESOURCE_TARGET, XACMLConstants.STRING_TYPE, XACMLConstants.SOURCE_KEY_ATTRIBUTE, false); RESOURCE_ATTRIBUTES[5] = new AttributeDesignator(AttributeDesignator.RESOURCE_TARGET, XACMLConstants.STRING_TYPE, XACMLConstants.SOURCE_TYPE_ATTRIBUTE, false); ENVIRONMENT_ATTRIBUTES = new AttributeDesignator[4]; ENVIRONMENT_ATTRIBUTES[0] = new AttributeDesignator(AttributeDesignator.ENVIRONMENT_TARGET, XACMLConstants.DATE_TYPE, XACMLConstants.CURRENT_DATE_ATTRIBUTE, false); ENVIRONMENT_ATTRIBUTES[1] = new AttributeDesignator(AttributeDesignator.ENVIRONMENT_TARGET, XACMLConstants.TIME_TYPE, XACMLConstants.CURRENT_TIME_ATTRIBUTE, false); ENVIRONMENT_ATTRIBUTES[2] = new AttributeDesignator(AttributeDesignator.ENVIRONMENT_TARGET, XACMLConstants.DATETIME_TYPE, XACMLConstants.CURRENT_DATETIME_ATTRIBUTE, false); ENVIRONMENT_ATTRIBUTES[3] = new AttributeDesignator(AttributeDesignator.ENVIRONMENT_TARGET, XACMLConstants.STRING_TYPE, XACMLConstants.ACCESS_CONTEXT_ATTRIBUTE, false); } private int type; private List listeners; private AttributeDesignator[] attributes; private Abbreviator abbrev; private AttributeValue[][] values; private URI[][] functions; private TargetTableModel() {} public TargetTableModel(int type, Abbreviator abbrev) { this.abbrev = abbrev; this.type = type; attributes = getAttributes(type); values = new AttributeValue[0][0]; functions = new URI[0][0]; } private static AttributeDesignator[] getAttributes(int type) { switch(type) { case AttributeDesignator.ACTION_TARGET: return ACTION_ATTRIBUTES; case AttributeDesignator.RESOURCE_TARGET: return RESOURCE_ATTRIBUTES; case AttributeDesignator.SUBJECT_TARGET: return SUBJECT_ATTRIBUTES; case AttributeDesignator.ENVIRONMENT_TARGET: return ENVIRONMENT_ATTRIBUTES; default: throw new IllegalArgumentException("Invalid target type"); } } //TableModel method implementations public int getColumnCount() { return attributes.length; } public int getRowCount() { return values.length + 1; } public boolean isCellEditable(int row, int col) { return false; } public Class getColumnClass(int col) { return String.class; } public Object getValueAt(int row, int col) { if(row == values.length) return ""; AttributeValue value = values[row][col]; if(value == null) return UNSPECIFIED; URI functionId = functions[row][col]; if(functionId == null) return UNSPECIFIED; String functionString = abbrev.getAbbreviatedTargetFunctionId(functionId, attributes[col].getType()); if(functionString == null) { LOG.warn("Abbreviated function string was unexpectedly null. FunctionId URI was '" + functionId + "' (Row " + row + ", column " + col + ")"); return UNSPECIFIED; } String stringValue = value.encode(); if(stringValue == null) { LOG.warn("String representation of a non-null attribute value was unexpectedly null. (Row " + row + ", column " + col + ")"); return UNSPECIFIED; } return "<html>" + XACMLUtil.XMLEscape(functionString) + " <b>" + XACMLUtil.XMLEscape(stringValue) + "</b>"; } public void setValueAt(Object value, int row, int col) { //do nothing } public AttributeDesignator getAttribute(int col) { return attributes[col]; } public URI getFunctionId(int row, int col) { return (row == values.length) ? null : functions[row][col]; } public AttributeValue getValue(int row, int col) { return (row == values.length) ? null : values[row][col]; } public void setValue(URI functionId, AttributeValue value, int row, int col) { TableModelEvent event; if(row == values.length) { if(value != null) { //add a new row if a value was entered into the last row addRow(); event = new TableModelEvent(this, row, row, TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT); } else return; } else event = new TableModelEvent(this, row, row, col, TableModelEvent.UPDATE); values[row][col] = value; functions[row][col] = functionId; //remove row if empty if(value == null && row < values.length) { boolean empty = true; for(int i = 0; i < attributes.length && empty; ++i) { if(values[row][i] != null) empty = false; } if(empty) { removeRow(row); return; } } fireTableChanged(event); } private void addRow() { URI[][] newF = new URI[functions.length + 1][]; System.arraycopy(functions, 0, newF, 0, functions.length); newF[functions.length] = new URI[attributes.length]; functions = newF; AttributeValue[][] newV = new AttributeValue[values.length + 1][]; System.arraycopy(values, 0, newV, 0, values.length); newV[values.length] = new AttributeValue[attributes.length]; values = newV; } public void removeRow(int row) { if(functions.length == 0 || functions.length >= row || row < 0) return; int row1 = row+1; URI[][] newF = new URI[functions.length - 1][]; System.arraycopy(functions, 0, newF, 0, row); System.arraycopy(functions, row1, newF, row1, functions.length - row1); functions = newF; AttributeValue[][] newV = new AttributeValue[values.length - 1][]; System.arraycopy(values, 0, newV, 0, row); System.arraycopy(values, row1, newV, row1, values.length - row1); values = newV; TableModelEvent event = new TableModelEvent(this, row, row, TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE); fireTableChanged(event); } public void setTarget(List target) { int length = (target == null) ? 0 : target.size(); functions = new URI[length][attributes.length]; values = new AttributeValue[length][attributes.length]; for(int i = 0; i < length; ++i) { List matches = (List)target.get(i); int col = -1; for(Iterator it = matches.iterator(); it.hasNext() && col < 0;) { TargetMatch match = (TargetMatch)it.next(); Evaluatable attribute = match.getMatchEvaluatable(); if(attribute instanceof AttributeDesignator) { col = getIndex((AttributeDesignator)attribute); if(col >= 0) setValue(i, col, match); } } } fireTableChanged(new TableModelEvent(this)); } private void fireTableChanged(TableModelEvent event) { if(listeners == null) return; for(Iterator it = listeners.iterator(); it.hasNext();) ((TableModelListener)it.next()).tableChanged(event); } public List createTarget() { List list = new ArrayList(values.length); for(int row = 0; row < values.length; ++row) { List matches = new ArrayList(attributes.length); for(int col = 0; col < attributes.length; ++col) { AttributeValue value = values[row][col]; URI functionId = functions[row][col]; if(value != null && functionId != null) { Function f; try { f = FunctionFactory.getTargetInstance().createFunction(functionId); if(f != null) matches.add(new TargetMatch(type, f, attributes[col], value)); } catch (UnknownIdentifierException e) { LOG.warn(e); } catch (FunctionTypeException e) { LOG.warn(e); } } } if(matches.size() > 0) list.add(matches); } return (list.size() > 0) ? list : null; } public void setValue(int row, int col, TargetMatch match) { AttributeValue value = match.getMatchValue(); URI functionId = match.getMatchFunction().getIdentifier(); setValue(functionId, value, row, col); } public int getIndex(AttributeDesignator attribute) { for(int i = 0; i < attributes.length; ++i) { if(equals(attribute, (attributes[i]))) return i; } return -1; } public static boolean equals(AttributeDesignator one, AttributeDesignator two) { if(one == null) return two == null; if(two == null) return false; if(!one.getId().equals(two.getId())) return false; if(!one.getType().equals(two.getType())) return false; if(!equals(one.getCategory(), two.getCategory())) return false; if(!equals(one.getIssuer(), two.getIssuer())) return false; return true; } public static boolean equals(URI one, URI two) { if(one == null) return two == null; if(two == null) return false; return one.equals(two); } public String getColumnName(int pos) { URI attributeID = attributes[pos].getId(); return abbrev.getAbbreviatedId(attributeID); } public void addTableModelListener(TableModelListener listener) { if(listener == null) return; if(listeners == null) listeners = new ArrayList(2); listeners.add(listener); } public void removeTableModelListener(TableModelListener listener) { if(listeners == null || listener == null) return; listeners.remove(listener); } }