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 java.io.File; 020 import java.io.FileInputStream; 021 import java.io.FileOutputStream; 022 import java.io.IOException; 023 import java.nio.channels.FileChannel; 024 025 /** 026 * File rename action. 027 */ 028 public class FileRenameAction extends AbstractAction { 029 030 /** 031 * Source. 032 */ 033 private final File source; 034 035 /** 036 * Destination. 037 */ 038 private final File destination; 039 040 /** 041 * If true, rename empty files, otherwise delete empty files. 042 */ 043 private final boolean renameEmptyFiles; 044 045 /** 046 * Creates an FileRenameAction. 047 * 048 * @param src current file name. 049 * @param dst new file name. 050 * @param renameEmptyFiles if true, rename file even if empty, otherwise delete empty files. 051 */ 052 public FileRenameAction(final File src, final File dst, final boolean renameEmptyFiles) { 053 source = src; 054 destination = dst; 055 this.renameEmptyFiles = renameEmptyFiles; 056 } 057 058 /** 059 * Rename file. 060 * 061 * @return true if successfully renamed. 062 */ 063 @Override 064 public boolean execute() { 065 return execute(source, destination, renameEmptyFiles); 066 } 067 068 /** 069 * Rename file. 070 * 071 * @param source current file name. 072 * @param destination new file name. 073 * @param renameEmptyFiles if true, rename file even if empty, otherwise delete empty files. 074 * @return true if successfully renamed. 075 */ 076 public static boolean execute(final File source, final File destination, final boolean renameEmptyFiles) { 077 if (renameEmptyFiles || source.length() > 0) { 078 final File parent = destination.getParentFile(); 079 if (parent != null && !parent.exists()) { 080 if (!parent.mkdirs()) { 081 LOGGER.error("Unable to create directory {}", parent.getAbsolutePath()); 082 return false; 083 } 084 } 085 try { 086 if (!source.renameTo(destination)) { 087 try { 088 copyFile(source, destination); 089 return source.delete(); 090 } catch (final IOException iex) { 091 LOGGER.error("Unable to rename file {} to {} - {}", source.getAbsolutePath(), 092 destination.getAbsolutePath(), iex.getMessage()); 093 } 094 } 095 return true; 096 } catch (final Exception ex) { 097 try { 098 copyFile(source, destination); 099 return source.delete(); 100 } catch (final IOException iex) { 101 LOGGER.error("Unable to rename file {} to {} - {}", source.getAbsolutePath(), 102 destination.getAbsolutePath(), iex.getMessage()); 103 } 104 } 105 } else { 106 try { 107 source.delete(); 108 } catch (Exception ex) { 109 LOGGER.error("Unable to delete empty file " + source.getAbsolutePath()); 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 }