improve repository manager and handler relation

This commit is contained in:
Sebastian Sdorra
2010-11-25 21:56:06 +01:00
parent 4898870e85
commit b6298938ec
23 changed files with 958 additions and 983 deletions

View File

@@ -40,15 +40,12 @@ import com.google.inject.Provider;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import sonia.scm.repository.GitRepositoryHandler; import sonia.scm.repository.GitRepositoryHandler;
import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryManager;
import sonia.scm.web.filter.PermissionFilter; import sonia.scm.web.filter.RegexPermissionFilter;
import sonia.scm.web.security.SecurityContext; import sonia.scm.web.security.SecurityContext;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
/** /**
@@ -56,7 +53,7 @@ import javax.servlet.http.HttpServletRequest;
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
@Singleton @Singleton
public class GitPermissionFilter extends PermissionFilter public class GitPermissionFilter extends RegexPermissionFilter
{ {
/** Field description */ /** Field description */
@@ -70,14 +67,13 @@ public class GitPermissionFilter extends PermissionFilter
* *
* *
* @param securityContextProvider * @param securityContextProvider
* @param handler * @param repositoryManager
*/ */
@Inject @Inject
public GitPermissionFilter(Provider<SecurityContext> securityContextProvider, public GitPermissionFilter(Provider<SecurityContext> securityContextProvider,
GitRepositoryHandler handler) RepositoryManager repositoryManager)
{ {
super(securityContextProvider); super(securityContextProvider, repositoryManager);
this.handler = handler;
} }
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
@@ -86,14 +82,12 @@ public class GitPermissionFilter extends PermissionFilter
* Method description * Method description
* *
* *
* @param name
*
* @return * @return
*/ */
@Override @Override
protected Repository getRepository(String name) protected String getType()
{ {
return handler.getByName(name); return GitRepositoryHandler.TYPE_NAME;
} }
/** /**
@@ -109,9 +103,4 @@ public class GitPermissionFilter extends PermissionFilter
{ {
return request.getRequestURI().endsWith(PATTERN_WRITEREQUEST); return request.getRequestURI().endsWith(PATTERN_WRITEREQUEST);
} }
//~--- fields ---------------------------------------------------------------
/** Field description */
private GitRepositoryHandler handler;
} }

View File

@@ -66,22 +66,6 @@ public class HgRepositoryHandler
/** Field description */ /** Field description */
public static final Type TYPE = new Type(TYPE_NAME, TYPE_DISPLAYNAME); public static final Type TYPE = new Type(TYPE_NAME, TYPE_DISPLAYNAME);
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param repository
*
* @return
*/
@Override
public String createResourcePath(Repository repository)
{
return "/hg/".concat(repository.getName());
}
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
/** /**

View File

@@ -40,6 +40,7 @@ import com.google.inject.Singleton;
import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.HgRepositoryHandler;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.web.cgi.AbstractCGIServlet; import sonia.scm.web.cgi.AbstractCGIServlet;
import sonia.scm.web.cgi.EnvList; import sonia.scm.web.cgi.EnvList;
@@ -81,11 +82,15 @@ public class HgCGIServlet extends AbstractCGIServlet
* Constructs ... * Constructs ...
* *
* *
*
* @param repositoryManager
* @param handler * @param handler
*/ */
@Inject @Inject
public HgCGIServlet(HgRepositoryHandler handler) public HgCGIServlet(RepositoryManager repositoryManager,
HgRepositoryHandler handler)
{ {
this.repositoryManager = repositoryManager;
this.handler = handler; this.handler = handler;
} }
@@ -194,7 +199,7 @@ public class HgCGIServlet extends AbstractCGIServlet
*/ */
private Repository getRepository(String repositoryname) private Repository getRepository(String repositoryname)
{ {
return handler.getByName(repositoryname); return repositoryManager.get(HgRepositoryHandler.TYPE_NAME, repositoryname);
} }
//~--- fields --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
@@ -204,4 +209,7 @@ public class HgCGIServlet extends AbstractCGIServlet
/** Field description */ /** Field description */
private HgRepositoryHandler handler; private HgRepositoryHandler handler;
/** Field description */
private RepositoryManager repositoryManager;
} }

View File

@@ -41,7 +41,9 @@ import com.google.inject.Singleton;
import sonia.scm.repository.HgRepositoryHandler; import sonia.scm.repository.HgRepositoryHandler;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.web.filter.PermissionFilter; import sonia.scm.web.filter.PermissionFilter;
import sonia.scm.web.filter.RegexPermissionFilter;
import sonia.scm.web.security.SecurityContext; import sonia.scm.web.security.SecurityContext;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
@@ -53,7 +55,7 @@ import javax.servlet.http.HttpServletRequest;
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
@Singleton @Singleton
public class HgPermissionFilter extends PermissionFilter public class HgPermissionFilter extends RegexPermissionFilter
{ {
/** /**
@@ -61,14 +63,13 @@ public class HgPermissionFilter extends PermissionFilter
* *
* *
* @param securityContextProvider * @param securityContextProvider
* @param handler * @param repositoryManager
*/ */
@Inject @Inject
public HgPermissionFilter(Provider<SecurityContext> securityContextProvider, public HgPermissionFilter(Provider<SecurityContext> securityContextProvider,
HgRepositoryHandler handler) RepositoryManager repositoryManager)
{ {
super(securityContextProvider); super(securityContextProvider, repositoryManager);
this.handler = handler;
} }
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
@@ -77,14 +78,12 @@ public class HgPermissionFilter extends PermissionFilter
* Method description * Method description
* *
* *
* @param name
*
* @return * @return
*/ */
@Override @Override
protected Repository getRepository(String name) protected String getType()
{ {
return handler.getByName(name); return HgRepositoryHandler.TYPE_NAME;
} }
/** /**
@@ -100,9 +99,4 @@ public class HgPermissionFilter extends PermissionFilter
{ {
return !request.getMethod().equalsIgnoreCase("GET"); return !request.getMethod().equalsIgnoreCase("GET");
} }
//~--- fields ---------------------------------------------------------------
/** Field description */
private HgRepositoryHandler handler;
} }

