/* (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.concurrent; import java.io.IOException; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.SortedSet; import org.geoserver.security.GeoServerUserGroupService; import org.geoserver.security.GeoServerUserGroupStore; import org.geoserver.security.config.SecurityNamedServiceConfig; import org.geoserver.security.event.UserGroupLoadedEvent; import org.geoserver.security.event.UserGroupLoadedListener; import org.geoserver.security.impl.GeoServerUser; import org.geoserver.security.impl.GeoServerUserGroup; import org.springframework.dao.DataAccessException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; /** * This is a wrapper class for a {@link GeoServerUserGroupService} * This wrapper protects internal data structures using read/write locks * * @author christian * */ public class LockingUserGroupService extends AbstractLockingService implements GeoServerUserGroupService, UserGroupLoadedListener { protected Set<UserGroupLoadedListener> listeners = Collections.synchronizedSet(new HashSet<UserGroupLoadedListener>()); /** * Constructor for the locking wrapper * * @param service */ public LockingUserGroupService(GeoServerUserGroupService service) { super(service); service.registerUserGroupLoadedListener(this); } /** * @return the wrapped service */ public GeoServerUserGroupService getService() { return (GeoServerUserGroupService) super.getService(); } @Override public GeoServerUserGroupStore createStore() throws IOException { GeoServerUserGroupStore store = getService().createStore(); return store != null ? new LockingUserGroupStore(store) : null; } /** * READ_LOCK * @see org.geoserver.security.GeoServerUserGroupService#getGroupByGroupname(java.lang.String) */ public GeoServerUserGroup getGroupByGroupname(String groupname) throws IOException{ readLock(); try { return getService().getGroupByGroupname(groupname); } finally { readUnLock(); } } /** * READ_LOCK * @see org.geoserver.security.GeoServerUserGroupService#createUserObject(java.lang.String, java.lang.String, boolean) */ public GeoServerUser createUserObject(String username, String password, boolean isEnabled) throws IOException{ readLock(); try { return getService().createUserObject(username, password, isEnabled); } finally { readUnLock(); } } /** * WRITE_LOCK * @see org.geoserver.security.GeoServerUserGroupService#load() */ public void load() throws IOException { writeLock(); try { getService().load(); } finally { writeUnLock(); } } /** * READ_LOCK * @see org.geoserver.security.GeoServerUserGroupService#getUserByUsername(java.lang.String) */ public GeoServerUser getUserByUsername(String username) throws IOException { readLock(); try { return getService().getUserByUsername(username); } finally { readUnLock(); } } /** * READ_LOCK * @see org.geoserver.security.GeoServerUserGroupService#createGroupObject(java.lang.String, boolean) */ public GeoServerUserGroup createGroupObject(String groupname, boolean isEnabled) throws IOException{ readLock(); try { return getService().createGroupObject(groupname, isEnabled); } finally { readUnLock(); } } /** * READ_LOCK * @see org.geoserver.security.GeoServerUserGroupService#getUsers() */ public SortedSet<GeoServerUser> getUsers() throws IOException{ readLock(); try { return getService().getUsers(); } finally { readUnLock(); } } /** * READ_LOCK * @see org.geoserver.security.GeoServerUserGroupService#getUserGroups() */ public SortedSet<GeoServerUserGroup> getUserGroups() throws IOException{ readLock(); try { return getService().getUserGroups(); } finally { readUnLock(); } } /** * READ_LOCK * @see org.geoserver.security.GeoServerUserGroupService#getUsersForGroup(org.geoserver.security.impl.GeoServerUserGroup) */ public SortedSet<GeoServerUser> getUsersForGroup(GeoServerUserGroup group) throws IOException{ readLock(); try { return getService().getUsersForGroup(group); } finally { readUnLock(); } } /** * READ_LOCK * @see org.geoserver.security.GeoServerUserGroupService#getGroupsForUser(org.geoserver.security.impl.GeoServerUser) */ public SortedSet<GeoServerUserGroup> getGroupsForUser(GeoServerUser user) throws IOException{ readLock(); try { return getService().getGroupsForUser(user); } finally { readUnLock(); } } /** * Fire {@link UserGroupLoadedEvent} for all listeners */ protected void fireUserGroupLoadedEvent() { UserGroupLoadedEvent event = new UserGroupLoadedEvent(this); for (UserGroupLoadedListener listener : listeners) { listener.usersAndGroupsChanged(event); } } /** * NO_LOCK * @see org.geoserver.security.GeoServerUserGroupService#registerUserGroupChangedListener(org.geoserver.security.event.UserGroupChangedListener) */ public void registerUserGroupLoadedListener(UserGroupLoadedListener listener) { listeners.add(listener); } /** * NO_LOCK * @see org.geoserver.security.GeoServerUserGroupService#unregisterUserGroupChangedListener(org.geoserver.security.event.UserGroupChangedListener) */ public void unregisterUserGroupLoadedListener(UserGroupLoadedListener listener) { listeners.remove(listener); } /** * NO_LOCK * @see org.geoserver.security.event.UserGroupChangedListener#usersAndGroupsChanged(org.geoserver.security.event.UserGroupChangedEvent) */ public void usersAndGroupsChanged(UserGroupLoadedEvent event) { // if (rwl.isWriteLockedByCurrentThread()) // writeUnLock(); // else // readUnLock(); fireUserGroupLoadedEvent(); } /** * WRITE_LOCK * @see org.geoserver.security.GeoServerUserGroupService#initializeFromConfig(org.geoserver.security.config.SecurityNamedServiceConfig) */ @Override public void initializeFromConfig(SecurityNamedServiceConfig config) throws IOException { writeLock(); try { getService().initializeFromConfig(config); } finally { writeUnLock(); } } /** * READ_LOCK * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String) */ @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { readLock(); try { return getService().loadUserByUsername(username); } finally { readUnLock(); } } /** * NO_LOCK */ @Override public String getPasswordEncoderName() { return getService().getPasswordEncoderName(); } /** * NO_LOCK */ @Override public String getPasswordValidatorName() { return getService().getPasswordValidatorName(); } /** * READ_LOCK * @see org.geoserver.security.GeoServerUserGroupService#getUserCount() */ public int getUserCount() throws IOException{ readLock(); try { return getService().getUserCount(); } finally { readUnLock(); } } /** * READ_LOCK * @see org.geoserver.security.GeoServerUserGroupService#getGroupCount() */ public int getGroupCount() throws IOException{ readLock(); try { return getService().getGroupCount(); } finally { readUnLock(); } } /** * READ_LOCK */ @Override public SortedSet<GeoServerUser> getUsersHavingProperty(String propname) throws IOException { readLock(); try { return getService().getUsersHavingProperty(propname); } finally { readUnLock(); } } /** * READ_LOCK */ @Override public int getUserCountHavingProperty(String propname) throws IOException { readLock(); try { return getService().getUserCountHavingProperty(propname); } finally { readUnLock(); } } /** * READ_LOCK */ @Override public SortedSet<GeoServerUser> getUsersNotHavingProperty(String propname) throws IOException { readLock(); try { return getService().getUsersNotHavingProperty(propname); } finally { readUnLock(); } } /** * READ_LOCK */ @Override public int getUserCountNotHavingProperty(String propname) throws IOException { readLock(); try { return getService().getUserCountNotHavingProperty(propname); } finally { readUnLock(); } } /** * READ_LOCK */ @Override public SortedSet<GeoServerUser> getUsersHavingPropertyValue(String propname, String propvalue) throws IOException { readLock(); try { return getService().getUsersHavingPropertyValue(propname, propvalue); } finally { readUnLock(); } } /** * READ_LOCK */ @Override public int getUserCountHavingPropertyValue(String propname, String propvalue) throws IOException { readLock(); try { return getService().getUserCountHavingPropertyValue(propname, propvalue); } finally { readUnLock(); } } }