/* * Copyright 2013 Robert von Burg <eitch@eitchnet.ch> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package li.strolch.privilege.xml; import java.text.MessageFormat; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import li.strolch.privilege.helper.XmlConstants; import li.strolch.privilege.model.IPrivilege; import li.strolch.privilege.model.internal.PrivilegeImpl; import li.strolch.privilege.model.internal.Role; import li.strolch.utils.helper.StringHelper; /** * @author Robert von Burg <eitch@eitchnet.ch> */ public class PrivilegeRolesSaxReader extends DefaultHandler { protected static final Logger logger = LoggerFactory.getLogger(PrivilegeRolesSaxReader.class); private Deque<ElementParser> buildersStack = new ArrayDeque<>(); private List<Role> roles; public PrivilegeRolesSaxReader() { this.roles = new ArrayList<>(); } public List<Role> getRoles() { return this.roles; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals(XmlConstants.XML_ROLE)) { this.buildersStack.push(new RoleParser()); } else if (qName.equals(XmlConstants.XML_PROPERTIES)) { this.buildersStack.push(new PropertyParser()); } if (!this.buildersStack.isEmpty()) this.buildersStack.peek().startElement(uri, localName, qName, attributes); } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (!this.buildersStack.isEmpty()) this.buildersStack.peek().characters(ch, start, length); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (!this.buildersStack.isEmpty()) this.buildersStack.peek().endElement(uri, localName, qName); ElementParser elementParser = null; if (qName.equals(XmlConstants.XML_ROLE)) { elementParser = this.buildersStack.pop(); } else if (qName.equals(XmlConstants.XML_PROPERTIES)) { elementParser = this.buildersStack.pop(); } if (!this.buildersStack.isEmpty() && elementParser != null) this.buildersStack.peek().notifyChild(elementParser); } // <Role name="AppUser"> // <Privilege name="li.strolch.privilege.test.model.TestRestrictable"> // <AllAllowed>true</AllAllowed> // </Privilege> // </Role> // <Role name="system_admin_privileges"> // <Privilege name="li.strolch.privilege.test.model.TestSystemUserAction"> // <AllAllowed>true</AllAllowed> // </Privilege> // <Privilege name="li.strolch.privilege.test.model.TestSystemRestrictable"> // <AllAllowed>true</AllAllowed> // </Privilege> // </Role> public class RoleParser extends ElementParserAdapter { private StringBuilder text; private String roleName; private String privilegeName; private String privilegePolicy; private boolean allAllowed; private Set<String> denyList; private Set<String> allowList; private Map<String, IPrivilege> privileges; public RoleParser() { init(); } private void init() { this.privileges = new HashMap<>(); this.text = null; this.roleName = null; this.privilegeName = null; this.privilegePolicy = null; this.allAllowed = false; this.denyList = new HashSet<>(); this.allowList = new HashSet<>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { this.text = new StringBuilder(); if (qName.equals(XmlConstants.XML_ROLE)) { this.roleName = attributes.getValue(XmlConstants.XML_ATTR_NAME); } else if (qName.equals(XmlConstants.XML_PRIVILEGE)) { this.privilegeName = attributes.getValue(XmlConstants.XML_ATTR_NAME); this.privilegePolicy = attributes.getValue(XmlConstants.XML_ATTR_POLICY); } else if (qName.equals(XmlConstants.XML_ALLOW) || qName.equals(XmlConstants.XML_DENY) || qName.equals(XmlConstants.XML_ALL_ALLOWED)) { // no-op } else { throw new IllegalArgumentException("Unhandled tag " + qName); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (this.text != null) this.text.append(ch, start, length); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (qName.equals(XmlConstants.XML_ALL_ALLOWED)) { this.allAllowed = StringHelper.parseBoolean(this.text.toString().trim()); } else if (qName.equals(XmlConstants.XML_ALLOW)) { this.allowList.add(this.text.toString().trim()); } else if (qName.equals(XmlConstants.XML_DENY)) { this.denyList.add(this.text.toString().trim()); } else if (qName.equals(XmlConstants.XML_PRIVILEGE)) { IPrivilege privilege = new PrivilegeImpl(this.privilegeName, this.privilegePolicy, this.allAllowed, this.denyList, this.allowList); this.privileges.put(this.privilegeName, privilege); this.privilegeName = null; this.privilegePolicy = null; this.allAllowed = false; this.denyList = new HashSet<>(); this.allowList = new HashSet<>(); } else if (qName.equals(XmlConstants.XML_ROLE)) { Role role = new Role(this.roleName, this.privileges); getRoles().add(role); logger.info(MessageFormat.format("New Role: {0}", role)); //$NON-NLS-1$ init(); } } } class PropertyParser extends ElementParserAdapter { // <Property name="organizationalUnit" value="Development" /> public Map<String, String> parameterMap = new HashMap<>(); @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals(XmlConstants.XML_PROPERTY)) { String key = attributes.getValue(XmlConstants.XML_ATTR_NAME); String value = attributes.getValue(XmlConstants.XML_ATTR_VALUE); this.parameterMap.put(key, value); } else if (qName.equals(XmlConstants.XML_PROPERTIES)) { // NO-OP } else { throw new IllegalArgumentException("Unhandled tag " + qName); } } public Map<String, String> getParameterMap() { return this.parameterMap; } } }