Commits

Sebastian Sdorra  committed 9b3b0b8 Merge

merge with branch issue-340

  • Participants
  • Parent commits 737980c, d5b804e

Comments (0)

Files changed (50)

File scm-core/src/main/java/sonia/scm/ScmState.java

 
 //~--- non-JDK imports --------------------------------------------------------
 
+import sonia.scm.security.PermissionDescriptor;
 import sonia.scm.user.User;
 import sonia.scm.web.security.WebSecurityContext;
 
 //~--- JDK imports ------------------------------------------------------------
 
 import java.util.Collection;
+import java.util.List;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
     Collection<String> groups, Collection<Type> repositoryTypes,
     String defaultUserType, ScmClientConfig clientConfig)
   {
+    this(provider, user, groups, repositoryTypes, defaultUserType,
+      clientConfig, null);
+  }
+
+  /**
+   * Constructs {@link ScmState} object.
+   *
+   *
+   * @param provider context provider
+   * @param user current user
+   * @param groups groups of the current user
+   * @param repositoryTypes available repository types
+   * @param defaultUserType default user type
+   * @param clientConfig client configuration
+   * @param availablePermissions list of available permissions
+   *
+   * @since 1.31
+   */
+  public ScmState(SCMContextProvider provider, User user,
+    Collection<String> groups, Collection<Type> repositoryTypes,
+    String defaultUserType, ScmClientConfig clientConfig,
+    List<PermissionDescriptor> availablePermissions)
+  {
     this.version = provider.getVersion();
     this.user = user;
     this.groups = groups;
     this.repositoryTypes = repositoryTypes;
     this.clientConfig = clientConfig;
     this.defaultUserType = defaultUserType;
+    this.availablePermissions = availablePermissions;
   }
 
   //~--- get methods ----------------------------------------------------------
 
   /**
+   * Returns a list of available global permissions.
+   *
+   *
+   * @return available global permissions
+   * @since 1.31
+   */
+  public List<PermissionDescriptor> getAvailablePermissions()
+  {
+    return availablePermissions;
+  }
+
+  /**
    * Returns configuration for SCM-Manager clients.
    *
    *
   //~--- set methods ----------------------------------------------------------
 
   /**
+   * Sets a list of available global permissions.
+   *
+   *
+   * @param permissions list of available global permisisons
+   * @since 1.31
+   */
+  public void setAvailablePermissions(List<PermissionDescriptor> permissions)
+  {
+    this.availablePermissions = permissions;
+  }
+
+  /**
    * Setter for the client configuration
    *
    *
 
   //~--- fields ---------------------------------------------------------------
 
+  /**
+   * Avaliable global permission
+   * @since 1.31
+   */
+  private List<PermissionDescriptor> availablePermissions;
+
   /** Field description */
   private ScmClientConfig clientConfig;
 

File scm-core/src/main/java/sonia/scm/repository/Permission.java

 
 import com.google.common.base.Objects;
 
+import sonia.scm.security.PermissionObject;
+
 //~--- JDK imports ------------------------------------------------------------
 
 import java.io.Serializable;
  */
 @XmlRootElement(name = "permissions")
 @XmlAccessorType(XmlAccessType.FIELD)
-public class Permission implements Serializable
+public class Permission implements PermissionObject, Serializable
 {
 
   /** Field description */
     final Permission other = (Permission) obj;
 
     return Objects.equal(name, other.name) && Objects.equal(type, other.type)
-           && Objects.equal(groupPermission, groupPermission);
+      && Objects.equal(groupPermission, groupPermission);
   }
 
   /**
    *
    * @return name of the user or group
    */
