public static DaemonLog createInstance( File file, Applicable<? super OutputStream, ? extends ResourceProviderDefinition<? extends Handler>> loggingHandlerFactory) { ResourceProvider<OutputStream> streamProvider = ResourceProvider.of(new LogFileStreamProvider(file)); ResourceProvider<? extends Handler> handlerProvider = streamProvider.flatMap(loggingHandlerFactory); return new DaemonLog(handlerProvider, true, true); }
/** @author Victor Nazarov <[email protected]> */ public class DaemonLog { private static final DaemonLog STANDARD_OUT = new DaemonLog( ResourceProvider.forExisting(System.out).flatMap(FlushingLoggingFactory.INSTANCE), false, false); private static final DaemonLog STANDARD_ERR = new DaemonLog( ResourceProvider.forExisting(System.err).flatMap(FlushingLoggingFactory.INSTANCE), false, false); public static DaemonLog standardOut() { return STANDARD_OUT; } public static DaemonLog standardErr() { return STANDARD_ERR; } public static DaemonLog createInstance(File file) { return createInstance(file, FlushingLoggingFactory.INSTANCE); } public static DaemonLog createInstance( File file, Applicable<? super OutputStream, ? extends ResourceProviderDefinition<? extends Handler>> loggingHandlerFactory) { ResourceProvider<OutputStream> streamProvider = ResourceProvider.of(new LogFileStreamProvider(file)); ResourceProvider<? extends Handler> handlerProvider = streamProvider.flatMap(loggingHandlerFactory); return new DaemonLog(handlerProvider, true, true); } private final ResourceProviderDefinition<? extends Handler> handlerProvider; private final boolean closesStandardOut; private final boolean closesStandardErr; private DaemonLog( ResourceProviderDefinition<? extends Handler> handlerProvider, boolean closesStandardOut, boolean closesStandardErr) { this.handlerProvider = handlerProvider; this.closesStandardOut = closesStandardOut; this.closesStandardErr = closesStandardErr; } public ResourceProviderDefinition<? extends Handler> handlerProvider() { return handlerProvider; } boolean closesStandardOut() { return closesStandardOut; } boolean closesStandardErr() { return closesStandardErr; } private static class FlushingLoggingFactory implements Applicable<OutputStream, ResourceProvider<Handler>> { public static final Applicable<OutputStream, ResourceProvider<Handler>> INSTANCE = new FlushingLoggingFactory(); @Override public ResourceProvider<Handler> apply(final OutputStream stream) { return ResourceProvider.of(new FlushingHandlerResourceProvider(stream)); } private static class FlushingHandlerResourceProvider implements ResourceProviderDefinition<Handler> { private final OutputStream stream; FlushingHandlerResourceProvider(OutputStream stream) { this.stream = stream; } @Override public void provideResourceTo(Consumer<? super Handler> consumer) { Handler handler = Handlers.createFlushingHandler(stream); try { consumer.accept(handler); } finally { handler.close(); } } } } private static class LogFileStreamProvider implements ResourceProviderDefinition<OutputStream> { private final File file; LogFileStreamProvider(File file) { this.file = file; } @Override public void provideResourceTo(Consumer<? super OutputStream> consumer) { try { OutputStream stream = new HUPReopeningFileOutputStream(file); try { BufferedOutputStream bufferedStream = new BufferedOutputStream(stream); try { consumer.accept(bufferedStream); } finally { try { bufferedStream.close(); } catch (Exception ex) { Logger.getLogger(LogFileStreamProvider.class.getName()).log(Level.SEVERE, null, ex); } } } finally { try { stream.close(); } catch (Exception ex) { Logger.getLogger(LogFileStreamProvider.class.getName()).log(Level.SEVERE, null, ex); } } } catch (IOException ex) { throw new RuntimeException(ex); } } } }
@Override public ResourceProvider<Handler> apply(final OutputStream stream) { return ResourceProvider.of(new FlushingHandlerResourceProvider(stream)); }