Commits

Anonymous committed c9cedec

Added refactoring and XML provider contributed by Dave Brondsema

Comments (0)

Files changed (19)

src/java/com/opensymphony/user/provider/file/FileAccessProvider.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import com.opensymphony.user.Entity;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+
+/**
+ * @author Dave Brondsema
+ */
+abstract public class FileAccessProvider implements com.opensymphony.user.provider.AccessProvider {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    protected static final Log log = LogFactory.getLog(FileAccessProvider.class);
+
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    protected FileGroupsCache groupCache; /* this must be set by any child class's init() function */
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public boolean addToGroup(String username, String groupname) {
+        if (!inGroup(username, groupname)) {
+            boolean rv = getGroup(groupname).users.add(username);
+
+            return rv && groupCache.store();
+        }
+
+        return false;
+    }
+
+    public boolean create(String name) {
+        if (groupCache.groups.containsKey(name)) {
+            return false;
+        }
+
+        FileGroup group = new FileGroup();
+        group.name = name;
+        groupCache.groups.put(name, group);
+
+        return groupCache.store();
+    }
+
+    public void flushCaches() {
+        groupCache.store();
+    }
+
+    public boolean handles(String name) {
+        if (groupCache == null) {
+            return false;
+        }
+
+        return groupCache.groups.containsKey(name);
+
+        // @TODO: Major hack
+
+        /*
+        if (!handle) {
+        handle = new SerializableCredentialsProvider().handles(name);
+        }
+
+        return handle;
+        */
+        /*
+
+        this needs to check if this access provider handles groups AND users
+
+        but it has no reference to the in memory users
+
+
+        old version:
+
+        return groups.containsKey( name );
+
+        */
+    }
+
+    public boolean inGroup(String username, String groupname) {
+        FileGroup group = getGroup(groupname);
+
+        return (group != null) && group.users.contains(username);
+    }
+
+    public boolean init(Properties properties) {
+        return true;
+    }
+
+    public List list() {
+        return Collections.unmodifiableList(new ArrayList(groupCache.groups.keySet()));
+    }
+
+    public List listGroupsContainingUser(String username) {
+        List result = new ArrayList();
+        Iterator i = groupCache.groups.keySet().iterator();
+
+        while (i.hasNext()) {
+            String currentGroup = (String) i.next();
+
+            if (inGroup(username, currentGroup)) {
+                result.add(currentGroup);
+            }
+        }
+
+        return Collections.unmodifiableList(result);
+    }
+
+    public List listUsersInGroup(String groupname) {
+        FileGroup g = getGroup(groupname);
+
+        if (g == null) {
+            return Collections.EMPTY_LIST;
+        }
+
+        return Collections.unmodifiableList(getGroup(groupname).users);
+    }
+
+    public boolean load(String name, Entity.Accessor accessor) {
+        accessor.setMutable(true);
+
+        return true;
+    }
+
+    public boolean remove(String name) {
+        boolean rv = groupCache.groups.remove(name) != null;
+
+        return rv && groupCache.store();
+    }
+
+    public boolean removeFromGroup(String username, String groupname) {
+        boolean rv = getGroup(groupname).users.remove(username);
+
+        return rv && groupCache.store();
+    }
+
+    public boolean store(String name, Entity.Accessor accessor) {
+        return groupCache.store();
+    }
+
+    private FileGroup getGroup(String groupname) {
+        FileGroup group = (FileGroup) groupCache.groups.get(groupname);
+
+        return group;
+    }
+}

src/java/com/opensymphony/user/provider/file/FileCredentialsProvider.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import com.opensymphony.user.Entity;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+
+/**
+* Following properties are <b>required</b>:
+* <ul>
+* <li><b>storeFile</b> - the absolute path to the store file (<i>ex:c:\\users.store</i>)</li>
+* </ul>
+*/
+public class FileCredentialsProvider implements com.opensymphony.user.provider.CredentialsProvider {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    private static final Log log = LogFactory.getLog(FileCredentialsProvider.class);
+
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    protected FileUsersCache userCache;
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public boolean authenticate(String name, String password) {
+        FileUser user = (FileUser) userCache.users.get(name);
+
+        if (user == null) {
+            return false;
+        }
+
+        return password.equals(user.password);
+    }
+
+    public boolean changePassword(String name, String password) {
+        FileUser user = (FileUser) userCache.users.get(name);
+
+        if (user == null) {
+            return false;
+        }
+
+        user.password = password;
+
+        return userCache.store();
+    }
+
+    public boolean create(String name) {
+        if (userCache.users.containsKey(name)) {
+            return false;
+        }
+
+        FileUser user = new FileUser();
+        user.name = name;
+        userCache.users.put(name, user);
+
+        return userCache.store();
+    }
+
+    public void flushCaches() {
+        userCache.store();
+    }
+
+    public boolean handles(String name) {
+        if (userCache == null) {
+            return false;
+        }
+
+        return userCache.users.containsKey(name);
+    }
+
+    public boolean init(Properties properties) {
+        return true;
+    }
+
+    public List list() {
+        return Collections.unmodifiableList(new ArrayList(userCache.users.keySet()));
+    }
+
+    public boolean load(String name, Entity.Accessor accessor) {
+        accessor.setMutable(true);
+
+        return true;
+    }
+
+    public boolean remove(String name) {
+        boolean rv = userCache.users.remove(name) != null;
+
+        return rv && userCache.store();
+    }
+
+    public boolean store(String name, Entity.Accessor accessor) {
+        return userCache.store();
+    }
+}

