001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017 package org.apache.logging.log4j.core.appender.rolling.helper; 018 019 import org.apache.logging.log4j.Logger; 020 import org.apache.logging.log4j.status.StatusLogger; 021 022 import java.io.File; 023 import java.io.FileInputStream; 024 import java.io.FileOutputStream; 025 import java.io.IOException; 026 import java.nio.channels.FileChannel; 027 028 029 /** 030 * File rename action. 031 */ 032 public final class FileRenameAction extends AbstractAction { 033 034 private static final Logger LOGGER = StatusLogger.getLogger(); 035 036 /** 037 * Source. 038 */ 039 private final File source; 040 041 /** 042 * Destination. 043 */ 044 private final File destination; 045 046 /** 047 * If true, rename empty files, otherwise delete empty files. 048 */ 049 private final boolean renameEmptyFiles; 050 051 /** 052 * Creates an FileRenameAction. 053 * 054 * @param src current file name. 055 * @param dst new file name. 056 * @param renameEmptyFiles if true, rename file even if empty, otherwise delete empty files. 057 */ 058 public FileRenameAction(final File src, final File dst, boolean renameEmptyFiles) { 059 source = src; 060 destination = dst; 061 this.renameEmptyFiles = renameEmptyFiles; 062 } 063 064 /** 065 * Rename file. 066 * 067 * @return true if successfully renamed. 068 */ 069 @Override 070 public boolean execute() { 071 return execute(source, destination, renameEmptyFiles); 072 } 073 074 /** 075 * Rename file. 076 * 077 * @param source current file name. 078 * @param destination new file name. 079 * @param renameEmptyFiles if true, rename file even if empty, otherwise delete empty files. 080 * @return true if successfully renamed. 081 */ 082 public static boolean execute(final File source, final File destination, boolean renameEmptyFiles) { 083 if (renameEmptyFiles || (source.length() > 0)) { 084 File parent = destination.getParentFile(); 085 if (!parent.exists()) { 086 if (!parent.mkdirs()) { 087 LOGGER.error("Unable to create directory {}", parent.getAbsolutePath()); 088 return false; 089 } 090 } 091 try { 092 if (!source.renameTo(destination)) { 093 try { 094 copyFile(source, destination); 095 return source.delete(); 096 } catch (IOException iex) { 097 LOGGER.error("Unable to rename file {} to {} - {}", source.getAbsolutePath(), 098 destination.getAbsolutePath(), iex.getMessage()); 099 } 100 } 101 return true; 102 } catch (Exception ex) { 103 try { 104 copyFile(source, destination); 105 return source.delete(); 106 } catch (IOException iex) { 107 LOGGER.error("Unable to rename file {} to {} - {}", source.getAbsolutePath(), 108 destination.getAbsolutePath(), iex.getMessage()); 109 } 110 } 111 } 112 113 return false; 114 } 115 116 private static void copyFile(final File source, final File destination) throws IOException { 117 if (!destination.exists()) { 118 destination.createNewFile(); 119 } 120 121 FileChannel srcChannel = null; 122 FileChannel destChannel = null; 123 FileInputStream srcStream = null; 124 FileOutputStream destStream = null; 125 try { 126 srcStream = new FileInputStream(source); 127 destStream = new FileOutputStream(destination); 128 srcChannel = srcStream.getChannel(); 129 destChannel = destStream.getChannel(); 130 destChannel.transferFrom(srcChannel, 0, srcChannel.size()); 131 } finally { 132 if (srcChannel != null) { 133 srcChannel.close(); 134 } 135 if (srcStream != null) { 136 srcStream.close(); 137 } 138 if (destChannel != null) { 139 destChannel.close(); 140 } 141 if (destStream != null) { 142 destStream.close(); 143 } 144 } 145 } 146 }