001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.upgrade;
043:
044: import java.io.*;
045: import java.util.*;
046: import java.util.regex.Matcher;
047: import java.util.regex.Pattern;
048: import org.openide.util.*;
049:
050: import org.openide.filesystems.*;
051:
052: /** Does copy of objects on filesystems.
053: *
054: * @author Jaroslav Tulach
055: */
056: final class Copy extends Object {
057: private FileObject sourceRoot;
058: private FileObject targetRoot;
059: private Set thoseToCopy;
060: private PathTransformation transformation;
061:
062: private Copy(FileObject source, FileObject target, Set thoseToCopy,
063: PathTransformation transformation) {
064: this .sourceRoot = source;
065: this .targetRoot = target;
066: this .thoseToCopy = thoseToCopy;
067: this .transformation = transformation;
068: }
069:
070: /** Does a selective copy of one source tree to another.
071: * @param source file object to copy from
072: * @param target file object to copy to
073: * @param thoseToCopy set on which contains (relativeNameOfAFileToCopy)
074: * is being called to find out whether to copy or not
075: * @throws IOException if coping fails
076: */
077: public static void copyDeep(FileObject source, FileObject target,
078: Set thoseToCopy) throws IOException {
079: copyDeep(source, target, thoseToCopy, null);
080: }
081:
082: public static void copyDeep(FileObject source, FileObject target,
083: Set thoseToCopy, PathTransformation transformation)
084: throws IOException {
085: Copy instance = new Copy(source, target, thoseToCopy,
086: transformation);
087: instance.copyFolder(instance.sourceRoot);
088: }
089:
090: private void copyFolder(FileObject sourceFolder) throws IOException {
091: FileObject[] srcChildren = sourceFolder.getChildren();
092: for (int i = 0; i < srcChildren.length; i++) {
093: FileObject child = srcChildren[i];
094: if (child.isFolder()) {
095: copyFolder(child);
096: // make sure 'include xyz/.*' copies xyz folder's attributes
097: if ((thoseToCopy.contains(child.getPath()) || thoseToCopy
098: .contains(child.getPath() + "/"))
099: && //NOI18N
100: child.getAttributes().hasMoreElements()) {
101: copyFolderAttributes(child);
102: }
103: } else {
104: if (thoseToCopy.contains(child.getPath())) {
105: copyFile(child);
106: }
107: }
108: }
109: }
110:
111: private void copyFolderAttributes(FileObject sourceFolder)
112: throws IOException {
113: FileObject targetFolder = FileUtil.createFolder(targetRoot,
114: sourceFolder.getPath());
115: if (sourceFolder.getAttributes().hasMoreElements()) {
116: FileUtil.copyAttributes(sourceFolder, targetFolder);
117: }
118: }
119:
120: private void copyFile(FileObject sourceFile) throws IOException {
121: String targetPath = (transformation != null) ? transformation
122: .transformPath(sourceFile.getPath()) : sourceFile
123: .getPath();
124: boolean isTransformed = !targetPath
125: .equals(sourceFile.getPath());
126: FileObject tg = targetRoot.getFileObject(targetPath);
127: try {
128: if (tg == null) {
129: // copy the file otherwise keep old content
130: FileObject targetFolder = null;
131: String name = null, ext = null;
132: if (isTransformed) {
133: FileObject targetFile = FileUtil.createData(
134: targetRoot, targetPath);
135: targetFolder = targetFile.getParent();
136: name = targetFile.getName();
137: ext = targetFile.getExt();
138: targetFile.delete();
139: } else {
140: targetFolder = FileUtil.createFolder(targetRoot,
141: sourceFile.getParent().getPath());
142: name = sourceFile.getName();
143: ext = sourceFile.getExt();
144: }
145: tg = FileUtil.copyFile(sourceFile, targetFolder, name,
146: ext);
147: }
148: } catch (IOException ex) {
149: if (sourceFile.getNameExt().endsWith("_hidden")) {
150: return;
151: }
152: throw ex;
153: }
154: FileUtil.copyAttributes(sourceFile, tg);
155: }
156:
157: public static void appendSelectedLines(File sourceFile,
158: File targetFolder, String[] regexForSelection)
159: throws IOException {
160: if (!sourceFile.exists()) {
161: return;
162: }
163: Pattern[] linePattern = new Pattern[regexForSelection.length];
164: for (int i = 0; i < linePattern.length; i++) {
165: linePattern[i] = Pattern.compile(regexForSelection[i]);
166: }
167: ByteArrayOutputStream bos = new ByteArrayOutputStream();
168: File targetFile = new File(targetFolder, sourceFile.getName());
169: if (!targetFolder.exists()) {
170: targetFolder.mkdirs();
171: }
172: assert targetFolder.exists();
173:
174: if (!targetFile.exists()) {
175: targetFile.createNewFile();
176: } else {
177: //read original content into ByteArrayOutputStream
178: FileInputStream targetIS = new FileInputStream(targetFile);
179: try {
180: FileUtil.copy(targetIS, bos);
181: } finally {
182: targetIS.close();
183: }
184: }
185: assert targetFile.exists();
186:
187: //append lines into ByteArrayOutputStream
188: String line = null;
189: BufferedReader sourceReader = new BufferedReader(
190: new FileReader(sourceFile));
191: try {
192: while ((line = sourceReader.readLine()) != null) {
193: if (linePattern != null) {
194: for (int i = 0; i < linePattern.length; i++) {
195: Matcher m = linePattern[i].matcher(line);
196: if (m.matches()) {
197: bos.write(line.getBytes());
198: bos.write('\n');
199: break;
200: }
201: }
202: } else {
203: bos.write(line.getBytes());
204: bos.write('\n');
205: }
206: }
207: } finally {
208: sourceReader.close();
209: }
210:
211: ByteArrayInputStream bin = new ByteArrayInputStream(bos
212: .toByteArray());
213: FileOutputStream targetOS = new FileOutputStream(targetFile);
214: try {
215: FileUtil.copy(bin, targetOS);
216: } finally {
217: bin.close();
218: targetOS.close();
219: }
220: }
221:
222: /** Updates the IDE.
223: * @param sourceDir original instalation of the IDE
224: * @param targetSystem target system to copy files to
225: * @param backupSystem filesystem to do backupSystemFo to (or null)
226: * @exception IOException if the copying fails
227: *
228: protected final void upgradeIde (String ver, File src, File trg) throws Exception {
229:
230:
231: int version = getIdeVersion (ver);
232: if (version < 0 || version >= versions.length) {
233: message (getString ("MSG_BAD_IDE"));
234: for (int i = 0 ; i < versions.length ; i++ ) {
235: message (versions[i]);
236: }
237: throw new Exception ("Invalid IDE version"); //NOI18N
238: }
239:
240: message (getString ("MSG_UPDATE_FROM", versions[version]));
241:
242: FileSystem srcFS = null;
243: FileSystem trgFS = null;
244: FileSystem tmpFS = null;
245: Object filter [] = null;
246:
247: if (-1 != ver.indexOf (DIRTYPE_INST)) {
248: File srcFile = new File (src, "system"); //NOI18N
249: File trgFile = new File (trg, "system"); //NOI18N
250: srcFS = createFileSystem (srcFile);
251: trgFS = createFileSystem (trgFile);
252:
253: if (srcFS == null) {
254: message (getString ("MSG_directory_not_exist", srcFile.getAbsolutePath ())); //NOI18N
255: throw new Exception ("Directory doesn't exist - " + srcFile.getAbsolutePath ()); //NOI18N
256: }
257:
258: if (trgFS == null) {
259: message (getString ("MSG_directory_not_exist", trgFile.getAbsolutePath ()));
260: throw new Exception ("Directory doesn't exist - " + trgFile.getAbsolutePath ()); //NOI18N
261: }
262:
263: File tmpRoot = new File (trg, "system_backup"); //NOI18N
264: if (!tmpRoot.exists ()) {
265: // message (getString ("MSG_BackupDir_exists", tmpRoot.getAbsolutePath ())); //NOI18N
266: // throw new Exception ("Backup directory already exists - " + tmpRoot.getAbsolutePath ()); //NOI18N
267: // } else {
268: tmpRoot.mkdirs ();
269: }
270: tmpFS = createFileSystem (tmpRoot);
271:
272: filter = originalFiles (nonCpFiles[version]);
273: } else {
274: srcFS = createFileSystem (src); //NOI18N
275: trgFS = createFileSystem (trg); //NOI18N
276:
277: if (srcFS == null) {
278: message (getString ("MSG_directory_not_exist", src.getAbsolutePath ())); //NOI18N
279: throw new Exception ("Directory doesn't exist - " + src.getAbsolutePath ()); //NOI18N
280: }
281:
282: if (trgFS == null) {
283: message (getString ("MSG_directory_not_exist", trg.getAbsolutePath ())); //NOI18N
284: throw new Exception ("Directory doesn't exist - " + trg.getAbsolutePath ()); //NOI18N
285: }
286:
287: File tmpRoot = new File (trg.getParentFile (), "userdir_backup"); //NOI18N
288: if (!tmpRoot.exists ()) {
289: // message (getString ("MSG_BackupDir_exists", tmpRoot.getAbsolutePath ())); //NOI18N
290: // throw new Exception ("Backup directory already exists - " + tmpRoot.getAbsolutePath ()); //NOI18N
291: // } else {
292: tmpRoot.mkdirs ();
293: }
294: tmpFS = createFileSystem (tmpRoot);
295:
296: filter = originalFiles (userdirNonCpFiles);
297: }
298:
299: if (tmpFS != null) {
300: // clean up temporary filesystem
301: FileObject ch [] = tmpFS.getRoot ().getChildren ();
302: for (int i = 0; i < ch.length; i++) {
303: deleteAll (ch[i]);
304: }
305: // make a backup copy
306: copyAttributes(trgFS.getRoot (), tmpFS.getRoot ());
307: recursiveCopy(trgFS.getRoot (), tmpFS.getRoot ());
308: }
309:
310: try {
311: update (srcFS, trgFS, getLastModified (src), filter);
312: }
313: catch (Exception e) {
314: if (tmpFS != null) {
315: message (getString ("MSG_recovery_started")); //NOI18N
316: deleteAll (trgFS.getRoot ());
317: copyAttributes (tmpFS.getRoot (), trgFS.getRoot ());
318: recursiveCopy (tmpFS.getRoot (), trgFS.getRoot ());
319: message (getString ("MSG_recovery_finished")); //NOI18N
320: }
321: throw e;
322: }
323: }
324:
325: private FileSystem createFileSystem (File root) {
326: LocalFileSystem lfs = null;
327:
328: if (root.exists () && root.isDirectory ()) {
329: try {
330: lfs = new LocalFileSystem ();
331: lfs.setRootDirectory (root);
332: }
333: catch (Exception e) {
334: lfs = null;
335: }
336: }
337:
338: return lfs == null ? null : new AttrslessLocalFileSystem (lfs);
339: }
340:
341: private void update(
342: FileSystem src, FileSystem trg, long sourceBaseTime, Object[] filter
343: ) throws IOException {
344:
345: items = 0;
346: maxItems = 0;
347:
348: copyAttributes (src.getRoot (),trg.getRoot ());
349: recursiveCopyWithFilter (
350: src.getRoot (),
351: trg.getRoot (),
352: filter,
353: sourceBaseTime
354: );
355: }
356:
357: /** copies recursively directory, skips files existing in target location
358: * @param source source directory
359: * @param dest destination directory
360: */
361: private void recursiveCopy(FileObject sourceFolder,
362: FileObject destFolder) throws IOException {
363: FileObject childrens[] = sourceFolder.getChildren();
364: for (int i = 0; i < childrens.length; i++) {
365: final FileObject subSourceFo = childrens[i];
366: FileObject subTargetFo = null;
367:
368: if (subSourceFo.isFolder()) {
369: subTargetFo = destFolder.getFileObject(subSourceFo
370: .getName());
371: if (subTargetFo == null) {
372: subTargetFo = destFolder.createFolder(subSourceFo
373: .getName());
374:
375: }
376: copyAttributes(subSourceFo, subTargetFo);
377: recursiveCopy(subSourceFo, subTargetFo);
378: } else {
379: subTargetFo = destFolder.getFileObject(subSourceFo
380: .getNameExt());
381: if (subTargetFo == null) {
382: if (Utilities.getOperatingSystem() == Utilities.OS_VMS
383: && subSourceFo.getNameExt()
384: .equalsIgnoreCase("_nbattrs."))
385: subTargetFo = FileUtil.copyFile(subSourceFo,
386: destFolder, subSourceFo.getNameExt(),
387: subSourceFo.getExt());
388: else
389: subTargetFo = FileUtil.copyFile(subSourceFo,
390: destFolder, subSourceFo.getName(),
391: subSourceFo.getExt());
392: }
393: copyAttributes(subSourceFo, subTargetFo);
394: }
395: }
396: }
397:
398: private void message(String s) {
399:
400: }
401:
402: private void progress(int x, int y) {
403:
404: }
405:
406: private int maxItems;
407: private int items;
408: private int timeDev;
409:
410: /** Copies recursively dircectory. Files are copied when when basicTime + timeDev < time of file.
411: * @param source source directory
412: * @param #dest destination dirctory
413: */
414: private void recursiveCopyWithFilter(FileObject source,
415: FileObject dest, Object[] filter, long basicTime)
416: throws IOException {
417: FileObject childrens[] = source.getChildren();
418: if (source.isFolder() == false) {
419: message(getString("MSG_IS_NOT_FOLDER", source.getName()));
420: }
421:
422: // adjust max number of items
423: maxItems += childrens.length;
424:
425: for (int i = 0; i < childrens.length; i++) {
426: FileObject subSourceFo = childrens[i];
427:
428: // report progress
429: items++;
430: progress(items, maxItems);
431:
432: if (!canCopy(subSourceFo, filter, basicTime))
433: continue;
434:
435: FileObject subTargetFo = null;
436: if (subSourceFo.isFolder()) {
437: subTargetFo = dest.getFileObject(subSourceFo
438: .getNameExt());
439: if (subTargetFo == null) {
440: subTargetFo = dest.createFolder(subSourceFo
441: .getNameExt());
442:
443: }
444: copyAttributes(subSourceFo, subTargetFo);
445: recursiveCopyWithFilter(subSourceFo, subTargetFo,
446: filter, basicTime);
447: } else {
448: subTargetFo = dest.getFileObject(subSourceFo.getName(),
449: subSourceFo.getExt());
450:
451: if (subTargetFo != null) {
452: FileLock lock = subTargetFo.lock();
453: subTargetFo.delete(lock);
454: lock.releaseLock();
455: }
456:
457: if (Utilities.getOperatingSystem() == Utilities.OS_VMS
458: && subSourceFo.getNameExt().equalsIgnoreCase(
459: "_nbattrs."))
460: subTargetFo = copyFile(subSourceFo, dest,
461: subSourceFo.getNameExt());
462: else
463: subTargetFo = copyFile(subSourceFo, dest,
464: subSourceFo.getName());
465: copyAttributes(subSourceFo, subTargetFo);
466: }
467: }
468: }
469:
470: private FileObject copyFile(FileObject src, FileObject trg,
471: String newName) throws IOException {
472: return FileUtil.copyFile(src, trg, newName);
473: }
474:
475: private static void copyAttributes(FileObject source,
476: FileObject dest) throws IOException {
477: Enumeration attrKeys = source.getAttributes();
478: while (attrKeys.hasMoreElements()) {
479: String key = (String) attrKeys.nextElement();
480: Object value = source.getAttribute(key);
481: if (value != null) {
482: dest.setAttribute(key, value);
483: }
484: }
485: }
486:
487: /** test if file can be copied
488: */
489: private boolean canCopy(FileObject fo, Object[] filter,
490: long basicTime) throws IOException {
491: String nonCopiedFiles[] = (String[]) filter[0];
492: String wildcards[] = (String[]) filter[1];
493: String name = fo.getPath();
494:
495: if (fo.isFolder()) {
496: return Arrays.binarySearch(nonCopiedFiles, name + "/*") < 0; //NOI18N
497: }
498:
499: for (int i = 0; i < wildcards.length; i++) {
500: if (name.endsWith(wildcards[i])) {
501: return false;
502: }
503: }
504:
505: long time = fo.lastModified().getTime();
506:
507: boolean canCopy = Arrays.binarySearch(nonCopiedFiles, name) < 0
508: && basicTime + timeDev <= time;
509: if (!canCopy) {
510: return false;
511: }
512:
513: // #31623 - the fastjavac settings should not be imported.
514: // In NB3.5 the fastjavac was separated into its own module.
515: // Its old settings (bounded to java module) must not be imported.
516: // For fastjavac settings created by NB3.5 this will work, because they
517: // will be bound to new "org.netbeans.modules.java.fastjavac" module.
518: if (fo.getExt().equals("settings")) { //NOI18N
519: boolean tag1 = false;
520: boolean tag2 = false;
521: BufferedReader reader = null;
522: try {
523: reader = new BufferedReader(new InputStreamReader(fo
524: .getInputStream()));
525: String line;
526: while (null != (line = reader.readLine())) {
527: if (line.indexOf("<module name=") != -1) { //NOI18N
528: if (line
529: .indexOf("<module name=\"org.netbeans.modules.java/1\"") != -1) { //NOI18N
530: tag1 = true; // it is java module setting
531: } else {
532: break; // some other setting, ignore this file
533: }
534: }
535: if (line.indexOf("<serialdata class=") != -1) { //NOI18N
536: if (line
537: .indexOf("<serialdata class=\"org.netbeans.modules.java.FastJavacCompilerType\">") != -1) { //NOI18N
538: tag2 = true; // it is fastjavac setting
539: if (tag1) {
540: break;
541: }
542: } else {
543: break; // some other setting, ignore this file
544: }
545: }
546: }
547: } catch (IOException ex) {
548: // ignore this problem.
549: // in worst case the fastjavac settings will be copied.
550: } finally {
551: if (reader != null) {
552: reader.close();
553: }
554: }
555: if (tag1 && tag2) {
556: return false; // ignore this file. it is fastjavac settings
557: }
558: }
559:
560: return true;
561: }
562:
563: // ************************* version retrieving code ********************
564:
565: /** We support import just from release 3.6
566: * @param dir user dir to check for version
567: * @return either null or name of the version
568: */
569: public static String getIdeVersion(File dir) {
570: String version = null;
571: String dirType = null;
572: String branding = null;
573:
574: if (new File(dir, "system").exists()) {
575: return "3.6";
576: }
577: return null;
578: }
579:
580: // ************** strings from bundle ***************
581:
582: protected static String getString(String key) {
583: return NbBundle.getMessage(Copy.class, key);
584: }
585:
586: protected static String getString(String key, String param) {
587: return NbBundle.getMessage(Copy.class, key, param);
588: }
589:
590: private static class AttrslessLocalFileSystem extends
591: AbstractFileSystem implements AbstractFileSystem.Attr {
592: public AttrslessLocalFileSystem(LocalFileSystem fs) {
593: super ();
594: this .change = new LocalFileSystem.Impl(fs);
595: this .info = (AbstractFileSystem.Info) this .change;
596: this .list = (AbstractFileSystem.List) this .change;
597: this .attr = this ;
598: }
599:
600: public boolean isReadOnly() {
601: return false;
602: }
603:
604: public String getDisplayName() {
605: return getClass().toString(); // this will never be shown to user
606: }
607:
608: // ***** no-op implementation of AbstractFileSystem.Attr *****
609:
610: public void deleteAttributes(String name) {
611: }
612:
613: public Enumeration<String> attributes(String name) {
614: return org.openide.util.Enumerations.empty();
615: }
616:
617: public void renameAttributes(String oldName, String newName) {
618: }
619:
620: public void writeAttribute(String name, String attrName,
621: Object value) throws IOException {
622: }
623:
624: public Object readAttribute(String name, String attrName) {
625: return null;
626: }
627: }
628: }
|