Set namespace while creating a repository

This commit is contained in:
Philipp Czora
2018-06-29 17:10:14 +02:00
parent 0402596cf1
commit ffabda3f83
12 changed files with 210 additions and 494 deletions

View File

@@ -1,9 +1,9 @@
/** /**
* Copyright (c) 2010, Sebastian Sdorra All rights reserved. * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
* * <p>
* 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:
* * <p>
* 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. 2. Redistributions in * this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of * binary form must reproduce the above copyright notice, this list of
@@ -11,7 +11,7 @@
* materials provided with the distribution. 3. Neither the name of SCM-Manager; * 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 * nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* * <p>
* 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 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -22,13 +22,11 @@
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * 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 * 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. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* * <p>
* http://bitbucket.org/sdorra/scm-manager * http://bitbucket.org/sdorra/scm-manager
*
*/ */
package sonia.scm.annotation; package sonia.scm.annotation;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
@@ -107,84 +105,51 @@ import javax.xml.transform.stream.StreamResult;
*/ */
@SupportedAnnotationTypes("*") @SupportedAnnotationTypes("*")
@MetaInfServices(Processor.class) @MetaInfServices(Processor.class)
@SuppressWarnings({ "Since16", "Since15" }) @SuppressWarnings({"Since16", "Since15"})
@SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedSourceVersion(SourceVersion.RELEASE_8)
public final class ScmAnnotationProcessor extends AbstractProcessor public final class ScmAnnotationProcessor extends AbstractProcessor {
{
/** Field description */
private static final String DESCRIPTOR_MODULE = "META-INF/scm/module.xml"; private static final String DESCRIPTOR_MODULE = "META-INF/scm/module.xml";
/** Field description */
private static final String DESCRIPTOR_PLUGIN = "META-INF/scm/plugin.xml"; private static final String DESCRIPTOR_PLUGIN = "META-INF/scm/plugin.xml";
/** Field description */
private static final String EL_MODULE = "module"; private static final String EL_MODULE = "module";
/** Field description */
private static final String EMPTY = ""; private static final String EMPTY = "";
/** Field description */
private static final String PROPERTY_VALUE = "yes"; private static final String PROPERTY_VALUE = "yes";
/** Field description */
private static final Set<String> SUBSCRIBE_ANNOTATIONS = private static final Set<String> SUBSCRIBE_ANNOTATIONS =
ImmutableSet.of(Subscribe.class.getName()); ImmutableSet.of(Subscribe.class.getName());
/** Field description */
private static final Set<ClassAnnotation> CLASS_ANNOTATIONS = private static final Set<ClassAnnotation> CLASS_ANNOTATIONS =
ImmutableSet.of(new ClassAnnotation("rest-resource", Path.class), ImmutableSet.of(new ClassAnnotation("rest-resource", Path.class),
new ClassAnnotation("rest-provider", Provider.class)); new ClassAnnotation("rest-provider", Provider.class));
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param annotations
* @param roundEnv
*
* @return
*/
@Override @Override
public boolean process(Set<? extends TypeElement> annotations, public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) RoundEnvironment roundEnv) {
{ if (!roundEnv.processingOver()) {
if (!roundEnv.processingOver())
{
Set<DescriptorElement> descriptorElements = Sets.newHashSet(); Set<DescriptorElement> descriptorElements = Sets.newHashSet();
Set<TypeElement> subscriberAnnotations = Sets.newHashSet(); Set<TypeElement> subscriberAnnotations = Sets.newHashSet();
for (TypeElement e : annotations) for (TypeElement e : annotations) {
{
PluginAnnotation pa = e.getAnnotation(PluginAnnotation.class); PluginAnnotation pa = e.getAnnotation(PluginAnnotation.class);
if (pa != null) if (pa != null) {
{
scanForClassAnnotations(descriptorElements, roundEnv, e, pa.value()); scanForClassAnnotations(descriptorElements, roundEnv, e, pa.value());
} }
if (SUBSCRIBE_ANNOTATIONS.contains(e.getQualifiedName().toString())) if (SUBSCRIBE_ANNOTATIONS.contains(e.getQualifiedName().toString())) {
{
subscriberAnnotations.add(e); subscriberAnnotations.add(e);
} }
} }
for (ClassAnnotation ca : CLASS_ANNOTATIONS) for (ClassAnnotation ca : CLASS_ANNOTATIONS) {
{
TypeElement annotation = findAnnotation(annotations, TypeElement annotation = findAnnotation(annotations,
ca.annotationClass); ca.annotationClass);
if (annotation != null) if (annotation != null) {
{
scanForClassAnnotations(descriptorElements, roundEnv, annotation, scanForClassAnnotations(descriptorElements, roundEnv, annotation,
ca.elementName); ca.elementName);
} }
} }
for (TypeElement annotation : subscriberAnnotations) for (TypeElement annotation : subscriberAnnotations) {
{
scanForSubscriberAnnotations(descriptorElements, roundEnv, annotation); scanForSubscriberAnnotations(descriptorElements, roundEnv, annotation);
} }
@@ -194,46 +159,25 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
return false; return false;
} }
/**
* Method description private void close(Closeable closeable) {
* if (closeable != null) {
* try {
* @param closeable
*/
private void close(Closeable closeable)
{
if (closeable != null)
{
try
{
closeable.close(); closeable.close();
} } catch (IOException ex) {
catch (IOException ex)
{
printException("could not close closeable", ex); printException("could not close closeable", ex);
} }
} }
} }
/**
* Method description
*
*
* @param annotations
* @param annotationClass
*
* @return
*/
private TypeElement findAnnotation(Set<? extends TypeElement> annotations, private TypeElement findAnnotation(Set<? extends TypeElement> annotations,
Class<? extends Annotation> annotationClass) Class<? extends Annotation> annotationClass) {
{
TypeElement annotation = null; TypeElement annotation = null;
for (TypeElement te : annotations) for (TypeElement typeElement : annotations) {
{ if (typeElement.getQualifiedName().toString().equals(annotationClass.getName())) {
if (te.getQualifiedName().toString().equals(annotationClass.getName())) annotation = typeElement;
{
annotation = te;
break; break;
} }
@@ -242,24 +186,13 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
return annotation; return annotation;
} }
/**
* Method description private File findDescriptor(Filer filer) throws IOException {
*
*
* @param filer
*
* @return
*
* @throws IOException
*/
private File findDescriptor(Filer filer) throws IOException
{
FileObject f = filer.getResource(StandardLocation.CLASS_OUTPUT, EMPTY, FileObject f = filer.getResource(StandardLocation.CLASS_OUTPUT, EMPTY,
DESCRIPTOR_PLUGIN); DESCRIPTOR_PLUGIN);
File file = new File(f.toUri()); File file = new File(f.toUri());
if (!file.exists()) if (!file.exists()) {
{
f = filer.getResource(StandardLocation.CLASS_OUTPUT, EMPTY, f = filer.getResource(StandardLocation.CLASS_OUTPUT, EMPTY,
DESCRIPTOR_MODULE); DESCRIPTOR_MODULE);
file = new File(f.toUri()); file = new File(f.toUri());
@@ -268,68 +201,40 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
return file; return file;
} }
/**
* Method description private Document parseDocument(File file) {
*
*
* @param f
*
* @param file
*
* @return
*/
private Document parseDocument(File file)
{
Document doc = null; Document doc = null;
InputStream input = null; InputStream input = null;
try try {
{
DocumentBuilder builder = DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder(); DocumentBuilderFactory.newInstance().newDocumentBuilder();
if (file.exists()) if (file.exists()) {
{
input = new FileInputStream(file); input = new FileInputStream(file);
doc = builder.parse(input); doc = builder.parse(input);
} } else {
else
{
doc = builder.newDocument(); doc = builder.newDocument();
doc.appendChild(doc.createElement(EL_MODULE)); doc.appendChild(doc.createElement(EL_MODULE));
} }
} } catch (ParserConfigurationException | SAXException | IOException
catch (ParserConfigurationException | SAXException | IOException | DOMException ex) {
| DOMException ex)
{
printException("could not parse document", ex); printException("could not parse document", ex);
} } finally {
finally
{
close(input); close(input);
} }
return doc; return doc;
} }
/**
* Method description private String prepareArrayElement(Object obj) {
*
*
* @param obj
*
* @return
*/
private String prepareArrayElement(Object obj)
{
String v = obj.toString(); String v = obj.toString();
if (v.startsWith("\"")) if (v.startsWith("\"")) {
{
v = v.substring(1); v = v.substring(1);
if (v.endsWith("")) if (v.endsWith("")) {
{
v = v.substring(0, v.length() - 1); v = v.substring(0, v.length() - 1);
} }
} }
@@ -337,15 +242,8 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
return v; return v;
} }
/**
* Method description private void printException(String msg, Throwable throwable) {
*
*
* @param msg
* @param throwable
*/
private void printException(String msg, Throwable throwable)
{
processingEnv.getMessager().printMessage(Kind.ERROR, msg); processingEnv.getMessager().printMessage(Kind.ERROR, msg);
String stack = Throwables.getStackTraceAsString(throwable); String stack = Throwables.getStackTraceAsString(throwable);
@@ -353,83 +251,58 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
processingEnv.getMessager().printMessage(Kind.ERROR, stack); processingEnv.getMessager().printMessage(Kind.ERROR, stack);
} }
/**
* Method description
*
*
* @param descriptorElements
* @param roundEnv
* @param annotation
* @param elementName
* @param elements
*
* @return
*/
private void scanForClassAnnotations( private void scanForClassAnnotations(
Set<DescriptorElement> descriptorElements, RoundEnvironment roundEnv, Set<DescriptorElement> descriptorElements, RoundEnvironment roundEnv,
TypeElement annotation, String elementName) TypeElement annotation, String elementName) {
{
Set<ClassWithAttributes> classes = Sets.newHashSet(); Set<ClassWithAttributes> classes = Sets.newHashSet();
for (Element e : roundEnv.getElementsAnnotatedWith(annotation)) for (Element e : roundEnv.getElementsAnnotatedWith(annotation)) {
{
if (e.getKind().isClass() || e.getKind().isInterface()) if (isClassOrInterface(e)) {
{
TypeElement type = (TypeElement) e; TypeElement type = (TypeElement) e;
String desc = processingEnv.getElementUtils().getDocComment(type); String desc = processingEnv.getElementUtils().getDocComment(type);
if (desc != null) if (desc != null) {
{
desc = desc.trim(); desc = desc.trim();
} }
//J-
classes.add( classes.add(
new ClassWithAttributes( new ClassWithAttributes(
type.getQualifiedName().toString(), type.getQualifiedName().toString(), desc, getAttributesFromAnnotation(e, annotation)
desc,
getAttributesFromAnnotation(e, annotation)
) )
); );
//J+
} }
} }
descriptorElements.add(new ClassSetElement(elementName, classes)); descriptorElements.add(new ClassSetElement(elementName, classes));
} }
/**
* Method description private boolean isClassOrInterface(Element e) {
* return e.getKind().isClass() || e.getKind().isInterface();
* }
* @param descriptorElements
* @param roundEnv
* @param annotation
*/
private void scanForSubscriberAnnotations( private void scanForSubscriberAnnotations(
Set<DescriptorElement> descriptorElements, RoundEnvironment roundEnv, Set<DescriptorElement> descriptorElements, RoundEnvironment roundEnv,
TypeElement annotation) TypeElement annotation) {
{ for (Element el : roundEnv.getElementsAnnotatedWith(annotation)) {
for (Element el : roundEnv.getElementsAnnotatedWith(annotation)) if (el.getKind() == ElementKind.METHOD) {
{
if (el.getKind() == ElementKind.METHOD)
{
ExecutableElement ee = (ExecutableElement) el; ExecutableElement ee = (ExecutableElement) el;
List<? extends VariableElement> params = ee.getParameters(); List<? extends VariableElement> params = ee.getParameters();
if ((params != null) && (params.size() == 1)) if ((params != null) && (params.size() == 1)) {
{
VariableElement param = params.get(0); VariableElement param = params.get(0);
Element clazz = el.getEnclosingElement(); Element clazz = el.getEnclosingElement();
String desc = processingEnv.getElementUtils().getDocComment(clazz); String desc = processingEnv.getElementUtils().getDocComment(clazz);
if (desc != null) if (desc != null) {
{
desc = desc.trim(); desc = desc.trim();
} }
//J-
descriptorElements.add( descriptorElements.add(
new SubscriberElement( new SubscriberElement(
clazz.toString(), clazz.toString(),
@@ -437,60 +310,39 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
desc desc
) )
); );
//J+
} }
} }
} }
} }
/**
* Method description private void write(Set<DescriptorElement> descriptorElements) {
*
*
* @param descriptorElements
*/
private void write(Set<DescriptorElement> descriptorElements)
{
Filer filer = processingEnv.getFiler(); Filer filer = processingEnv.getFiler();
try try {
{
File file = findDescriptor(filer); File file = findDescriptor(filer);
Document doc = parseDocument(file); Document doc = parseDocument(file);
if (doc != null) if (doc != null) {
{
org.w3c.dom.Element root = doc.getDocumentElement(); org.w3c.dom.Element root = doc.getDocumentElement();
for (DescriptorElement el : descriptorElements) for (DescriptorElement el : descriptorElements) {
{
el.append(doc, root); el.append(doc, root);
} }
writeDocument(doc, file); writeDocument(doc, file);
} }
} } catch (IOException ex) {
catch (IOException ex)
{
printException("could not open plugin descriptor", ex); printException("could not open plugin descriptor", ex);
} }
} }
/**
* Method description private void writeDocument(Document doc, File file) {
*
*
* @param doc
* @param f
* @param file
*/
private void writeDocument(Document doc, File file)
{
Writer writer = null; Writer writer = null;
try try {
{
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
writer = new FileWriter(file); writer = new FileWriter(file);
@@ -499,42 +351,24 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
transformer.setOutputProperty(OutputKeys.INDENT, PROPERTY_VALUE); transformer.setOutputProperty(OutputKeys.INDENT, PROPERTY_VALUE);
transformer.transform(new DOMSource(doc), new StreamResult(writer)); transformer.transform(new DOMSource(doc), new StreamResult(writer));
} } catch (IOException | IllegalArgumentException | TransformerException ex) {
catch (IOException | IllegalArgumentException | TransformerException ex)
{
printException("could not write document", ex); printException("could not write document", ex);
} } finally {
finally
{
close(writer); close(writer);
} }
} }
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param el
* @param annotation
*
* @return
*/
private Map<String, String> getAttributesFromAnnotation(Element el, private Map<String, String> getAttributesFromAnnotation(Element el,
TypeElement annotation) TypeElement annotation) {
{
Map<String, String> attributes = Maps.newHashMap(); Map<String, String> attributes = Maps.newHashMap();
for (AnnotationMirror am : el.getAnnotationMirrors()) for (AnnotationMirror annotationMirror : el.getAnnotationMirrors()) {
{ String qn = annotationMirror.getAnnotationType().asElement().toString();
String qn = am.getAnnotationType().asElement().toString();
if (qn.equals(annotation.toString())) if (qn.equals(annotation.toString())) {
{
for (Entry<? extends ExecutableElement, for (Entry<? extends ExecutableElement,
? extends AnnotationValue> entry : am.getElementValues().entrySet()) ? extends AnnotationValue> entry : annotationMirror.getElementValues().entrySet()) {
{
attributes.put(entry.getKey().getSimpleName().toString(), attributes.put(entry.getKey().getSimpleName().toString(),
getValue(entry.getValue())); getValue(entry.getValue()));
} }
@@ -544,77 +378,42 @@ public final class ScmAnnotationProcessor extends AbstractProcessor
return attributes; return attributes;
} }
/**
* Method description private String getValue(AnnotationValue v) {
*
*
* @param v
*
* @return
*/
private String getValue(AnnotationValue v)
{
String value; String value;
Object object = v.getValue(); Object object = v.getValue();
if (object instanceof Iterable) if (object instanceof Iterable) {
{
Iterator<?> it = ((Iterable<?>) object).iterator(); Iterator<?> it = ((Iterable<?>) object).iterator();
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
while (it.hasNext()) while (it.hasNext()) {
{
buffer.append(prepareArrayElement(it.next())); buffer.append(prepareArrayElement(it.next()));
if (it.hasNext()) if (it.hasNext()) {
{
buffer.append(","); buffer.append(",");
} }
} }
value = buffer.toString(); value = buffer.toString();
} } else {
else
{
value = object.toString(); value = object.toString();
} }
return value; return value;
} }
//~--- inner classes --------------------------------------------------------
/** private static final class ClassAnnotation {
* Class description
*
*
* @version Enter version here..., 14/03/18
* @author Enter your name here...
*/
private static final class ClassAnnotation
{
/**
* Constructs ...
*
*
* @param elementName
* @param annotationClass
*/
public ClassAnnotation(String elementName, public ClassAnnotation(String elementName,
Class<? extends Annotation> annotationClass) Class<? extends Annotation> annotationClass) {
{
this.elementName = elementName; this.elementName = elementName;
this.annotationClass = annotationClass; this.annotationClass = annotationClass;
} }
//~--- fields -------------------------------------------------------------
/** Field description */
private final Class<? extends Annotation> annotationClass; private final Class<? extends Annotation> annotationClass;
/** Field description */
private final String elementName; private final String elementName;
} }
} }

