KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > refactoring > spi > BackupFacility


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.refactoring.spi;
21
22 import java.io.File JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24 import java.io.FileOutputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Collection JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import org.openide.filesystems.FileObject;
30 import org.openide.filesystems.FileUtil;
31 import org.openide.util.Lookup;
32
33 /**
34  * Simple backup facility
35  * can be used to backup files and implement undo
36  * For instance Java Refactoring module implements undo this way:
37  *
38  * public Problem prepare(RefactoringElementsBag elements) {
39  * .
40  * .
41  * elements.registerTransaction(new RetoucheCommit(results));
42  * }
43  *
44  * where RetoucheCommit is Transaction:
45  * <pre>
46  * BackupFacility.Handle handle;
47  * public void commit() {
48  * FileObject[] files;
49  * .
50  * .
51  * handle = BackupFacility.getDefault().backup(files);
52  * doCommit();
53  * }
54  * public void rollback() {
55  * //rollback all files
56  * handle.restore();
57  * }
58  * </pre>
59  *
60  * You can register your own implementation via META-INF services.
61  * @see Transaction
62  * @see RefactoringElementImplementation#performChange
63  * @see RefactoringElementImplementation#undoChange
64  * @see RefactoringElementsBag#registerTransaction
65  * @see RefactoringElementsBag#registerFileChange
66  * @see BackupFacility.Handle
67  * @author Jan Becicka
68  */

69 public abstract class BackupFacility {
70     
71     private BackupFacility() {
72     }
73     
74     private static BackupFacility defaultInstance;
75     
76     /**
77      * does beckup
78      * @param file file(s) to backup
79      * @return handle which can be used to restore files
80      * @throws java.io.IOException if backup failed
81      */

82     public abstract Handle backup(FileObject... file) throws IOException JavaDoc;
83     
84     /**
85      * does backup
86      * @param fileObjects FileObjects to backup
87      * @return handle which can be used to restore files
88      * @throws java.io.IOException
89      */

90     public final Handle backup(Collection JavaDoc<? extends FileObject> fileObjects) throws IOException JavaDoc {
91         return backup(fileObjects.toArray(new FileObject[fileObjects.size()]));
92     }
93     
94     /**
95      * do cleanup
96      * all backup files are deleted
97      * all internal structures cleared
98      * default implementa
99      */

100     public abstract void clear();
101     
102     /**
103      * @return default instance of this class. If there is instance of this
104      * class in META-INF services -> this class is returned. Otherwise default
105      * implementation is used.
106      */

107     public static BackupFacility getDefault() {
108         BackupFacility instance = Lookup.getDefault().lookup(BackupFacility.class);
109         return (instance != null) ? instance : getDefaultInstance();
110     }
111     
112     private static synchronized BackupFacility getDefaultInstance() {
113         if (defaultInstance == null) {
114             defaultInstance = new DefaultImpl();
115         }
116         
117         return defaultInstance;
118     }
119     
120     /**
121      * Handle class representing handle to file{s), which were backuped
122      * by
123      * {@link org.netbeans.modules.refactoring.spi.BackupFacility.backup()}
124      */

125     public interface Handle {
126         /**
127          * restore file(s), which was stored by {@link org.netbeans.modules.refactoring.spi.BackupFacility.backup()}
128          * @throws java.io.IOException if restore failed.
129          */

130         void restore() throws IOException JavaDoc;
131     }
132     
133     private static class DefaultHandle implements Handle {
134         ArrayList JavaDoc<Long JavaDoc> handle;
135         DefaultImpl instance;
136         private DefaultHandle(DefaultImpl instance, ArrayList JavaDoc<Long JavaDoc> handles) {
137             this.handle = handles;
138             this.instance = instance;
139         }
140         public void restore() throws IOException JavaDoc {
141             for (long l:handle) {
142                 instance.restore(l);
143             }
144         }
145     }
146     
147     private static class DefaultImpl extends BackupFacility {
148         
149         private long currentId = 0;
150         private HashMap JavaDoc<Long JavaDoc, BackupEntry> map = new HashMap JavaDoc();
151         
152         private class BackupEntry {
153             private File JavaDoc file;
154             private String JavaDoc path;
155         }
156         
157         /** Creates a new instance of BackupFacility */
158         private DefaultImpl() {
159         }
160         
161         public Handle backup(FileObject ... file) throws IOException JavaDoc {
162             ArrayList JavaDoc<Long JavaDoc> list = new ArrayList JavaDoc();
163             for (FileObject f:file) {
164                 list.add(backup(f));
165             }
166             return new DefaultHandle(this, list);
167         }
168         /**
169          * does beckup
170          * @param file to backup
171          * @return id of backup file
172          * @throws java.io.IOException if backup failed
173          */

174         public long backup(FileObject file) throws IOException JavaDoc {
175             BackupEntry entry = new BackupEntry();
176             entry.file = File.createTempFile("nbbackup", null); //NOI18N
177
copy(FileUtil.toFile(file), entry.file);
178             entry.path = file.getPath();
179             map.put(currentId, entry);
180             entry.file.deleteOnExit();
181             return currentId++;
182         }
183         /**
184          * restore file, which was stored by backup(file)
185          * @param id identification of backup transaction
186          * @throws java.io.IOException if restore failed.
187          */

188         void restore(long id) throws IOException JavaDoc {
189             BackupEntry entry = map.get(id);
190             if(entry==null) {
191                 throw new IllegalArgumentException JavaDoc("Backup with id " + id + "does not exist");
192             }
193             File JavaDoc backup = File.createTempFile("nbbackup", null); //NOI18N
194
backup.deleteOnExit();
195             File JavaDoc f = new File JavaDoc(entry.path);
196             if (createNewFile(f)) {
197                 backup.createNewFile();
198                 copy(f,backup);
199             }
200             copy(entry.file,f);
201             FileUtil.toFileObject(f).refresh(true);
202             entry.file.delete();
203             if (backup.exists()) {
204                 entry.file = backup;
205             } else {
206                 map.remove(id);
207             }
208         }
209         
210         /**
211          * workaround for #93390
212          */

213         private boolean createNewFile(File JavaDoc f) throws IOException JavaDoc {
214             if (f.exists())
215                 return true;
216             createNewFile(f.getParentFile());
217             f.createNewFile();
218             return false;
219             
220         }
221         
222         private void copy(File JavaDoc a, File JavaDoc b) throws IOException JavaDoc {
223             FileInputStream JavaDoc fs = new FileInputStream JavaDoc(a);
224             FileOutputStream JavaDoc fo = new FileOutputStream JavaDoc(b);
225             try {
226                 FileUtil.copy(fs, fo);
227             } finally {
228                 fs.close();
229                 fo.close();
230             }
231         }
232         
233         public void clear() {
234             for(BackupEntry entry: map.values()) {
235                 entry.file.delete();
236             }
237             map.clear();
238         }
239     }
240 }
Popular Tags