/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * 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, or (at your option) any later version. * * 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., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.metadata; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.NavigableMap; import java.util.TreeMap; import org.teiid.connector.DataPlugin; import org.teiid.metadata.Grant.Permission; /** * Simple holder for metadata. */ public class MetadataStore implements Serializable { private static final long serialVersionUID = -3130247626435324312L; protected NavigableMap<String, Schema> schemas = new TreeMap<String, Schema>(String.CASE_INSENSITIVE_ORDER); protected List<Schema> schemaList = new ArrayList<Schema>(); //used for a stable ordering protected NavigableMap<String, Datatype> datatypes = new TreeMap<String, Datatype>(String.CASE_INSENSITIVE_ORDER); protected NavigableMap<String, Datatype> unmondifiableDatatypes = Collections.unmodifiableNavigableMap(datatypes); private Map<String, Grant> grants = new TreeMap<String, Grant>(String.CASE_INSENSITIVE_ORDER); protected LinkedHashMap<String, Role> roles = new LinkedHashMap<String, Role>(); public NavigableMap<String, Schema> getSchemas() { return schemas; } public Schema getSchema(String name) { return this.schemas.get(name); } public void addSchema(Schema schema) { if (this.schemas.put(schema.getName(), schema) != null) { throw new DuplicateRecordException(DataPlugin.Event.TEIID60012, DataPlugin.Util.gs(DataPlugin.Event.TEIID60012, schema.getName())); } this.schemaList.add(schema); } public List<Schema> getSchemaList() { return schemaList; } public Schema removeSchema(String schemaName) { Schema s = this.schemas.remove(schemaName); if ( s != null) { this.schemaList.remove(s); } return s; } public void addDataTypes(Map<String, Datatype> typeMap) { if (typeMap != null){ for (Map.Entry<String, Datatype> entry:typeMap.entrySet()) { addDatatype(entry.getKey(), entry.getValue()); } } } public void addDatatype(String name, Datatype datatype) { if (!this.datatypes.containsKey(name)) { this.datatypes.put(name, datatype); } } public NavigableMap<String, Datatype> getDatatypes() { return unmondifiableDatatypes; } /** * Get the type information excluding aliases and case sensitive by name * @return */ public NavigableMap<String, Datatype> getDatatypesExcludingAliases() { TreeMap<String, Datatype> result = new TreeMap<String, Datatype>(); for (Map.Entry<String, Datatype> entry : this.datatypes.entrySet()) { if (entry.getKey().equals(entry.getValue().getName())) { result.put(entry.getKey(), entry.getValue()); } } return result; } public void merge(MetadataStore store) { if (store != null) { for (Schema s:store.getSchemaList()) { addSchema(s); } addDataTypes(store.getDatatypes()); addGrants(store.grants.values()); roles.putAll(store.roles); } } void addGrants(Collection<Grant> grants) { if (grants == null) { return; } for (Grant g:grants) { addGrant(g); } } void addGrant(Grant grant) { if (grant == null) { return; } Grant previous = this.grants.get(grant.getRole()); if (previous == null) { this.grants.put(grant.getRole(), grant); } else { for (Permission addPermission : grant.getPermissions()) { boolean found = false; for (Permission currentPermission : new ArrayList<Permission>(previous.getPermissions())) { if (currentPermission.resourceMatches(addPermission)) { found = true; if (addPermission.getMask() != null) { if (currentPermission.getMask() != null) { throw new MetadataException(DataPlugin.Event.TEIID60035, DataPlugin.Util.gs(DataPlugin.Event.TEIID60035, addPermission.getMask(), currentPermission.getMask())); } currentPermission.setMask(addPermission.getMask()); currentPermission.setMaskOrder(addPermission.getMaskOrder()); } if (addPermission.getCondition() != null) { if (currentPermission.getCondition() != null) { throw new MetadataException(DataPlugin.Event.TEIID60036, DataPlugin.Util.gs(DataPlugin.Event.TEIID60036, addPermission.getMask(), currentPermission.getMask())); } currentPermission.setCondition(addPermission.getCondition(), addPermission.isConditionAConstraint()); } currentPermission.appendPrivileges(addPermission.getPrivileges()); } if (currentPermission.getPrivileges().isEmpty() && currentPermission.getRevokePrivileges().isEmpty() && currentPermission.getCondition() == null && currentPermission.getMask() == null) { previous.removePermission(currentPermission); } if (found) { break; } } if (!found) { previous.addPermission(addPermission); } } if (previous.getPermissions().isEmpty()) { this.grants.remove(grant.getRole()); } } } public void removeGrant(Grant toRemoveGrant) { if (toRemoveGrant == null) { return; } Grant previous = this.grants.get(toRemoveGrant.getRole()); if (previous == null) { this.grants.put(toRemoveGrant.getRole(), toRemoveGrant); } else { for (Permission revokePermission : toRemoveGrant.getPermissions()) { boolean found = false; for (Permission currentPermission : new ArrayList<Permission>(previous.getPermissions())) { if (currentPermission.resourceMatches(revokePermission)) { found = true; if (revokePermission.getMask() != null) { if (currentPermission.getMask() != null) { currentPermission.setMask(null); currentPermission.setMaskOrder(null); } else { //TODO: could be exception } } if (revokePermission.getCondition() != null) { if (currentPermission.getCondition() != null) { currentPermission.setCondition(null, null); } else { //TODO: could be exception } } currentPermission.removePrivileges(revokePermission.getRevokePrivileges()); } if (currentPermission.getPrivileges().isEmpty() && currentPermission.getRevokePrivileges().isEmpty() && currentPermission.getCondition() == null && currentPermission.getMask() == null) { previous.removePermission(currentPermission); } if (found) { break; } } if (!found) { previous.addPermission(revokePermission); } } if (previous.getPermissions().isEmpty()) { this.grants.remove(toRemoveGrant.getRole()); } } } public Collection<Grant> getGrants() { return this.grants.values(); } void addRole(Role role) { this.roles.put(role.getName(), role); } Role getRole(String roleName) { return this.roles.get(roleName); } Collection<Role> getRoles() { return this.roles.values(); } Role removeRole(String roleName) { return this.roles.remove(roleName); } }