Skip to content

Commit

Permalink
[69] robo4j-core test logger
Browse files Browse the repository at this point in the history
  • Loading branch information
mirage22 committed Oct 7, 2024
1 parent f33273d commit b450f38
Show file tree
Hide file tree
Showing 18 changed files with 997 additions and 1,005 deletions.
28 changes: 12 additions & 16 deletions robo4j-core/src/main/java/com/robo4j/reflect/ReflectionScan.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,17 @@
*/
package com.robo4j.reflect;

import com.robo4j.logging.SimpleLoggingUtil;
import com.robo4j.util.StreamUtils;
import com.robo4j.util.StringConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
Expand All @@ -42,19 +39,20 @@
* @author Miro Wengner (@miragemiko)
*/
public final class ReflectionScan {
private static final Logger LOGGER = LoggerFactory.getLogger(ReflectionScan.class);
private static final String FILE = "file:";
private static final String SUFFIX = ".class";
private static final String EXCLAMATION = "\u0021"; //Exclamation mark !
private static final String EXCLAMATION = "\u0021"; //Exclamation mark !
private static final char SLASH = '/';
private static final char DOT = '.';

private final ClassLoader loader;

public ReflectionScan(ClassLoader loader){
public ReflectionScan(ClassLoader loader) {
this.loader = loader;
}

public List<String> scanForEntities(String... entityPackages){
public List<String> scanForEntities(String... entityPackages) {
final List<String> result = new ArrayList<>();
for (String packageName : entityPackages) {
packageName = packageName.trim();
Expand All @@ -63,17 +61,15 @@ public List<String> scanForEntities(String... entityPackages){
if (classesInPackage.isEmpty()) {
classesInPackage.addAll(scanPackageOnDisk(loader, packageName));
if (classesInPackage.isEmpty()) {
SimpleLoggingUtil.debug(getClass(),
"We did not find any annotated classes in package " + packageName);
LOGGER.debug("We did not find any annotated classes in package {}", packageName);
} else {
result.addAll(classesInPackage);
}
} else {
result.addAll(classesInPackage);
}
} catch (IOException e) {
// TODO: provide robust logging
e.printStackTrace();
LOGGER.error(e.getMessage(), e);
}
}
return result;
Expand Down Expand Up @@ -114,7 +110,7 @@ private List<String> scanJarPackage(ClassLoader loader, String packageName) thro
}

private List<String> scanPackageOnDisk(ClassLoader loader, String packageName) throws IOException {
final var packagePathStr = slashify(packageName);
final var packagePathStr = slashify(packageName);
// TODO: improve reflection, review usage
return loader.resources(packagePathStr).map(URL::getFile).map(File::new)
.map(f -> findClasses(f, packageName)).flatMap(List::stream).collect(Collectors.toList());
Expand All @@ -135,8 +131,8 @@ private List<String> findClassesIntern(File dir, String path) {
} else if (file.getName().endsWith(SUFFIX)) {
final StringBuilder sb = new StringBuilder();
sb.append(path.replace(File.separatorChar, DOT))
.append(DOT)
.append(file.getName(), 0, file.getName().length() - SUFFIX.length());
.append(DOT)
.append(file.getName(), 0, file.getName().length() - SUFFIX.length());

result.add(sb.toString());
}
Expand Down
196 changes: 95 additions & 101 deletions robo4j-core/src/main/java/com/robo4j/scheduler/DefaultScheduler.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,115 +16,109 @@
*/
package com.robo4j.scheduler;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.robo4j.RoboContext;
import com.robo4j.RoboReference;
import com.robo4j.RoboUnit;
import com.robo4j.logging.SimpleLoggingUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

/**
* This is the default scheduler used in Robo4J.
*
*
* @author Marcus Hirt (@hirt)
* @author Miroslav Wengner (@miragemiko)
*/
public class DefaultScheduler implements Scheduler {
private static final int DEFAULT_NUMBER_OF_THREADS = 2;
private static final int TERMINATION_TIMEOUT_SEC = 4;

private final ScheduledExecutorService executor;
private final RoboContext context;

/**
* Default constructor.
*
* @param context
* the context.
*/
public DefaultScheduler(RoboContext context) {
this(context, DEFAULT_NUMBER_OF_THREADS);
}

/**
* Constructor.
*
* @param context
* the context.
* @param numberOfThreads
* the number of threads in the thread pool.
*/
public DefaultScheduler(RoboContext context, int numberOfThreads) {
this.context = context;
this.executor = new ScheduledThreadPoolExecutor(numberOfThreads,
new RoboThreadFactory(new ThreadGroup("Robo4J Scheduler"), "Robo4J Scheduler", true));
}

@Override
public <T> ScheduledFuture<?> schedule(RoboReference<T> target, T message, long delay, long interval, TimeUnit unit,
int numberOfInvocations) {
return schedule(target, message, delay, interval, unit, numberOfInvocations, null);
}

@Override
public <T> ScheduledFuture<?> schedule(RoboReference<T> target, T message, long delay, long period, TimeUnit unit,
int numberOfInvocations, FinalInvocationListener listener) {
ScheduledMessageWrapper<T> command = createCommand(target, numberOfInvocations, message, listener);
ScheduledFuture<?> future = executor.scheduleAtFixedRate(command, delay, period, unit);
command.setFuture(future);
return future;
}

private <T> ScheduledMessageWrapper<T> createCommand(RoboReference<T> reference, int numberOfInvocations, T message,
FinalInvocationListener listener) {
return new ScheduledMessageWrapper<>(context, reference, numberOfInvocations, message, listener);
}

@Override
public <T> ScheduledFuture<?> schedule(RoboReference<T> target, T message, long delay, long interval, TimeUnit unit) {
return executor.scheduleAtFixedRate(() -> deliverMessage(target, message), delay, interval, unit);
}

@Override
public void shutdown() throws InterruptedException {
executor.shutdown();
var status = executor.awaitTermination(TERMINATION_TIMEOUT_SEC, TimeUnit.SECONDS);
SimpleLoggingUtil.debug(DefaultScheduler.class, "shutdown status:" + status);
}

static <T> void deliverMessage(final RoboReference<T> reference, final T message) {
// Performance optimization - let the scheduling thread deliver the
// message directly if this is robo unit implementation, instead of
// enqueuing it with the message executor.
if (reference instanceof RoboUnit) {
((RoboUnit<T>) reference).onMessage(message);
} else {
reference.sendMessage(message);
}
}

@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long delay, long interval, TimeUnit unit) {
return executor.scheduleAtFixedRate(runnable, delay, interval, unit);
}

@Override
public void schedule(Runnable runnable, long delay, TimeUnit unit) {
executor.schedule(runnable, delay, unit);
}

@Override
public void execute(Runnable r) {
executor.execute(r);
}

@Override
public <T> Future<T> submit(Callable<T> r) {
return executor.submit(r);
}
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultScheduler.class);
private static final int DEFAULT_NUMBER_OF_THREADS = 2;
private static final int TERMINATION_TIMEOUT_SEC = 4;

private final ScheduledExecutorService executor;
private final RoboContext context;

/**
* Default constructor.
*
* @param context the context.
*/
public DefaultScheduler(RoboContext context) {
this(context, DEFAULT_NUMBER_OF_THREADS);
}

/**
* Constructor.
*
* @param context the context.
* @param numberOfThreads the number of threads in the thread pool.
*/
public DefaultScheduler(RoboContext context, int numberOfThreads) {
this.context = context;
this.executor = new ScheduledThreadPoolExecutor(numberOfThreads,
new RoboThreadFactory(new ThreadGroup("Robo4J Scheduler"), "Robo4J Scheduler", true));
}

@Override
public <T> ScheduledFuture<?> schedule(RoboReference<T> target, T message, long delay, long interval, TimeUnit unit,
int numberOfInvocations) {
return schedule(target, message, delay, interval, unit, numberOfInvocations, null);
}

@Override
public <T> ScheduledFuture<?> schedule(RoboReference<T> target, T message, long delay, long period, TimeUnit unit,
int numberOfInvocations, FinalInvocationListener listener) {
ScheduledMessageWrapper<T> command = createCommand(target, numberOfInvocations, message, listener);
ScheduledFuture<?> future = executor.scheduleAtFixedRate(command, delay, period, unit);
command.setFuture(future);
return future;
}

private <T> ScheduledMessageWrapper<T> createCommand(RoboReference<T> reference, int numberOfInvocations, T message,
FinalInvocationListener listener) {
return new ScheduledMessageWrapper<>(context, reference, numberOfInvocations, message, listener);
}

@Override
public <T> ScheduledFuture<?> schedule(RoboReference<T> target, T message, long delay, long interval, TimeUnit unit) {
return executor.scheduleAtFixedRate(() -> deliverMessage(target, message), delay, interval, unit);
}

@Override
public void shutdown() throws InterruptedException {
executor.shutdown();
var status = executor.awaitTermination(TERMINATION_TIMEOUT_SEC, TimeUnit.SECONDS);
LOGGER.debug("shutdown status:{}", status);
}

static <T> void deliverMessage(final RoboReference<T> reference, final T message) {
// Performance optimization - let the scheduling thread deliver the
// message directly if this is robo unit implementation, instead of
// enqueuing it with the message executor.
if (reference instanceof RoboUnit) {
((RoboUnit<T>) reference).onMessage(message);
} else {
reference.sendMessage(message);
}
}

@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long delay, long interval, TimeUnit unit) {
return executor.scheduleAtFixedRate(runnable, delay, interval, unit);
}

@Override
public void schedule(Runnable runnable, long delay, TimeUnit unit) {
executor.schedule(runnable, delay, unit);
}

@Override
public void execute(Runnable r) {
executor.execute(r);
}

@Override
public <T> Future<T> submit(Callable<T> r) {
return executor.submit(r);
}
}
Loading

0 comments on commit b450f38

Please sign in to comment.