/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.security.impl; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import org.geoserver.security.GeoServerRoleConverter; import org.springframework.security.core.GrantedAuthority; /** * Converts {@link GeoServerRole} and collections of roles into a * string representation and vice versa. * * Default format by example: * * role1;role2;role3 * * Default format with role parameters by example * * role1(param1=value1,param2=value2);role2(param3=value3);role3 * * @author mcr * */ public class GeoServerRoleConverterImpl implements GeoServerRoleConverter { private String roleDelimiterString =";"; private String roleParameterDelimiterString =","; private String roleParameterStartString = "("; private String roleParameterEndString = ")"; private String roleParameterAssignmentString = "="; private boolean checked = false; public String getRoleDelimiterString() { return roleDelimiterString; } public void setRoleDelimiterString(String roleDelimiterString) { this.roleDelimiterString = roleDelimiterString; checked=false; } public String getRoleParameterDelimiterString() { return roleParameterDelimiterString; } public void setRoleParameterDelimiterString(String roleParameterDelimiterString) { this.roleParameterDelimiterString = roleParameterDelimiterString; checked=false; } public String getRoleParameterStartString() { return roleParameterStartString; } public void setRoleParameterStartString(String roleParameterStartString) { this.roleParameterStartString = roleParameterStartString; checked=false; } public String getRoleParameterEndString() { return roleParameterEndString; } public void setRoleParameterEndString(String roleParameterEndString) { this.roleParameterEndString = roleParameterEndString; checked=false; } public String getRoleParameterAssignmentString() { return roleParameterAssignmentString; } public void setRoleParameterAssignmentString(String roleParameterAssignmentString) { this.roleParameterAssignmentString = roleParameterAssignmentString; checked=false; } /* (non-Javadoc) * @see org.geoserver.security.impl.GeoServerRoleConverter#convertRoleToString(org.geoserver.security.impl.GeoServerRole) */ @Override public String convertRoleToString(GeoServerRole role) { checkDelimiters(); StringBuffer buff = new StringBuffer(); writeRole(buff, role); return buff.toString(); } /** * internal helper method * * @param buff * @param role */ protected void writeRole(StringBuffer buff,GeoServerRole role) { buff.append(role.getAuthority()); Properties props = role.getProperties(); if (props == null || props.isEmpty()) return; buff.append(getRoleParameterStartString()); boolean firstTime=true; for (Entry<Object,Object> entry : props.entrySet()) { if (firstTime==true) firstTime=false; else buff.append(getRoleParameterDelimiterString()); buff.append(entry.getKey()).append(getRoleParameterAssignmentString()); buff.append(entry.getValue()==null ? "" : entry.getValue()); } buff.append(getRoleParameterEndString()); } /* (non-Javadoc) * @see org.geoserver.security.impl.GeoServerRoleConverter#convertRolesToString(java.util.Collection) */ @Override public String convertRolesToString(Collection<? extends GrantedAuthority> roles) { checkDelimiters(); StringBuffer buff = new StringBuffer(); boolean firstTime=true; for (GrantedAuthority role : roles) { if (firstTime==true) firstTime=false; else buff.append(getRoleDelimiterString()); writeRole(buff, (GeoServerRole)role); } return buff.toString(); } /** * internal helper method to split strings based on * delimiter strings * * @param theString * @param delim * */ protected List<String> splitString(String theString, String delim) { List<String> result = new ArrayList<String>(); int startIndex = 0; while (true) { int index = theString.indexOf(delim,startIndex); if (index==-1) { result.add(theString.substring(startIndex)); break; } else { result.add(theString.substring(startIndex,index)); startIndex = index+delim.length(); } } return result; } /* (non-Javadoc) * @see org.geoserver.security.impl.GeoServerRoleConverter#convertRolesFromString(java.lang.String, java.lang.String) */ @Override public Collection<GeoServerRole> convertRolesFromString(String rolesString, String userName) { checkDelimiters(); List<GeoServerRole> roles = new ArrayList<GeoServerRole>(); List<String> working = splitString(rolesString,getRoleDelimiterString()); for (String roleString: working) { GeoServerRole role = convertRoleFromString(roleString, userName); if (role!=null) roles.add(role); } return roles; } /* (non-Javadoc) * @see org.geoserver.security.impl.GeoServerRoleConverter#convertRoleFromString(java.lang.String, java.lang.String) */ @Override public GeoServerRole convertRoleFromString(String roleString, String userName) { if (roleString == null) return null; roleString=roleString.trim(); if (roleString.isEmpty()) return null; checkDelimiters(); List<String> working = splitString(roleString.trim(),getRoleParameterStartString()); GeoServerRole result= new GeoServerRole(working.get(0)); if (working.size()==1) { return result; } // we have role parameters result.setUserName(userName); if (working.get(1).endsWith(getRoleParameterEndString())==false) throw createExcpetion(roleString+ " does not end with "+ getRoleParameterEndString()); int index = working.get(1).lastIndexOf(getRoleParameterEndString()); String roleParamString = working.get(1).substring(0, index).trim(); working = splitString(roleParamString,getRoleParameterDelimiterString()); for (String kvp : working) { List<String> tmp = splitString(kvp.trim(), getRoleParameterAssignmentString()); if (tmp.size()!=2) throw createExcpetion(roleString+ " Invalid role string: "+roleString); result.getProperties().put(tmp.get(0).trim(), tmp.get(1).trim()); } return result; } /** * internal method the check for proper delimter strings */ protected void checkDelimiters() { if (checked) return; if (roleDelimiterString==null || roleDelimiterString.isEmpty()) throw createExcpetion("Missing roleDelimiterString"); if (roleParameterDelimiterString ==null || roleParameterDelimiterString.isEmpty()) throw createExcpetion("Missing roleParameterDelimiterString"); if (roleParameterStartString ==null || roleParameterStartString.isEmpty()) throw createExcpetion("Missing roleParameterStartString"); if (roleParameterEndString ==null || roleParameterEndString.isEmpty()) throw createExcpetion("Missing roleParameterEndString"); if (roleParameterAssignmentString ==null || roleParameterAssignmentString.isEmpty()) throw createExcpetion("Missing roleParameterAssignmentString"); Set<String> set= new HashSet<String>(); set.add(roleDelimiterString); set.add(roleParameterDelimiterString); set.add(roleParameterStartString); set.add(roleParameterEndString); set.add(roleParameterAssignmentString); if (set.size()< 5) throw createExcpetion("Delimiters must be unique"); checked=true; } protected RuntimeException createExcpetion(String msg) { return new RuntimeException(msg); } }