View File

@@ -40,8 +40,10 @@ import com.google.inject.Provider;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.SvnRepositoryHandler; import sonia.scm.repository.SvnRepositoryHandler;
import sonia.scm.web.filter.PermissionFilter; import sonia.scm.web.filter.PermissionFilter;
import sonia.scm.web.filter.RegexPermissionFilter;
import sonia.scm.web.security.SecurityContext; import sonia.scm.web.security.SecurityContext;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
@@ -57,7 +59,7 @@ import javax.servlet.http.HttpServletRequest;
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
@Singleton @Singleton
public class SvnPermissionFilter extends PermissionFilter public class SvnPermissionFilter extends RegexPermissionFilter
{ {
/** Field description */ /** Field description */
@@ -74,14 +76,13 @@ public class SvnPermissionFilter extends PermissionFilter
* *
* *
* @param securityContextProvider * @param securityContextProvider
* @param handler * @param repositoryManager
*/ */
@Inject @Inject
public SvnPermissionFilter(Provider<SecurityContext> securityContextProvider, public SvnPermissionFilter(Provider<SecurityContext> securityContextProvider,
SvnRepositoryHandler handler) RepositoryManager repositoryManager)
{ {
super(securityContextProvider); super(securityContextProvider, repositoryManager);
this.handler = handler;
} }
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
@@ -90,14 +91,12 @@ public class SvnPermissionFilter extends PermissionFilter
* Method description * Method description
* *
* *
* @param name
*
* @return * @return
*/ */
@Override @Override
protected Repository getRepository(String name) protected String getType()
{ {
return handler.getByName(name); return SvnRepositoryHandler.TYPE_NAME;
} }
/** /**
@@ -113,9 +112,4 @@ public class SvnPermissionFilter extends PermissionFilter
{ {
return WRITEMETHOD_SET.contains(request.getMethod().toUpperCase()); return WRITEMETHOD_SET.contains(request.getMethod().toUpperCase());
} }
//~--- fields ---------------------------------------------------------------
/** Field description */
private SvnRepositoryHandler handler;
} }

View File

@@ -1,10 +1,10 @@
/** /**
* Copyright (c) 2010, Sebastian Sdorra * Copyright (c) 2010, Sebastian Sdorra
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
@@ -13,7 +13,7 @@
* 3. Neither the name of SCM-Manager; nor the names of its * 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this * contributors may be used to endorse or promote products derived from this
* software without specific prior written permission. * software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -24,22 +24,29 @@
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 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 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* http://bitbucket.org/sdorra/scm-manager * http://bitbucket.org/sdorra/scm-manager
* *
*/ */
package sonia.scm; package sonia.scm;
//~--- JDK imports ------------------------------------------------------------
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.util.Collection;
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
*
* @param <T>
* @param <E>
*/ */
public interface HandlerBase<T extends TypedObject, E extends Exception> extends Initable, Closeable public interface HandlerBase<T extends TypedObject, E extends Exception>
extends Initable, Closeable
{ {
/** /**
@@ -74,37 +81,4 @@ public interface HandlerBase<T extends TypedObject, E extends Exception> extends
* @throws IOException * @throws IOException
*/ */
public void modify(T object) throws E, IOException; public void modify(T object) throws E, IOException;
/**
* Method description
*
*
* @param object
*
* @throws E
* @throws IOException
*/
public void refresh(T object) throws E, IOException;
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
*
* @param id
*
* @return
*/
public T get(String id);
/**
* Method description
*
*
* @return
*/
public Collection<T> getAll();
} }

View File

@@ -35,6 +35,8 @@ package sonia.scm;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import java.util.Collection; import java.util.Collection;
/** /**
@@ -48,6 +50,38 @@ public interface Manager<T extends TypedObject, E extends Exception>
extends HandlerBase<T, E> extends HandlerBase<T, E>
{ {
/**
* Method description
*
*
* @param object
*
* @throws E
* @throws IOException
*/
public void refresh(T object) throws E, IOException;
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
*
* @param id
*
* @return
*/
public T get(String id);
/**
* Method description
*
*
* @return
*/
public Collection<T> getAll();
/** /**
* Method description * Method description
* *

View File

@@ -49,7 +49,6 @@ import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import javax.xml.bind.JAXB; import javax.xml.bind.JAXB;
@@ -212,18 +211,6 @@ public abstract class AbstractRepositoryHandler<C extends SimpleRepositoryConfig
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param repository
*/
protected void initNewRepository(Repository repository)
{
repository.setId(UUID.randomUUID().toString());
repository.setCreationDate(System.currentTimeMillis());
}
/** /**
* Method description * Method description
* *

View File

@@ -47,15 +47,8 @@ import sonia.scm.util.IOUtil;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.io.File; import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.xml.bind.JAXB;
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
@@ -70,7 +63,7 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
/** Field description */ /** Field description */
public static final String DIRECTORY_REPOSITORY = "repositories"; public static final String DIRECTORY_REPOSITORY = "repositories";
/** Field description */ /** the logger for AbstractSimpleRepositoryHandler */
private static final Logger logger = private static final Logger logger =
LoggerFactory.getLogger(AbstractSimpleRepositoryHandler.class); LoggerFactory.getLogger(AbstractSimpleRepositoryHandler.class);
@@ -89,8 +82,6 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
public void create(Repository repository) public void create(Repository repository)
throws RepositoryException, IOException throws RepositoryException, IOException
{ {
initNewRepository(repository);
File directory = getDirectory(repository); File directory = getDirectory(repository);
if (directory.exists()) if (directory.exists())
@@ -100,8 +91,6 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
create(repository, directory); create(repository, directory);
postCreate(repository, directory); postCreate(repository, directory);
repository.setType(getType().getName());
storeRepositoryConfig(repository);
} }
/** /**
@@ -136,16 +125,14 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
throws RepositoryException, IOException throws RepositoryException, IOException
{ {
File directory = getDirectory(repository); File directory = getDirectory(repository);
File repositoryFile = getRepositoryFile(repository);
if (directory.exists() && repositoryFile.exists()) if (directory.exists())
{ {
IOUtil.delete(directory); IOUtil.delete(directory);
IOUtil.delete(repositoryFile);
} }
else else if (logger.isWarnEnabled())
{ {
throw new RepositoryException("repository does not exists"); logger.warn("repository {} not found", repository);
} }
} }
@@ -159,7 +146,6 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
public void init(SCMContextProvider context) public void init(SCMContextProvider context)
{ {
super.init(context); super.init(context);
createConfigDirectory(context);
} }
/** /**
@@ -207,125 +193,12 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
public void modify(Repository repository) public void modify(Repository repository)
throws RepositoryException, IOException throws RepositoryException, IOException
{ {
Repository old = get(repository.getId());
if (old.getName().equals(repository.getName())) // nothing todo
{
storeRepositoryConfig(repository);
}
else
{
throw new RepositoryException(
"the name of a repository could not changed");
}
}
/**
* Method description
*
*
* @param repository
*
* @throws IOException
* @throws RepositoryException
*/
@Override
public void refresh(Repository repository)
throws RepositoryException, IOException
{
Repository fresh = get(repository.getId());
fresh.copyProperties(repository);
} }
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param id
*
* @return
*/
@Override
public Repository get(String id)
{
File repositoryFile = getRepositoryFile(id);
Repository repository = null;
if (repositoryFile.exists())
{
repository = getRepositoryFromConfig(repositoryFile);
}
return repository;
}
/**
* Method description
*
*
* @return
*/
@Override
public Collection<Repository> getAll()
{
List<Repository> repositories = new ArrayList<Repository>();
File[] repositoryFiles = configDirectory.listFiles(new FilenameFilter()
{
@Override
public boolean accept(File dir, String name)
{
return name.endsWith(".xml");
}
});
for (File repositoryFile : repositoryFiles)
{
try
{
Repository repository = getRepositoryFromConfig(repositoryFile);
if (repository != null)
{
repositories.add(repository);
}
}
catch (Exception ex)
{
logger.error(ex.getMessage(), ex);
}
}
return repositories;
}
/**
* Method description
*
*
* @param repositoryname
*
* @return
*/
public Repository getByName(String repositoryname)
{
Repository repository = null;
for (Repository r : getAll())
{
if (r.getName().equals(repositoryname))
{
repository = r;
break;
}
}
return repository;
}
/** /**
* Method description * Method description
* *
@@ -395,24 +268,6 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
} }
} }
/**
* Method description
*
*
* @param context
*/
protected void createConfigDirectory(SCMContextProvider context)
{
configDirectory =
new File(baseDirectory,
"config".concat(File.separator).concat(getType().getName()));
if (!configDirectory.exists() &&!configDirectory.mkdirs())
{
throw new ConfigurationException("could not create config directory");
}
}
/** /**
* Method description * Method description
* *
@@ -436,75 +291,4 @@ public abstract class AbstractSimpleRepositoryHandler<C extends SimpleRepository
*/ */
protected void postCreate(Repository repository, File directory) protected void postCreate(Repository repository, File directory)
throws IOException, RepositoryException {} throws IOException, RepositoryException {}
/**
* Method description
*
*
* @param repository
*/
protected void storeRepositoryConfig(Repository repository)
{
JAXB.marshal(repository, getRepositoryFile(repository));
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param repositoryFile
*
* @return
*/
protected Repository getRepositoryFromConfig(File repositoryFile)
{
Repository repository = JAXB.unmarshal(repositoryFile, Repository.class);
File directory = getDirectory(repository);
if (!directory.exists())
{
if (logger.isWarnEnabled())
{
logger.warn("could not find repository ".concat(repository.getName()));
}
repository = null;
}
return repository;
}
/**
* Method description
*
*
*
* @param id
*
* @return
*/
private File getRepositoryFile(String id)
{
return new File(configDirectory, id.concat(".xml"));
}
/**
* Method description
*
*
* @param repository
*
* @return
*/
private File getRepositoryFile(Repository repository)
{
return getRepositoryFile(repository.getId());
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private File configDirectory;
} }

View File