+  @Override
   public String getName()
   {
     return name;
    *
    * @return true if the permision is a group permission
    */
+  @Override
   public boolean isGroupPermission()
   {
     return groupPermission;

File scm-core/src/main/java/sonia/scm/repository/PermissionUtil.java

 import org.slf4j.LoggerFactory;
 
 import sonia.scm.config.ScmConfiguration;
-import sonia.scm.group.GroupNames;
+import sonia.scm.security.RepositoryPermission;
 import sonia.scm.security.Role;
 import sonia.scm.security.ScmSecurityException;
 import sonia.scm.util.AssertUtil;
 import sonia.scm.web.security.WebSecurityContext;
 
-//~--- JDK imports ------------------------------------------------------------
-
-import java.util.List;
-
 /**
  *
  * @author Sebastian Sdorra
   public static boolean hasPermission(ScmConfiguration configuration,
     Repository repository, PermissionType pt)
   {
-    boolean result = false;
+    boolean result;
 
     Subject subject = SecurityUtils.getSubject();
 
       }
       else
       {
-        List<Permission> permissions = repository.getPermissions();
-
-        if (permissions != null)
-        {
-          GroupNames groupNames =
-            subject.getPrincipals().oneByType(GroupNames.class);
-
-          result = hasPermission(permissions, username, groupNames, pt);
-
-        }
+        result = subject.isPermitted(new RepositoryPermission(repository, pt));
       }
     }
     else
 
     return permitted;
   }
-
-  /**
-   * Method description
-   *
-   *
-   * @param permissions
-   * @param username
-   * @param groups
-   * @param pt
-   *
-   * @return
-   */
-  private static boolean hasPermission(List<Permission> permissions,
-    String username, GroupNames groups, PermissionType pt)
-  {
-    boolean result = false;
-
-    for (Permission p : permissions)
-    {
-      String name = p.getName();
-
-      if (((name != null) && (p.getType().getValue() >= pt.getValue()))
-        && (name.equals(username)
-          || (p.isGroupPermission() && groups.contains(p.getName()))))
-      {
-        result = true;
-
-        break;
-      }
-    }
-
-    return result;
-  }
 }

File scm-core/src/main/java/sonia/scm/security/AssignedPermission.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.security;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Objects;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Serializable;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Permission object which is assigned to a specific user or group.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.31
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlRootElement(name = "assigned-permission")
+public class AssignedPermission implements PermissionObject, Serializable
+{
+
+  /** serial version uid */
+  private static final long serialVersionUID = -7411338422110323879L;
+
+  //~--- constructors ---------------------------------------------------------
+
+  /**
+   * Constructor is only visible for JAXB.
+   *
+   */
+  public AssignedPermission() {}
+
+  /**
+   * Constructs a new AssignedPermission.
+   *
+   *
+   * @param permission assigned permission
+   */
+  public AssignedPermission(AssignedPermission permission)
+  {
+    this.name = permission.name;
+    this.groupPermission = permission.groupPermission;
+    this.permission = permission.permission;
+  }
+
+  /**
+   * Constructs a new AssingnedPermmission.
+   *
+   *
+   * @param name name of the user
+   * @param permission permission string
+   */
+  public AssignedPermission(String name, String permission)
+  {
+    this.name = name;
+    this.permission = permission;
+  }
+
+  /**
+   * Constructs a new AssingnedPermmission.
+   *
+   *
+   * @param name name of the user or group
+   * @param groupPermission true if the permission should be assigned to a group
+   * @param permission permission string
+   */
+  public AssignedPermission(String name, boolean groupPermission,
+    String permission)
+  {
+    this.name = name;
+    this.groupPermission = groupPermission;
+    this.permission = permission;
+  }
+
+  //~--- methods --------------------------------------------------------------
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean equals(Object obj)
+  {
+    if (obj == null)
+    {
+      return false;
+    }
+
+    if (getClass() != obj.getClass())
+    {
+      return false;
+    }
+
+    final AssignedPermission other = (AssignedPermission) obj;
+
+    return Objects.equal(name, other.name)
+      && Objects.equal(groupPermission, other.groupPermission)
+      && Objects.equal(permission, other.permission);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int hashCode()
+  {
+    return Objects.hashCode(name, groupPermission, permission);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    //J-
+    return Objects.toStringHelper(this)
+                  .add("name", name)
+                  .add("groupPermisison", groupPermission)
+                  .add("permission", permission)
+                  .toString();
+    //J+
+  }
+
+  //~--- get methods ----------------------------------------------------------
+
+  /**
+   * Returns the name of the user or group which the permission is assigned.
+   *
+   *
+   * @return name of user or group
+   */
+  @Override
+  public String getName()
+  {
+    return name;
+  }
+
+  /**
+   * Returns the string representation of the permission.
+   *
+   *
+   * @return string representation of the permission
+   */
+  public String getPermission()
+  {
+    return permission;
+  }
+
+  /**
+   * Returns true if the permission is assigned to a group.
+   *
+   *
+   * @return true if the permission is assigned to a group
+   */
+  @Override
+  public boolean isGroupPermission()
+  {
+    return groupPermission;
+  }
+
+  //~--- fields ---------------------------------------------------------------
+
+  /** group permission indicator */
+  @XmlElement(name = "group-permission")
+  private boolean groupPermission;
+
+  /** name of the user or group */
+  private String name;
+
+  /** string representation of the permission */
+  private String permission;
+}

File scm-core/src/main/java/sonia/scm/security/PermissionDescriptor.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.security;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Objects;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Serializable;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Descriptor for available permission objects.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.31
+ */
+@XmlRootElement(name = "permission")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class PermissionDescriptor implements Serializable
+{
+
+  /** Field description */
+  private static final long serialVersionUID = -9141065458354047154L;
+
+  //~--- constructors ---------------------------------------------------------
+
+  /**
+   * Constructor is only visible for JAXB.
+   *
+   */
+  public PermissionDescriptor() {}
+
+  /**
+   * Constructs ...
+   *
+   *
+   * @param displayName
+   * @param description
+   * @param value
+   */
+  public PermissionDescriptor(String displayName, String description,
+    String value)
+  {
+    this.displayName = displayName;
+    this.description = description;
+    this.value = value;
+  }
+
+  //~--- methods --------------------------------------------------------------
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean equals(Object obj)
+  {
+    if (obj == null)
+    {
+      return false;
+    }
+
+    if (getClass() != obj.getClass())
+    {
+      return false;
+    }
+
+    final PermissionDescriptor other = (PermissionDescriptor) obj;
+
+    return Objects.equal(displayName, other.displayName)
+      && Objects.equal(description, other.description)
+      && Objects.equal(value, other.value);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int hashCode()
+  {
+    return Objects.hashCode(displayName, description, value);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+
+    //J-
+    return Objects.toStringHelper(this)
+                  .add("displayName", displayName)
+                  .add("description", description)
+                  .add("value", value)
+                  .toString();
+
+    //J+
+  }
+
+  //~--- get methods ----------------------------------------------------------
+
+  /**
+   * Returns the description of the permission.
+   *
+   *
+   * @return description
+   */
+  public String getDescription()
+  {
+    return description;
+  }
+
+  /**
+   * Returns the display name of the permission.
+   *
+   *
+   * @return display name
+   */
+  public String getDisplayName()
+  {
+    return displayName;
+  }
+
+  /**
+   * Returns the string representation of the permission.
+   *
+   *
+   * @return string representation
+   */
+  public String getValue()
+  {
+    return value;
+  }
+
+  //~--- fields ---------------------------------------------------------------
+
+  /** description */
+  private String description;
+
+  /** display name */
+  @XmlElement(name = "display-name")
+  private String displayName;
+
+  /** value */
+  private String value;
+}

File scm-core/src/main/java/sonia/scm/security/PermissionObject.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.security;
+
+/**
+ * Interface for permission objects.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.31
+ */
+public interface PermissionObject
+{
+
+  /**
+   * Returns the name of the user or group which the permission is assigned.
+   *
+   *
+   * @return name of user or group
+   */
+  public String getName();
+
+  /**
+   * Returns the id of the stored permission object.
+   *
+   *
+   * @return id of permission
+   */
+  public boolean isGroupPermission();
+}

File scm-core/src/main/java/sonia/scm/security/SecuritySystem.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.security;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Predicate;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.List;
+
+/**
+ * The SecuritySystem manages global permissions.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.31
+ */
+public interface SecuritySystem
+{
+
+  /**
+   * Store a new permission.
+   *
+   *
+   * @param permission permission to be stored
+   *
+   * @return stored permission
+   */
+  public StoredAssignedPermission addPermission(AssignedPermission permission);
+
+  /**
+   * Delete stored permission.
+   *
+   *
+   * @param permission permission to be deleted
+   */
+  public void deletePermission(StoredAssignedPermission permission);
+
+  /**
+   * Delete stored permission.
+   *
+   *
+   * @param id id  of the permission
+   */
+  public void deletePermission(String id);
+
+  /**
+   * Modify stored permission.
+   *
+   *
+   * @param permission stored permisison
+   */
+  public void modifyPermission(StoredAssignedPermission permission);
+
+  //~--- get methods ----------------------------------------------------------
+
+  /**
+   * Return all stored permissions.
+   *
+   *
+   * @return stored permission
+   */
+  public List<StoredAssignedPermission> getAllPermissions();
+
+  /**
+   * Return all available permissions.
+   *
+   *
+   * @return available permissions
+   */
+  public List<PermissionDescriptor> getAvailablePermissions();
+
+  /**
+   * Return the stored permission which is stored with the given id.
+   *
+   *
+   * @param id id of the stored permission
+   *
+   * @return stored permission
+   */
+  public StoredAssignedPermission getPermission(String id);
+
+  /**
+   * Returns all stored permissions which are matched by the given
+   * {@link Predicate}.
+   *
+   *
+   * @param predicate predicate to filter
+   *
+   * @return filtered permissions
+   */
+  public List<StoredAssignedPermission> getPermissions(
+    Predicate<AssignedPermission> predicate);
+}

File scm-core/src/main/java/sonia/scm/security/StoredAssignedPermission.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.security;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Permission object which is stored and assigned to a specific user or group.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.31
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlRootElement(name = "assigned-permission")
+public class StoredAssignedPermission extends AssignedPermission
+{
+
+  /** serial version uid */
+  private static final long serialVersionUID = -4593919877023168090L;
+
+  //~--- constructors ---------------------------------------------------------
+
+  /**
+   * Constructor is only visible for JAXB.
+   *
+   */
+  public StoredAssignedPermission() {}
+
+  /**
+   * Constructs a new StoredAssignedPermission.
+   *
+   *
+   * @param id id of the permission object
+   * @param permission assigned permission object
+   */
+  public StoredAssignedPermission(String id, AssignedPermission permission)
+  {
+    super(permission);
+    this.id = id;
+
+  }
+
+  //~--- get methods ----------------------------------------------------------
+
+  /**
+   * Returns the id of the stored permission object.
+   *
+   *
+   * @return id of permission
+   */
+  public String getId()
+  {
+    return id;
+  }
+
+  //~--- fields ---------------------------------------------------------------
+
+  /** id */
+  private String id;
+}

File scm-core/src/main/java/sonia/scm/security/StoredAssignedPermissionEvent.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.security;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Objects;
+
+import sonia.scm.HandlerEvent;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Serializable;
+
+/**
+ * Event which is fired after a {@link StoredAssignedPermission} was added,
+ * removed or changed.
+ *
+ * @author Sebastian Sdorra
+ * @since 1.31
+ */
+public final class StoredAssignedPermissionEvent implements Serializable
+{
+
+  /** serial version uid */
+  private static final long serialVersionUID = 706824497813169009L;
+
+  //~--- constructors ---------------------------------------------------------
+
+  /**
+   * Constructs a new StoredAssignedPermissionEvent.
+   *
+   *
+   * @param type type of the event
+   * @param permission permission object which has changed
+   */
+  public StoredAssignedPermissionEvent(HandlerEvent type,
+    StoredAssignedPermission permission)
+  {
+    this.type = type;
+    this.permission = permission;
+  }
+
+  //~--- methods --------------------------------------------------------------
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean equals(Object obj)
+  {
+    if (obj == null)
+    {
+      return false;
+    }
+
+    if (getClass() != obj.getClass())
+    {
+      return false;
+    }
+
+    final StoredAssignedPermissionEvent other =
+      (StoredAssignedPermissionEvent) obj;
+
+    return Objects.equal(type, other.type)
+      && Objects.equal(permission, other.permission);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int hashCode()
+  {
+    return Objects.hashCode(type, permission);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    //J-
+    return Objects.toStringHelper(this)
+                  .add("type", type)
+                  .add("permission", permission)
+                  .toString();
+    //J+
+  }
+
+  //~--- get methods ----------------------------------------------------------
+
+  /**
+   * Return the type of the event.
+   *
+   *
+   * @return type of event
+   */
+  public HandlerEvent getEventType()
+  {
+    return type;
+  }
+
+  /**
+   * Returns the changed permission object.
+   *
+   *
+   * @return changed permission
+   */
+  public StoredAssignedPermission getPermission()
+  {
+    return permission;
+  }
+
+  //~--- fields ---------------------------------------------------------------
+
+  /** changed permission */
+  private StoredAssignedPermission permission;
+
+  /** type of the event */
+  private HandlerEvent type;
+}

File scm-core/src/main/java/sonia/scm/store/ConfigurationEntryStore.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.store;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Predicate;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.Collection;
+
+/**
+ * A ConfigurationEntryStore can be used to store multiple entries of structured 
+ * configuration data. <b>Note:<b> the default implementation use JAXB to 
+ * marshall the items.
+ *
+ * @author Sebastian Sdorra
+ *
+ * @param <V> store value type
+ * @since 1.31
+ */
+public interface ConfigurationEntryStore<V> extends DataStore<V>
+{
+
+  /**
+   * Return all values matching the given {@link Predicate}.
+   *
+   *
+   * @param predicate predicate to match values
+   *
+   * @return filtered collection of values
+   */
+  public Collection<V> getMatchingValues(Predicate<V> predicate);
+}

File scm-core/src/main/java/sonia/scm/store/ConfigurationEntryStoreFactory.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.store;
+
+/**
+ * The ConfigurationEntryStoreFactory can be used to create new or get existing
+ * {@link ConfigurationEntryStore}s. <b>Note:</b> the default implementation 
+ * uses the same location as the {@link StoreFactory}, so be sure that the 
+ * store names are unique for all {@link ConfigurationEntryStore}s and 
+ * {@link Store}s.
+ * 
+ * @author Sebastian Sdorra
+ * @since 1.31
+ * 
+ * @apiviz.landmark
+ * @apiviz.uses sonia.scm.store.ConfigurationEntryStore
+ */
+public interface ConfigurationEntryStoreFactory
+{
+
+  /**
+   * Get an existing {@link ConfigurationEntryStore} or create a new one.
+   *
+   *
+   * @param type type of the store objects
+   * @param name name of the store
+   * @param <T> type of the store objects
+   *
+   * @return {@link ConfigurationEntryStore} with given name and type
+   */
+  public <T> ConfigurationEntryStore<T> getStore(Class<T> type, String name);
+}

File scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStore.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.store;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Maps;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.security.KeyGenerator;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.FileOutputStream;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.stream.StreamSource;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ *
+ * @param <V>
+ */
+public class JAXBConfigurationEntryStore<V>
+  implements ConfigurationEntryStore<V>
+{
+
+  /** Field description */
+  private static final Object LOCK = new Object();
+
+  /** Field description */
+  private static final String TAG_CONFIGURATION = "configuration";
+
+  /** Field description */
+  private static final String TAG_ENTRY = "entry";
+
+  /** Field description */
+  private static final String TAG_KEY = "key";
+
+  /** Field description */
+  private static final String TAG_VALUE = "value";
+
+  /**
+   * the logger for JAXBConfigurationEntryStore
+   */
+  private static final Logger logger =
+    LoggerFactory.getLogger(JAXBConfigurationEntryStore.class);
+
+  //~--- constructors ---------------------------------------------------------
+
+  /**
+   * Constructs ...
+   *
+   *
+   *
+   * @param keyGenerator
+   * @param file
+   * @param type
+   */
+  JAXBConfigurationEntryStore(KeyGenerator keyGenerator, File file,
+    Class<V> type)
+  {
+    this.keyGenerator = keyGenerator;
+    this.file = file;
+    this.type = type;
+
+    try
+    {
+      this.context = JAXBContext.newInstance(type);
+
+      if (file.exists())
+      {
+        load();
+      }
+    }
+    catch (JAXBException ex)
+    {
+      throw new StoreException("could not create jaxb context", ex);
+    }
+  }
+
+  //~--- methods --------------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   */
+  @Override
+  public void clear()
+  {
+    logger.debug("clear configuration store");
+
+    synchronized (LOCK)
+    {
+      entries.clear();
+      store();
+    }
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param item
+   *
+   * @return
+   */
+  @Override
+  public String put(V item)
+  {
+    String id = keyGenerator.createKey();
+
+    put(id, item);
+
+    return id;
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param id
+   * @param item
+   */
+  @Override
+  public void put(String id, V item)
+  {
+    logger.debug("put item {} to configuration store", id);
+
+    synchronized (LOCK)
+    {
+      entries.put(id, item);
+      store();
+    }
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param id
+   */
+  @Override
+  public void remove(String id)
+  {
+    logger.debug("remove item {} from configuration store", id);
+
+    synchronized (LOCK)
+    {
+      entries.remove(id);
+      store();
+    }
+  }
+
+  //~--- get methods ----------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param id
+   *
+   * @return
+   */
+  @Override
+  public V get(String id)
+  {
+    logger.trace("get item {} from configuration store", id);
+
+    return entries.get(id);
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @return
+   */
+  @Override
+  public Map<String, V> getAll()
+  {
+    logger.trace("get all items from configuration store");
+
+    return Collections.unmodifiableMap(entries);
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param predicate
+   *
+   * @return
+   */
+  @Override
+  public Collection<V> getMatchingValues(Predicate<V> predicate)
+  {
+    return Collections2.filter(entries.values(), predicate);
+  }
+
+  //~--- methods --------------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param writer
+   */
+  private void close(XMLStreamWriter writer)
+  {
+    if (writer != null)
+    {
+      try
+      {
+        writer.close();
+      }
+      catch (XMLStreamException ex)
+      {
+        logger.error("could not close writer", ex);
+      }
+    }
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param reader
+   */
+  private void close(XMLStreamReader reader)
+  {
+    if (reader != null)
+    {
+      try
+      {
+        reader.close();
+      }
+      catch (XMLStreamException ex)
+      {
+        logger.error("could not close reader", ex);
+      }
+    }
+  }
+
+  /**
+   *   Method description
+   *
+   *
+   *   @return
+   */
+  private void load()
+  {
+    logger.debug("load configuration from {}", file);
+
+    XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+
+    XMLStreamReader reader = null;
+
+    try
+    {
+      Unmarshaller u = context.createUnmarshaller();
+
+      reader = xmlInputFactory.createXMLStreamReader(new StreamSource(file));
+      reader.nextTag();
+      reader.nextTag();
+
+      while (reader.isStartElement() && reader.getLocalName().equals(TAG_ENTRY))
+      {
+
+        // read key
+        reader.nextTag();
+
+        String key = reader.getElementText();
+
+        // read entry
+        reader.nextTag();
+
+        V v = (V) u.unmarshal(reader, type).getValue();
+
+        entries.put(key, v);
+      }
+    }
+    catch (Exception ex)
+    {
+      throw new StoreException("could not load configuration", ex);
+    }
+    finally
+    {
+      close(reader);
+    }
+  }
+
+  /**
+   * Method description
+   *
+   */
+  private void store()
+  {
+    logger.debug("store configuration to {}", file);
+
+    XMLStreamWriter writer = null;
+
+    try
+    {
+      writer = XMLOutputFactory.newFactory().createXMLStreamWriter(
+        new FileOutputStream(file));
+      writer.writeStartDocument();
+      writer.writeStartElement(TAG_CONFIGURATION);
+
+      Marshaller m = context.createMarshaller();
+
+      m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+      m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
+
+      for (Entry<String, V> e : entries.entrySet())
+      {
+        writer.writeStartElement(TAG_ENTRY);
+        writer.writeStartElement(TAG_KEY);
+        writer.writeCharacters(e.getKey());
+        writer.writeEndElement();
+
+        JAXBElement<V> je = new JAXBElement<V>(QName.valueOf(TAG_VALUE), type,
+                              e.getValue());
+
+        m.marshal(je, writer);
+      }
+
+      writer.writeEndElement();
+      writer.writeEndDocument();
+    }
+    catch (Exception ex)
+    {
+      throw new StoreException("could not store configuration", ex);
+    }
+    finally
+    {
+      close(writer);
+    }
+  }
+
+  //~--- fields ---------------------------------------------------------------
+
+  /** Field description */
+  private JAXBContext context;
+
+  /** Field description */
+  private Map<String, V> entries = Maps.newHashMap();
+
+  /** Field description */
+  private File file;
+
+  /** Field description */
+  private KeyGenerator keyGenerator;
+
+  /** Field description */
+  private Class<V> type;
+}

File scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStoreFactory.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.store;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.SCMContextProvider;
+import sonia.scm.security.KeyGenerator;
+import sonia.scm.util.IOUtil;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@Singleton
+public class JAXBConfigurationEntryStoreFactory
+  implements ConfigurationEntryStoreFactory
+{
+
+  /**
+   * the logger for JAXBConfigurationEntryStoreFactory
+   */
+  private static final Logger logger =
+    LoggerFactory.getLogger(JAXBConfigurationEntryStoreFactory.class);
+
+  //~--- constructors ---------------------------------------------------------
+
+  /**
+   * Constructs ...
+   *
+   *
+   * @param keyGenerator
+   * @param context
+   */
+  @Inject
+  public JAXBConfigurationEntryStoreFactory(KeyGenerator keyGenerator,
+    SCMContextProvider context)
+  {
+    this.keyGenerator = keyGenerator;
+    directory = new File(context.getBaseDirectory(),
+      StoreConstants.CONFIGDIRECTORY_NAME);
+    IOUtil.mkdirs(directory);
+  }
+
+  //~--- get methods ----------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param type
+   * @param name
+   * @param <T>
+   *
+   * @return
+   */
+  @Override
+  public <T> ConfigurationEntryStore<T> getStore(Class<T> type, String name)
+  {
+    logger.debug("create new configuration store for type {} with name {}",
+      type, name);
+
+    return new JAXBConfigurationEntryStore<T>(keyGenerator,
+      new File(directory, name.concat(StoreConstants.FILE_EXTENSION)), type);
+  }
+
+  //~--- fields ---------------------------------------------------------------
+
+  /** Field description */
+  private File directory;
+
+  /** Field description */
+  private KeyGenerator keyGenerator;
+}

File scm-dao-xml/src/main/java/sonia/scm/store/JAXBDataStore.java

 public class JAXBDataStore<T> extends FileBasedStore<T> implements DataStore<T>
 {
 
-  /** Field description */
-  private static final String SUFFIX = ".xml";
-
   /**
    * the logger for JAXBDataStore
    */
    */