View File

@@ -33,8 +33,6 @@
package sonia.scm.plugin; package sonia.scm.plugin;
//~--- JDK imports ------------------------------------------------------------
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@@ -0,0 +1,8 @@
package sonia.scm.repository;
import sonia.scm.plugin.ExtensionPoint;
@ExtensionPoint
public interface NamespaceStrategy {
String getNamespace();
}

View File

@@ -33,8 +33,6 @@
package sonia.scm.repository.spi; package sonia.scm.repository.spi;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.plugin.ExtensionPoint; import sonia.scm.plugin.ExtensionPoint;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
@@ -55,5 +53,5 @@ public interface RepositoryServiceResolver
* *
* @return * @return
*/ */
public RepositoryServiceProvider reslove(Repository repository); public RepositoryServiceProvider resolve(Repository repository);
} }

View File

@@ -76,7 +76,7 @@ public class GitRepositoryServiceResolver implements RepositoryServiceResolver
* @return * @return
*/ */
@Override @Override
public GitRepositoryServiceProvider reslove(Repository repository) public GitRepositoryServiceProvider resolve(Repository repository)
{ {
GitRepositoryServiceProvider provider = null; GitRepositoryServiceProvider provider = null;

View File

@@ -82,7 +82,7 @@ public class HgRepositoryServiceResolver implements RepositoryServiceResolver
* @return * @return
*/ */
@Override @Override
public HgRepositoryServiceProvider reslove(Repository repository) public HgRepositoryServiceProvider resolve(Repository repository)
{ {
HgRepositoryServiceProvider provider = null; HgRepositoryServiceProvider provider = null;

View File

@@ -76,7 +76,7 @@ public class SvnRepositoryServiceResolver implements RepositoryServiceResolver
* @return * @return
*/ */
@Override @Override
public SvnRepositoryServiceProvider reslove(Repository repository) public SvnRepositoryServiceProvider resolve(Repository repository)
{ {
SvnRepositoryServiceProvider provider = null; SvnRepositoryServiceProvider provider = null;

View File

@@ -62,14 +62,7 @@ import sonia.scm.plugin.DefaultPluginLoader;
import sonia.scm.plugin.DefaultPluginManager; import sonia.scm.plugin.DefaultPluginManager;
import sonia.scm.plugin.PluginLoader; import sonia.scm.plugin.PluginLoader;
import sonia.scm.plugin.PluginManager; import sonia.scm.plugin.PluginManager;
import sonia.scm.repository.DefaultRepositoryManager; import sonia.scm.repository.*;
import sonia.scm.repository.DefaultRepositoryProvider;
import sonia.scm.repository.HealthCheckContextListener;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryDAO;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.RepositoryManagerProvider;
import sonia.scm.repository.RepositoryProvider;
import sonia.scm.repository.api.HookContextFactory; import sonia.scm.repository.api.HookContextFactory;
import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.repository.api.RepositoryServiceFactory;
import sonia.scm.repository.spi.HookEventFacade; import sonia.scm.repository.spi.HookEventFacade;
@@ -360,6 +353,8 @@ public class ScmServletModule extends ServletModule
// bind events // bind events
// bind(LastModifiedUpdateListener.class); // bind(LastModifiedUpdateListener.class);
bind(NamespaceStrategy.class, DefaultNamespaceStrategy.class);
} }
/** /**

View File

@@ -0,0 +1,11 @@
package sonia.scm.repository;
import sonia.scm.plugin.Extension;
@Extension
public class DefaultNamespaceStrategy implements NamespaceStrategy{
@Override
public String getNamespace() {
return "42";
}
}

View File

@@ -1,10 +1,10 @@
/** /**
* Copyright (c) 2010, Sebastian Sdorra * Copyright (c) 2010, Sebastian Sdorra
* All rights reserved. * All rights reserved.
* * <p>
* 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:
* * <p>
* 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.
* * <p>
* 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,13 +24,11 @@
* 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.
* * <p>
* http://bitbucket.org/sdorra/scm-manager * http://bitbucket.org/sdorra/scm-manager
*
*/ */
package sonia.scm.repository; package sonia.scm.repository;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
@@ -84,71 +82,53 @@ import javax.servlet.http.HttpServletRequest;
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
@Singleton @Singleton
public class DefaultRepositoryManager extends AbstractRepositoryManager public class DefaultRepositoryManager extends AbstractRepositoryManager {
{
/** Field description */
private static final String THREAD_NAME = "Hook-%s"; private static final String THREAD_NAME = "Hook-%s";
/** Field description */
private static final Logger logger = private static final Logger logger =
LoggerFactory.getLogger(DefaultRepositoryManager.class); LoggerFactory.getLogger(DefaultRepositoryManager.class);
private final ScmConfiguration configuration;
private final ExecutorService executorService;
private final Map<String, RepositoryHandler> handlerMap;
private final KeyGenerator keyGenerator;
private final RepositoryDAO repositoryDAO;
private final Set<Type> types;
private RepositoryMatcher repositoryMatcher;
private NamespaceStrategy namespaceStrategy;
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
* @param configuration
* @param contextProvider
* @param keyGenerator
* @param repositoryDAO
* @param handlerSet
* @param repositoryMatcher
*/
@Inject @Inject
public DefaultRepositoryManager(ScmConfiguration configuration, public DefaultRepositoryManager(ScmConfiguration configuration,
SCMContextProvider contextProvider, KeyGenerator keyGenerator, SCMContextProvider contextProvider, KeyGenerator keyGenerator,
RepositoryDAO repositoryDAO, Set<RepositoryHandler> handlerSet, RepositoryDAO repositoryDAO, Set<RepositoryHandler> handlerSet,
RepositoryMatcher repositoryMatcher) RepositoryMatcher repositoryMatcher,
{ NamespaceStrategy namespaceStrategy) {
this.configuration = configuration; this.configuration = configuration;
this.keyGenerator = keyGenerator; this.keyGenerator = keyGenerator;
this.repositoryDAO = repositoryDAO; this.repositoryDAO = repositoryDAO;
this.repositoryMatcher = repositoryMatcher; this.repositoryMatcher = repositoryMatcher;
this.namespaceStrategy = namespaceStrategy;
//J-
ThreadFactory factory = new ThreadFactoryBuilder() ThreadFactory factory = new ThreadFactoryBuilder()
.setNameFormat(THREAD_NAME).build(); .setNameFormat(THREAD_NAME).build();
this.executorService = new SubjectAwareExecutorService( this.executorService = new SubjectAwareExecutorService(
Executors.newCachedThreadPool(factory) Executors.newCachedThreadPool(factory)
); );
//J+
handlerMap = new HashMap<>(); handlerMap = new HashMap<>();
types = new HashSet<>(); types = new HashSet<>();
for (RepositoryHandler handler : handlerSet) for (RepositoryHandler handler : handlerSet) {
{
addHandler(contextProvider, handler); addHandler(contextProvider, handler);
} }
} }
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @throws IOException
*/
@Override @Override
public void close() throws IOException public void close() throws IOException {
{
executorService.shutdown(); executorService.shutdown();
for (RepositoryHandler handler : handlerMap.values()) for (RepositoryHandler handler : handlerMap.values()) {
{
IOUtil.close(handler); IOUtil.close(handler);
} }
} }
@@ -164,24 +144,22 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @throws RepositoryException * @throws RepositoryException
*/ */
public void create(Repository repository, boolean initRepository) public void create(Repository repository, boolean initRepository)
throws RepositoryException, IOException throws RepositoryException, IOException {
{
logger.info("create repository {} of type {}", repository.getName(), logger.info("create repository {} of type {}", repository.getName(),
repository.getType()); repository.getType());
RepositoryPermissions.create().check(); RepositoryPermissions.create().check();
AssertUtil.assertIsValid(repository); AssertUtil.assertIsValid(repository);
if (repositoryDAO.contains(repository)) if (repositoryDAO.contains(repository)) {
{
throw RepositoryAlreadyExistsException.create(repository); throw RepositoryAlreadyExistsException.create(repository);
} }
repository.setId(keyGenerator.createKey()); repository.setId(keyGenerator.createKey());
repository.setCreationDate(System.currentTimeMillis()); repository.setCreationDate(System.currentTimeMillis());
repository.setNamespace(namespaceStrategy.getNamespace());
if (initRepository) if (initRepository) {
{
getHandler(repository).create(repository); getHandler(repository).create(repository);
} }
@@ -201,8 +179,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
*/ */
@Override @Override
public void create(Repository repository) public void create(Repository repository)
throws RepositoryException, IOException throws RepositoryException, IOException {
{
create(repository, true); create(repository, true);
} }
@@ -217,31 +194,25 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
*/ */
@Override @Override
public void delete(Repository repository) public void delete(Repository repository)
throws RepositoryException, IOException throws RepositoryException, IOException {
{ if (logger.isInfoEnabled()) {
if (logger.isInfoEnabled())
{
logger.info("delete repository {} of type {}", repository.getName(), logger.info("delete repository {} of type {}", repository.getName(),
repository.getType()); repository.getType());
} }
RepositoryPermissions.delete(repository).check(); RepositoryPermissions.delete(repository).check();
if (configuration.isEnableRepositoryArchive() &&!repository.isArchived()) if (configuration.isEnableRepositoryArchive() && !repository.isArchived()) {
{
throw new RepositoryIsNotArchivedException( throw new RepositoryIsNotArchivedException(
"Repository could not deleted, because it is not archived."); "Repository could not deleted, because it is not archived.");
} }
if (repositoryDAO.contains(repository)) if (repositoryDAO.contains(repository)) {
{
fireEvent(HandlerEventType.BEFORE_DELETE, repository); fireEvent(HandlerEventType.BEFORE_DELETE, repository);
getHandler(repository).delete(repository); getHandler(repository).delete(repository);
repositoryDAO.delete(repository); repositoryDAO.delete(repository);
fireEvent(HandlerEventType.DELETE, repository); fireEvent(HandlerEventType.DELETE, repository);
} } else {
else
{
throw new RepositoryNotFoundException( throw new RepositoryNotFoundException(
"repository ".concat(repository.getName()).concat(" not found")); "repository ".concat(repository.getName()).concat(" not found"));
} }
@@ -258,8 +229,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
*/ */
@Override @Override
public void importRepository(Repository repository) public void importRepository(Repository repository)
throws RepositoryException, IOException throws RepositoryException, IOException {
{
create(repository, false); create(repository, false);
} }
@@ -270,7 +240,8 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @param context * @param context
*/ */
@Override @Override
public void init(SCMContextProvider context) {} public void init(SCMContextProvider context) {
}
/** /**
* Method description * Method description
@@ -283,10 +254,8 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
*/ */
@Override @Override
public void modify(Repository repository) public void modify(Repository repository)
throws RepositoryException, IOException throws RepositoryException, IOException {
{ if (logger.isInfoEnabled()) {
if (logger.isInfoEnabled())
{
logger.info("modify repository {} of type {}", repository.getName(), logger.info("modify repository {} of type {}", repository.getName(),
repository.getType()); repository.getType());
} }
@@ -296,17 +265,14 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
Repository oldRepository = repositoryDAO.get(repository.getType(), Repository oldRepository = repositoryDAO.get(repository.getType(),
repository.getName()); repository.getName());
if (oldRepository != null) if (oldRepository != null) {
{
RepositoryPermissions.modify(oldRepository).check(); RepositoryPermissions.modify(oldRepository).check();
fireEvent(HandlerEventType.BEFORE_MODIFY, repository, oldRepository); fireEvent(HandlerEventType.BEFORE_MODIFY, repository, oldRepository);
repository.setLastModified(System.currentTimeMillis()); repository.setLastModified(System.currentTimeMillis());
getHandler(repository).modify(repository); getHandler(repository).modify(repository);
repositoryDAO.modify(repository); repositoryDAO.modify(repository);
fireEvent(HandlerEventType.MODIFY, repository, oldRepository); fireEvent(HandlerEventType.MODIFY, repository, oldRepository);
} } else {
else
{
throw new RepositoryNotFoundException( throw new RepositoryNotFoundException(
"repository ".concat(repository.getName()).concat(" not found")); "repository ".concat(repository.getName()).concat(" not found"));
} }
@@ -323,20 +289,16 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
*/ */
@Override @Override
public void refresh(Repository repository) public void refresh(Repository repository)
throws RepositoryException, IOException throws RepositoryException, IOException {
{
AssertUtil.assertIsNotNull(repository); AssertUtil.assertIsNotNull(repository);
RepositoryPermissions.read(repository).check(); RepositoryPermissions.read(repository).check();
Repository fresh = repositoryDAO.get(repository.getType(), Repository fresh = repositoryDAO.get(repository.getType(),
repository.getName()); repository.getName());
if (fresh != null) if (fresh != null) {
{
fresh.copyProperties(repository); fresh.copyProperties(repository);
} } else {
else
{
throw new RepositoryNotFoundException( throw new RepositoryNotFoundException(
"repository ".concat(repository.getName()).concat(" not found")); "repository ".concat(repository.getName()).concat(" not found"));
} }
@@ -353,16 +315,14 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @return * @return
*/ */
@Override @Override
public Repository get(String id) public Repository get(String id) {
{
AssertUtil.assertIsNotEmpty(id); AssertUtil.assertIsNotEmpty(id);
RepositoryPermissions.read(id).check(); RepositoryPermissions.read(id).check();
Repository repository = repositoryDAO.get(id); Repository repository = repositoryDAO.get(id);
if (repository != null) if (repository != null) {
{
repository = repository.clone(); repository = repository.clone();
} }
@@ -379,15 +339,13 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @return * @return
*/ */
@Override @Override
public Repository get(String type, String name) public Repository get(String type, String name) {
{
AssertUtil.assertIsNotEmpty(type); AssertUtil.assertIsNotEmpty(type);
AssertUtil.assertIsNotEmpty(name); AssertUtil.assertIsNotEmpty(name);
Repository repository = repositoryDAO.get(type, name); Repository repository = repositoryDAO.get(type, name);
if (repository != null) if (repository != null) {
{
RepositoryPermissions.read(repository).check(); RepositoryPermissions.read(repository).check();
repository = repository.clone(); repository = repository.clone();
} }
@@ -404,25 +362,21 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @return * @return
*/ */
@Override @Override
public Collection<Repository> getAll(Comparator<Repository> comparator) public Collection<Repository> getAll(Comparator<Repository> comparator) {
{
List<Repository> repositories = Lists.newArrayList(); List<Repository> repositories = Lists.newArrayList();
PermissionActionCheck<Repository> check = RepositoryPermissions.read(); PermissionActionCheck<Repository> check = RepositoryPermissions.read();
for (Repository repository : repositoryDAO.getAll()) for (Repository repository : repositoryDAO.getAll()) {
{
if (handlerMap.containsKey(repository.getType()) if (handlerMap.containsKey(repository.getType())
&& check.isPermitted(repository)) && check.isPermitted(repository)) {
{
Repository r = repository.clone(); Repository r = repository.clone();
repositories.add(r); repositories.add(r);
} }
} }
if (comparator != null) if (comparator != null) {
{
Collections.sort(repositories, comparator); Collections.sort(repositories, comparator);
} }
@@ -436,8 +390,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @return * @return
*/ */
@Override @Override
public Collection<Repository> getAll() public Collection<Repository> getAll() {
{
return getAll(null); return getAll(null);
} }
@@ -454,19 +407,15 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
*/ */
@Override @Override
public Collection<Repository> getAll(Comparator<Repository> comparator, public Collection<Repository> getAll(Comparator<Repository> comparator,
int start, int limit) int start, int limit) {
{
final PermissionActionCheck<Repository> check = final PermissionActionCheck<Repository> check =
RepositoryPermissions.read(); RepositoryPermissions.read();
return Util.createSubCollection(repositoryDAO.getAll(), comparator, return Util.createSubCollection(repositoryDAO.getAll(), comparator,
new CollectionAppender<Repository>() new CollectionAppender<Repository>() {
{
@Override @Override
public void append(Collection<Repository> collection, Repository item) public void append(Collection<Repository> collection, Repository item) {
{ if (check.isPermitted(item)) {
if (check.isPermitted(item))
{
collection.add(item.clone()); collection.add(item.clone());
} }
} }
@@ -483,8 +432,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @return * @return
*/ */
@Override @Override
public Collection<Repository> getAll(int start, int limit) public Collection<Repository> getAll(int start, int limit) {
{
return getAll(null, start, limit); return getAll(null, start, limit);
} }
@@ -495,14 +443,11 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @return * @return
*/ */
@Override @Override
public Collection<Type> getConfiguredTypes() public Collection<Type> getConfiguredTypes() {
{
List<Type> validTypes = Lists.newArrayList(); List<Type> validTypes = Lists.newArrayList();
for (RepositoryHandler handler : handlerMap.values()) for (RepositoryHandler handler : handlerMap.values()) {
{ if (handler.isConfigured()) {
if (handler.isConfigured())
{
validTypes.add(handler.getType()); validTypes.add(handler.getType());
} }
} }
@@ -519,8 +464,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @return * @return
*/ */
@Override @Override
public Repository getFromRequest(HttpServletRequest request) public Repository getFromRequest(HttpServletRequest request) {
{
AssertUtil.assertIsNotNull(request); AssertUtil.assertIsNotNull(request);
return getFromUri(HttpUtil.getStrippedURI(request)); return getFromUri(HttpUtil.getStrippedURI(request));
@@ -536,15 +480,12 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @return * @return
*/ */
@Override @Override
public Repository getFromTypeAndUri(String type, String uri) public Repository getFromTypeAndUri(String type, String uri) {
{ if (Strings.isNullOrEmpty(type)) {
if (Strings.isNullOrEmpty(type))
{
throw new ArgumentIsInvalidException("argument type is required"); throw new ArgumentIsInvalidException("argument type is required");
} }
if (Strings.isNullOrEmpty(uri)) if (Strings.isNullOrEmpty(uri)) {
{
throw new ArgumentIsInvalidException("argument uri is required"); throw new ArgumentIsInvalidException("argument uri is required");
} }
@@ -553,16 +494,13 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
Repository repository = null; Repository repository = null;
if (handlerMap.containsKey(type)) if (handlerMap.containsKey(type)) {
{
Collection<Repository> repositories = repositoryDAO.getAll(); Collection<Repository> repositories = repositoryDAO.getAll();
PermissionActionCheck<Repository> check = RepositoryPermissions.read(); PermissionActionCheck<Repository> check = RepositoryPermissions.read();
for (Repository r : repositories) for (Repository r : repositories) {
{ if (repositoryMatcher.matches(r, type, uri)) {
if (repositoryMatcher.matches(r, type, uri))
{
check.check(r); check.check(r);
repository = r.clone(); repository = r.clone();
@@ -571,8 +509,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
} }
} }
if ((repository == null) && logger.isDebugEnabled()) if ((repository == null) && logger.isDebugEnabled()) {
{
logger.debug("could not find repository with type {} and uri {}", type, logger.debug("could not find repository with type {} and uri {}", type,
uri); uri);
} }
@@ -589,20 +526,17 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @return * @return
*/ */
@Override @Override
public Repository getFromUri(String uri) public Repository getFromUri(String uri) {
{
AssertUtil.assertIsNotEmpty(uri); AssertUtil.assertIsNotEmpty(uri);
if (uri.startsWith(HttpUtil.SEPARATOR_PATH)) if (uri.startsWith(HttpUtil.SEPARATOR_PATH)) {
{
uri = uri.substring(1); uri = uri.substring(1);
} }
int typeSeperator = uri.indexOf(HttpUtil.SEPARATOR_PATH); int typeSeperator = uri.indexOf(HttpUtil.SEPARATOR_PATH);
Repository repository = null; Repository repository = null;
if (typeSeperator > 0) if (typeSeperator > 0) {
{
String type = uri.substring(0, typeSeperator); String type = uri.substring(0, typeSeperator);
uri = uri.substring(typeSeperator + 1); uri = uri.substring(typeSeperator + 1);
@@ -621,8 +555,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @return * @return
*/ */
@Override @Override
public RepositoryHandler getHandler(String type) public RepositoryHandler getHandler(String type) {
{
return handlerMap.get(type); return handlerMap.get(type);
} }
@@ -633,8 +566,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @return * @return
*/ */
@Override @Override
public Long getLastModified() public Long getLastModified() {
{
return repositoryDAO.getLastModified(); return repositoryDAO.getLastModified();
} }
@@ -645,8 +577,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @return * @return
*/ */
@Override @Override
public Collection<Type> getTypes() public Collection<Type> getTypes() {
{
return types; return types;
} }
@@ -661,22 +592,19 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @param handler * @param handler
*/ */
private void addHandler(SCMContextProvider contextProvider, private void addHandler(SCMContextProvider contextProvider,
RepositoryHandler handler) RepositoryHandler handler) {
{
AssertUtil.assertIsNotNull(handler); AssertUtil.assertIsNotNull(handler);
Type type = handler.getType(); Type type = handler.getType();
AssertUtil.assertIsNotNull(type); AssertUtil.assertIsNotNull(type);
if (handlerMap.containsKey(type.getName())) if (handlerMap.containsKey(type.getName())) {
{
throw new ConfigurationException( throw new ConfigurationException(
type.getName().concat("allready registered")); type.getName().concat("allready registered"));
} }
if (logger.isInfoEnabled()) if (logger.isInfoEnabled()) {
{
logger.info("added RepositoryHandler {} for type {}", handler.getClass(), logger.info("added RepositoryHandler {} for type {}", handler.getClass(),
type); type);
} }
@@ -700,44 +628,18 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager
* @throws RepositoryException * @throws RepositoryException
*/ */
private RepositoryHandler getHandler(Repository repository) private RepositoryHandler getHandler(Repository repository)
throws RepositoryException throws RepositoryException {
{
String type = repository.getType(); String type = repository.getType();
RepositoryHandler handler = handlerMap.get(type); RepositoryHandler handler = handlerMap.get(type);
if (handler == null) if (handler == null) {
{
throw new RepositoryHandlerNotFoundException( throw new RepositoryHandlerNotFoundException(
"could not find handler for ".concat(type)); "could not find handler for ".concat(type));
} } else if (!handler.isConfigured()) {
else if (!handler.isConfigured())
{
throw new RepositoryException("handler is not configured"); throw new RepositoryException("handler is not configured");
} }
return handler; return handler;
} }
//~--- fields ---------------------------------------------------------------
/** Field description */
private final ScmConfiguration configuration;
/** Field description */
private final ExecutorService executorService;
/** Field description */
private final Map<String, RepositoryHandler> handlerMap;
/** Field description */
private final KeyGenerator keyGenerator;
/** Field description */
private final RepositoryDAO repositoryDAO;
/** Field description */
private final Set<Type> types;
/** Field description */
private RepositoryMatcher repositoryMatcher;
} }

View File

@@ -94,6 +94,8 @@ public class DefaultRepositoryManagerPerfTest {
private final KeyGenerator keyGenerator = new DefaultKeyGenerator(); private final KeyGenerator keyGenerator = new DefaultKeyGenerator();
private final NamespaceStrategy namespaceStrategy = new DefaultNamespaceStrategy();
@Mock @Mock
private RepositoryHandler repositoryHandler; private RepositoryHandler repositoryHandler;
@@ -117,7 +119,8 @@ public class DefaultRepositoryManagerPerfTest {
keyGenerator, keyGenerator,
repositoryDAO, repositoryDAO,
handlerSet, handlerSet,
repositoryMatcher repositoryMatcher,
namespaceStrategy
); );
setUpTestRepositories(); setUpTestRepositories();

View File

@@ -539,10 +539,12 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository, Re
ScmConfiguration configuration = new ScmConfiguration(); ScmConfiguration configuration = new ScmConfiguration();
NamespaceStrategy namespaceStrategy = new DefaultNamespaceStrategy();
configuration.setEnableRepositoryArchive(archiveEnabled); configuration.setEnableRepositoryArchive(archiveEnabled);
return new DefaultRepositoryManager(configuration, contextProvider, return new DefaultRepositoryManager(configuration, contextProvider,
keyGenerator, repositoryDAO, handlerSet, createRepositoryMatcher()); keyGenerator, repositoryDAO, handlerSet, createRepositoryMatcher(), namespaceStrategy);
} }
private void createRepository(RepositoryManager m, Repository repository) private void createRepository(RepositoryManager m, Repository repository)