org.asteriskjava.util.internal.FileTrace Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of asterisk-java Show documentation
Show all versions of asterisk-java Show documentation
The free Java library for Asterisk PBX integration.
The newest version!
package org.asteriskjava.util.internal;
import org.asteriskjava.util.DateUtil;
import org.asteriskjava.util.Log;
import org.asteriskjava.util.LogFactory;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
/**
* Writes a trace file to the file system.
*/
public class FileTrace implements Trace {
public static final String TRACE_DIRECTORY_PROPERTY = "org.asteriskjava.trace.directory";
protected static final String FILE_PREFIX = "aj-trace";
protected static final String FILE_SUFFIX = ".txt";
private final Log logger = LogFactory.getLog(FileTrace.class);
// ok to share instance as access to this object is synchronized anyway
private final DateFormat df = new SimpleDateFormat("yyyyMMddHHmmsszzz");
private Charset charset = StandardCharsets.UTF_8;
private FileChannel channel;
private boolean exceptionLogged = false;
private RandomAccessFile randomAccessFile;
public FileTrace(Socket socket) throws IOException {
randomAccessFile = new RandomAccessFile(getFile(socket), "rw");
channel = randomAccessFile.getChannel();
print(getHeader(socket));
}
private String getHeader(Socket socket) {
final StringBuilder sb = new StringBuilder();
sb.append("Local: ");
sb.append(socket.getLocalAddress());
sb.append(":");
sb.append(socket.getLocalPort());
sb.append("\n");
sb.append("Remote: ");
sb.append(socket.getInetAddress());
sb.append(":");
sb.append(socket.getPort());
sb.append("\n");
sb.append("\n");
return sb.toString();
}
private File getFile(Socket socket) {
final String directory = System.getProperty(TRACE_DIRECTORY_PROPERTY, System.getProperty("java.io.tmpdir"));
final String fileName = getFileName(socket);
logger.info("Writing trace to " + directory + File.separator + fileName);
return new File(directory, fileName);
}
private String getFileName(Socket socket) {
final StringBuilder sb = new StringBuilder(FILE_PREFIX);
sb.append("_");
sb.append(df.format(DateUtil.getDate()));
sb.append("_");
sb.append(socket.getLocalAddress().getHostAddress());
sb.append("_");
sb.append(socket.getLocalPort());
sb.append("_");
sb.append(socket.getInetAddress().getHostAddress());
sb.append("_");
sb.append(socket.getPort());
sb.append(FILE_SUFFIX);
return sb.toString();
}
public synchronized void received(String s) {
try {
print(format("<<< ", s));
} catch (IOException e) {
logException(e);
}
}
public synchronized void sent(String s) {
try {
print(format(">>> ", s));
} catch (IOException e) {
logException(e);
}
}
private void logException(IOException e) {
// avoid excessive failure logging
if (exceptionLogged) {
return;
}
logger.warn("Unable to write trace to disk", e);
exceptionLogged = true;
}
protected String format(String prefix, String s) {
final StringBuilder sb = new StringBuilder(df.format(DateUtil.getDate()));
final String filler = String.format("%" + sb.length() + "s", "");
String[] lines = s.split("\n");
for (int i = 0; i < lines.length; i++) {
if (i != 0) {
sb.append(filler);
}
sb.append(" ");
sb.append(prefix);
sb.append(lines[i]);
sb.append("\n");
}
return sb.toString();
}
protected void print(String s) throws IOException {
final CharBuffer charBuffer = CharBuffer.allocate(s.length());
charBuffer.put(s);
charBuffer.flip();
print(charset.encode(charBuffer));
}
private void print(ByteBuffer byteBuffer) throws IOException {
int bytesWritten = 0;
while (bytesWritten < byteBuffer.remaining()) {
// Loop if only part of the buffer contents get written.
bytesWritten = channel.write(byteBuffer);
if (bytesWritten == 0) {
throw new IOException("Unable to write trace to channel. Media may be full.");
}
}
}
public void close() {
try {
randomAccessFile.close();
} catch (IOException e) {
logException(e);
}
}
}