Skip to content

Commit

Permalink
Fixing System.err closure issue
Browse files Browse the repository at this point in the history
  • Loading branch information
dansiviter committed Jul 25, 2023
1 parent 22a2594 commit 4a8cd83
Show file tree
Hide file tree
Showing 14 changed files with 131 additions and 255 deletions.
25 changes: 4 additions & 21 deletions core/src/main/java/uk/dansiviter/jule/AsyncConsoleHandler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021 Daniel Siviter
* Copyright 2023 Daniel Siviter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,30 +16,13 @@
package uk.dansiviter.jule;

/**
* Async implementation which simply delegates to {@link ConsoleHandlerExt}.
* Async implementation which simply delegates to {@link ConsoleHandler}.
*/
public class AsyncConsoleHandler extends AsyncStreamHandler<ConsoleHandlerExt> {
public class AsyncConsoleHandler extends AsyncStreamHandler<ConsoleHandler> {
/**
* Constructs an asynchronous {@code ConsoleHandlerExt}
*/
public AsyncConsoleHandler() {
super(new ConsoleHandlerExt());
property("stdOut")
.map(Boolean::parseBoolean)
.ifPresent(this::setStdOut);
}

/**
* @return {@code true} if using {@link System#out}.
*/
public boolean isStdOut() {
return this.delegate.isStdOut();
}

/**
* @param stdOut if {@code true} this uses {@link System#out}.
*/
public void setStdOut(boolean stdOut) {
this.delegate.setStdOut(stdOut);
super(new ConsoleHandler());
}
}
38 changes: 27 additions & 11 deletions core/src/main/java/uk/dansiviter/jule/AsyncHandler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021 Daniel Siviter
* Copyright 2023 Daniel Siviter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,6 +15,7 @@
*/
package uk.dansiviter.jule;

import static java.nio.charset.Charset.defaultCharset;
import static java.util.concurrent.ForkJoinPool.commonPool;
import static java.util.logging.ErrorManager.GENERIC_FAILURE;
import static java.util.logging.ErrorManager.OPEN_FAILURE;
Expand Down Expand Up @@ -60,9 +61,10 @@
* (defaults to {@link java.util.concurrent.Flow#defaultBufferSize()}). </li>
* </ul>
*/
public abstract class AsyncHandler<R> extends AbstractHandler {
private final Subscriber<R> subscriber = new LogSubscriber();
private final SubmissionPublisher<R> publisher;
public abstract class AsyncHandler extends AbstractHandler {
private static final LogRecord FLUSH = new LogRecord(Level.OFF, "flush");
private final Subscriber<LogRecord> subscriber = new LogSubscriber();
private final SubmissionPublisher<LogRecord> publisher;
/** Closed status */
protected final AtomicBoolean closed = new AtomicBoolean();

Expand Down Expand Up @@ -101,23 +103,32 @@ public void publish(LogRecord r) {
this.publisher.submit(transform(r));
}

@Override
public void flush() {
this.publisher.submit(FLUSH);
}

/**
* Perform any pre-flight transformation of this record. This will be called on the log calling thread.
*
* @param r the record to transform.
* @return the transformed record.
*/
@SuppressWarnings("unchecked")
protected R transform(LogRecord r) {
return (R) r;
protected LogRecord transform(LogRecord r) {
return r;
}

/**
* This will be called asynchronously.
*
* @param r the log record to process.
*/
protected abstract void doPublish(R r);
protected abstract void doPublish(LogRecord r);

/**
* This will be called asynchronously.
*/
protected void doFlush() { }

/**
* @return {@code true} if closed.
Expand All @@ -140,7 +151,7 @@ public void close() throws SecurityException {
/**
*
*/
private class LogSubscriber implements Subscriber<R> {
private class LogSubscriber implements Subscriber<LogRecord> {
private Subscription subscription;

@Override
Expand All @@ -150,13 +161,18 @@ public void onSubscribe(Subscription subscription) {
}

@Override
public void onNext(R item) {
public void onNext(LogRecord item) {
try {
if (item == FLUSH) {
doFlush();
}

doPublish(item);
} catch (RuntimeException e) {
getErrorManager().error(e.getMessage(), e, WRITE_FAILURE);
} finally {
this.subscription.request(1);
}
this.subscription.request(1);
}

@Override
Expand Down
7 changes: 4 additions & 3 deletions core/src/main/java/uk/dansiviter/jule/AsyncStreamHandler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021 Daniel Siviter
* Copyright 2023 Daniel Siviter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -24,7 +24,7 @@
/**
* Async implementation of {@link StreamHandler} which simply delegates.
*/
public abstract class AsyncStreamHandler<H extends StreamHandler> extends AsyncHandler<LogRecord> {
public abstract class AsyncStreamHandler<H extends StreamHandler> extends AsyncHandler {
/** Delegate {@code StreamHandler} */
protected final H delegate;

Expand Down Expand Up @@ -57,12 +57,13 @@ protected void doPublish(LogRecord r) {
}

@Override
public void flush() {
protected void doFlush() {
this.delegate.flush();
}

@Override
public void close() throws SecurityException {
super.close();
this.delegate.close();
}

Expand Down
38 changes: 38 additions & 0 deletions core/src/main/java/uk/dansiviter/jule/ConsoleHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2023 Daniel Siviter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.dansiviter.jule;

import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;
import java.util.logging.StreamHandler;

/**
* A improvement on {@link java.util.logging.ConsoleHandler} where uses {@code STDOUT}.
*/
public class ConsoleHandler extends StreamHandler {
/**
* Default constructor that uses permits setting of output.
*/
public ConsoleHandler() {
super(System.out, new SimpleFormatter());
}

@Override
public synchronized void publish(LogRecord record) {
super.publish(record);
flush();
}
}
59 changes: 0 additions & 59 deletions core/src/main/java/uk/dansiviter/jule/ConsoleHandlerExt.java

This file was deleted.

21 changes: 16 additions & 5 deletions core/src/main/java/uk/dansiviter/jule/PlatformLoggerUtil.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* Copyright 2023 Daniel Siviter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.dansiviter.jule;

import java.lang.System.Logger;
Expand All @@ -11,7 +26,6 @@
public enum PlatformLoggerUtil { ;
private static final Optional<Class<?>> PLATFORM_LOGGER;
private static final Optional<Class<?>> BRIDGE;
private static final Optional<Class<?>> LEVEL;
private static final Optional<Method> LOGP;
private static final Optional<Method> LOGP_THROWN;

Expand All @@ -20,25 +34,22 @@ public enum PlatformLoggerUtil { ;
static {
Class<?> platformLogger;
Class<?> bridge;
Class<?> level;
Method logp;
Method logpThrown;
try {
platformLogger = Class.forName("sun.util.logging.PlatformLogger");
bridge = Class.forName("sun.util.logging.PlatformLogger$Bridge");
level = Class.forName("sun.util.logging.PlatformLogger$Level");
var level = Class.forName("sun.util.logging.PlatformLogger$Level");
logp = bridge.getDeclaredMethod("logp", level, String.class, String.class, Supplier.class);
logpThrown = bridge.getDeclaredMethod("logp", level, String.class, String.class, Throwable.class, Supplier.class);
} catch (ReflectiveOperationException e) {
platformLogger = null;
bridge = null;
level = null;
logp = null;
logpThrown = null;
}
PLATFORM_LOGGER = Optional.of(platformLogger);
BRIDGE = Optional.ofNullable(bridge);
LEVEL = Optional.ofNullable(level);
LOGP = Optional.ofNullable(logp);
LOGP_THROWN = Optional.ofNullable(logpThrown);
}
Expand Down
67 changes: 0 additions & 67 deletions core/src/test/java/uk/dansiviter/jule/AsyncConsoleHandlerTest.java

This file was deleted.

Loading

0 comments on commit 4a8cd83

Please sign in to comment.