Конфигурирование Java FileHandler, Регистрирующегося для создания каталоги, если они не существуют

Ищите ACL2. Это - основанный на шепелявости механизм формальной логики, который использовался для многого проекта "реального мира" как формальные методы в безопасности программного обеспечения и доказательствах правильности для Аппаратных средств вычислений с плавающей точкой.

14
задан Dougnukem 12 August 2009 в 02:05
поделиться

4 ответа

Чтобы обойти ограничения среды ведения журналов Java и нерешенную ошибку: Ошибка 6244047: невозможно указать драйверы для ведения журнала FileHandler, если они не существуют

Я пришел с двумя подходами (хотя на самом деле будет работать только первый подход), оба требуют вашего статического метода void main () для вашего приложения для инициализации системы журналирования.

например

public static void main(String[] args) {    

    initLogging();
     ...
    }

Первый подход жестко кодирует каталоги журналов, которые вы ожидаете чтобы существовать и создает их, если они не существуют.

private static void initLogging() {
    try {
        //Create logging.properties specified directory for logging in home directory
        //TODO: If they ever fix this bug (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6244047) in the Java Logging API we wouldn't need this hack
        File homeLoggingDir = new File (System.getProperty("user.home")+"/webwars-logs/weblings-gameplatform/");
        if (!homeLoggingDir.exists() ) {
            homeLoggingDir.mkdirs();
            logger.info("Creating missing logging directory: " + homeLoggingDir);
        }
    } catch(Exception e) {
        e.printStackTrace();
    }

    try {
        logger.info("[GamePlatform] : Starting...");
    } catch (Exception exc) {
        exc.printStackTrace();

    }
}

Второй подход может перехватить IOException и создать каталоги, перечисленные в исключении, проблема с этим подходом заключается в том, что инфраструктура ведения журнала уже не смогла создать FileHandler, поэтому ловушка и устранение ошибки по-прежнему оставляет систему регистрации в плохом состоянии.

4
ответ дан 1 December 2019 в 13:22
поделиться

Вы можете написать что-то вроде этого.

package org.log;

import java.io.IOException;
import org.apache.log4j.RollingFileAppender;

public class MyRollingFileAppender extends RollingFileAppender {

    @Override
    public synchronized void setFile(String fileName, boolean append,
        boolean bufferedIO, int bufferSize) throws IOException {
        //Your logic goes here
        super.setFile(fileName, append, bufferedIO, bufferSize);
    }

}

Затем в вашей конфигурации

log4j.appender.fileAppender=org.log.MyRollingFileAppender

Это отлично работает для меня.

5
ответ дан 1 December 2019 в 13:22
поделиться

Кажется, что это делает log4j версии 1.2.15.

Вот фрагмент кода, который это делает

public
 synchronized
 void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
                                                        throws IOException {
    LogLog.debug("setFile called: "+fileName+", "+append);

    // It does not make sense to have immediate flush and bufferedIO.
    if(bufferedIO) {
      setImmediateFlush(false);
    }

    reset();
    FileOutputStream ostream = null;
    try {
          //
          //   attempt to create file
          //
          ostream = new FileOutputStream(fileName, append);
    } catch(FileNotFoundException ex) {
          //
          //   if parent directory does not exist then
          //      attempt to create it and try to create file
          //      see bug 9150
          //
          String parentName = new File(fileName).getParent();
          if (parentName != null) {
             File parentDir = new File(parentName);
             if(!parentDir.exists() && parentDir.mkdirs()) {
                ostream = new FileOutputStream(fileName, append);
             } else {
                throw ex;
             }
          } else {
             throw ex;
          }
    }
    Writer fw = createWriter(ostream);
    if(bufferedIO) {
      fw = new BufferedWriter(fw, bufferSize);
    }
    this.setQWForFiles(fw);
    this.fileName = fileName;
    this.fileAppend = append;
    this.bufferedIO = bufferedIO;
    this.bufferSize = bufferSize;
    writeHeader();
    LogLog.debug("setFile ended");
}

Этот фрагмент кода взят из FileAppender, RollingFileAppender расширяет FileAppender.

Здесь не проверяется, есть ли у нас разрешение на создание родительских папок, но если родительские папки не существуют, он попытается создать родительские папки.

EDITED

Если вам нужны дополнительные функциональные возможности, вы всегда можно расширить RollingFileAppender и переопределить метод setFile ().

8
ответ дан 1 December 2019 в 13:22
поделиться

В качестве возможного решения, я думаю, есть 2 подхода (посмотрите на некоторые из предыдущих ответов). Я могу расширить класс Java Logging Handler и написать свой собственный обработчик. Я также мог скопировать функциональность log4j и адаптировать ее к структуре ведения журналов Java.

Вот пример копирования базового FileHandler и создания CustomFileHandler см. pastebin для полного класса :

Ключ - это метод openFiles (), в котором он пытается создать FileOutputStream и проверяет и создает родительский каталог, если он не существует (мне также пришлось скопировать методы LogManager, защищенные пакетом, почему они вообще сделали этот пакет защищенным):

// Private method to open the set of output files, based on the
// configured instance variables.
private void openFiles() throws IOException {
    LogManager manager = LogManager.getLogManager();

...

    // Create a lock file. This grants us exclusive access
    // to our set of output files, as long as we are alive.
    int unique = -1;
    for (;;) {
        unique++;
        if (unique > MAX_LOCKS) {
            throw new IOException("Couldn't get lock for " + pattern);
        }
        // Generate a lock file name from the "unique" int.
        lockFileName = generate(pattern, 0, unique).toString() + ".lck";
        // Now try to lock that filename.
        // Because some systems (e.g. Solaris) can only do file locks
        // between processes (and not within a process), we first check
        // if we ourself already have the file locked.
        synchronized (locks) {
            if (locks.get(lockFileName) != null) {
                // We already own this lock, for a different FileHandler
                // object. Try again.
                continue;
            }
            FileChannel fc;
            try {
                File lockFile = new File(lockFileName);
                if (lockFile.getParent() != null) {
                    File lockParentDir = new File(lockFile.getParent());
                    // create the log dir if it does not exist
                    if (!lockParentDir.exists()) {
                        lockParentDir.mkdirs();
                    }
                }

                lockStream = new FileOutputStream(lockFileName);
                fc = lockStream.getChannel();
            } catch (IOException ix) {
                // We got an IOException while trying to open the file.
                // Try the next file.
                continue;
            }
            try {
                FileLock fl = fc.tryLock();
                if (fl == null) {
                    // We failed to get the lock. Try next file.
                    continue;
                }
                // We got the lock OK.
            } catch (IOException ix) {
                // We got an IOException while trying to get the lock.
                // This normally indicates that locking is not supported
                // on the target directory. We have to proceed without
                // getting a lock. Drop through.
            }
            // We got the lock. Remember it.
            locks.put(lockFileName, lockFileName);
            break;
        }
    }

... }

1
ответ дан 1 December 2019 в 13:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: