1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.util; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 import android.os.Build; 21 22 import java.io.File; 23 import java.io.IOException; 24 25 /** 26 * @deprecated Use {@code AtomicFile} instead. It would 27 * be nice to update all existing uses of this to switch to AtomicFile, but since 28 * their on-file semantics are slightly different that would run the risk of losing 29 * data if at the point of the platform upgrade to the new code it would need to 30 * roll back to the backup file. This can be solved... but is it worth it and 31 * all of the testing needed to make sure it is correct? 32 */ 33 @Deprecated 34 public class JournaledFile { 35 File mReal; 36 File mTemp; 37 boolean mWriting; 38 39 @UnsupportedAppUsage JournaledFile(File real, File temp)40 public JournaledFile(File real, File temp) { 41 mReal = real; 42 mTemp = temp; 43 } 44 45 /** Returns the file for you to read. 46 * @more 47 * Prefers the real file. If it doesn't exist, uses the temp one, and then copies 48 * it to the real one. If there is both a real file and a temp one, assumes that the 49 * temp one isn't fully written and deletes it. 50 */ 51 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) chooseForRead()52 public File chooseForRead() { 53 File result; 54 if (mReal.exists()) { 55 result = mReal; 56 if (mTemp.exists()) { 57 mTemp.delete(); 58 } 59 } else if (mTemp.exists()) { 60 result = mTemp; 61 mTemp.renameTo(mReal); 62 } else { 63 return mReal; 64 } 65 return result; 66 } 67 68 /** 69 * Returns a file for you to write. 70 * @more 71 * If a write is already happening, throws. In other words, you must provide your 72 * own locking. 73 * <p> 74 * Call {@link #commit} to commit the changes, or {@link #rollback} to forget the changes. 75 */ 76 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) chooseForWrite()77 public File chooseForWrite() { 78 if (mWriting) { 79 throw new IllegalStateException("uncommitted write already in progress"); 80 } 81 if (!mReal.exists()) { 82 // If the real one doesn't exist, it's either because this is the first time 83 // or because something went wrong while copying them. In this case, we can't 84 // trust anything that's in temp. In order to have the chooseForRead code not 85 // use the temporary one until it's fully written, create an empty file 86 // for real, which will we'll shortly delete. 87 try { 88 mReal.createNewFile(); 89 } catch (IOException e) { 90 // Ignore 91 } 92 } 93 94 if (mTemp.exists()) { 95 mTemp.delete(); 96 } 97 mWriting = true; 98 return mTemp; 99 } 100 101 /** 102 * Commit changes. 103 */ 104 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) commit()105 public void commit() { 106 if (!mWriting) { 107 throw new IllegalStateException("no file to commit"); 108 } 109 mWriting = false; 110 mTemp.renameTo(mReal); 111 } 112 113 /** 114 * Roll back changes. 115 */ 116 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) rollback()117 public void rollback() { 118 if (!mWriting) { 119 throw new IllegalStateException("no file to roll back"); 120 } 121 mWriting = false; 122 mTemp.delete(); 123 } 124 } 125