src/java/com/opensymphony/user/provider/file/FileEntitiesCache.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+
+/**
+ * @author Dave Brondsema
+ */
+abstract class FileEntitiesCache {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    protected static final Log log = LogFactory.getLog(FileEntitiesCache.class);
+
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    protected String storeFile;
+    protected String storeFileType;
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public FileEntitiesCache(String storeFile, String storeFileType) {
+        this.storeFile = storeFile;
+        this.storeFileType = storeFileType;
+
+        if (storeFile == null) {
+            log.fatal("property storeFile must be specified");
+        }
+
+        if (storeFileType == null) {
+            log.fatal("property storeFileType must be specified; one of (file,resource)");
+        }
+
+        if (!storeFileType.equalsIgnoreCase("file") && !storeFileType.equalsIgnoreCase("resource")) {
+            log.fatal("property storeFileType must be one of (file,resource)");
+        }
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    abstract public boolean load();
+
+    abstract public boolean store();
+
+    protected InputStream getInputStreamFromStoreFile() throws IOException {
+        if (storeFileType.equalsIgnoreCase("file")) {
+            return new FileInputStream(storeFile);
+        } else if (storeFileType.equalsIgnoreCase("resource")) {
+            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+            return classLoader.getResourceAsStream(storeFile);
+        } else {
+            log.fatal("property storeFileType must be one of (file,resource)");
+
+            return null;
+        }
+    }
+}

src/java/com/opensymphony/user/provider/file/FileGroup.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import java.io.Serializable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+class FileGroup implements Serializable {
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    public List users = new ArrayList();
+    public String name;
+}

src/java/com/opensymphony/user/provider/file/FileGroupsCache.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * @author Dave Brondsema
+ */
+abstract class FileGroupsCache extends FileEntitiesCache {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    protected static final Log log = LogFactory.getLog(FileGroupsCache.class);
+
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    public Map groups;
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public FileGroupsCache(String storeFile, String storeFileType) {
+        super(storeFile, storeFileType);
+        groups = new HashMap();
+    }
+}

src/java/com/opensymphony/user/provider/file/FileProfileProvider.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import com.opensymphony.module.propertyset.PropertySet;
+import com.opensymphony.module.propertyset.PropertySetManager;
+
+import com.opensymphony.user.Entity;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+
+/**
+* Following properties are <b>required</b>:
+* <ul>
+* <li><b>storeFile</b> - the absolute path to the store file
+(<i>ex:c:\properties.store</i>)</li>
+* </ul>
+*/
+public class FileProfileProvider implements com.opensymphony.user.provider.ProfileProvider {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    protected static final Log log = LogFactory.getLog(FileProfileProvider.class);
+
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    protected FilePropertySetCache propertySetCache;
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public PropertySet getPropertySet(String name) {
+        if (!propertySetCache.propertySets.containsKey(name)) {
+            return null;
+        }
+
+        return (PropertySet) propertySetCache.propertySets.get(name);
+    }
+
+    public boolean create(String name) {
+        if (propertySetCache.propertySets.containsKey(name)) {
+            return false;
+        }
+
+        PropertySet propertySet = PropertySetManager.getInstance("serializable", null);
+        propertySetCache.propertySets.put(name, propertySet);
+
+        return propertySetCache.store();
+    }
+
+    public void flushCaches() {
+        propertySetCache.store();
+    }
+
+    public boolean handles(String name) {
+        return propertySetCache.propertySets.containsKey(name);
+    }
+
+    public boolean init(Properties properties) {
+        return true;
+    }
+
+    public List list() {
+        return Collections.unmodifiableList(new ArrayList(propertySetCache.propertySets.keySet()));
+    }
+
+    public boolean load(String name, Entity.Accessor accessor) {
+        return true;
+    }
+
+    public boolean remove(String name) {
+        boolean rv = propertySetCache.propertySets.remove(name) != null;
+
+        return rv && propertySetCache.store();
+    }
+
+    public boolean store(String name, Entity.Accessor accessor) {
+        return propertySetCache.store();
+    }
+}

src/java/com/opensymphony/user/provider/file/FilePropertySetCache.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+abstract class FilePropertySetCache extends FileEntitiesCache {
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    protected Map propertySets;
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    protected FilePropertySetCache(String storeFile, String storeFileType) {
+        super(storeFile, storeFileType);
+        propertySets = new HashMap();
+    }
+}

src/java/com/opensymphony/user/provider/file/FileUser.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import java.io.Serializable;
+
+
+class FileUser implements Serializable {
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    String name;
+    String password;
+}

src/java/com/opensymphony/user/provider/file/FileUsersCache.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * @author Dave Brondsema
+ */
+abstract class FileUsersCache extends FileEntitiesCache {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    protected static final Log log = LogFactory.getLog(FileUsersCache.class);
+
+    //~ Instance fields ////////////////////////////////////////////////////////
+
+    public Map users;
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public FileUsersCache(String storeFile, String storeFileType) {
+        super(storeFile, storeFileType);
+
+        users = new HashMap();
+    }
+}

src/java/com/opensymphony/user/provider/file/SerializableAccessProvider.java

  */
 package com.opensymphony.user.provider.file;
 
-import com.opensymphony.user.Entity;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
 import java.util.Properties;
 
 
 (<i>ex:c:\groups.store</i>)</li>
 * </ul>
 */
-public class SerializableAccessProvider implements com.opensymphony.user.provider.AccessProvider {
+public class SerializableAccessProvider extends FileAccessProvider {
     //~ Static fields/initializers /////////////////////////////////////////////
 
     protected static final Log log = LogFactory.getLog(SerializableAccessProvider.class);
-    public static String storeFile;
 
     //~ Methods ////////////////////////////////////////////////////////////////
 
-    public boolean addToGroup(String username, String groupname) {
-        if (!inGroup(username, groupname)) {
-            boolean rv = getGroup(groupname).users.add(username);
+    /**
+     * @see com.opensymphony.user.provider.UserProvider#init(Properties)
+     */
+    public boolean init(Properties properties) {
+        boolean retVal = super.init(properties);
 
-            return rv && SerializableGroupCache.getInstance().store();
+        if (retVal) {
+            groupCache = new SerializableGroupsCache(properties.getProperty("storeFile"), properties.getProperty("storeFileType"));
+
+            return true;
         }
 
         return false;
     }
-
-    public boolean create(String name) {
-        if (SerializableGroupCache.getInstance().groups.containsKey(name)) {
-            return false;
-        }
-
-        SerializableMemoryGroup group = new SerializableMemoryGroup();
-        group.name = name;
-        SerializableGroupCache.getInstance().groups.put(name, group);
-
-        return SerializableGroupCache.getInstance().store();
-    }
-
-    public void flushCaches() {
-        // do nothing - we already have everything in memory.
-    }
-
-    public boolean handles(String name) {
-        // @TODO: Major hack
-        boolean handle = SerializableGroupCache.getInstance().groups.containsKey(name);
-
-        if (!handle) {
-            handle = new SerializableCredentialsProvider().handles(name);
-        }
-
-        return handle;
-
-        /*
-
-        this needs to check if this access provider handles groups AND users
-
-        but it has no reference to the in memory users
-
-
-        old version:
-
-        return groups.containsKey( name );
-
-        */
-    }
-
-    public boolean inGroup(String username, String groupname) {
-        SerializableMemoryGroup group = getGroup(groupname);
-
-        return (group != null) && group.users.contains(username);
-    }
-
-    public boolean init(Properties properties) {
-        storeFile = properties.getProperty("storeFile");
-
-        return true;
-    }
-
-    public List list() {
-        return Collections.unmodifiableList(new ArrayList(SerializableGroupCache.getInstance().groups.keySet()));
-    }
-
-    public List listGroupsContainingUser(String username) {
-        List result = new ArrayList();
-        Iterator i = SerializableGroupCache.getInstance().groups.keySet().iterator();
-
-        while (i.hasNext()) {
-            String currentGroup = (String) i.next();
-
-            if (inGroup(username, currentGroup)) {
-                result.add(currentGroup);
-            }
-        }
-
-        return Collections.unmodifiableList(result);
-    }
-
-    public List listUsersInGroup(String groupname) {
-        SerializableMemoryGroup g = getGroup(groupname);
-
-        if (g == null) {
-            return Collections.EMPTY_LIST;
-        }
-
-        return Collections.unmodifiableList(getGroup(groupname).users);
-    }
-
-    public boolean load(String name, Entity.Accessor accessor) {
-        accessor.setMutable(true);
-
-        return true;
-    }
-
-    public boolean remove(String name) {
-        boolean rv = SerializableGroupCache.getInstance().groups.remove(name) != null;
-
-        return rv && SerializableGroupCache.getInstance().store();
-    }
-
-    public boolean removeFromGroup(String username, String groupname) {
-        boolean rv = getGroup(groupname).users.remove(username);
-
-        return rv && SerializableGroupCache.getInstance().store();
-    }
-
-    public boolean store(String name, Entity.Accessor accessor) {
-        return SerializableGroupCache.getInstance().store();
-    }
-
-    private SerializableMemoryGroup getGroup(String groupname) {
-        SerializableMemoryGroup group = (SerializableMemoryGroup) SerializableGroupCache.getInstance().groups.get(groupname);
-
-        return group;
-    }
-
-    //~ Inner Classes //////////////////////////////////////////////////////////
-
-    class SerializableMemoryGroup implements Serializable {
-        List users = new ArrayList();
-        String name;
-    }
 }
-
-
-class SerializableGroupCache implements Serializable {
-    //~ Static fields/initializers /////////////////////////////////////////////
-
-    private static transient SerializableGroupCache instance;
-
-    //~ Instance fields ////////////////////////////////////////////////////////
-
-    protected Map groups;
-
-    //~ Constructors ///////////////////////////////////////////////////////////
-
-    private SerializableGroupCache() {
-        groups = new HashMap();
-    }
-
-    //~ Methods ////////////////////////////////////////////////////////////////
-
-    protected static SerializableGroupCache load() {
-        try {
-            FileInputStream fis = new FileInputStream(new File(SerializableAccessProvider.storeFile));
-            ObjectInputStream ois = new ObjectInputStream(fis);
-            SerializableGroupCache o = (SerializableGroupCache) ois.readObject();
-            fis.close();
-
-            return o;
-        } catch (Exception e) {
-            SerializableAccessProvider.log.fatal("cannot store in file " + SerializableAccessProvider.storeFile + ". Create a new blank store.");
-        }
-
-        return new SerializableGroupCache();
-    }
-
-    protected static boolean store() {
-        try {
-            FileOutputStream fos = new FileOutputStream(new File(SerializableAccessProvider.storeFile));
-            ObjectOutputStream oos = new ObjectOutputStream(fos);
-            oos.writeObject(getInstance());
-            fos.close();
-
-            return true;
-        } catch (Exception e) {
-            SerializableAccessProvider.log.fatal("cannot store in file " + SerializableAccessProvider.storeFile + ".");
-        }
-
-        return false;
-    }
-
-    static SerializableGroupCache getInstance() {
-        if (instance == null) {
-            instance = load();
-        }
-
-        return instance;
-    }
-}

src/java/com/opensymphony/user/provider/file/SerializableCredentialsProvider.java

  */
 package com.opensymphony.user.provider.file;
 
-import com.opensymphony.user.Entity;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
 import java.util.Properties;
 
 
 /**
 * Following properties are <b>required</b>:
 * <ul>
-* <li><b>storeFile</b> - the absolute path to the store file (<i>ex:c:\
-users.store</i>)</li>
+* <li><b>storeFile</b> - the absolute path to the store file (<i>ex:c:\\users.store</i>)</li>
 * </ul>
 */
-public class SerializableCredentialsProvider implements com.opensymphony.user.provider.CredentialsProvider {
+public class SerializableCredentialsProvider extends FileCredentialsProvider {
     //~ Static fields/initializers /////////////////////////////////////////////
 
     protected static final Log log = LogFactory.getLog(SerializableCredentialsProvider.class);
-    public static String storeFile;
 
     //~ Methods ////////////////////////////////////////////////////////////////
 
-    public boolean authenticate(String name, String password) {
-        SerializableMemoryCredentials user = (SerializableMemoryCredentials) SerializableUserCache.getInstance().users.get(name);
+    public boolean init(Properties properties) {
+        boolean retVal = super.init(properties);
 
-        if (user == null) {
-            return false;
-        }
-
-        return password.equals(user.password);
-    }
-
-    public boolean changePassword(String name, String password) {
-        SerializableMemoryCredentials user = (SerializableMemoryCredentials) SerializableUserCache.getInstance().users.get(name);
-
-        if (user == null) {
-            return false;
-        }
-
-        user.password = password;
-
-        return SerializableUserCache.getInstance().store();
-    }
-
-    public boolean create(String name) {
-        if (SerializableUserCache.getInstance().users.containsKey(name)) {
-            return false;
-        }
-
-        SerializableMemoryCredentials user = new SerializableMemoryCredentials();
-        user.name = name;
-        SerializableUserCache.getInstance().users.put(name, user);
-
-        return SerializableUserCache.getInstance().store();
-    }
-
-    public void flushCaches() {
-        // do nothing - we already have everything in memory.
-    }
-
-    public boolean handles(String name) {
-        return SerializableUserCache.getInstance().users.containsKey(name);
-    }
-
-    public boolean init(Properties properties) {
-        storeFile = properties.getProperty("storeFile");
-
-        return true;
-    }
-
-    public List list() {
-        return Collections.unmodifiableList(new ArrayList(SerializableUserCache.getInstance().users.keySet()));
-    }
-
-    public boolean load(String name, Entity.Accessor accessor) {
-        accessor.setMutable(true);
-
-        return true;
-    }
-
-    public boolean remove(String name) {
-        boolean rv = SerializableUserCache.getInstance().users.remove(name) != null;
-
-        return rv && SerializableUserCache.getInstance().store();
-    }
-
-    public boolean store(String name, Entity.Accessor accessor) {
-        return SerializableUserCache.getInstance().store();
-    }
-
-    //~ Inner Classes //////////////////////////////////////////////////////////
-
-    class SerializableMemoryCredentials implements Serializable {
-        String name;
-        String password;
-    }
-}
-
-
-class SerializableUserCache implements Serializable {
-    //~ Static fields/initializers /////////////////////////////////////////////
-
-    private static transient SerializableUserCache instance;
-
-    //~ Instance fields ////////////////////////////////////////////////////////
-
-    protected Map users;
-
-    //~ Constructors ///////////////////////////////////////////////////////////
-
-    private SerializableUserCache() {
-        users = new HashMap();
-    }
-
-    //~ Methods ////////////////////////////////////////////////////////////////
-
-    protected static SerializableUserCache load() {
-        try {
-            FileInputStream fis = new FileInputStream(new File(SerializableCredentialsProvider.storeFile));
-            ObjectInputStream ois = new ObjectInputStream(fis);
-            SerializableUserCache o = (SerializableUserCache) ois.readObject();
-            fis.close();
-
-            return o;
-        } catch (Exception e) {
-            SerializableCredentialsProvider.log.fatal("cannot store in file " + SerializableCredentialsProvider.storeFile + ". Create a new blank store.");
-        }
-
-        return new SerializableUserCache();
-    }
-
-    protected static boolean store() {
-        try {
-            FileOutputStream fos = new FileOutputStream(new File(SerializableCredentialsProvider.storeFile));
-            ObjectOutputStream oos = new ObjectOutputStream(fos);
-            oos.writeObject(getInstance());
-            fos.close();
+        if (retVal) {
+            userCache = new SerializableUsersCache(properties.getProperty("storeFile"), properties.getProperty("storeFileType"));
 
             return true;
-        } catch (Exception e) {
-            SerializableCredentialsProvider.log.fatal("cannot store in file " + SerializableCredentialsProvider.storeFile + ".");
         }
 
         return false;
     }
-
-    static SerializableUserCache getInstance() {
-        if (instance == null) {
-            instance = load();
-        }
-
-        return instance;
-    }
 }

src/java/com/opensymphony/user/provider/file/SerializableGroupsCache.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+
+class SerializableGroupsCache extends FileGroupsCache implements Serializable {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    protected static final Log log = LogFactory.getLog(SerializableGroupsCache.class);
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public SerializableGroupsCache(String storeFile, String storeFileType) {
+        super(storeFile, storeFileType);
+        load();
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public boolean load() {
+        try {
+            ObjectInputStream ois = new ObjectInputStream(getInputStreamFromStoreFile());
+            SerializableGroupsCache g = (SerializableGroupsCache) ois.readObject();
+
+            // copy data into this class
+            groups = g.groups;
+
+            return true;
+        } catch (Exception e) {
+            log.fatal("cannot load from file " + storeFile + ". Create a new blank store.", e);
+        }
+
+        return false;
+    }
+
+    public boolean store() {
+        try {
+            FileOutputStream fos = new FileOutputStream(new File(storeFile));
+            ObjectOutputStream oos = new ObjectOutputStream(fos);
+            oos.writeObject(this);
+            fos.close();
+
+            return true;
+        } catch (Exception e) {
+            log.fatal("cannot store in file " + storeFile + ".", e);
+        }
+
+        return false;
+    }
+}

src/java/com/opensymphony/user/provider/file/SerializableProfileProvider.java

  */
 package com.opensymphony.user.provider.file;
 
-import com.opensymphony.module.propertyset.PropertySet;
-import com.opensymphony.module.propertyset.PropertySetManager;
-
-import com.opensymphony.user.Entity;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
 import java.util.Properties;
 
 
 (<i>ex:c:\properties.store</i>)</li>
 * </ul>
 */
-public class SerializableProfileProvider implements com.opensymphony.user.provider.ProfileProvider {
+public class SerializableProfileProvider extends FileProfileProvider {
     //~ Static fields/initializers /////////////////////////////////////////////
 
     protected static final Log log = LogFactory.getLog(SerializableProfileProvider.class);
-    public static String storeFile;
 
     //~ Methods ////////////////////////////////////////////////////////////////
 
-    public PropertySet getPropertySet(String name) {
-        if (!SerializablePropertySetCache.getInstance().propertySets.containsKey(name)) {
-            return null;
-        }
+    public boolean init(Properties properties) {
+        boolean retVal = super.init(properties);
 
-        return (PropertySet) SerializablePropertySetCache.getInstance().propertySets.get(name);
-    }
-
-    public boolean create(String name) {
-        if (SerializablePropertySetCache.getInstance().propertySets.containsKey(name)) {
-            return false;
-        }
-
-        PropertySet propertySet = PropertySetManager.getInstance("serializable", null);
-        SerializablePropertySetCache.getInstance().propertySets.put(name, propertySet);
-
-        return SerializablePropertySetCache.getInstance().store();
-    }
-
-    public void flushCaches() {
-        // do nothing - we already have everything in memory.
-    }
-
-    public boolean handles(String name) {
-        return SerializablePropertySetCache.getInstance().propertySets.containsKey(name);
-    }
-
-    public boolean init(Properties properties) {
-        storeFile = properties.getProperty("storeFile");
-
-        return true;
-    }
-
-    public List list() {
-        // @todo: implement
-        return null;
-    }
-
-    public boolean load(String name, Entity.Accessor accessor) {
-        return true;
-    }
-
-    public boolean remove(String name) {
-        boolean rv = SerializablePropertySetCache.getInstance().propertySets.remove(name) != null;
-
-        return rv && SerializablePropertySetCache.getInstance().store();
-    }
-
-    public boolean store(String name, Entity.Accessor accessor) {
-        return SerializablePropertySetCache.getInstance().store();
-    }
-}
-
-
-class SerializablePropertySetCache implements Serializable {
-    //~ Static fields/initializers /////////////////////////////////////////////
-
-    private static transient SerializablePropertySetCache instance;
-
-    //~ Instance fields ////////////////////////////////////////////////////////
-
-    protected Map propertySets;
-
-    //~ Constructors ///////////////////////////////////////////////////////////
-
-    private SerializablePropertySetCache() {
-        propertySets = new HashMap();
-    }
-
-    //~ Methods ////////////////////////////////////////////////////////////////
-
-    protected static SerializablePropertySetCache load() {
-        try {
-            FileInputStream fis = new FileInputStream(new File(SerializableProfileProvider.storeFile));
-            ObjectInputStream ois = new ObjectInputStream(fis);
-            SerializablePropertySetCache o = (SerializablePropertySetCache) ois.readObject();
-            fis.close();
-
-            return o;
-        } catch (Exception e) {
-            SerializableProfileProvider.log.fatal("cannot store in file " + SerializableProfileProvider.storeFile + ". Create a new blank store.");
-        }
-
-        return new SerializablePropertySetCache();
-    }
-
-    protected static boolean store() {
-        try {
-            FileOutputStream fos = new FileOutputStream(new File(SerializableProfileProvider.storeFile));
-            ObjectOutputStream oos = new ObjectOutputStream(fos);
-            oos.writeObject(getInstance());
-            fos.close();
+        if (retVal) {
+            propertySetCache = new SerializablePropertySetCache(properties.getProperty("storeFile"), properties.getProperty("storeFileType"));
 
             return true;
-        } catch (Exception e) {
-            SerializableProfileProvider.log.fatal("cannot store in file " + SerializableProfileProvider.storeFile + ".");
         }
 
         return false;
     }
-
-    static SerializablePropertySetCache getInstance() {
-        if (instance == null) {
-            instance = load();
-        }
-
-        return instance;
-    }
 }

src/java/com/opensymphony/user/provider/file/SerializablePropertySetCache.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+
+class SerializablePropertySetCache extends FilePropertySetCache {
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public SerializablePropertySetCache(String storeFile, String storeFileType) {
+        super(storeFile, storeFileType);
+        load();
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public boolean load() {
+        try {
+            ObjectInputStream ois = new ObjectInputStream(getInputStreamFromStoreFile());
+            SerializablePropertySetCache ps = (SerializablePropertySetCache) ois.readObject();
+
+            // copy data into this class
+            propertySets = ps.propertySets;
+
+            return true;
+        } catch (Exception e) {
+            log.fatal("cannot load from file " + storeFile + ". Create a new blank store.", e);
+        }
+
+        return false;
+    }
+
+    public boolean store() {
+        try {
+            FileOutputStream fos = new FileOutputStream(new File(storeFile));
+            ObjectOutputStream oos = new ObjectOutputStream(fos);
+            oos.writeObject(this);
+            fos.close();
+
+            return true;
+        } catch (Exception e) {
+            log.fatal("cannot store in file " + storeFile + ".", e);
+        }
+
+        return false;
+    }
+}

src/java/com/opensymphony/user/provider/file/SerializableUsersCache.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+
+class SerializableUsersCache extends FileUsersCache implements Serializable {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    private static final Log log = LogFactory.getLog(SerializableUsersCache.class);
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public SerializableUsersCache(String storeFile, String storeFileType) {
+        super(storeFile, storeFileType);
+        load();
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public boolean load() {
+        try {
+            ObjectInputStream ois = new ObjectInputStream(getInputStreamFromStoreFile());
+            SerializableUsersCache u = (SerializableUsersCache) ois.readObject();
+
+            users = u.users;
+
+            return true;
+        } catch (Exception e) {
+            log.fatal("cannot load from file " + storeFile + ". Create a new blank store.", e);
+        }
+
+        return false;
+    }
+
+    public boolean store() {
+        try {
+            FileOutputStream fos = new FileOutputStream(new File(storeFile));
+            ObjectOutputStream oos = new ObjectOutputStream(fos);
+            oos.writeObject(this);
+            fos.close();
+
+            return true;
+        } catch (Exception e) {
+            log.fatal("cannot store in file " + storeFile + ".", e);
+        }
+
+        return false;
+    }
+}

src/java/com/opensymphony/user/provider/file/XMLAccessProvider.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Properties;
+
+
+/**
+* Following properties are <b>required</b>:
+* <ul>
+* <li><b>storeFile</b> - the absolute path to the store file (<i>ex: c:\groups.xml</i>) or a resource location in the jar (<i>ex: /groups.xml</i>) </li>
+* <li><b>storeFileType</b> - one of (file, resource)
+* </ul>
+*
+* XML format example:
+* <pre>
+* &lt;groups&gt;
+*   &lt;group id="myGroup"&gt;
+*     &lt;user id="myUser"/&gt;
+*     &lt;user id="someOtherUser"/&gt;
+*   &lt;/group&gt;
+*   &lt;group id="anEmptyGroup"/&gt;
+*   &lt;group id="foo"&gt;
+*     &lt;user id="bar"/&gt;
+*     &lt;user id="baz"/&gt;
+*   &lt;/group&gt;
+* &lt;/groups&gt;
+* </pre>
+*
+* @author Dave Brondsema
+*
+*/
+public class XMLAccessProvider extends FileAccessProvider {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    protected static final Log log = LogFactory.getLog(SerializableAccessProvider.class);
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public boolean init(Properties properties) {
+        boolean retVal = super.init(properties);
+
+        if (retVal) {
+            groupCache = new XMLGroupsCache(properties.getProperty("storeFile"), properties.getProperty("storeFileType"));
+
+            return true;
+        }
+
+        return false;
+    }
+}

src/java/com/opensymphony/user/provider/file/XMLCredentialsProvider.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Properties;
+
+
+/**
+* Following properties are <b>required</b>:
+* <ul>
+* <li><b>storeFile</b> - the absolute path to the store file (<i>ex: c:\groups.xml</i>) or a resource location in the jar (<i>ex: /groups.xml</i>) </li>
+* <li><b>storeFileType</b> - one of (file, resource)
+* </ul>
+*
+* XML format example:
+* <pre>
+* &lt;users&gt;
+*   &lt;user id="myUser" password="abcdef"/&gt;
+*   &lt;user id="foo"/&gt;
+* &lt;/users&gt;
+* </pre>
+*
+* @author Dave Brondsema
+*
+*/
+public class XMLCredentialsProvider extends FileCredentialsProvider {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    protected static final Log log = LogFactory.getLog(XMLCredentialsProvider.class);
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public boolean init(Properties properties) {
+        boolean retVal = super.init(properties);
+
+        if (retVal) {
+            userCache = new XMLUsersCache(properties.getProperty("storeFile"), properties.getProperty("storeFileType"));
+
+            return true;
+        }
+
+        return false;
+    }
+}

src/java/com/opensymphony/user/provider/file/XMLGroupsCache.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+
+import org.dom4j.io.OutputFormat;
+import org.dom4j.io.SAXReader;
+import org.dom4j.io.XMLWriter;
+
+import java.io.FileWriter;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+
+class XMLGroupsCache extends FileGroupsCache {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    protected static final Log log = LogFactory.getLog(XMLGroupsCache.class);
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public XMLGroupsCache(String storeFile, String storeFileType) {
+        super(storeFile, storeFileType);
+        load();
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public boolean load() {
+        try {
+            // clear the groups first
+            groups = new HashMap();
+
+            SAXReader reader = new SAXReader();
+            Document document = null;
+            document = reader.read(getInputStreamFromStoreFile());
+
+            Element root = document.getRootElement();
+
+            if (log.isDebugEnabled()) {
+                log.debug("loaded " + storeFile);
+            }
+
+            // read each <group>
+            for (Iterator i = root.elementIterator(); i.hasNext();) {
+                Element groupElement = (Element) i.next();
+
+                if (groupElement.getName().equals("group")) {
+                    String groupName = groupElement.attribute("id").getValue();
+
+                    FileGroup group = new FileGroup();
+                    group.name = groupName;
+
+                    // read 
+                    for (Iterator j = groupElement.elementIterator();
+                            j.hasNext();) {
+                        Element userElement = (Element) j.next();
+
+                        if (userElement.getName().equals("user")) {
+                            String userName = userElement.attribute("id").getValue();
+                            group.users.add(userName);
+                            log.debug("added user " + userName + " to group " + groupName);
+                        } else {
+                            log.warn("expected 'user' element, found " + userElement.getName() + " in " + storeFile);
+                        }
+                    }
+
+                    groups.put(groupName, group);
+                    log.debug("added group " + groupName);
+                } else {
+                    log.warn("expected 'group' element, found " + groupElement.getName() + " in " + storeFile);
+                }
+            }
+
+            return true;
+        } catch (Exception e) {
+            log.fatal("cannot load from " + storeFile + ".", e);
+        }
+
+        return false;
+    }
+
+    public boolean store() {
+        try {
+            Document document = DocumentHelper.createDocument();
+            Element root = document.addElement("groups");
+
+            // a <group id="foo"> for each group
+            for (Iterator i = groups.keySet().iterator(); i.hasNext();) {
+                String groupKey = i.next().toString();
+                FileGroup group = (FileGroup) groups.get(groupKey);
+                Element groupElement = root.addElement("group").addAttribute("id", group.name);
+
+                // a <user id="bar"/> for each group's member
+                for (Iterator j = group.users.iterator(); j.hasNext();) {
+                    groupElement.addElement("user").addAttribute("id", j.next().toString());
+                }
+            }
+
+            // print it nicely
+            OutputFormat format = OutputFormat.createPrettyPrint();
+            XMLWriter writer = new XMLWriter(new FileWriter(storeFile));
+            writer.write(document);
+            writer.close();
+
+            return true;
+        } catch (Exception e) {
+            log.fatal("cannot store in file " + storeFile + ".", e);
+        }
+
+        return false;
+    }
+}

src/java/com/opensymphony/user/provider/file/XMLUsersCache.java

+/*
+ * Copyright (c) 2002-2003 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.user.provider.file;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+
+import org.dom4j.io.OutputFormat;
+import org.dom4j.io.SAXReader;
+import org.dom4j.io.XMLWriter;
+
+import java.io.FileWriter;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+
+class XMLUsersCache extends FileUsersCache {
+    //~ Static fields/initializers /////////////////////////////////////////////
+
+    protected static final Log log = LogFactory.getLog(XMLUsersCache.class);
+
+    //~ Constructors ///////////////////////////////////////////////////////////
+
+    public XMLUsersCache(String storeFile, String storeFileType) {
+        super(storeFile, storeFileType);
+        load();
+    }
+
+    //~ Methods ////////////////////////////////////////////////////////////////
+
+    public boolean load() {
+        try {
+            // clear the groups first
+            users = new HashMap();
+
+            SAXReader reader = new SAXReader();
+            Document document = reader.read(getInputStreamFromStoreFile());
+            Element root = document.getRootElement();
+
+            if (log.isDebugEnabled()) {
+                log.debug("loaded " + storeFile);
+            }
+
+            // read each <user>
+            for (Iterator i = root.elementIterator(); i.hasNext();) {
+                Element groupElement = (Element) i.next();
+
+                if (groupElement.getName().equals("user")) {
+                    if (groupElement.attribute("id") == null) {
+                        log.warn("attribute 'id' required for <user/> in " + storeFile);
+
+                        continue;
+                    }
+
+                    String userName = groupElement.attribute("id").getValue();
+                    String userPassword = null;
+
+                    if (groupElement.attribute("password") != null) {
+                        userPassword = groupElement.attribute("password").getValue();
+                    }
+
+                    FileUser user = new FileUser();
+                    user.name = userName;
+                    user.password = userPassword;
+
+                    users.put(userName, user);
+                    log.debug("added user credentials " + userName);
+                } else {
+                    log.warn("expected 'user' element, found " + groupElement.getName() + " in " + storeFile);
+                }
+            }
+
+            return true;
+        } catch (Exception e) {
+            log.fatal("cannot load from file " + storeFile + ".", e);
+        }
+
+        return false;
+    }
+
+    public boolean store() {
+        try {
+            Document document = DocumentHelper.createDocument();
+            Element root = document.addElement("users");
+
+            // a <user id="foo" password="bar"> for each group
+            for (Iterator i = users.keySet().iterator(); i.hasNext();) {
+                String userKey = i.next().toString();
+                FileUser user = (FileUser) users.get(userKey);
+                Element userElement = root.addElement("user").addAttribute("id", user.name).addAttribute("password", user.password);
+            }
+
+            // print it nicely
+            OutputFormat format = OutputFormat.createPrettyPrint();
+            XMLWriter writer = new XMLWriter(new FileWriter(storeFile));
+            writer.write(document);
+            writer.close();
+
+            return true;
+        } catch (Exception e) {
+            log.fatal("cannot store in file " + storeFile + ".", e);
+        }
+
+        return false;
+    }
+}