Skip to content
This repository was archived by the owner on Dec 27, 2023. It is now read-only.

Commit 5f0db2f

Browse files
feat: abstract class to load factories (#488)
Co-authored-by: g00563573 <L0kuj;lfyysq>
1 parent fa631f1 commit 5f0db2f

File tree

20 files changed

+359
-279
lines changed

20 files changed

+359
-279
lines changed

asto-core/src/main/java/com/artipie/asto/factory/StorageConfig.java renamed to asto-core/src/main/java/com/artipie/asto/factory/Config.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
import java.util.stream.Collectors;
1313

1414
/**
15-
* Storage config.
15+
* Factory config.
1616
*
1717
* @since 1.13.0
1818
*/
19-
public interface StorageConfig {
19+
public interface Config {
2020

2121
/**
2222
* Gets string value.
@@ -40,26 +40,26 @@ public interface StorageConfig {
4040
* @param key Key.
4141
* @return Config.
4242
*/
43-
StorageConfig config(String key);
43+
Config config(String key);
4444

4545
/**
4646
* Strict storage config throws {@code NullPointerException} when value is not exist.
4747
*
4848
* @since 1.13.0
4949
*/
50-
class StrictStorageConfig implements StorageConfig {
50+
class StrictStorageConfig implements Config {
5151

5252
/**
5353
* Original config.
5454
*/
55-
private final StorageConfig original;
55+
private final Config original;
5656

5757
/**
5858
* Ctor.
5959
*
6060
* @param original Original config.
6161
*/
62-
public StrictStorageConfig(final StorageConfig original) {
62+
public StrictStorageConfig(final Config original) {
6363
this.original = original;
6464
}
6565

@@ -80,7 +80,7 @@ public Collection<String> sequence(final String key) {
8080
}
8181

8282
@Override
83-
public StorageConfig config(final String key) {
83+
public Config config(final String key) {
8484
return Objects.requireNonNull(
8585
this.original.config(key),
8686
String.format("No config found for key %s", key)
@@ -93,7 +93,7 @@ public StorageConfig config(final String key) {
9393
*
9494
* @since 1.13.0
9595
*/
96-
class YamlStorageConfig implements StorageConfig {
96+
class YamlStorageConfig implements Config {
9797
/**
9898
* Original {@code YamlMapping}.
9999
*/
@@ -145,8 +145,13 @@ public Collection<String> sequence(final String key) {
145145
}
146146

147147
@Override
148-
public StorageConfig config(final String key) {
148+
public Config config(final String key) {
149149
return new YamlStorageConfig(this.original.yamlMapping(key));
150150
}
151+
152+
@Override
153+
public String toString() {
154+
return this.original.toString();
155+
}
151156
}
152157
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* The MIT License (MIT) Copyright (c) 2020-2022 artipie.com
3+
* https://github.com/artipie/asto/LICENSE.txt
4+
*/
5+
package com.artipie.asto.factory;
6+
7+
import com.artipie.ArtipieException;
8+
import com.google.common.base.Strings;
9+
import com.google.common.collect.Lists;
10+
import com.jcabi.log.Logger;
11+
import java.lang.reflect.InvocationTargetException;
12+
import java.util.Arrays;
13+
import java.util.HashMap;
14+
import java.util.List;
15+
import java.util.Map;
16+
import org.reflections.Reflections;
17+
import org.reflections.scanners.Scanners;
18+
19+
/**
20+
* Loader for various factories for different objects.
21+
* @param <F> Factory class
22+
* @param <A> Factory annotation class
23+
* @param <C> Config class
24+
* @param <O> Object to instantiate class
25+
* @since 1.16
26+
*/
27+
@SuppressWarnings("unchecked")
28+
public abstract class FactoryLoader<F, A, C, O> {
29+
30+
/**
31+
* The name of the factory <-> factory.
32+
* @checkstyle VisibilityModifierCheck (5 lines)
33+
*/
34+
protected final Map<String, F> factories;
35+
36+
/**
37+
* Annotation class.
38+
*/
39+
private final Class<A> annot;
40+
41+
/**
42+
* Ctor.
43+
* @param annot Annotation class
44+
* @param env Environment
45+
*/
46+
protected FactoryLoader(final Class<A> annot, final Map<String, String> env) {
47+
this.annot = annot;
48+
this.factories = this.init(env);
49+
}
50+
51+
/**
52+
* Default package name.
53+
* @return The name of the default scan package
54+
*/
55+
abstract String defPackage();
56+
57+
/**
58+
* Environment parameter to define packages to find factories.
59+
* Package names should be separated by semicolon ';'.
60+
* @return Env param name
61+
*/
62+
abstract String scanPackagesEnv();
63+
64+
/**
65+
* Find factory by name and create object.
66+
* @param name The factory name
67+
* @param config Configuration
68+
* @return The object
69+
*/
70+
abstract O newObject(String name, C config);
71+
72+
/**
73+
* Get the name of the factory from provided element. Call {@link Class#getAnnotations()}
74+
* method on the element, filter required annotations and get factory implementation name.
75+
* @param element Element to get annotations from
76+
* @return The name of the factory
77+
*/
78+
abstract String getFactoryName(Class<?> element);
79+
80+
/**
81+
* Finds and initiates annotated classes in default and env packages.
82+
*
83+
* @param env Environment parameters.
84+
* @return Map of StorageFactories.
85+
*/
86+
private Map<String, F> init(final Map<String, String> env) {
87+
final List<String> pkgs = Lists.newArrayList(this.defPackage());
88+
final String pgs = env.get(this.scanPackagesEnv());
89+
if (!Strings.isNullOrEmpty(pgs)) {
90+
pkgs.addAll(Arrays.asList(pgs.split(";")));
91+
}
92+
final Map<String, F> res = new HashMap<>();
93+
pkgs.forEach(
94+
pkg -> new Reflections(pkg)
95+
.get(Scanners.TypesAnnotated.with(this.annot).asClass())
96+
.forEach(
97+
element -> {
98+
final String type = this.getFactoryName(element);
99+
final F existed = res.get(type);
100+
if (existed != null) {
101+
throw new ArtipieException(
102+
String.format(
103+
"Factory with type '%s' already exists [class=%s].",
104+
type, existed.getClass().getSimpleName()
105+
)
106+
);
107+
}
108+
try {
109+
res.put(type, (F) element.getDeclaredConstructor().newInstance());
110+
Logger.info(
111+
StoragesLoader.class,
112+
"Initiated factory [type=%s, class=%s]",
113+
type, element.getSimpleName()
114+
);
115+
} catch (final InstantiationException | IllegalAccessException
116+
| InvocationTargetException | NoSuchMethodException err) {
117+
throw new ArtipieException(err);
118+
}
119+
}
120+
)
121+
);
122+
return res;
123+
}
124+
125+
}

asto-core/src/main/java/com/artipie/asto/factory/StorageFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public interface StorageFactory {
2020
* @param cfg Storage configuration.
2121
* @return Storage
2222
*/
23-
Storage newStorage(StorageConfig cfg);
23+
Storage newStorage(Config cfg);
2424

2525
/**
2626
* Create new storage.
@@ -30,7 +30,7 @@ public interface StorageFactory {
3030
*/
3131
default Storage newStorage(YamlMapping cfg) {
3232
return this.newStorage(
33-
new StorageConfig.YamlStorageConfig(cfg)
33+
new Config.YamlStorageConfig(cfg)
3434
);
3535
}
3636
}

asto-core/src/main/java/com/artipie/asto/factory/Storages.java

Lines changed: 0 additions & 138 deletions
This file was deleted.

0 commit comments

Comments
 (0)