add the interface StoreFactory and refactor storeFactories

This commit is contained in:
Mohamed Karray
2018-11-27 11:35:02 +01:00
parent 39e5c19251
commit 7a1de0f67b
42 changed files with 485 additions and 291 deletions

View File

@@ -39,6 +39,7 @@ import com.google.inject.Singleton;
import sonia.scm.group.Group;
import sonia.scm.group.GroupDAO;
import sonia.scm.store.StoreParameters;
import sonia.scm.xml.AbstractXmlDAO;
import sonia.scm.store.ConfigurationStoreFactory;
@@ -64,9 +65,11 @@ public class XmlGroupDAO extends AbstractXmlDAO<Group, XmlGroupDatabase>
* @param storeFactory
*/
@Inject
public XmlGroupDAO(ConfigurationStoreFactory storeFactory)
{
super(storeFactory.getStore(XmlGroupDatabase.class, STORE_NAME));
public XmlGroupDAO(ConfigurationStoreFactory storeFactory) {
super(storeFactory.getStore(new StoreParameters()
.withType(XmlGroupDatabase.class)
.withName(STORE_NAME)
.build()));
}
//~--- methods --------------------------------------------------------------

View File

@@ -36,14 +36,18 @@ package sonia.scm.repository.xml;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import sonia.scm.SCMContextProvider;
import sonia.scm.repository.InitialRepositoryLocationResolver;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.PathBasedRepositoryDAO;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryPathNotFoundException;
import sonia.scm.store.ConfigurationStoreFactory;
import sonia.scm.store.JAXBConfigurationStore;
import sonia.scm.store.StoreConstants;
import sonia.scm.util.IOUtil;
import sonia.scm.xml.AbstractXmlDAO;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
@@ -65,14 +69,10 @@ public class XmlRepositoryDAO
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
* @param storeFactory
*/
@Inject
public XmlRepositoryDAO(ConfigurationStoreFactory storeFactory, InitialRepositoryLocationResolver initialRepositoryLocationResolver) {
super(storeFactory.getStore(XmlRepositoryDatabase.class, STORE_NAME));
public XmlRepositoryDAO(InitialRepositoryLocationResolver initialRepositoryLocationResolver, SCMContextProvider context) {
super(new JAXBConfigurationStore<>(XmlRepositoryDatabase.class, new File(context.getBaseDirectory(), StoreConstants.CONFIG_DIRECTORY_NAME + File.separator + STORE_NAME + StoreConstants.FILE_EXTENSION)));
IOUtil.mkdirs(new File(context.getBaseDirectory(), StoreConstants.CONFIG_DIRECTORY_NAME + File.separator + STORE_NAME + StoreConstants.FILE_EXTENSION));
this.initialRepositoryLocationResolver = initialRepositoryLocationResolver;
}

View File

@@ -31,18 +31,23 @@
package sonia.scm.store;
//~--- non-JDK imports --------------------------------------------------------
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.SCMContextProvider;
import sonia.scm.repository.InternalRepositoryException;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryLocationResolver;
import sonia.scm.util.IOUtil;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
//~--- JDK imports ------------------------------------------------------------
/**
* Abstract store factory for file based stores.
*
*
* @author Sebastian Sdorra
*/
public abstract class FileBasedStoreFactory {
@@ -51,18 +56,14 @@ public abstract class FileBasedStoreFactory {
* the logger for FileBasedStoreFactory
*/
private static final Logger LOG = LoggerFactory.getLogger(FileBasedStoreFactory.class);
private static final String BASE_DIRECTORY = "var";
private final SCMContextProvider context;
private RepositoryLocationResolver repositoryLocationResolver;
private final String dataDirectoryName;
private File dataDirectory;
protected FileBasedStoreFactory(SCMContextProvider context,
String dataDirectoryName) {
this.context = context;
protected FileBasedStoreFactory(RepositoryLocationResolver repositoryLocationResolver, String dataDirectoryName) {
this.repositoryLocationResolver = repositoryLocationResolver;
this.dataDirectoryName = dataDirectoryName;
}
@@ -76,9 +77,8 @@ public abstract class FileBasedStoreFactory {
*/
protected File getDirectory(String name) {
if (dataDirectory == null) {
dataDirectory = new File(context.getBaseDirectory(),
BASE_DIRECTORY.concat(File.separator).concat(dataDirectoryName));
LOG.debug("create data directory {}", dataDirectory);
dataDirectory = new File(repositoryLocationResolver.getGlobalStoreDirectory(), dataDirectoryName);
LOG.debug("get data directory {}", dataDirectory);
}
File storeDirectory = new File(dataDirectory, name);
@@ -86,4 +86,25 @@ public abstract class FileBasedStoreFactory {
return storeDirectory;
}
/**
* Returns data directory for given name.
*
* @param name name of data directory
*
* @return data directory
*/
protected File getDirectory(String name, Repository repository) {
if (dataDirectory == null) {
try {
dataDirectory = new File(repositoryLocationResolver.getStoresDirectory(repository), dataDirectoryName);
} catch (IOException e) {
throw new InternalRepositoryException(repository, MessageFormat.format("Error on getting the store directory {0} of the repository {1}", dataDirectory.getAbsolutePath(), repository.getNamespaceAndName()), e);
}
LOG.debug("create data directory {}", dataDirectory);
}
File storeDirectory = new File(dataDirectory, name);
IOUtil.mkdirs(storeDirectory);
return storeDirectory;
}
}

View File

@@ -37,7 +37,7 @@ import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.SCMContextProvider;
import sonia.scm.repository.RepositoryLocationResolver;
import sonia.scm.security.KeyGenerator;
/**
@@ -60,21 +60,21 @@ public class FileBlobStoreFactory extends FileBasedStoreFactory implements BlobS
/**
* Constructs a new instance.
*
* @param context scm context
* @param repositoryLocationResolver
* @param keyGenerator key generator
*/
@Inject
public FileBlobStoreFactory(SCMContextProvider context,
KeyGenerator keyGenerator) {
super(context, DIRECTORY_NAME);
public FileBlobStoreFactory(RepositoryLocationResolver repositoryLocationResolver, KeyGenerator keyGenerator) {
super(repositoryLocationResolver, DIRECTORY_NAME);
this.keyGenerator = keyGenerator;
}
@Override
public BlobStore getBlobStore(String name) {
LOG.debug("create new blob with name {}", name);
return new FileBlobStore(keyGenerator, getDirectory(name));
public BlobStore getStore(StoreParameters storeParameters) {
if (storeParameters.getRepository() != null) {
return new FileBlobStore(keyGenerator, getDirectory(storeParameters.getName(), storeParameters.getRepository()));
}
return new FileBlobStore(keyGenerator, getDirectory(storeParameters.getName()));
}
}

View File

@@ -42,6 +42,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.SCMContextProvider;
import sonia.scm.repository.Repository;
import sonia.scm.security.KeyGenerator;
import sonia.scm.util.IOUtil;
@@ -91,18 +92,16 @@ public class JAXBConfigurationEntryStoreFactory
*
* @param type
* @param name
* @param <T>
*
* @return
*/
@Override
public <T> ConfigurationEntryStore<T> getStore(Class<T> type, String name)
private ConfigurationEntryStore getStore(Class type, String name)
{
logger.debug("create new configuration store for type {} with name {}",
type, name);
//J-
return new JAXBConfigurationEntryStore<T>(
return new JAXBConfigurationEntryStore(
new File(directory,name.concat(StoreConstants.FILE_EXTENSION)),
keyGenerator,
type
@@ -117,4 +116,17 @@ public class JAXBConfigurationEntryStoreFactory
/** Field description */
private KeyGenerator keyGenerator;
@Override
public ConfigurationEntryStore getStore(StoreParameters storeParameters) {
if (storeParameters.getRepository() != null){
return getStore(storeParameters.getType(),storeParameters.getName(),storeParameters.getRepository());
}
return getStore(storeParameters.getType(),storeParameters.getName());
}
private ConfigurationEntryStore getStore(Class type, String name, Repository repository) {
return null;
}
}

View File

@@ -61,7 +61,7 @@ public class JAXBConfigurationStore<T> extends AbstractStore<T> {
private JAXBContext context;
JAXBConfigurationStore(Class<T> type, File configFile) {
public JAXBConfigurationStore(Class<T> type, File configFile) {
this.type = type;
try {

View File

@@ -32,17 +32,18 @@ package sonia.scm.store;
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.repository.InternalRepositoryException;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryLocationResolver;
import sonia.scm.util.IOUtil;
import java.io.File;
import java.io.IOException;
/**
* JAXB implementation of {@link ConfigurationStoreFactory}.
* JAXB implementation of {@link StoreFactory}.
*
* @author Sebastian Sdorra
*/
@@ -54,33 +55,65 @@ public class JAXBConfigurationStoreFactory implements ConfigurationStoreFactory
*/
private static final Logger LOG = LoggerFactory.getLogger(JAXBConfigurationStoreFactory.class);
private final File configDirectory;
private RepositoryLocationResolver repositoryLocationResolver;
/**
* Constructs a new instance.
*
* @param context scm context
* @param repositoryLocationResolver Resolver to get the repository Directory
*/
@Inject
public JAXBConfigurationStoreFactory(SCMContextProvider context) {
configDirectory = new File(context.getBaseDirectory(), StoreConstants.CONFIG_DIRECTORY_NAME);
IOUtil.mkdirs(configDirectory);
public JAXBConfigurationStoreFactory(RepositoryLocationResolver repositoryLocationResolver) {
this.repositoryLocationResolver = repositoryLocationResolver;
}
@Override
public <T> JAXBConfigurationStore<T> getStore(Class<T> type, String name) {
if (configDirectory == null) {
throw new IllegalStateException("store factory is not initialized");
}
/**
* Get or create the global config directory.
*
* @return the global config directory.
*/
private File getGlobalConfigDirectory() {
File baseDirectory = repositoryLocationResolver.getInitialBaseDirectory();
File configDirectory = new File(baseDirectory, StoreConstants.CONFIG_DIRECTORY_NAME);
return getOrCreateFile(configDirectory);
}
/**
* Get or create the repository specific config directory.
*
* @return the repository specific config directory.
*/
private File getRepositoryConfigDirectory(Repository repository) {
File baseDirectory = null;
try {
baseDirectory = repositoryLocationResolver.getConfigDirectory(repository);
} catch (IOException e) {
e.printStackTrace();
}
File configDirectory = new File(baseDirectory, StoreConstants.CONFIG_DIRECTORY_NAME);
return getOrCreateFile(configDirectory);
}
private File getOrCreateFile(File directory) {
if (!directory.exists()) {
IOUtil.mkdirs(directory);
}
return directory;
}
private JAXBConfigurationStore getStore(Class type, String name, File configDirectory) {
File configFile = new File(configDirectory, name.concat(StoreConstants.FILE_EXTENSION));
if (LOG.isDebugEnabled()) {
LOG.debug("create store for {} at {}", type.getName(),
configFile.getPath());
}
LOG.debug("create store for {} at {}", type.getName(), configFile.getPath());
return new JAXBConfigurationStore<>(type, configFile);
}
@Override
public JAXBConfigurationStore getStore(StoreParameters storeParameters) {
try {
return getStore(storeParameters.getType(), storeParameters.getName(),repositoryLocationResolver.getRepositoryDirectory(storeParameters.getRepository()));
} catch (IOException e) {
throw new InternalRepositoryException(storeParameters.getRepository(),"Error on getting the store of the repository"+ storeParameters.getRepository().getNamespaceAndName());
}
}
}

View File

@@ -40,7 +40,7 @@ import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.SCMContextProvider;
import sonia.scm.repository.RepositoryLocationResolver;
import sonia.scm.security.KeyGenerator;
/**
@@ -52,54 +52,23 @@ public class JAXBDataStoreFactory extends FileBasedStoreFactory
implements DataStoreFactory
{
/** Field description */
private static final Logger logger = LoggerFactory.getLogger(JAXBDataStoreFactory.class);
private static final String DIRECTORY_NAME = "data";
private KeyGenerator keyGenerator;
/**
* the logger for JAXBDataStoreFactory
*/
private static final Logger logger =
LoggerFactory.getLogger(JAXBDataStoreFactory.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param context
* @param keyGenerator
*/
@Inject
public JAXBDataStoreFactory(SCMContextProvider context,
KeyGenerator keyGenerator)
{
super(context, DIRECTORY_NAME);
public JAXBDataStoreFactory(RepositoryLocationResolver repositoryLocationResolver, KeyGenerator keyGenerator) {
super(repositoryLocationResolver, DIRECTORY_NAME);
this.keyGenerator = keyGenerator;
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param type
* @param name
* @param <T>
*
* @return
*/
@Override
public <T> DataStore<T> getStore(Class<T> type, String name)
{
logger.debug("create new store for type {} with name {}", type, name);
return new JAXBDataStore<>(keyGenerator, type, getDirectory(name));
@SuppressWarnings("unchecked")
public DataStore getStore(StoreParameters storeParameters) {
logger.debug("create new store for type {} with name {}", storeParameters.getType(), storeParameters.getName());
if (storeParameters.getRepository() != null) {
return new JAXBDataStore(keyGenerator, storeParameters.getType(), getDirectory(storeParameters.getName(), storeParameters.getRepository()));
}
return new JAXBDataStore(keyGenerator, storeParameters.getType(), getDirectory(storeParameters.getName()));
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private KeyGenerator keyGenerator;
}

View File

@@ -37,6 +37,7 @@ package sonia.scm.user.xml;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import sonia.scm.store.StoreParameters;
import sonia.scm.user.User;
import sonia.scm.user.UserDAO;
import sonia.scm.xml.AbstractXmlDAO;
@@ -65,7 +66,10 @@ public class XmlUserDAO extends AbstractXmlDAO<User, XmlUserDatabase>
@Inject
public XmlUserDAO(ConfigurationStoreFactory storeFactory)
{
super(storeFactory.getStore(XmlUserDatabase.class, STORE_NAME));
super(storeFactory.getStore(new StoreParameters()
.withType(XmlUserDatabase.class)
.withName(STORE_NAME)
.build()));
}
//~--- methods --------------------------------------------------------------

View File

@@ -52,6 +52,6 @@ public class FileBlobStoreTest extends BlobStoreTestBase
@Override
protected BlobStoreFactory createBlobStoreFactory()
{
return new FileBlobStoreFactory(contextProvider, new UUIDKeyGenerator());
return new FileBlobStoreFactory(repositoryLocationResolver, new UUIDKeyGenerator());
}
}

View File

@@ -37,25 +37,22 @@ package sonia.scm.store;
import com.google.common.io.Closeables;
import com.google.common.io.Resources;
import org.junit.Test;
import sonia.scm.security.AssignedPermission;
import sonia.scm.security.UUIDKeyGenerator;
import static org.junit.Assert.*;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.UUID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
//~--- JDK imports ------------------------------------------------------------
/**
*
* @author Sebastian Sdorra
@@ -132,13 +129,13 @@ public class JAXBConfigurationEntryStoreTest
public void testStoreAndLoad() throws IOException
{
String name = UUID.randomUUID().toString();
ConfigurationEntryStore<AssignedPermission> store =
createPermissionStore(RESOURCE_FIXED, name);
ConfigurationEntryStore<AssignedPermission> store = createPermissionStore(RESOURCE_FIXED, name);
store.put("a45", new AssignedPermission("tuser4", "repository:create"));
store =
createConfigurationStoreFactory().getStore(AssignedPermission.class,
name);
store = createConfigurationStoreFactory().getStore(new StoreParameters()
.withType(AssignedPermission.class)
.withName(name)
.build());
AssignedPermission ap = store.get("a45");
@@ -154,10 +151,9 @@ public class JAXBConfigurationEntryStoreTest
* @return
*/
@Override
protected ConfigurationEntryStoreFactory createConfigurationStoreFactory()
protected ConfigurationEntryStoreFactory createConfigurationStoreFactory()
{
return new JAXBConfigurationEntryStoreFactory(new UUIDKeyGenerator(),
contextProvider);
return new JAXBConfigurationEntryStoreFactory(new UUIDKeyGenerator(), contextProvider);
}
/**
@@ -225,8 +221,9 @@ public class JAXBConfigurationEntryStoreTest
}
copy(resource, name);
return createConfigurationStoreFactory().getStore(AssignedPermission.class,
name);
return createConfigurationStoreFactory().getStore(new StoreParameters()
.withType(AssignedPermission.class)
.withName(name)
.build());
}
}

View File

@@ -34,7 +34,7 @@ package sonia.scm.store;
/**
* Unit tests for {@link JAXBConfigurationStore}.
*
*
* @author Sebastian Sdorra
*/
public class JAXBConfigurationStoreTest extends StoreTestBase {
@@ -42,6 +42,6 @@ public class JAXBConfigurationStoreTest extends StoreTestBase {
@Override
protected ConfigurationStoreFactory createStoreFactory()
{
return new JAXBConfigurationStoreFactory(contextProvider);
return new JAXBConfigurationStoreFactory(repositoryLocationResolver);
}
}

View File

@@ -34,14 +34,14 @@ package sonia.scm.store;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.repository.Repository;
import sonia.scm.security.UUIDKeyGenerator;
/**
*
* @author Sebastian Sdorra
*/
public class JAXBDataStoreTest extends DataStoreTestBase
{
public class JAXBDataStoreTest extends DataStoreTestBase {
/**
* Method description
@@ -52,6 +52,25 @@ public class JAXBDataStoreTest extends DataStoreTestBase
@Override
protected DataStoreFactory createDataStoreFactory()
{
return new JAXBDataStoreFactory(contextProvider, new UUIDKeyGenerator());
return new JAXBDataStoreFactory(repositoryLocationResolver, new UUIDKeyGenerator());
}
@Override
protected DataStore getDataStore(Class type, Repository repository) {
StoreParameters params = new StoreParameters()
.withType(type)
.withName("test")
.forRepository(repository)
.build();
return createDataStoreFactory().getStore(params);
}
@Override
protected DataStore getDataStore(Class type) {
StoreParameters params = new StoreParameters()
.withType(type)
.withName("test")
.build();
return createDataStoreFactory().getStore(params);
}
}