Added
Link Here
|
1 |
/* |
2 |
* Sun Public License Notice |
3 |
* |
4 |
* The contents of this file are subject to the Sun Public License |
5 |
* Version 1.0 (the "License"). You may not use this file except in |
6 |
* compliance with the License. A copy of the License is available at |
7 |
* http://www.sun.com/ |
8 |
* |
9 |
* The Original Code is NetBeans. The Initial Developer of the Original |
10 |
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun |
11 |
* Microsystems, Inc. All Rights Reserved. |
12 |
*/ |
13 |
|
14 |
package org.netbeans.upgrade; |
15 |
|
16 |
import java.io.*; |
17 |
import java.util.*; |
18 |
import org.openide.util.*; |
19 |
import java.util.jar.*; |
20 |
import org.w3c.dom.*; |
21 |
import org.xml.sax.*; |
22 |
import org.openide.xml.XMLUtil; |
23 |
|
24 |
import org.openide.filesystems.*; |
25 |
import org.openide.filesystems.FileSystem; |
26 |
|
27 |
|
28 |
/** Does copy of objects on filesystems. |
29 |
* |
30 |
* @author Jaroslav Tulach |
31 |
*/ |
32 |
final class Copy extends Object { |
33 |
|
34 |
|
35 |
/** Does a selective copy of one source tree to another. |
36 |
* @param source file object to copy from |
37 |
* @param target file object to copy to |
38 |
* @param thoseToCopy set on which contains (relativeNameOfAFileToCopy) |
39 |
* is being called to find out whether to copy or not |
40 |
* @throws IOException if coping fails |
41 |
*/ |
42 |
public static void copyDeep (FileObject source, FileObject target, Set thoseToCopy) |
43 |
throws IOException { |
44 |
copyDeep (source, target, thoseToCopy, null); |
45 |
} |
46 |
|
47 |
private static void copyDeep ( |
48 |
FileObject source, FileObject target, Set thoseToCopy, String prefix |
49 |
) throws IOException { |
50 |
FileObject src = prefix == null ? source : FileUtil.createFolder (source, prefix); |
51 |
|
52 |
FileObject[] arr = src.getChildren(); |
53 |
for (int i = 0; i < arr.length; i++) { |
54 |
String fullname; |
55 |
if (prefix == null) { |
56 |
fullname = arr[i].getNameExt (); |
57 |
} else { |
58 |
fullname = prefix + "/" + arr[i].getNameExt (); |
59 |
} |
60 |
if (arr[i].isData ()) { |
61 |
if (!thoseToCopy.contains (fullname)) { |
62 |
continue; |
63 |
} |
64 |
} |
65 |
|
66 |
|
67 |
if (arr[i].isFolder()) { |
68 |
copyDeep (source, target, thoseToCopy, fullname); |
69 |
if (thoseToCopy.contains (fullname) && arr[i].getAttributes ().hasMoreElements ()) { |
70 |
FileObject tg = FileUtil.createFolder (target, fullname); |
71 |
FileUtil.copyAttributes (arr[i], tg); |
72 |
} |
73 |
} else { |
74 |
FileObject folder = prefix == null ? target : FileUtil.createFolder (target, prefix); |
75 |
FileObject tg = folder.getFileObject (arr[i].getNameExt ()); |
76 |
if (tg == null) { |
77 |
// copy the file otherwise keep old content |
78 |
tg = FileUtil.copyFile (arr[i], folder, arr[i].getName(), arr[i].getExt ()); |
79 |
} |
80 |
|
81 |
FileUtil.copyAttributes (arr[i], tg); |
82 |
} |
83 |
} |
84 |
|
85 |
|
86 |
} |
87 |
|
88 |
|
89 |
|
90 |
/** Updates the IDE. |
91 |
* @param sourceDir original instalation of the IDE |
92 |
* @param targetSystem target system to copy files to |
93 |
* @param backupSystem filesystem to do backupSystemFo to (or null) |
94 |
* @exception IOException if the copying fails |
95 |
* |
96 |
protected final void upgradeIde (String ver, File src, File trg) throws Exception { |
97 |
|
98 |
|
99 |
int version = getIdeVersion (ver); |
100 |
if (version < 0 || version >= versions.length) { |
101 |
message (getString ("MSG_BAD_IDE")); |
102 |
for (int i = 0 ; i < versions.length ; i++ ) { |
103 |
message (versions[i]); |
104 |
} |
105 |
throw new Exception ("Invalid IDE version"); //NOI18N |
106 |
} |
107 |
|
108 |
message (getString ("MSG_UPDATE_FROM", versions[version])); |
109 |
|
110 |
FileSystem srcFS = null; |
111 |
FileSystem trgFS = null; |
112 |
FileSystem tmpFS = null; |
113 |
Object filter [] = null; |
114 |
|
115 |
if (-1 != ver.indexOf (DIRTYPE_INST)) { |
116 |
File srcFile = new File (src, "system"); //NOI18N |
117 |
File trgFile = new File (trg, "system"); //NOI18N |
118 |
srcFS = createFileSystem (srcFile); |
119 |
trgFS = createFileSystem (trgFile); |
120 |
|
121 |
if (srcFS == null) { |
122 |
message (getString ("MSG_directory_not_exist", srcFile.getAbsolutePath ())); //NOI18N |
123 |
throw new Exception ("Directory doesn't exist - " + srcFile.getAbsolutePath ()); //NOI18N |
124 |
} |
125 |
|
126 |
if (trgFS == null) { |
127 |
message (getString ("MSG_directory_not_exist", trgFile.getAbsolutePath ())); |
128 |
throw new Exception ("Directory doesn't exist - " + trgFile.getAbsolutePath ()); //NOI18N |
129 |
} |
130 |
|
131 |
File tmpRoot = new File (trg, "system_backup"); //NOI18N |
132 |
if (!tmpRoot.exists ()) { |
133 |
// message (getString ("MSG_BackupDir_exists", tmpRoot.getAbsolutePath ())); //NOI18N |
134 |
// throw new Exception ("Backup directory already exists - " + tmpRoot.getAbsolutePath ()); //NOI18N |
135 |
// } else { |
136 |
tmpRoot.mkdirs (); |
137 |
} |
138 |
tmpFS = createFileSystem (tmpRoot); |
139 |
|
140 |
filter = originalFiles (nonCpFiles[version]); |
141 |
} else { |
142 |
srcFS = createFileSystem (src); //NOI18N |
143 |
trgFS = createFileSystem (trg); //NOI18N |
144 |
|
145 |
if (srcFS == null) { |
146 |
message (getString ("MSG_directory_not_exist", src.getAbsolutePath ())); //NOI18N |
147 |
throw new Exception ("Directory doesn't exist - " + src.getAbsolutePath ()); //NOI18N |
148 |
} |
149 |
|
150 |
if (trgFS == null) { |
151 |
message (getString ("MSG_directory_not_exist", trg.getAbsolutePath ())); //NOI18N |
152 |
throw new Exception ("Directory doesn't exist - " + trg.getAbsolutePath ()); //NOI18N |
153 |
} |
154 |
|
155 |
File tmpRoot = new File (trg.getParentFile (), "userdir_backup"); //NOI18N |
156 |
if (!tmpRoot.exists ()) { |
157 |
// message (getString ("MSG_BackupDir_exists", tmpRoot.getAbsolutePath ())); //NOI18N |
158 |
// throw new Exception ("Backup directory already exists - " + tmpRoot.getAbsolutePath ()); //NOI18N |
159 |
// } else { |
160 |
tmpRoot.mkdirs (); |
161 |
} |
162 |
tmpFS = createFileSystem (tmpRoot); |
163 |
|
164 |
filter = originalFiles (userdirNonCpFiles); |
165 |
} |
166 |
|
167 |
if (tmpFS != null) { |
168 |
// clean up temporary filesystem |
169 |
FileObject ch [] = tmpFS.getRoot ().getChildren (); |
170 |
for (int i = 0; i < ch.length; i++) { |
171 |
deleteAll (ch[i]); |
172 |
} |
173 |
// make a backup copy |
174 |
copyAttributes(trgFS.getRoot (), tmpFS.getRoot ()); |
175 |
recursiveCopy(trgFS.getRoot (), tmpFS.getRoot ()); |
176 |
} |
177 |
|
178 |
try { |
179 |
update (srcFS, trgFS, getLastModified (src), filter); |
180 |
} |
181 |
catch (Exception e) { |
182 |
if (tmpFS != null) { |
183 |
message (getString ("MSG_recovery_started")); //NOI18N |
184 |
deleteAll (trgFS.getRoot ()); |
185 |
copyAttributes (tmpFS.getRoot (), trgFS.getRoot ()); |
186 |
recursiveCopy (tmpFS.getRoot (), trgFS.getRoot ()); |
187 |
message (getString ("MSG_recovery_finished")); //NOI18N |
188 |
} |
189 |
throw e; |
190 |
} |
191 |
} |
192 |
|
193 |
private FileSystem createFileSystem (File root) { |
194 |
LocalFileSystem lfs = null; |
195 |
|
196 |
if (root.exists () && root.isDirectory ()) { |
197 |
try { |
198 |
lfs = new LocalFileSystem (); |
199 |
lfs.setRootDirectory (root); |
200 |
} |
201 |
catch (Exception e) { |
202 |
lfs = null; |
203 |
} |
204 |
} |
205 |
|
206 |
return lfs == null ? null : new AttrslessLocalFileSystem (lfs); |
207 |
} |
208 |
|
209 |
private void update( |
210 |
FileSystem src, FileSystem trg, long sourceBaseTime, Object[] filter |
211 |
) throws IOException { |
212 |
|
213 |
items = 0; |
214 |
maxItems = 0; |
215 |
|
216 |
copyAttributes (src.getRoot (),trg.getRoot ()); |
217 |
recursiveCopyWithFilter ( |
218 |
src.getRoot (), |
219 |
trg.getRoot (), |
220 |
filter, |
221 |
sourceBaseTime |
222 |
); |
223 |
} |
224 |
|
225 |
/** copies recursively directory, skips files existing in target location |
226 |
* @param source source directory |
227 |
* @param dest destination directory |
228 |
*/ |
229 |
private void recursiveCopy (FileObject sourceFolder, FileObject destFolder) throws IOException { |
230 |
FileObject childrens [] = sourceFolder.getChildren(); |
231 |
for (int i = 0 ; i < childrens.length ; i++ ) { |
232 |
final FileObject subSourceFo = childrens[i]; |
233 |
FileObject subTargetFo = null; |
234 |
|
235 |
if (subSourceFo.isFolder()) { |
236 |
subTargetFo = destFolder.getFileObject(subSourceFo.getName()); |
237 |
if (subTargetFo == null) { |
238 |
subTargetFo = destFolder.createFolder(subSourceFo.getName()); |
239 |
|
240 |
} |
241 |
copyAttributes(subSourceFo,subTargetFo); |
242 |
recursiveCopy(subSourceFo,subTargetFo); |
243 |
} else { |
244 |
subTargetFo = destFolder.getFileObject(subSourceFo.getNameExt()); |
245 |
if (subTargetFo == null) { |
246 |
if ( Utilities.getOperatingSystem () == Utilities.OS_VMS |
247 |
&& subSourceFo.getNameExt ().equalsIgnoreCase ( "_nbattrs.") ) |
248 |
subTargetFo = FileUtil.copyFile(subSourceFo, destFolder, subSourceFo.getNameExt(), subSourceFo.getExt()); |
249 |
else |
250 |
subTargetFo = FileUtil.copyFile(subSourceFo, destFolder, subSourceFo.getName(), subSourceFo.getExt()); |
251 |
} |
252 |
copyAttributes(subSourceFo,subTargetFo); |
253 |
} |
254 |
} |
255 |
} |
256 |
|
257 |
private void message (String s) { |
258 |
|
259 |
} |
260 |
private void progress (int x, int y) { |
261 |
|
262 |
} |
263 |
private int maxItems; |
264 |
private int items; |
265 |
private int timeDev; |
266 |
|
267 |
/** Copies recursively dircectory. Files are copied when when basicTime + timeDev < time of file. |
268 |
* @param source source directory |
269 |
* @param #dest destination dirctory |
270 |
*/ |
271 |
private void recursiveCopyWithFilter ( |
272 |
FileObject source, FileObject dest, Object[] filter, long basicTime |
273 |
) throws IOException { |
274 |
FileObject childrens [] = source.getChildren(); |
275 |
if (source.isFolder() == false ) { |
276 |
message (getString("MSG_IS_NOT_FOLDER", source.getName())); |
277 |
} |
278 |
|
279 |
// adjust max number of items |
280 |
maxItems += childrens.length; |
281 |
|
282 |
for (int i = 0 ; i < childrens.length ; i++ ) { |
283 |
FileObject subSourceFo = childrens[i]; |
284 |
|
285 |
// report progress |
286 |
items++; |
287 |
progress(items, maxItems); |
288 |
|
289 |
if (!canCopy (subSourceFo, filter, basicTime)) |
290 |
continue; |
291 |
|
292 |
FileObject subTargetFo = null; |
293 |
if (subSourceFo.isFolder ()) { |
294 |
subTargetFo = dest.getFileObject (subSourceFo.getNameExt ()); |
295 |
if (subTargetFo == null) { |
296 |
subTargetFo = dest.createFolder (subSourceFo.getNameExt ()); |
297 |
|
298 |
} |
299 |
copyAttributes (subSourceFo, subTargetFo); |
300 |
recursiveCopyWithFilter (subSourceFo, subTargetFo, filter, basicTime); |
301 |
} else { |
302 |
subTargetFo = dest.getFileObject (subSourceFo.getName (), subSourceFo.getExt ()); |
303 |
|
304 |
if (subTargetFo != null) { |
305 |
FileLock lock = subTargetFo.lock (); |
306 |
subTargetFo.delete (lock); |
307 |
lock.releaseLock (); |
308 |
} |
309 |
|
310 |
if ( Utilities.getOperatingSystem () == Utilities.OS_VMS |
311 |
&& subSourceFo.getNameExt ().equalsIgnoreCase ( "_nbattrs.") ) |
312 |
subTargetFo = copyFile (subSourceFo, dest, subSourceFo.getNameExt ()); |
313 |
else |
314 |
subTargetFo = copyFile (subSourceFo, dest, subSourceFo.getName ()); |
315 |
copyAttributes (subSourceFo, subTargetFo); |
316 |
} |
317 |
} |
318 |
} |
319 |
|
320 |
private FileObject copyFile (FileObject src, FileObject trg, String newName) throws IOException { |
321 |
return FileUtil.copyFile (src, trg, newName); |
322 |
} |
323 |
|
324 |
private static void copyAttributes (FileObject source, FileObject dest) throws IOException { |
325 |
Enumeration attrKeys = source.getAttributes(); |
326 |
while (attrKeys.hasMoreElements()) { |
327 |
String key = (String) attrKeys.nextElement(); |
328 |
Object value = source.getAttribute(key); |
329 |
if (value != null) { |
330 |
dest.setAttribute(key, value); |
331 |
} |
332 |
} |
333 |
} |
334 |
/** test if file can be copied |
335 |
*/ |
336 |
private boolean canCopy (FileObject fo, Object[] filter, long basicTime) throws IOException { |
337 |
String nonCopiedFiles [] = (String []) filter [0]; |
338 |
String wildcards [] = (String []) filter [1]; |
339 |
String name = fo.getPath(); |
340 |
|
341 |
if (fo.isFolder ()) { |
342 |
return Arrays.binarySearch (nonCopiedFiles, name + "/*") < 0; //NOI18N |
343 |
} |
344 |
|
345 |
for (int i = 0; i < wildcards.length; i++) { |
346 |
if (name.endsWith (wildcards [i])) { |
347 |
return false; |
348 |
} |
349 |
} |
350 |
|
351 |
long time = fo.lastModified().getTime(); |
352 |
|
353 |
boolean canCopy = Arrays.binarySearch (nonCopiedFiles, name) < 0 && |
354 |
basicTime + timeDev <= time; |
355 |
if (!canCopy) { |
356 |
return false; |
357 |
} |
358 |
|
359 |
// #31623 - the fastjavac settings should not be imported. |
360 |
// In NB3.5 the fastjavac was separated into its own module. |
361 |
// Its old settings (bounded to java module) must not be imported. |
362 |
// For fastjavac settings created by NB3.5 this will work, because they |
363 |
// will be bound to new "org.netbeans.modules.java.fastjavac" module. |
364 |
if (fo.getExt().equals("settings")) { //NOI18N |
365 |
boolean tag1 = false; |
366 |
boolean tag2 = false; |
367 |
BufferedReader reader = null; |
368 |
try { |
369 |
reader = new BufferedReader(new InputStreamReader(fo.getInputStream())); |
370 |
String line; |
371 |
while (null != (line = reader.readLine())) { |
372 |
if (line.indexOf("<module name=") != -1) { //NOI18N |
373 |
if (line.indexOf("<module name=\"org.netbeans.modules.java/1\"") != -1) { //NOI18N |
374 |
tag1 = true; // it is java module setting |
375 |
} else { |
376 |
break; // some other setting, ignore this file |
377 |
} |
378 |
} |
379 |
if (line.indexOf("<serialdata class=") != -1) { //NOI18N |
380 |
if (line.indexOf("<serialdata class=\"org.netbeans.modules.java.FastJavacCompilerType\">") != -1) { //NOI18N |
381 |
tag2 = true; // it is fastjavac setting |
382 |
if (tag1) { |
383 |
break; |
384 |
} |
385 |
} else { |
386 |
break; // some other setting, ignore this file |
387 |
} |
388 |
} |
389 |
} |
390 |
} catch (IOException ex) { |
391 |
// ignore this problem. |
392 |
// in worst case the fastjavac settings will be copied. |
393 |
} finally { |
394 |
if (reader != null) { |
395 |
reader.close(); |
396 |
} |
397 |
} |
398 |
if (tag1 && tag2) { |
399 |
return false; // ignore this file. it is fastjavac settings |
400 |
} |
401 |
} |
402 |
|
403 |
return true; |
404 |
} |
405 |
// ************************* version retrieving code ******************** |
406 |
|
407 |
|
408 |
/** We support import just from release 3.6 |
409 |
* @param dir user dir to check for version |
410 |
* @return either null or name of the version |
411 |
*/ |
412 |
public static String getIdeVersion (File dir) { |
413 |
String version = null; |
414 |
String dirType = null; |
415 |
String branding = null; |
416 |
|
417 |
if (new File (dir, "system").exists ()) { |
418 |
return "3.6"; |
419 |
} |
420 |
return null; |
421 |
} |
422 |
|
423 |
// ************** strings from bundle *************** |
424 |
|
425 |
protected static String getString (String key) { |
426 |
return NbBundle.getMessage (Copy.class, key); |
427 |
} |
428 |
|
429 |
protected static String getString (String key,String param) { |
430 |
return NbBundle.getMessage(Copy.class,key,param); |
431 |
} |
432 |
|
433 |
private static class AttrslessLocalFileSystem extends AbstractFileSystem implements AbstractFileSystem.Attr { |
434 |
public AttrslessLocalFileSystem (LocalFileSystem fs) { |
435 |
super (); |
436 |
this.change = new LocalFileSystem.Impl (fs); |
437 |
this.info = (AbstractFileSystem.Info) this.change; |
438 |
this.list = (AbstractFileSystem.List) this.change; |
439 |
this.attr = this; |
440 |
} |
441 |
public boolean isReadOnly () { |
442 |
return false; |
443 |
} |
444 |
public String getDisplayName () { |
445 |
return getClass ().toString (); // this will never be shown to user |
446 |
} |
447 |
|
448 |
// ***** no-op implementation of AbstractFileSystem.Attr ***** |
449 |
|
450 |
public void deleteAttributes (String name) { |
451 |
} |
452 |
public Enumeration attributes (String name) { |
453 |
return org.openide.util.enum.EmptyEnumeration.EMPTY; |
454 |
} |
455 |
public void renameAttributes (String oldName, String newName) { |
456 |
} |
457 |
public void writeAttribute (String name, String attrName, Object value) throws IOException { |
458 |
} |
459 |
public Object readAttribute (String name, String attrName) { |
460 |
return null; |
461 |
} |
462 |
} |
463 |
} |