001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jpos.util;
020
021import java.io.ByteArrayOutputStream;
022import java.io.IOException;
023import java.io.OutputStream;
024import java.util.concurrent.Executors;
025import java.util.concurrent.ScheduledExecutorService;
026import java.util.concurrent.Semaphore;
027import java.util.concurrent.TimeUnit;
028
029public class LogEventOutputStream extends OutputStream implements LogSource, Runnable {
030    private ByteArrayOutputStream baos = new ByteArrayOutputStream();
031    private Logger logger;
032    private String realm;
033    private ScheduledExecutorService logService;
034    private Semaphore lock = new Semaphore(1);
035    private volatile LogEvent evt;
036    private long delay;
037
038    public LogEventOutputStream() {
039        super();
040        baos = new ByteArrayOutputStream();
041        logService = Executors.newScheduledThreadPool(1);
042    }
043
044    public LogEventOutputStream(Logger logger, String realm, long delay) {
045        this();
046        this.logger = logger;
047        this.realm = realm;
048        this.delay = delay;
049    }
050
051    @Override
052    public void write(int b) throws IOException {
053        if (b == '\n') {
054            try {
055                lock.acquire();
056                if (evt == null) {
057                    evt = new LogEvent(this, "");
058                    logService.schedule(this, delay, TimeUnit.MILLISECONDS);
059                }
060                evt.addMessage(baos.toString());
061                baos = new ByteArrayOutputStream();
062            } catch (InterruptedException ignored) {
063            } finally {
064                lock.release();
065            }
066        } else {
067            baos.write(b);
068        }
069    }
070
071    @Override
072    public void setLogger(Logger logger, String realm) {
073        this.logger = logger;
074        this.realm = realm;
075    }
076
077    @Override
078    public String getRealm() {
079        return realm;
080    }
081
082    @Override
083    public Logger getLogger() {
084        return logger;
085    }
086
087    @Override
088    public void run() {
089        LogEvent event = null;
090        if (evt != null) {
091            try {
092                lock.acquire();
093                event = evt;
094                evt = null;
095            } catch (InterruptedException ignore) {
096            } finally {
097                lock.release();
098            }
099            if (event != null)
100                Logger.log(event);
101        }
102    }
103
104    @Override
105    public void close() throws IOException {
106        super.close();
107        try {
108            lock.acquire();
109            logService.shutdown();
110        } catch (InterruptedException ignore) {
111        } finally {
112            lock.release();
113        }
114    }
115}