@@ -63,10 +63,11 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = @XmlType(propOrder =
{ {
"id", "type", "name", "contact", "description", "creationDate", "url", "id", "type", "name", "contact", "description", "creationDate",
"permissions" "lastModified", "url", "permissions"
}) })
public class Repository implements TypedObject, Validateable, Serializable public class Repository
implements TypedObject, Validateable, Cloneable, Serializable
{ {
/** Field description */ /** Field description */
@@ -126,6 +127,29 @@ public class Repository implements TypedObject, Validateable, Serializable
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Override
public Repository clone()
{
Repository repository = null;
try
{
repository = (Repository) super.clone();
}
catch (CloneNotSupportedException ex)
{
throw new RuntimeException(ex);
}
return repository;
}
/** /**
* Method description * Method description
* *
@@ -142,6 +166,22 @@ public class Repository implements TypedObject, Validateable, Serializable
repository.setUrl(url); repository.setUrl(url);
} }
/**
* Method description
*
*
* @return
*/
@Override
public String toString()
{
StringBuilder buffer = new StringBuilder("Repository{type=");
buffer.append(type).append(", name=").append(name).append("}");
return buffer.toString();
}
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
/** /**
@@ -188,6 +228,17 @@ public class Repository implements TypedObject, Validateable, Serializable
return id; return id;
} }
/**
* Method description
*
*
* @return
*/
public Long getLastModified()
{
return lastModified;
}
/** /**
* Method description * Method description
* *
@@ -293,6 +344,17 @@ public class Repository implements TypedObject, Validateable, Serializable
this.id = id; this.id = id;
} }
/**
* Method description
*
*
* @param lastModified
*/
public void setLastModified(long lastModified)
{
this.lastModified = lastModified;
}
/** /**
* Method description * Method description
* *
@@ -352,6 +414,10 @@ public class Repository implements TypedObject, Validateable, Serializable
/** Field description */ /** Field description */
private String id; private String id;
/** Field description */
@XmlJavaTypeAdapter(XmlTimestampDateAdapter.class)
private Long lastModified;
/** Field description */ /** Field description */
private String name; private String name;

View File

@@ -47,6 +47,17 @@ public interface RepositoryManager
ListenerSupport<RepositoryListener> ListenerSupport<RepositoryListener>
{ {
/**
* Method description
*
*
* @param type
* @param name
*
* @return
*/
public Repository get(String type, String name);
/** /**
* Method description * Method description
* *

View File

@@ -0,0 +1,267 @@
/**
* 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.repository.xml;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.repository.Repository;
import sonia.scm.xml.XmlTimestampDateAdapter;
//~--- JDK imports ------------------------------------------------------------
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
*
* @author Sebastian Sdorra
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class XmlRepositoryDatabase
{
/**
* Method description
*
*
* @param repository
*/
public void add(Repository repository)
{
repositoryMap.put(createKey(repository), repository);
}
/**
* Method description
*
*
*
* @param type
* @param name
*
* @return
*/
public boolean contains(String type, String name)
{
return repositoryMap.containsKey(createKey(type, name));
}
/**
* Method description
*
*
* @param id
*
* @return
*/
public boolean contains(String id)
{
return get(id) != null;
}
/**
* Method description
*
*
* @param repository
*
* @return
*/
public boolean contains(Repository repository)
{
return repositoryMap.containsKey(createKey(repository));
}
/**
* Method description
*
*
* @param repository
*/
public void remove(Repository repository)
{
repositoryMap.remove(createKey(repository));
}
/**
* Method description
*
*
* @return
*/
public Collection<Repository> values()
{
return repositoryMap.values();
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param type
* @param name
*
* @return
*/
public Repository get(String type, String name)
{
return repositoryMap.get(createKey(type, name));
}
/**
* Method description
*
*
* @param id
*
* @return
*/
public Repository get(String id)
{
Repository repository = null;
for (Repository r : values())
{
if (r.getId().equals(id))
{
repository = r;
break;
}
}
return repository;
}
/**
* Method description
*
*
* @return
*/
public long getCreationTime()
{
return creationTime;
}
/**
* Method description
*
*
* @return
*/
public long getLastModified()
{
return lastModified;
}
//~--- set methods ----------------------------------------------------------
/**
* Method description
*
*
* @param creationTime
*/
public void setCreationTime(long creationTime)
{
this.creationTime = creationTime;
}
/**
* Method description
*
*
* @param lastModified
*/
public void setLastModified(long lastModified)
{
this.lastModified = lastModified;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param type
* @param name
*
* @return
*/
static String createKey(String type, String name)
{
return type.concat(":").concat(name);
}
/**
* Method description
*
*
* @param repository
*
* @return
*/
static String createKey(Repository repository)
{
return createKey(repository.getType(), repository.getName());
}
//~--- fields ---------------------------------------------------------------
/** Field description */
@XmlJavaTypeAdapter(XmlTimestampDateAdapter.class)
private Long creationTime;
/** Field description */
@XmlJavaTypeAdapter(XmlTimestampDateAdapter.class)
private Long lastModified;
/** Field description */
@XmlJavaTypeAdapter(XmlRepositoryMapAdapter.class)
@XmlElement(name = "repositories")
private Map<String, Repository> repositoryMap = new LinkedHashMap<String,
Repository>();
}

View File

@@ -0,0 +1,123 @@
/**
* 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.repository.xml;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.repository.Repository;
//~--- JDK imports ------------------------------------------------------------
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author Sebastian Sdorra
*/
@XmlRootElement(name = "repositories")
@XmlAccessorType(XmlAccessType.FIELD)
public class XmlRepositoryList implements Iterable<Repository>
{
/**
* Constructs ...
*
*/
public XmlRepositoryList() {}
/**
* Constructs ...
*
*
*
* @param repositoryMap
*/
public XmlRepositoryList(Map<String, Repository> repositoryMap)
{
this.repositories = new LinkedList<Repository>(repositoryMap.values());
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Override
public Iterator<Repository> iterator()
{
return repositories.iterator();
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public LinkedList<Repository> getRepositories()
{
return repositories;
}
//~--- set methods ----------------------------------------------------------
/**
* Method description
*
*
* @param repositories
*/
public void setRepositories(LinkedList<Repository> repositories)
{
this.repositories = repositories;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
@XmlElement(name = "repository")
private LinkedList<Repository> repositories;
}

View File

@@ -31,7 +31,7 @@
package sonia.scm.repository; package sonia.scm.repository.xml;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
@@ -46,32 +46,45 @@ import sonia.scm.HandlerEvent;
import sonia.scm.SCMContext; import sonia.scm.SCMContext;
import sonia.scm.SCMContextProvider; import sonia.scm.SCMContextProvider;
import sonia.scm.Type; import sonia.scm.Type;
import sonia.scm.repository.AbstractRepositoryManager;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryAllreadyExistExeption;
import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RepositoryHandler;
import sonia.scm.repository.RepositoryHandlerNotFoundException;
import sonia.scm.util.AssertUtil; import sonia.scm.util.AssertUtil;
import sonia.scm.util.IOUtil; import sonia.scm.util.IOUtil;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.LinkedList;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import javax.xml.bind.JAXB;
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
@Singleton @Singleton
public class BasicRepositoryManager extends AbstractRepositoryManager public class XmlRepositoryManager extends AbstractRepositoryManager
{ {
/** Field description */
public static final String DATABASEFILE =
"config".concat(File.separator).concat("repositories.xml");
/** Field description */ /** Field description */
private static final Logger logger = private static final Logger logger =
LoggerFactory.getLogger(BasicRepositoryManager.class); LoggerFactory.getLogger(XmlRepositoryManager.class);
//~--- constructors --------------------------------------------------------- //~--- constructors ---------------------------------------------------------
@@ -82,10 +95,10 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
* @param handlerSet * @param handlerSet
*/ */
@Inject @Inject
public BasicRepositoryManager(Set<RepositoryHandler> handlerSet) public XmlRepositoryManager(Set<RepositoryHandler> handlerSet)
{ {
handlerMap = new HashMap<String, RepositoryHandler>(); handlerMap = new HashMap<String, RepositoryHandler>();
types = new ArrayList<Type>(); types = new HashSet<Type>();
for (RepositoryHandler handler : handlerSet) for (RepositoryHandler handler : handlerSet)
{ {
@@ -130,7 +143,22 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
} }
AssertUtil.assertIsValid(repository); AssertUtil.assertIsValid(repository);
if (repositoryDB.contains(repository))
{
throw new RepositoryAllreadyExistExeption();
}
repository.setId(UUID.randomUUID().toString());
repository.setCreationDate(System.currentTimeMillis());
getHandler(repository).create(repository); getHandler(repository).create(repository);
synchronized (XmlRepositoryDatabase.class)
{
repositoryDB.add(repository);
storeDB();
}
fireEvent(repository, HandlerEvent.CREATE); fireEvent(repository, HandlerEvent.CREATE);
} }
@@ -153,7 +181,22 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
repository.getType()); repository.getType());
} }
getHandler(repository).delete(repository); if (repositoryDB.contains(repository))
{
getHandler(repository).delete(repository);
synchronized (XmlRepositoryDatabase.class)
{
repositoryDB.remove(repository);
storeDB();
}
}
else
{
throw new RepositoryException(
"repository ".concat(repository.getName()).concat(" not found"));
}
fireEvent(repository, HandlerEvent.DELETE); fireEvent(repository, HandlerEvent.DELETE);
} }
@@ -164,7 +207,23 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
* @param context * @param context
*/ */
@Override @Override
public void init(SCMContextProvider context) {} public void init(SCMContextProvider context)
{
File directory = context.getBaseDirectory();
repositoryDBFile = new File(directory, DATABASEFILE);
if (repositoryDBFile.exists())
{
loadDB();
}
else
{
IOUtil.mkdirs(repositoryDBFile.getParentFile());
repositoryDB = new XmlRepositoryDatabase();
repositoryDB.setCreationTime(System.currentTimeMillis());
}
}
/** /**
* Method description * Method description
@@ -186,7 +245,25 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
} }
AssertUtil.assertIsValid(repository); AssertUtil.assertIsValid(repository);
getHandler(repository).modify(repository);
if (repositoryDB.contains(repository))
{
getHandler(repository).modify(repository);
repository.setLastModified(System.currentTimeMillis());
synchronized (XmlRepositoryDatabase.class)
{
repositoryDB.remove(repository);
repositoryDB.add(repository.clone());
storeDB();
}
}
else
{
throw new RepositoryException(
"repository ".concat(repository.getName()).concat(" not found"));
}
fireEvent(repository, HandlerEvent.MODIFY); fireEvent(repository, HandlerEvent.MODIFY);
} }
@@ -203,7 +280,20 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
public void refresh(Repository repository) public void refresh(Repository repository)
throws RepositoryException, IOException throws RepositoryException, IOException
{ {
getHandler(repository).refresh(repository); AssertUtil.assertIsNotNull(repository);
Repository fresh = repositoryDB.get(repository.getType(),
repository.getName());
if (repository != null)
{
repository.copyProperties(fresh);
}
else
{
throw new RepositoryException(
"repository ".concat(repository.getName()).concat(" not found"));
}
} }
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
@@ -212,7 +302,6 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
* Method description * Method description
* *
* *
*
* @param id * @param id
* *
* @return * @return
@@ -220,19 +309,38 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
@Override @Override
public Repository get(String id) public Repository get(String id)
{ {
Repository repository = null; AssertUtil.assertIsNotEmpty(id);
for (RepositoryHandler handler : handlerMap.values()) Repository repository = repositoryDB.get(id);
if (repository != null)
{ {
if (handler.isConfigured()) repository = repository.clone();
{ }
repository = handler.get(id);
if (repository != null) return repository;
{ }
break;
} /**
} * Method description
*
*
* @param type
* @param name
*
* @return
*/
@Override
public Repository get(String type, String name)
{
AssertUtil.assertIsNotEmpty(type);
AssertUtil.assertIsNotEmpty(name);
Repository repository = repositoryDB.get(type, name);
if (repository != null)
{
repository = repository.clone();
} }
return repository; return repository;
@@ -247,29 +355,11 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
@Override @Override
public Collection<Repository> getAll() public Collection<Repository> getAll()
{ {
if (logger.isDebugEnabled()) LinkedList<Repository> repositories = new LinkedList<Repository>();
for (Repository repository : repositoryDB.values())
{ {
logger.debug("fetch all repositories"); repositories.add(repository.clone());
}
Set<Repository> repositories = new HashSet<Repository>();
for (RepositoryHandler handler : handlerMap.values())
{
if (handler.isConfigured())
{
Collection<Repository> handlerRepositories = handler.getAll();
if (handlerRepositories != null)
{
repositories.addAll(handlerRepositories);
}
}
}
if (logger.isDebugEnabled())
{
logger.debug("fetched {} repositories", repositories.size());
} }
return repositories; return repositories;
@@ -334,6 +424,26 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
types.add(type); types.add(type);
} }
/**
* Method description
*
*/
private void loadDB()
{
repositoryDB = JAXB.unmarshal(repositoryDBFile,
XmlRepositoryDatabase.class);
}
/**
* Method description
*
*/
private void storeDB()
{
repositoryDB.setLastModified(System.currentTimeMillis());
JAXB.marshal(repositoryDB, repositoryDBFile);
}
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
/** /**
@@ -372,5 +482,11 @@ public class BasicRepositoryManager extends AbstractRepositoryManager
private Map<String, RepositoryHandler> handlerMap; private Map<String, RepositoryHandler> handlerMap;
/** Field description */ /** Field description */
private List<Type> types; private XmlRepositoryDatabase repositoryDB;
/** Field description */
private File repositoryDBFile;
/** Field description */
private Set<Type> types;
} }

View File

@@ -31,26 +31,67 @@
package sonia.scm.user; package sonia.scm.repository.xml;
import sonia.scm.user.xml.XmlUserHandler; //~--- non-JDK imports --------------------------------------------------------
import sonia.scm.repository.Repository;
//~--- JDK imports ------------------------------------------------------------
import java.util.LinkedHashMap;
import java.util.Map;
import javax.xml.bind.annotation.adapters.XmlAdapter;
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
public class XmlUserHandlerTest extends UserHandlerTestBase public class XmlRepositoryMapAdapter
extends XmlAdapter<XmlRepositoryList, Map<String, Repository>>
{ {
/** /**
* Method description * Method description
* *
* *
* @param repositoryMap
*
* @return * @return
*
* @throws Exception
*/ */
@Override @Override
public UserHandler createUserHandler() public XmlRepositoryList marshal(Map<String, Repository> repositoryMap)
throws Exception
{ {
return new XmlUserHandler(); return new XmlRepositoryList(repositoryMap);
}
/**
* Method description
*
*
* @param repositories
*
* @return
*
* @throws Exception
*/
@Override
public Map<String, Repository> unmarshal(XmlRepositoryList repositories)
throws Exception
{
Map<String, Repository> repositoryMap = new LinkedHashMap<String,
Repository>();
for (Repository repository : repositories)
{
repositoryMap.put(XmlRepositoryDatabase.createKey(repository),
repository);
}
return repositoryMap;
} }
} }

View File

@@ -216,7 +216,7 @@ public class BasicUserManager implements UserManager
logger.info("refresh user {} of type {}", user.getName(), user.getType()); logger.info("refresh user {} of type {}", user.getName(), user.getType());
} }
getHandler(user).refresh(user); // getHandler(user).refresh(user);
} }
/** /**
@@ -250,8 +250,8 @@ public class BasicUserManager implements UserManager
{ {
if (handler.isConfigured()) if (handler.isConfigured())
{ {
user = handler.get(id);
// user = handler.get(id);
if (user != null) if (user != null)
{ {
break; break;
@@ -278,19 +278,20 @@ public class BasicUserManager implements UserManager
Set<User> repositories = new HashSet<User>(); Set<User> repositories = new HashSet<User>();
for (UserHandler handler : handlerMap.values()) /*
{ * for (UserHandler handler : handlerMap.values())
if (handler.isConfigured()) * {
{ * if (handler.isConfigured())
Collection<User> handlerRepositories = handler.getAll(); * {
* Collection<User> handlerRepositories = handler.getAll();
if (handlerRepositories != null) *
{ * if (handlerRepositories != null)
repositories.addAll(handlerRepositories); * {
} * repositories.addAll(handlerRepositories);
} * }
} * }
* }
*/
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("fetched {} users", repositories.size()); logger.debug("fetched {} users", repositories.size());

