
org.revenj.Revenj Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of revenj-core Show documentation
Show all versions of revenj-core Show documentation
DSL Platform compatible backend (https://dsl-platform.com)
The newest version!
package org.revenj;
import org.postgresql.ds.PGPoolingDataSource;
import org.revenj.database.postgres.converters.JsonConverter;
import org.revenj.extensibility.*;
import org.revenj.serialization.json.DslJsonSerialization;
import org.revenj.patterns.*;
import org.revenj.database.postgres.jinq.JinqMetaModel;
import org.revenj.security.PermissionManager;
import org.revenj.serialization.Serialization;
import org.revenj.serialization.xml.XmlJaxbSerialization;
import org.w3c.dom.Element;
import javax.sql.DataSource;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
public abstract class Revenj {
public static Container setup() throws IOException {
Properties properties = new Properties();
File revProps = new File("revenj.properties");
if (revProps.exists() && revProps.isFile()) {
properties.load(new FileReader(revProps));
} else {
String location = System.getProperty("revenj.properties");
if (location != null) {
revProps = new File(location);
if (revProps.exists() && revProps.isFile()) {
properties.load(new FileReader(revProps));
} else {
throw new IOException("Unable to find revenj.properties in alternative location. Searching in: " + revProps.getAbsolutePath());
}
} else {
throw new IOException("Unable to find revenj.properties. Searching in: " + revProps.getAbsolutePath());
}
}
return setup(properties);
}
public static Container setup(Properties properties) throws IOException {
String plugins = properties.getProperty("revenj.pluginsPath");
File pluginsPath = null;
if (plugins != null) {
File pp = new File(plugins);
pluginsPath = pp.isDirectory() ? pp : null;
}
return setup(
dataSource(properties),
properties,
Optional.ofNullable(pluginsPath),
Optional.ofNullable(Thread.currentThread().getContextClassLoader()));
}
public static DataSource dataSource(Properties properties) throws IOException {
String jdbcUrl = properties.getProperty("revenj.jdbcUrl");
if (jdbcUrl == null) {
throw new IOException("revenj.jdbcUrl is missing from Properties");
}
if (!jdbcUrl.startsWith("jdbc:postgresql:")) {
throw new IOException("Invalid revenj.jdbcUrl provided. Expecting: 'jdbc:postgresql:...'. Found: '" + jdbcUrl + "'.\n" +
"If you wish to use custom jdbc driver provide custom data source instead of using Postgres builtin data source.");
}
org.postgresql.ds.PGPoolingDataSource dataSource = new PGPoolingDataSource();
dataSource.setUrl(jdbcUrl);
String user = properties.getProperty("user");
String revUser = properties.getProperty("revenj.user");
if (revUser != null && revUser.length() > 0) {
dataSource.setUser(revUser);
} else if (user != null && user.length() > 0) {
dataSource.setUser(user);
}
String password = properties.getProperty("password");
String revPassword = properties.getProperty("revenj.password");
if (revPassword != null && revPassword.length() > 0) {
dataSource.setPassword(revPassword);
} else if (password != null && password.length() > 0) {
dataSource.setPassword(password);
}
return dataSource;
}
public static Container setup(
DataSource dataSource,
Properties properties,
Optional pluginsPath,
Optional classLoader) throws IOException {
ClassLoader loader;
if (pluginsPath.isPresent()) {
File[] jars = pluginsPath.get().listFiles(f -> f.getPath().toLowerCase().endsWith(".jar"));
List urls = new ArrayList<>(jars != null ? jars.length : 0);
if (jars != null) {
for (File j : jars) {
try {
urls.add(j.toURI().toURL());
} catch (MalformedURLException ex) {
throw new IOException(ex);
}
}
}
loader = classLoader.isPresent()
? new URLClassLoader(urls.toArray(new URL[urls.size()]), classLoader.get())
: new URLClassLoader(urls.toArray(new URL[urls.size()]));
} else if (classLoader.isPresent()) {
loader = classLoader.get();
} else {
loader = Thread.currentThread().getContextClassLoader();
}
ServiceLoader aspects = ServiceLoader.load(SystemAspect.class, loader);
return setup(dataSource, properties, Optional.of(loader), aspects.iterator());
}
private static class SimpleDomainModel implements DomainModel {
private String[] namespaces = new String[0];
private final ClassLoader loader;
private final ConcurrentMap> cache = new ConcurrentHashMap<>();
SimpleDomainModel(ClassLoader loader) {
this.loader = loader;
}
void setNamespace(String namespaces) {
String[] parts = namespaces == null ? new String[0] : namespaces.split(",");
this.namespaces = new String[parts.length];
for (int i = 0; i < parts.length; i++) {
String ns = parts[i];
this.namespaces[i] = ns.length() > 0 ? ns + "." : "";
}
}
@Override
public Optional> find(String name) {
if (name == null) {
return Optional.empty();
}
Class> found = cache.get(name);
if (found != null) {
return Optional.of(found);
}
String className = name.indexOf('+') != -1 ? name.replace('+', '$') : name;
for (String ns : namespaces) {
try {
Class> manifest = Class.forName(ns + className, true, loader);
cache.put(name, manifest);
return Optional.of(manifest);
} catch (ClassNotFoundException ignore) {
}
}
return Optional.empty();
}
}
public static Container container(boolean resolveUnknown, ClassLoader loader) {
Container container = new SimpleContainer(resolveUnknown);
for (SystemAspect aspect : ServiceLoader.load(SystemAspect.class, loader)) {
try {
aspect.configure(container);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return container;
}
public static Container setup(
DataSource dataSource,
Properties properties,
Optional classLoader,
Iterator aspects) throws IOException {
RevenjSystemState state = new RevenjSystemState();
ClassLoader loader = classLoader.orElse(Thread.currentThread().getContextClassLoader());
SimpleContainer container = new SimpleContainer("true".equals(properties.getProperty("revenj.resolveUnknown")));
container.registerAs(state, SystemState.class);
container.registerInstance(properties);
container.registerInstance(ServiceLocator.class, container, false);
container.registerInstance(DataSource.class, dataSource, false);
container.registerInstance(ClassLoader.class, loader, false);
container.register(GlobalEventStore.class, InstanceScope.SINGLETON);
container.register(JsonConverter.class, InstanceScope.SINGLETON);
SimpleDomainModel domainModel = new SimpleDomainModel(loader);
container.registerInstance(DomainModel.class, domainModel, false);
container.registerFactory(DataContext.class, LocatorDataContext::asDataContext, InstanceScope.CONTEXT);
container.registerFactory(UnitOfWork.class, LocatorDataContext::asUnitOfWork, InstanceScope.TRANSIENT);
container.registerFactory(
new Generic>(){}.type,
c -> (Function) connection -> LocatorDataContext.asDataContext(c, connection),
InstanceScope.CONTEXT);
PluginLoader plugins = new ServicesPluginLoader(loader);
container.registerInstance(PluginLoader.class, plugins, false);
PostgresDatabaseNotification databaseNotification =
new PostgresDatabaseNotification(
dataSource,
Optional.of(domainModel),
properties,
state,
container);
container.registerInstance(EagerNotification.class, databaseNotification, false);
container.registerInstance(DataChangeNotification.class, databaseNotification, true);
ChangeNotification.registerContainer(container, databaseNotification);
container.registerGenerics(
Query.class,
(c, arr) -> {
try {
return c.resolve(SearchableRepository.class, arr[0]).query();
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
},
InstanceScope.CONTEXT);
container.registerFactory(RepositoryBulkReader.class, PostgresBulkReader::create, InstanceScope.CONTEXT);
container.registerInstance(PermissionManager.class, new RevenjPermissionManager(container), false);
container.registerType(DslJsonSerialization.class, DslJsonSerialization.class, InstanceScope.SINGLETON);
container.registerType(new Generic>() {
}.type, DslJsonSerialization.class, InstanceScope.SINGLETON);
XmlJaxbSerialization xml = new XmlJaxbSerialization(container, Optional.of(plugins));
container.registerInstance(new Generic>() {
}.type, xml, false);
container.registerInstance(xml);
int total = 0;
if (aspects != null) {
JinqMetaModel.configure(container);
while (aspects.hasNext()) {
aspects.next().configure(container);
total++;
}
}
domainModel.setNamespace(properties.getProperty("revenj.namespace"));
properties.setProperty("revenj.aspectsCount", Integer.toString(total));
state.started(container);
return container;
}
public static void registerEvents(Container container, PluginLoader plugins, Class manifest, Class arrayManifest) throws Exception {
Type gt = Utils.makeGenericType(DomainEventHandler.class, manifest);
List> eventHandlers = plugins.find(DomainEventHandler.class, manifest);
for (Class h : eventHandlers) {
container.registerType(h, h, InstanceScope.CONTEXT);
container.registerType(gt, h, InstanceScope.CONTEXT);
}
gt = Utils.makeGenericType(DomainEventHandler.class, arrayManifest);
eventHandlers = plugins.find(DomainEventHandler.class, arrayManifest);
for (Class h : eventHandlers) {
container.registerType(h, h, InstanceScope.CONTEXT);
container.registerType(gt, h, InstanceScope.CONTEXT);
}
Type ct = Utils.makeGenericType(Callable.class, manifest);
gt = Utils.makeGenericType(DomainEventHandler.class, ct);
eventHandlers = plugins.find(DomainEventHandler.class, ct);
for (Class h : eventHandlers) {
container.registerType(h, h, InstanceScope.CONTEXT);
container.registerType(gt, h, InstanceScope.CONTEXT);
}
ct = Utils.makeGenericType(Callable.class, arrayManifest);
gt = Utils.makeGenericType(DomainEventHandler.class, ct);
eventHandlers = plugins.find(DomainEventHandler.class, ct);
for (Class h : eventHandlers) {
container.registerType(h, h, InstanceScope.CONTEXT);
container.registerType(gt, h, InstanceScope.CONTEXT);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy