Skip to content

Commit f5afee2

Browse files
committed
initial
1 parent b9a4455 commit f5afee2

16 files changed

+630
-0
lines changed

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# editorconfig.org
2+
3+
root = true
4+
5+
[*]
6+
charset = utf-8
7+
end_of_line = lf
8+
indent_size = 2
9+
indent_style = space
10+
insert_final_newline = true
11+
trim_trailing_whitespace = true
12+
spaces_around_operators = true

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
target/
2+
build/
3+
.idea/
4+
*.iml
5+
.gradle

pom.xml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>io.kanuka</groupId>
8+
<artifactId>kanuka</artifactId>
9+
<version>0.1-SNAPSHOT</version>
10+
11+
<parent>
12+
<groupId>org.avaje</groupId>
13+
<artifactId>java8-parent</artifactId>
14+
<version>1.3</version>
15+
</parent>
16+
17+
<dependencies>
18+
19+
<dependency>
20+
<groupId>javax.inject</groupId>
21+
<artifactId>javax.inject</artifactId>
22+
<version>1</version>
23+
</dependency>
24+
25+
</dependencies>
26+
27+
28+
</project>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.kanuka;
2+
3+
import java.util.List;
4+
5+
public interface BeanContext {
6+
7+
/**
8+
* Return the name of the bean context.
9+
*/
10+
String getName();
11+
12+
/**
13+
* Return a single bean given the type.
14+
*/
15+
<T> T getBean(Class<T> beanClass);
16+
17+
/**
18+
* Return a single bean given the type and name.
19+
*/
20+
<T> T getBean(Class<T> beanClass, String name);
21+
22+
/**
23+
* Return the list of beans that implement the interface or are marked with the annotation.
24+
*
25+
* @param interfaceOrAnnotation An interface class or annotation class.
26+
*/
27+
List<Object> getBeans(Class<?> interfaceOrAnnotation);
28+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.kanuka;
2+
3+
import io.kanuka.core.BeanContextFactory;
4+
import io.kanuka.core.Builder;
5+
import io.kanuka.core.BuilderFactory;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.ServiceLoader;
10+
11+
public class BootContext {
12+
13+
/**
14+
* Load all the named contexts.
15+
*/
16+
public BeanContext load() {
17+
18+
List<BeanContextFactory> factories = new ArrayList<>();
19+
ServiceLoader.load(BeanContextFactory.class).forEach(factories::add);
20+
21+
// sort factories by dependsOn
22+
23+
Builder rootBuilder = BuilderFactory.newRootBuilder();
24+
25+
for (BeanContextFactory factory : factories) {
26+
rootBuilder.addChild(factory.createContext(rootBuilder));
27+
}
28+
29+
// entire graph built, fire postConstruct
30+
rootBuilder.postConstruct();
31+
return rootBuilder.build();
32+
}
33+
34+
}

src/main/java/io/kanuka/Context.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.kanuka;
2+
3+
import java.util.List;
4+
5+
public class Context {
6+
7+
static BeanContext rootContext = init();
8+
9+
private static BeanContext init() {
10+
return new BootContext().load();
11+
}
12+
13+
public static <T> T getBean(Class<T> cls) {
14+
return rootContext.getBean(cls);
15+
}
16+
17+
public static <T> T getBean(Class<T> cls, String name) {
18+
return rootContext.getBean(cls, name);
19+
}
20+
21+
public static List<Object> getBeans(Class<?> cls) {
22+
return rootContext.getBeans(cls);
23+
}
24+
25+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.kanuka;
2+
3+
public @interface ContextModule {
4+
5+
/**
6+
* The name of the context.
7+
*/
8+
String name() default "";
9+
10+
/**
11+
* The list of dependencies this context depends on.
12+
*/
13+
String[] dependsOn() default {};
14+
15+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package io.kanuka.core;
2+
3+
import io.kanuka.BeanContext;
4+
5+
/**
6+
* This is the service loader interface defining the bean contexts that can be created.
7+
*/
8+
public interface BeanContextFactory {
9+
10+
/**
11+
* Return the name of the bean context this will create.
12+
*/
13+
String name();
14+
15+
/**
16+
* Create and return the BeanContext.
17+
*/
18+
BeanContext createContext(Builder parent);
19+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.kanuka.core;
2+
3+
public interface BeanLifeCycle {
4+
5+
void postConstruct();
6+
7+
void preDestroy();
8+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package io.kanuka.core;
2+
3+
import io.kanuka.BeanContext;
4+
5+
import java.util.Optional;
6+
7+
/**
8+
* Mutable object used when building the context.
9+
*/
10+
public interface Builder {
11+
12+
/**
13+
* Return the name of the context this builder is creating (will be the BeanContext name).
14+
*/
15+
String getName();
16+
17+
/**
18+
* Set a parent builder that can provide cross-module dependencies.
19+
*/
20+
void setParent(Builder parent);
21+
22+
/**
23+
* Add a bean instance to the context.
24+
*
25+
* @param bean The bean instance that has been created.
26+
* @param name The (optional) name of the instance.
27+
* @param interfaceClass Interfaces and class level annotations this bean provides or associates to.
28+
*/
29+
void addBean(Object bean, String name, String... interfaceClass);
30+
31+
/**
32+
* Add a lifecycle bean.
33+
*/
34+
void addLifecycle(BeanLifeCycle lifeCycleBean);
35+
36+
/**
37+
* Add a child context.
38+
*/
39+
void addChild(BeanContext context);
40+
41+
/**
42+
* Set the type of the current bean being created (to assist in error messages when injecting dependencies).
43+
*/
44+
void currentBean(String currentBean);
45+
46+
/**
47+
* Get an optional dependency.
48+
*/
49+
<T> Optional<T> getOptional(Class<T> cls);
50+
51+
/**
52+
* Get an optional named dependency.
53+
*/
54+
<T> Optional<T> getOptional(Class<T> cls, String name);
55+
56+
/**
57+
* Get a dependency.
58+
*/
59+
<T> T get(Class<T> cls);
60+
61+
/**
62+
* Get a named dependency.
63+
*/
64+
<T> T get(Class<T> cls, String name);
65+
66+
/**
67+
* Fire post construct on all beans in the context.
68+
*/
69+
void postConstruct();
70+
71+
/**
72+
* Build and return the bean context.
73+
*/
74+
BeanContext build();
75+
76+
77+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.kanuka.core;
2+
3+
public class BuilderFactory {
4+
5+
/**
6+
* Create the root level Builder.
7+
*/
8+
public static Builder newRootBuilder() {
9+
return new DBuilder(null);
10+
}
11+
12+
/**
13+
* Create a Builder for the named context (module).
14+
*/
15+
public static Builder newBuilder(String name) {
16+
return new DBuilder(name);
17+
}
18+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package io.kanuka.core;
2+
3+
import io.kanuka.BeanContext;
4+
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
import java.util.Map;
8+
9+
class DBeanContext implements BeanContext {
10+
11+
private final String name;
12+
13+
private final List<BeanLifeCycle> lifeCycleList;
14+
15+
private final Map<String, DContextEntry> beans;
16+
17+
private final Map<String, BeanContext> children;
18+
19+
DBeanContext(String name, List<BeanLifeCycle> lifeCycleList, Map<String, DContextEntry> beans, Map<String, BeanContext> children) {
20+
this.name = name;
21+
this.lifeCycleList = lifeCycleList;
22+
this.beans = beans;
23+
this.children = children;
24+
}
25+
26+
@Override
27+
public String getName() {
28+
return name;
29+
}
30+
31+
@Override
32+
public <T> T getBean(Class<T> beanClass) {
33+
return getBean(beanClass, null);
34+
}
35+
36+
@Override
37+
public <T> T getBean(Class<T> beanClass, String name) {
38+
DContextEntry entry = beans.get(beanClass.getCanonicalName());
39+
if (entry != null) {
40+
T bean = (T) entry.get(name);
41+
if (bean != null) {
42+
return bean;
43+
}
44+
}
45+
for (BeanContext childContext : children.values()) {
46+
T bean = childContext.getBean(beanClass);
47+
if (bean != null) {
48+
return bean;
49+
}
50+
}
51+
return null;
52+
}
53+
54+
@Override
55+
public List<Object> getBeans(Class<?> annCls) {
56+
57+
List<Object> list = new ArrayList<>();
58+
59+
DContextEntry entry = beans.get(annCls.getCanonicalName());
60+
if (entry != null) {
61+
entry.addAll(list);
62+
}
63+
for (BeanContext childContext : children.values()) {
64+
list.addAll(childContext.getBeans(annCls));
65+
}
66+
67+
return list;
68+
}
69+
}

0 commit comments

Comments
 (0)