Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
rbygrave committed Nov 7, 2018
1 parent b9a4455 commit f5afee2
Show file tree
Hide file tree
Showing 16 changed files with 630 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# editorconfig.org

root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
spaces_around_operators = true
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
target/
build/
.idea/
*.iml
.gradle
28 changes: 28 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>io.kanuka</groupId>
<artifactId>kanuka</artifactId>
<version>0.1-SNAPSHOT</version>

<parent>
<groupId>org.avaje</groupId>
<artifactId>java8-parent</artifactId>
<version>1.3</version>
</parent>

<dependencies>

<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>

</dependencies>


</project>
28 changes: 28 additions & 0 deletions src/main/java/io/kanuka/BeanContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.kanuka;

import java.util.List;

public interface BeanContext {

/**
* Return the name of the bean context.
*/
String getName();

/**
* Return a single bean given the type.
*/
<T> T getBean(Class<T> beanClass);

/**
* Return a single bean given the type and name.
*/
<T> T getBean(Class<T> beanClass, String name);

/**
* Return the list of beans that implement the interface or are marked with the annotation.
*
* @param interfaceOrAnnotation An interface class or annotation class.
*/
List<Object> getBeans(Class<?> interfaceOrAnnotation);
}
34 changes: 34 additions & 0 deletions src/main/java/io/kanuka/BootContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.kanuka;

import io.kanuka.core.BeanContextFactory;
import io.kanuka.core.Builder;
import io.kanuka.core.BuilderFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;

public class BootContext {

/**
* Load all the named contexts.
*/
public BeanContext load() {

List<BeanContextFactory> factories = new ArrayList<>();
ServiceLoader.load(BeanContextFactory.class).forEach(factories::add);

// sort factories by dependsOn

Builder rootBuilder = BuilderFactory.newRootBuilder();

for (BeanContextFactory factory : factories) {
rootBuilder.addChild(factory.createContext(rootBuilder));
}

// entire graph built, fire postConstruct
rootBuilder.postConstruct();
return rootBuilder.build();
}

}
25 changes: 25 additions & 0 deletions src/main/java/io/kanuka/Context.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.kanuka;

import java.util.List;

public class Context {

static BeanContext rootContext = init();

private static BeanContext init() {
return new BootContext().load();
}

public static <T> T getBean(Class<T> cls) {
return rootContext.getBean(cls);
}

public static <T> T getBean(Class<T> cls, String name) {
return rootContext.getBean(cls, name);
}

public static List<Object> getBeans(Class<?> cls) {
return rootContext.getBeans(cls);
}

}
15 changes: 15 additions & 0 deletions src/main/java/io/kanuka/ContextModule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.kanuka;

public @interface ContextModule {

/**
* The name of the context.
*/
String name() default "";

/**
* The list of dependencies this context depends on.
*/
String[] dependsOn() default {};

}
19 changes: 19 additions & 0 deletions src/main/java/io/kanuka/core/BeanContextFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.kanuka.core;

import io.kanuka.BeanContext;

/**
* This is the service loader interface defining the bean contexts that can be created.
*/
public interface BeanContextFactory {

/**
* Return the name of the bean context this will create.
*/
String name();

/**
* Create and return the BeanContext.
*/
BeanContext createContext(Builder parent);
}
8 changes: 8 additions & 0 deletions src/main/java/io/kanuka/core/BeanLifeCycle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.kanuka.core;

public interface BeanLifeCycle {

void postConstruct();

void preDestroy();
}
77 changes: 77 additions & 0 deletions src/main/java/io/kanuka/core/Builder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package io.kanuka.core;

import io.kanuka.BeanContext;

import java.util.Optional;

/**
* Mutable object used when building the context.
*/
public interface Builder {

/**
* Return the name of the context this builder is creating (will be the BeanContext name).
*/
String getName();

/**
* Set a parent builder that can provide cross-module dependencies.
*/
void setParent(Builder parent);

/**
* Add a bean instance to the context.
*
* @param bean The bean instance that has been created.
* @param name The (optional) name of the instance.
* @param interfaceClass Interfaces and class level annotations this bean provides or associates to.
*/
void addBean(Object bean, String name, String... interfaceClass);

/**
* Add a lifecycle bean.
*/
void addLifecycle(BeanLifeCycle lifeCycleBean);

/**
* Add a child context.
*/
void addChild(BeanContext context);

/**
* Set the type of the current bean being created (to assist in error messages when injecting dependencies).
*/
void currentBean(String currentBean);

/**
* Get an optional dependency.
*/
<T> Optional<T> getOptional(Class<T> cls);

/**
* Get an optional named dependency.
*/
<T> Optional<T> getOptional(Class<T> cls, String name);

/**
* Get a dependency.
*/
<T> T get(Class<T> cls);

/**
* Get a named dependency.
*/
<T> T get(Class<T> cls, String name);

/**
* Fire post construct on all beans in the context.
*/
void postConstruct();

/**
* Build and return the bean context.
*/
BeanContext build();


}
18 changes: 18 additions & 0 deletions src/main/java/io/kanuka/core/BuilderFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.kanuka.core;

public class BuilderFactory {

/**
* Create the root level Builder.
*/
public static Builder newRootBuilder() {
return new DBuilder(null);
}

/**
* Create a Builder for the named context (module).
*/
public static Builder newBuilder(String name) {
return new DBuilder(name);
}
}
69 changes: 69 additions & 0 deletions src/main/java/io/kanuka/core/DBeanContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package io.kanuka.core;

import io.kanuka.BeanContext;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

class DBeanContext implements BeanContext {

private final String name;

private final List<BeanLifeCycle> lifeCycleList;

private final Map<String, DContextEntry> beans;

private final Map<String, BeanContext> children;

DBeanContext(String name, List<BeanLifeCycle> lifeCycleList, Map<String, DContextEntry> beans, Map<String, BeanContext> children) {
this.name = name;
this.lifeCycleList = lifeCycleList;
this.beans = beans;
this.children = children;
}

@Override
public String getName() {
return name;
}

@Override
public <T> T getBean(Class<T> beanClass) {
return getBean(beanClass, null);
}

@Override
public <T> T getBean(Class<T> beanClass, String name) {
DContextEntry entry = beans.get(beanClass.getCanonicalName());
if (entry != null) {
T bean = (T) entry.get(name);
if (bean != null) {
return bean;
}
}
for (BeanContext childContext : children.values()) {
T bean = childContext.getBean(beanClass);
if (bean != null) {
return bean;
}
}
return null;
}

@Override
public List<Object> getBeans(Class<?> annCls) {

List<Object> list = new ArrayList<>();

DContextEntry entry = beans.get(annCls.getCanonicalName());
if (entry != null) {
entry.addAll(list);
}
for (BeanContext childContext : children.values()) {
list.addAll(childContext.getBeans(annCls));
}

return list;
}
}
Loading

0 comments on commit f5afee2

Please sign in to comment.