View File

@@ -117,6 +117,22 @@ public class User
return user; return user;
} }
/**
* Method description
*
*
* @param user
*/
public void copyProperties(User user)
{
user.setAdmin(admin);
user.setDisplayName(displayName);
user.setMail(mail);
user.setName(name);
user.setPassword(password);
user.setType(type);
}
/** /**
* Method description * Method description
* *

View File

@@ -225,7 +225,6 @@ public class XmlUserHandler implements UserHandler
* @throws IOException * @throws IOException
* @throws UserException * @throws UserException
*/ */
@Override
public void refresh(User user) throws UserException, IOException public void refresh(User user) throws UserException, IOException
{ {
User fresh = userDB.get(user.getName()); User fresh = userDB.get(user.getName());
@@ -235,10 +234,7 @@ public class XmlUserHandler implements UserHandler
throw new UserException("user does not exists"); throw new UserException("user does not exists");
} }
user.setDisplayName(fresh.getDisplayName()); fresh.copyProperties(user);
user.setMail(fresh.getMail());
user.setPassword(fresh.getPassword());
user.setType(TYPE_NAME);
} }
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
@@ -251,7 +247,6 @@ public class XmlUserHandler implements UserHandler
* *
* @return * @return
*/ */
@Override
public User get(String id) public User get(String id)
{ {
User user = userDB.get(id); User user = userDB.get(id);
@@ -270,7 +265,6 @@ public class XmlUserHandler implements UserHandler
* *
* @return * @return
*/ */
@Override
public Collection<User> getAll() public Collection<User> getAll()
{ {
LinkedList<User> users = new LinkedList<User>(); LinkedList<User> users = new LinkedList<User>();

View File

@@ -1,515 +0,0 @@
/**
* 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.user;
//~--- non-JDK imports --------------------------------------------------------
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import sonia.scm.SCMContextProvider;
import sonia.scm.util.IOUtil;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
/**
*
* @author Sebastian Sdorra
*/
public abstract class UserHandlerTestBase
{
/** Field description */
public static final int THREAD_COUNT = 10;
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public abstract UserHandler createUserHandler();
/**
* Method description
*
*
* @throws IOException
*/
@After
public void tearDownTest() throws IOException
{
try
{
handler.close();
}
finally
{
IOUtil.delete(tempDirectory);
}
}
/**
* Method description
*
*
* @throws IOException
* @throws UserException
*/
@Test
public void testCreate() throws UserException, IOException
{
User zaphod = getTestUser();
handler.create(zaphod);
User otherUser = handler.get("zaphod");
assertNotNull(otherUser);
assertUserEquals(zaphod, otherUser);
}
/**
* Method description
*
*
* @throws IOException
* @throws UserException
*/
@Test(expected = UserAllreadyExistException.class)
public void testCreateExisting() throws UserException, IOException
{
User zaphod = getTestUser();
handler.create(zaphod);
assertNotNull(handler.get("zaphod"));
User sameUser = getTestUser();
handler.create(sameUser);
}
/**
* Method description
*
*
* @throws IOException
* @throws UserException
*/
@Test
public void testDelete() throws UserException, IOException
{
User zaphod = getTestUser();
handler.create(zaphod);
assertNotNull(handler.get("zaphod"));
handler.delete(zaphod);
assertNull(handler.get("zaphod"));
}
/**
* Method description
*
*
* @throws IOException
* @throws UserException
*/
@Test
public void testGet() throws UserException, IOException
{
User zaphod = getTestUser();
handler.create(zaphod);
assertNotNull(handler.get("zaphod"));
// test for reference
zaphod.setDisplayName("Tricia McMillan");
zaphod = handler.get("zaphod");
assertNotNull(zaphod);
assertEquals("Zaphod Beeblebrox", zaphod.getDisplayName());
}
/**
* Method description
*
*
* @throws IOException
* @throws UserException
*/
@Test
public void testGetAll() throws UserException, IOException
{
User zaphod = getTestUser();
handler.create(zaphod);
assertNotNull(handler.get("zaphod"));
User trillian = new User("trillian", "Tricia McMillan",
"tricia.mcmillan@hitchhiker.com");
handler.create(trillian);
assertNotNull(handler.get("trillian"));
boolean foundZaphod = false;
boolean foundTrillian = false;
Collection<User> users = handler.getAll();
assertNotNull(users);
assertFalse(users.isEmpty());
assertTrue(users.size() >= 2);
for (User u : users)
{
if (u.getName().equals("zaphod"))
{
foundZaphod = true;
assertUserEquals(zaphod, u);
}
else if (u.getName().equals("trillian"))
{
foundTrillian = true;
assertUserEquals(trillian, u);
}
}
assertTrue(foundZaphod);
assertTrue(foundTrillian);
// test for reference
trillian = null;
for (User u : users)
{
if (u.getName().equals("trillian"))
{
trillian = u;
}
}
assertNotNull(trillian);
trillian.setDisplayName("Zaphod Beeblebrox");
User reference = null;
for (User u : handler.getAll())
{
if (u.getName().equals("trillian"))
{
reference = u;
}
}
assertNotNull(reference);
assertEquals(reference.getDisplayName(), "Tricia McMillan");
}
/**
* Method description
*
*
* @throws IOException
* @throws UserException
*/
@Test
public void testModify() throws UserException, IOException
{
User zaphod = getTestUser();
handler.create(zaphod);
assertNotNull(handler.get("zaphod"));
zaphod.setDisplayName("Tricia McMillan");
handler.modify(zaphod);
User otherUser = handler.get("zaphod");
assertNotNull(otherUser);
assertEquals(otherUser.getDisplayName(), "Tricia McMillan");
}
/**
* Method description
*
*
* @throws IOException
* @throws UserException
*/
@Test(expected = UserException.class)
public void testModifyNotExisting() throws UserException, IOException
{
User zaphod = getTestUser();
handler.modify(zaphod);
}
/**
* Method description
*
*
* @throws IOException
* @throws InterruptedException
* @throws UserException
*/
@Test
public void testMultiThreaded()
throws UserException, IOException, InterruptedException
{
int initialSize = handler.getAll().size();
List<MultiThreadTester> testers = new ArrayList<MultiThreadTester>();
for (int i = 0; i < THREAD_COUNT; i++)
{
testers.add(new MultiThreadTester(handler));
}
for (MultiThreadTester tester : testers)
{
new Thread(tester).start();
}
boolean fin = false;
while (!fin)
{
Thread.sleep(100l);
fin = true;
for (MultiThreadTester tester : testers)
{
if (!tester.finished)
{
fin = false;
}
}
}
assertTrue((initialSize + THREAD_COUNT) == handler.getAll().size());
}
/**
* Method description
*
*
* @throws IOException
* @throws UserException
*/
@Test
public void testRefresh() throws UserException, IOException
{
User zaphod = getTestUser();
handler.create(zaphod);
assertNotNull(handler.get("zaphod"));
zaphod.setDisplayName("Tricia McMillan");
handler.refresh(zaphod);
assertEquals(zaphod.getDisplayName(), "Zaphod Beeblebrox");
}
//~--- set methods ----------------------------------------------------------
/**
* Method description
*
*/
@Before
public void setUpTest()
{
tempDirectory = new File(System.getProperty("java.io.tmpdir"),
UUID.randomUUID().toString());
assertTrue(tempDirectory.mkdirs());
handler = createUserHandler();
SCMContextProvider provider = mock(SCMContextProvider.class);
when(provider.getBaseDirectory()).thenReturn(tempDirectory);
handler.init(provider);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param user
* @param otherUser
*/
private void assertUserEquals(User user, User otherUser)
{
assertEquals(user.getName(), otherUser.getName());
assertEquals(user.getDisplayName(), otherUser.getDisplayName());
assertEquals(user.getMail(), otherUser.getMail());
assertEquals(user.getPassword(), otherUser.getPassword());
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
private User getTestUser()
{
return new User("zaphod", "Zaphod Beeblebrox",
"zaphod.beeblebrox@hitchhiker.com");
}
//~--- inner classes --------------------------------------------------------
/**
* Class description
*
*
* @version Enter version here..., 2010-11-23
* @author Sebastian Sdorra
*/
private static class MultiThreadTester implements Runnable
{
/**
* Constructs ...
*
*
* @param userHandler
*/
public MultiThreadTester(UserHandler userHandler)
{
this.userHandler = userHandler;
}
//~--- methods ------------------------------------------------------------
/**
* Method description
*
*/
@Override
public void run()
{
try
{
User user = createUser();
modifyAndDeleteUser(user);
createUser();
}
catch (Exception ex)
{
throw new RuntimeException(ex);
}
finished = true;
}
/**
* Method description
*
*
* @return
*
* @throws IOException
* @throws UserException
*/
private User createUser() throws UserException, IOException
{
String id = UUID.randomUUID().toString();
User user = new User(id, id.concat(" displayName"),
id.concat("@mail.com"));
userHandler.create(user);
return user;
}
/**
* Method description
*
*
* @param user
*
* @throws IOException
* @throws UserException
*/
private void modifyAndDeleteUser(User user)
throws UserException, IOException
{
String name = user.getName();
String nd = name.concat(" new displayname");
user.setDisplayName(nd);
userHandler.modify(user);
User otherUser = userHandler.get(name);
assertNotNull(otherUser);
assertEquals(nd, otherUser.getDisplayName());
userHandler.delete(user);
otherUser = userHandler.get(name);
assertNull(otherUser);
}
//~--- fields -------------------------------------------------------------
/** Field description */
private boolean finished = false;
/** Field description */
private UserHandler userHandler;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private UserHandler handler;
/** Field description */
private File tempDirectory;
}

View File

@@ -50,9 +50,6 @@ import sonia.scm.web.security.SecurityContext;
import java.io.IOException; import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@@ -69,10 +66,6 @@ public abstract class PermissionFilter extends HttpFilter
private static final Logger logger = private static final Logger logger =
LoggerFactory.getLogger(PermissionFilter.class); LoggerFactory.getLogger(PermissionFilter.class);
/** Field description */
public static final Pattern PATTERN_REPOSITORYNAME =
Pattern.compile("/[^/]+/([^/]+)(?:/.*)?");
//~--- constructors --------------------------------------------------------- //~--- constructors ---------------------------------------------------------
/** /**
@@ -88,6 +81,16 @@ public abstract class PermissionFilter extends HttpFilter
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param request
*
* @return
*/
protected abstract Repository getRepository(HttpServletRequest request);
/** /**
* Method description * Method description
* *
@@ -170,50 +173,6 @@ public abstract class PermissionFilter extends HttpFilter
} }
} }
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param request
*
* @return
*/
protected Repository getRepository(HttpServletRequest request)
{
Repository repository = null;
String uri = request.getRequestURI();
uri = uri.substring(request.getContextPath().length());
Matcher m = PATTERN_REPOSITORYNAME.matcher(uri);
if (m.matches())
{
String repositoryname = m.group(1);
repository = getRepository(repositoryname);
}
return repository;
}
/**
* Method description
*
*
* @param name
*
* @return
*/
protected Repository getRepository(String name)
{
return null;
}
;
//~--- fields --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
/** Field description */ /** Field description */

View File

@@ -0,0 +1,134 @@
/**
* 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.web.filter;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Provider;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.web.security.SecurityContext;
//~--- JDK imports ------------------------------------------------------------
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
/**
*
* @author Sebastian Sdorra
*/
public abstract class RegexPermissionFilter extends PermissionFilter
{
/** Field description */
public static final Pattern PATTERN_REPOSITORYNAME =
Pattern.compile("/[^/]+/([^/]+)(?:/.*)?");
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param securityContextProvider
* @param repositoryManager
*/
public RegexPermissionFilter(
Provider<SecurityContext> securityContextProvider,
RepositoryManager repositoryManager)
{
super(securityContextProvider);
this.repositoryManager = repositoryManager;
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
protected abstract String getType();
/**
* Method description
*
*
* @param request
*
* @return
*/
@Override
protected Repository getRepository(HttpServletRequest request)
{
Repository repository = null;
String uri = request.getRequestURI();
uri = uri.substring(request.getContextPath().length());
Matcher m = PATTERN_REPOSITORYNAME.matcher(uri);
if (m.matches())
{
String repositoryname = m.group(1);
repository = getRepository(repositoryname);
}
return repository;
}
/**
* Method description
*
*
* @param name
*
* @return
*/
protected Repository getRepository(String name)
{
return repositoryManager.get(getType(), name);
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private RepositoryManager repositoryManager;
}

View File

@@ -43,12 +43,10 @@ import org.slf4j.LoggerFactory;
import sonia.scm.api.rest.UriExtensionsConfig; import sonia.scm.api.rest.UriExtensionsConfig;
import sonia.scm.cache.CacheManager; import sonia.scm.cache.CacheManager;
import sonia.scm.cache.CacheRepositoryManagerDecorator;
import sonia.scm.cache.EhCacheManager; import sonia.scm.cache.EhCacheManager;
import sonia.scm.config.ScmConfiguration; import sonia.scm.config.ScmConfiguration;
import sonia.scm.filter.SecurityFilter; import sonia.scm.filter.SecurityFilter;
import sonia.scm.plugin.ScriptResourceServlet; import sonia.scm.plugin.ScriptResourceServlet;
import sonia.scm.repository.BasicRepositoryManager;
import sonia.scm.repository.RepositoryHandler; import sonia.scm.repository.RepositoryHandler;
import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryManager;
import sonia.scm.security.EncryptionHandler; import sonia.scm.security.EncryptionHandler;
@@ -84,6 +82,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.xml.bind.JAXB; import javax.xml.bind.JAXB;
import sonia.scm.repository.xml.XmlRepositoryManager;
/** /**
* *
@@ -168,7 +167,7 @@ public class ScmServletModule extends ServletModule
bind(CacheManager.class).to(EhCacheManager.class); bind(CacheManager.class).to(EhCacheManager.class);
//bind(RepositoryManager.class).annotatedWith(Undecorated.class).to( //bind(RepositoryManager.class).annotatedWith(Undecorated.class).to(
// BasicRepositoryManager.class); // BasicRepositoryManager.class);
bind(RepositoryManager.class).to(BasicRepositoryManager.class); bind(RepositoryManager.class).to(XmlRepositoryManager.class);
bind(UserManager.class).to(BasicUserManager.class); bind(UserManager.class).to(BasicUserManager.class);
bind(ScmWebPluginContext.class).toInstance(webPluginContext); bind(ScmWebPluginContext.class).toInstance(webPluginContext);

View File

@@ -228,6 +228,21 @@ public class CacheRepositoryManagerDecorator
return repository; return repository;
} }
/**
* TODO cache result
*
*
* @param type
* @param name
*
* @return
*/
@Override
public Repository get(String type, String name)
{
return orginal.get(type, name);
}
/** /**
* Method description * Method description
* *