package net.sf.microlog.appender; import java.io.IOException; import java.io.OutputStream; import javax.microedition.io.Connector; import javax.microedition.io.file.FileConnection; import net.sf.microlog.Level; import net.sf.microlog.util.PropertiesGetter; /** * A class that logs to a file. The class uses the FileConnection API from * JSR-75. * <p> * The file name can be passed with the property * <code>microlog.appender.FileAppender.filename</code>. * * npearman - Modified for Sony Ericsson filesystem * * @author Johan Karlsson (johan.karlsson@jayway.se) * @author Karsten Ohme * @since 0.1 */ public class FileAppender extends AbstractAppender { public static final String FILENAME_STRING = "microlog.appender.FileAppender.filename"; public static final String DEFAULT_FILENAME = "microlog.txt"; public static final String DEFAULT_EMULATOR_ROOT = "/root1"; private static final int BUFFER_SIZE = 256; private static final String FILE_PROTOCOL = "file://"; private final String lineSeparator = "\r\n"; private String fileSeparator = "/"; private String rootDir = "/e:/"; private String fileName = DEFAULT_FILENAME; private FileConnection fileConnection; private OutputStream outputStream; /** * Create a FileAppender. */ public FileAppender() { super(); String separator = System.getProperty("file.separator"); if (separator != null) { this.fileSeparator = separator; } } /** * Get the separator that is used when creating the URI for the logfile. * * @return the fileSeparator */ public String getFileSeparator() { return fileSeparator; } /** * Set the separator that is used for creating the URI for the logfile. * * Note that changing this after the logfile has been opened has no effect. * * @param fileSeparator * the fileSeparator to set */ public void setFileSeparator(String fileSeparator) { this.fileSeparator = fileSeparator; } /** * Set the filename of the logfile. * * @return the fileName */ public String getFileName() { return fileName; } /** * Get the filename of the logfile. * * Note that changing this after the logfile has been opened has no effect. * * @param fileName * the fileName to set */ public void setFileName(String fileName) { this.fileName = fileName; } /** * Get the size of the log. * * @return the size of the log. */ public long getLogSize() { long logSize = SIZE_UNDEFINED; if (fileConnection != null) { try { logSize = fileConnection.fileSize(); } catch (IOException e) { e.printStackTrace(); } } return logSize; } /** * Configure the FileAppender. * <p> * The file name can be passed with the property * <code>microlog.appender.FileAppender.filename</code>. * * @param properties * Properties to configure with */ public synchronized void configure(PropertiesGetter properties) { // Set the record store name from Properties fileName = properties.getString(FILENAME_STRING); if (fileName == null) { fileName = DEFAULT_FILENAME; } } /** * @see mobscrob.logging.microlog.appender.AbstractAppender#openLog() */ public synchronized void openLog() { if (logOpen) { System.out.println("MicroLog already opened"); return; } if (fileConnection == null) { try { long fileSize = 0; String connectionString = getConnectionString(); System.out.println("Creating log " + connectionString); // DO NOT use Connector.open(<url>, <mode>) fileConnection = (FileConnection) Connector .open(connectionString); System.out.println("Opened FileConnection"); if (!fileConnection.exists()) { System.out.println("Creating file - doesn't exist"); // create file fileConnection.create(); } else { fileSize = fileConnection.fileSize(); System.out.println("File exists, file size: " + fileSize); } // open stream at end of file outputStream = fileConnection.openOutputStream(fileSize); logOpen = true; System.out.println("Finished opening FileAppender"); } catch (Throwable e) { System.out.println("Unable to open log: " + e.getMessage()); e.printStackTrace(); // close streams on error closeLog(); } } } /** * @see mobscrob.logging.microlog.appender.AbstractAppender#doLog(net.sf.microlog.Level, * java.lang.Object, java.lang.Throwable) */ public void doLog(Level level, Object message, Throwable t) { if (logOpen && formatter != null) { synchronized (fileConnection) { String logString = formatter.format(level, message, t); try { byte[] stringData = logString.getBytes(); outputStream.write(stringData); outputStream.write(lineSeparator.getBytes()); outputStream.flush(); } catch (IOException e) { e.printStackTrace(); } } } } /** * @see mobscrob.logging.microlog.appender.AbstractAppender#clearLog() */ public synchronized void clearLog() { if (fileConnection != null && fileConnection.isOpen()) { try { fileConnection.truncate(0); } catch (IOException e) { e.printStackTrace(); } } } /** * @see mobscrob.logging.microlog.appender.AbstractAppender#closeLog() */ public synchronized void closeLog() { logOpen = false; if (outputStream != null) { try { outputStream.flush(); outputStream.close(); } catch (Exception ex) { } } if (fileConnection != null && fileConnection.isOpen()) { try { fileConnection.close(); } catch (IOException e) { } } while (fileConnection != null && fileConnection.isOpen()) { // wait a while for file to close System.out.println("Waiting 2 secs for log file to close.."); try { Thread.sleep(2000); } catch (Exception ex) { } } } /** * Get the connection string to use for opening the FileConnection. * * @return the connection String. */ private synchronized String getConnectionString() { StringBuffer stringBuffer = new StringBuffer(BUFFER_SIZE); stringBuffer.append(FILE_PROTOCOL); stringBuffer.append(rootDir); stringBuffer.append(fileName); return stringBuffer.toString(); } }