/**
* Copyright (C) 2011 Brian Ferris <bdferris@onebusaway.org>
*
* 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 org.onebusaway.users.impl.logging;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.onebusaway.users.services.logging.UserInteractionLoggingOutlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserInteractionLoggingOutletImpl implements
UserInteractionLoggingOutlet {
private static Logger _log = LoggerFactory.getLogger(UserInteractionLoggingOutletImpl.class);
private static ExecutorService _executorService = Executors.newFixedThreadPool(2);
private String _path;
private Process _process;
private PrintWriter _out;
private boolean _logProcessOutput = true;
public void setPath(String path) {
_path = path;
}
public void setLogProcessOutput(boolean logProcessOutput) {
_logProcessOutput = logProcessOutput;
}
@PostConstruct
public void setup() throws IOException {
if (_path.startsWith("|")) {
String path = _path.substring(1);
String[] args = path.split("\\s+");
if (_log.isDebugEnabled())
_log.debug("opening process for logging: " + Arrays.toString(args));
Runtime runtime = Runtime.getRuntime();
_process = runtime.exec(args);
_out = new PrintWriter(
new OutputStreamWriter(_process.getOutputStream()), true);
if (_logProcessOutput) {
_executorService.execute(new OutputLogger("stdout", new BufferedReader(
new InputStreamReader(_process.getInputStream()))));
_executorService.execute(new OutputLogger("stderr", new BufferedReader(
new InputStreamReader(_process.getErrorStream()))));
}
} else {
if (_log.isDebugEnabled())
_log.debug("opening file for logging: " + _path);
_out = new PrintWriter(new FileWriter(_path, true), true);
}
}
@PreDestroy
public void tearDown() throws InterruptedException {
if (_out != null)
_out.close();
if (_process != null) {
try {
_process.getOutputStream().close();
} catch (IOException ex) {
_log.warn("error closing process output stream", ex);
}
int exitValue = _process.waitFor();
if (exitValue != 0)
_log.warn("logging process did not return normally: exitValue="
+ exitValue);
}
if (_executorService != null)
_executorService.shutdownNow();
}
@Override
public void logInteraction(String serialized) {
if (_log.isDebugEnabled())
_log.debug("logging interaction: " + serialized);
_out.println(serialized);
}
private static class OutputLogger implements Runnable {
private BufferedReader _reader;
private String _prefix;
public OutputLogger(String prefix, BufferedReader reader) {
_prefix = prefix;
_reader = reader;
}
@Override
public void run() {
try {
String line = null;
while ((line = _reader.readLine()) != null) {
_log.info("output: prefix=" + _prefix + " output=" + line);
}
} catch (IOException ex) {
_log.warn("error reading output: prefix=" + _prefix, ex);
} finally {
try {
_reader.close();
} catch (IOException e) {
}
}
_log.debug("exiting output logger: prefix=" + _prefix);
}
}
}