Java tutorial
/* Copyright (c) 2001 - 2013 OpenPlans - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.security.xml; import static org.geoserver.security.xml.XMLConstants.A_GROUP_ENABLED_UR; import static org.geoserver.security.xml.XMLConstants.A_GROUP_NAME_UR; import static org.geoserver.security.xml.XMLConstants.A_MEMBER_NAME_UR; import static org.geoserver.security.xml.XMLConstants.A_PROPERTY_NAME_UR; import static org.geoserver.security.xml.XMLConstants.A_USER_ENABLED_UR; import static org.geoserver.security.xml.XMLConstants.A_USER_NAME_UR; import static org.geoserver.security.xml.XMLConstants.A_USER_PASSWORD_UR; import static org.geoserver.security.xml.XMLConstants.A_VERSION_UR; import static org.geoserver.security.xml.XMLConstants.E_GROUPS_UR; import static org.geoserver.security.xml.XMLConstants.E_GROUP_UR; import static org.geoserver.security.xml.XMLConstants.E_MEMBER_UR; import static org.geoserver.security.xml.XMLConstants.E_PROPERTY_UR; import static org.geoserver.security.xml.XMLConstants.E_USERREGISTRY_UR; import static org.geoserver.security.xml.XMLConstants.E_USERS_UR; import static org.geoserver.security.xml.XMLConstants.E_USER_UR; import static org.geoserver.security.xml.XMLConstants.NS_UR; import static org.geoserver.security.xml.XMLConstants.VERSION_UR_1_0; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.SortedSet; import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.io.IOUtils; import org.geoserver.security.GeoServerUserGroupService; import org.geoserver.security.file.LockFile; import org.geoserver.security.impl.AbstractUserGroupStore; import org.geoserver.security.impl.GeoServerUser; import org.geoserver.security.impl.GeoServerUserGroup; import org.geoserver.security.validation.PasswordPolicyException; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * @author christian * */ public class XMLUserGroupStore extends AbstractUserGroupStore { static Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geoserver.security.xml"); protected File userFile; protected LockFile lockFile = null; /** * Validate against schema on load/store, * default = true; */ private boolean validatingXMLSchema = true; public boolean isValidatingXMLSchema() { return validatingXMLSchema; } public void setValidatingXMLSchema(boolean validatingXMLSchema) { this.validatingXMLSchema = validatingXMLSchema; } /* (non-Javadoc) * @see org.geoserver.security.GeoserverUserGroupStore#initializeFromServer(org.geoserver.security.GeoserverUserGroupService) */ public void initializeFromService(GeoServerUserGroupService service) throws IOException { this.userFile = ((XMLUserGroupService) service).userFile; this.validatingXMLSchema = ((XMLUserGroupService) service).isValidatingXMLSchema(); super.initializeFromService(service); } /* (non-Javadoc) * @see org.geoserver.security.impl.AbstractUserGroupStore#serialize() */ @Override protected void serialize() throws IOException { DocumentBuilder builder = null; try { DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance(); builder = fac.newDocumentBuilder(); } catch (ParserConfigurationException e1) { throw new IOException(e1); } Document doc = builder.newDocument(); Element userreg = doc.createElement(E_USERREGISTRY_UR); doc.appendChild(userreg); userreg.setAttribute(javax.xml.XMLConstants.XMLNS_ATTRIBUTE, NS_UR); userreg.setAttribute(A_VERSION_UR, VERSION_UR_1_0); Element users = doc.createElement(E_USERS_UR); userreg.appendChild(users); for (GeoServerUser userObject : helper.userMap.values()) { Element user = doc.createElement(E_USER_UR); users.appendChild(user); user.setAttribute(A_USER_NAME_UR, userObject.getUsername()); if (userObject.getPassword() != null) { user.setAttribute(A_USER_PASSWORD_UR, userObject.getPassword()); } user.setAttribute(A_USER_ENABLED_UR, String.valueOf(userObject.isEnabled())); for (Object key : userObject.getProperties().keySet()) { Element property = doc.createElement(E_PROPERTY_UR); user.appendChild(property); property.setAttribute(A_PROPERTY_NAME_UR, key.toString()); property.setTextContent(userObject.getProperties().getProperty(key.toString())); } } Element groups = doc.createElement(E_GROUPS_UR); userreg.appendChild(groups); for (GeoServerUserGroup groupObject : helper.groupMap.values()) { Element group = doc.createElement(E_GROUP_UR); groups.appendChild(group); group.setAttribute(A_GROUP_NAME_UR, groupObject.getGroupname()); group.setAttribute(A_GROUP_ENABLED_UR, groupObject.isEnabled() ? "true" : "false"); SortedSet<GeoServerUser> userObjects = helper.group_userMap.get(groupObject); if (userObjects != null) { for (GeoServerUser userObject : userObjects) { Element member = doc.createElement(E_MEMBER_UR); group.appendChild(member); member.setAttribute(A_MEMBER_NAME_UR, userObject.getUsername()); } } } // serialize the dom try { // TODO, wait for JAVA 6 // if (isValidatingXMLSchema()) { // XMLValidator.Singleton.validateUserGroupRegistry(doc); // } Transformer tx = TransformerFactory.newInstance().newTransformer(); tx.setOutputProperty(OutputKeys.METHOD, "XML"); tx.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); tx.setOutputProperty(OutputKeys.INDENT, "yes"); OutputStream out = new BufferedOutputStream(new FileOutputStream(userFile)); try { tx.transform(new DOMSource(doc), new StreamResult(out)); out.flush(); } finally { IOUtils.closeQuietly(out); } /* standard java, but there is no possiTbility to set * the number of chars to indent, each line is starting at * column 0 Source source = new DOMSource(doc); Result result = new StreamResult( new OutputStreamWriter(new FileOutputStream(userFile),"UTF-8")); Transformer xformer = TransformerFactory.newInstance().newTransformer(); xformer.setOutputProperty(OutputKeys.INDENT, "yes"); xformer.transform(source, result); */ } catch (Exception e) { throw new IOException(e); } } /* (non-Javadoc) * @see org.geoserver.security.impl.AbstractUserGroupService#deserialize() */ @Override protected void deserialize() throws IOException { super.deserialize(); releaseLock(); } protected void ensureLock() throws IOException { if (lockFile != null) return; // we have one lockFile = new LockFile(userFile); try { lockFile.writeLock(); } catch (IOException ex) { // cannot obtain lock lockFile = null; // assert lockFile == null throw ex; // throw again } } protected void releaseLock() { if (lockFile == null) return; // we have none lockFile.writeUnLock(); lockFile = null; } @Override public String toString() { return getName(); } @Override public void store() throws IOException { ensureLock(); super.store(); releaseLock(); } @Override public void addUser(GeoServerUser user) throws IOException, PasswordPolicyException { ensureLock(); super.addUser(user); } @Override public void addGroup(GeoServerUserGroup group) throws IOException { ensureLock(); super.addGroup(group); } @Override public void updateUser(GeoServerUser user) throws IOException, PasswordPolicyException { ensureLock(); super.updateUser(user); } @Override public void updateGroup(GeoServerUserGroup group) throws IOException { ensureLock(); super.updateGroup(group); } @Override public boolean removeUser(GeoServerUser user) throws IOException { ensureLock(); return super.removeUser(user); } @Override public boolean removeGroup(GeoServerUserGroup group) throws IOException { ensureLock(); return super.removeGroup(group); } @Override public void associateUserToGroup(GeoServerUser user, GeoServerUserGroup group) throws IOException { ensureLock(); super.associateUserToGroup(user, group); } @Override public void disAssociateUserFromGroup(GeoServerUser user, GeoServerUserGroup group) throws IOException { ensureLock(); super.disAssociateUserFromGroup(user, group); } @Override public void clear() throws IOException { ensureLock(); super.clear(); } @Override public GeoServerUser createUserObject(String username, String password, boolean isEnabled) throws IOException { XMLGeoserverUser user = new XMLGeoserverUser(username); user.setEnabled(isEnabled); user.setPassword(password); return user; } }