Source Code Cross Referenced for Sync.java in  » Build » ANT » org » apache » tools » ant » taskdefs » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Build » ANT » org.apache.tools.ant.taskdefs 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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:         */
018:
019:        package org.apache.tools.ant.taskdefs;
020:
021:        import java.io.File;
022:
023:        import java.util.HashSet;
024:        import java.util.Iterator;
025:        import java.util.Map;
026:        import java.util.Set;
027:
028:        import org.apache.tools.ant.BuildException;
029:        import org.apache.tools.ant.DirectoryScanner;
030:        import org.apache.tools.ant.Project;
031:        import org.apache.tools.ant.Task;
032:        import org.apache.tools.ant.types.AbstractFileSet;
033:        import org.apache.tools.ant.types.FileSet;
034:        import org.apache.tools.ant.types.PatternSet;
035:        import org.apache.tools.ant.types.Resource;
036:        import org.apache.tools.ant.types.ResourceCollection;
037:        import org.apache.tools.ant.types.selectors.FileSelector;
038:        import org.apache.tools.ant.types.selectors.NoneSelector;
039:
040:        /**
041:         * Synchronize a local target directory from the files defined
042:         * in one or more filesets.
043:         *
044:         * <p>Uses a &lt;copy&gt; task internally, but forbidding the use of
045:         * mappers and filter chains. Files of the destination directory not
046:         * present in any of the source fileset are removed.</p>
047:         *
048:         * @since Ant 1.6
049:         *
050:         * revised by <a href="mailto:daniel.armbrust@mayo.edu">Dan Armbrust</a>
051:         * to remove orphaned directories.
052:         *
053:         * @ant.task category="filesystem"
054:         */
055:        public class Sync extends Task {
056:
057:            // Same as regular <copy> task... see at end-of-file!
058:            private MyCopy myCopy;
059:
060:            // Similar to a fileset, but doesn't allow dir attribute to be set
061:            private SyncTarget syncTarget;
062:
063:            // Override Task#init
064:            /**
065:             * Initialize the sync task.
066:             * @throws BuildException if there is a problem.
067:             * @see Task#init()
068:             */
069:            public void init() throws BuildException {
070:                // Instantiate it
071:                myCopy = new MyCopy();
072:                configureTask(myCopy);
073:
074:                // Default config of <mycopy> for our purposes.
075:                myCopy.setFiltering(false);
076:                myCopy.setIncludeEmptyDirs(false);
077:                myCopy.setPreserveLastModified(true);
078:            }
079:
080:            private void configureTask(Task helper) {
081:                helper.setProject(getProject());
082:                helper.setTaskName(getTaskName());
083:                helper.setOwningTarget(getOwningTarget());
084:                helper.init();
085:            }
086:
087:            // Override Task#execute
088:            /**
089:             * Execute the sync task.
090:             * @throws BuildException if there is an error.
091:             * @see Task#execute()
092:             */
093:            public void execute() throws BuildException {
094:                // The destination of the files to copy
095:                File toDir = myCopy.getToDir();
096:
097:                // The complete list of files to copy
098:                Set allFiles = myCopy.nonOrphans;
099:
100:                // If the destination directory didn't already exist,
101:                // or was empty, then no previous file removal is necessary!
102:                boolean noRemovalNecessary = !toDir.exists()
103:                        || toDir.list().length < 1;
104:
105:                // Copy all the necessary out-of-date files
106:                log("PASS#1: Copying files to " + toDir, Project.MSG_DEBUG);
107:                myCopy.execute();
108:
109:                // Do we need to perform further processing?
110:                if (noRemovalNecessary) {
111:                    log("NO removing necessary in " + toDir, Project.MSG_DEBUG);
112:                    return; // nope ;-)
113:                }
114:
115:                // Get rid of all files not listed in the source filesets.
116:                log("PASS#2: Removing orphan files from " + toDir,
117:                        Project.MSG_DEBUG);
118:                int[] removedFileCount = removeOrphanFiles(allFiles, toDir);
119:                logRemovedCount(removedFileCount[0], "dangling director", "y",
120:                        "ies");
121:                logRemovedCount(removedFileCount[1], "dangling file", "", "s");
122:
123:                // Get rid of empty directories on the destination side
124:                if (!myCopy.getIncludeEmptyDirs()) {
125:                    log("PASS#3: Removing empty directories from " + toDir,
126:                            Project.MSG_DEBUG);
127:                    int removedDirCount = removeEmptyDirectories(toDir, false);
128:                    logRemovedCount(removedDirCount, "empty director", "y",
129:                            "ies");
130:                }
131:            }
132:
133:            private void logRemovedCount(int count, String prefix,
134:                    String singularSuffix, String pluralSuffix) {
135:                File toDir = myCopy.getToDir();
136:
137:                String what = (prefix == null) ? "" : prefix;
138:                what += (count < 2) ? singularSuffix : pluralSuffix;
139:
140:                if (count > 0) {
141:                    log("Removed " + count + " " + what + " from " + toDir,
142:                            Project.MSG_INFO);
143:                } else {
144:                    log("NO " + what + " to remove from " + toDir,
145:                            Project.MSG_VERBOSE);
146:                }
147:            }
148:
149:            /**
150:             * Removes all files and folders not found as keys of a table
151:             * (used as a set!).
152:             *
153:             * <p>If the provided file is a directory, it is recursively
154:             * scanned for orphaned files which will be removed as well.</p>
155:             *
156:             * <p>If the directory is an orphan, it will also be removed.</p>
157:             *
158:             * @param  nonOrphans the table of all non-orphan <code>File</code>s.
159:             * @param  file the initial file or directory to scan or test.
160:             * @return the number of orphaned files and directories actually removed.
161:             * Position 0 of the array is the number of orphaned directories.
162:             * Position 1 of the array is the number or orphaned files.
163:             */
164:            private int[] removeOrphanFiles(Set nonOrphans, File toDir) {
165:                int[] removedCount = new int[] { 0, 0 };
166:                String[] excls = (String[]) nonOrphans
167:                        .toArray(new String[nonOrphans.size() + 1]);
168:                // want to keep toDir itself
169:                excls[nonOrphans.size()] = "";
170:
171:                DirectoryScanner ds = null;
172:                if (syncTarget != null) {
173:                    FileSet fs = new FileSet();
174:                    fs.setDir(toDir);
175:                    fs.setCaseSensitive(syncTarget.isCaseSensitive());
176:                    fs.setFollowSymlinks(syncTarget.isFollowSymlinks());
177:
178:                    // preserveInTarget would find all files we want to keep,
179:                    // but we need to find all that we want to delete - so the
180:                    // meaning of all patterns and selectors must be inverted
181:                    PatternSet ps = syncTarget.mergePatterns(getProject());
182:                    fs.appendExcludes(ps.getIncludePatterns(getProject()));
183:                    fs.appendIncludes(ps.getExcludePatterns(getProject()));
184:                    fs.setDefaultexcludes(!syncTarget.getDefaultexcludes());
185:
186:                    // selectors are implicitly ANDed in DirectoryScanner.  To
187:                    // revert their logic we wrap them into a <none> selector
188:                    // instead.
189:                    FileSelector[] s = syncTarget.getSelectors(getProject());
190:                    if (s.length > 0) {
191:                        NoneSelector ns = new NoneSelector();
192:                        for (int i = 0; i < s.length; i++) {
193:                            ns.appendSelector(s[i]);
194:                        }
195:                        fs.appendSelector(ns);
196:                    }
197:                    ds = fs.getDirectoryScanner(getProject());
198:                } else {
199:                    ds = new DirectoryScanner();
200:                    ds.setBasedir(toDir);
201:                }
202:                ds.addExcludes(excls);
203:
204:                ds.scan();
205:                String[] files = ds.getIncludedFiles();
206:                for (int i = 0; i < files.length; i++) {
207:                    File f = new File(toDir, files[i]);
208:                    log("Removing orphan file: " + f, Project.MSG_DEBUG);
209:                    f.delete();
210:                    ++removedCount[1];
211:                }
212:                String[] dirs = ds.getIncludedDirectories();
213:                // ds returns the directories in lexicographic order.
214:                // iterating through the array backwards means we are deleting
215:                // leaves before their parent nodes - thus making sure (well,
216:                // more likely) that the directories are empty when we try to
217:                // delete them.
218:                for (int i = dirs.length - 1; i >= 0; --i) {
219:                    File f = new File(toDir, dirs[i]);
220:                    if (f.list().length < 1) {
221:                        log("Removing orphan directory: " + f,
222:                                Project.MSG_DEBUG);
223:                        f.delete();
224:                        ++removedCount[0];
225:                    }
226:                }
227:                return removedCount;
228:            }
229:
230:            /**
231:             * Removes all empty directories from a directory.
232:             *
233:             * <p><em>Note that a directory that contains only empty
234:             * directories, directly or not, will be removed!</em></p>
235:             *
236:             * <p>Recurses depth-first to find the leaf directories
237:             * which are empty and removes them, then unwinds the
238:             * recursion stack, removing directories which have
239:             * become empty themselves, etc...</p>
240:             *
241:             * @param  dir the root directory to scan for empty directories.
242:             * @param  removeIfEmpty whether to remove the root directory
243:             *         itself if it becomes empty.
244:             * @return the number of empty directories actually removed.
245:             */
246:            private int removeEmptyDirectories(File dir, boolean removeIfEmpty) {
247:                int removedCount = 0;
248:                if (dir.isDirectory()) {
249:                    File[] children = dir.listFiles();
250:                    for (int i = 0; i < children.length; ++i) {
251:                        File file = children[i];
252:                        // Test here again to avoid method call for non-directories!
253:                        if (file.isDirectory()) {
254:                            removedCount += removeEmptyDirectories(file, true);
255:                        }
256:                    }
257:                    if (children.length > 0) {
258:                        // This directory may have become empty...
259:                        // We need to re-query its children list!
260:                        children = dir.listFiles();
261:                    }
262:                    if (children.length < 1 && removeIfEmpty) {
263:                        log("Removing empty directory: " + dir,
264:                                Project.MSG_DEBUG);
265:                        dir.delete();
266:                        ++removedCount;
267:                    }
268:                }
269:                return removedCount;
270:            }
271:
272:            //
273:            // Various copy attributes/subelements of <copy> passed thru to <mycopy>
274:            //
275:
276:            /**
277:             * Sets the destination directory.
278:             * @param destDir the destination directory
279:             */
280:            public void setTodir(File destDir) {
281:                myCopy.setTodir(destDir);
282:            }
283:
284:            /**
285:             * Used to force listing of all names of copied files.
286:             * @param verbose if true force listing of all names of copied files.
287:             */
288:            public void setVerbose(boolean verbose) {
289:                myCopy.setVerbose(verbose);
290:            }
291:
292:            /**
293:             * Overwrite any existing destination file(s).
294:             * @param overwrite if true overwrite any existing destination file(s).
295:             */
296:            public void setOverwrite(boolean overwrite) {
297:                myCopy.setOverwrite(overwrite);
298:            }
299:
300:            /**
301:             * Used to copy empty directories.
302:             * @param includeEmpty If true copy empty directories.
303:             */
304:            public void setIncludeEmptyDirs(boolean includeEmpty) {
305:                myCopy.setIncludeEmptyDirs(includeEmpty);
306:            }
307:
308:            /**
309:             * If false, note errors to the output but keep going.
310:             * @param failonerror true or false
311:             */
312:            public void setFailOnError(boolean failonerror) {
313:                myCopy.setFailOnError(failonerror);
314:            }
315:
316:            /**
317:             * Adds a set of files to copy.
318:             * @param set a fileset
319:             */
320:            public void addFileset(FileSet set) {
321:                add(set);
322:            }
323:
324:            /**
325:             * Adds a collection of filesystem resources to copy.
326:             * @param rc a resource collection
327:             * @since Ant 1.7
328:             */
329:            public void add(ResourceCollection rc) {
330:                myCopy.add(rc);
331:            }
332:
333:            /**
334:             * The number of milliseconds leeway to give before deciding a
335:             * target is out of date.
336:             *
337:             * <p>Default is 0 milliseconds, or 2 seconds on DOS systems.</p>
338:             * @param granularity a <code>long</code> value
339:             * @since Ant 1.6.2
340:             */
341:            public void setGranularity(long granularity) {
342:                myCopy.setGranularity(granularity);
343:            }
344:
345:            /**
346:             * A container for patterns and selectors that can be used to
347:             * specify files that should be kept in the target even if they
348:             * are not present in any source directory.
349:             *
350:             * <p>You must not invoke this method more than once.</p>
351:             * @param s a preserveintarget nested element
352:             * @since Ant 1.7
353:             */
354:            public void addPreserveInTarget(SyncTarget s) {
355:                if (syncTarget != null) {
356:                    throw new BuildException("you must not specify multiple "
357:                            + "preserveintarget elements.");
358:                }
359:                syncTarget = s;
360:            }
361:
362:            /**
363:             * Subclass Copy in order to access it's file/dir maps.
364:             */
365:            public static class MyCopy extends Copy {
366:
367:                // List of files that must be copied, irrelevant from the
368:                // fact that they are newer or not than the destination.
369:                private Set nonOrphans = new HashSet();
370:
371:                /** Constructor for MyCopy. */
372:                public MyCopy() {
373:                }
374:
375:                /**
376:                 * @see Copy#scan(File, File, String[], String[])
377:                 */
378:                /** {@inheritDoc} */
379:                protected void scan(File fromDir, File toDir, String[] files,
380:                        String[] dirs) {
381:                    assertTrue("No mapper", mapperElement == null);
382:
383:                    super .scan(fromDir, toDir, files, dirs);
384:
385:                    for (int i = 0; i < files.length; ++i) {
386:                        nonOrphans.add(files[i]);
387:                    }
388:                    for (int i = 0; i < dirs.length; ++i) {
389:                        nonOrphans.add(dirs[i]);
390:                    }
391:                }
392:
393:                /**
394:                 * @see Copy#scan(Resource[], File)
395:                 */
396:                /** {@inheritDoc} */
397:                protected Map scan(Resource[] resources, File toDir) {
398:                    assertTrue("No mapper", mapperElement == null);
399:
400:                    Map m = super .scan(resources, toDir);
401:
402:                    Iterator iter = m.keySet().iterator();
403:                    while (iter.hasNext()) {
404:                        nonOrphans.add(((Resource) iter.next()).getName());
405:                    }
406:                    return m;
407:                }
408:
409:                /**
410:                 * Get the destination directory.
411:                 * @return the destination directory
412:                 */
413:                public File getToDir() {
414:                    return destDir;
415:                }
416:
417:                /**
418:                 * Get the includeEmptyDirs attribute.
419:                 * @return true if emptyDirs are to be included
420:                 */
421:                public boolean getIncludeEmptyDirs() {
422:                    return includeEmpty;
423:                }
424:
425:                /**
426:                 * Yes, we can.
427:                 * @return true always.
428:                 * @since Ant 1.7
429:                 */
430:                protected boolean supportsNonFileResources() {
431:                    return true;
432:                }
433:            }
434:
435:            /**
436:             * Inner class used to hold exclude patterns and selectors to save
437:             * stuff that happens to live in the target directory but should
438:             * not get removed.
439:             *
440:             * @since Ant 1.7
441:             */
442:            public static class SyncTarget extends AbstractFileSet {
443:
444:                /**
445:                 * Constructor for SyncTarget.
446:                 * This just changes the default value of "defaultexcludes" from
447:                 * true to false.
448:                 */
449:                public SyncTarget() {
450:                    super ();
451:                }
452:
453:                /**
454:                 * Override AbstractFileSet#setDir(File) to disallow
455:                 * setting the directory.
456:                 * @param dir ignored
457:                 * @throws BuildException always
458:                 */
459:                public void setDir(File dir) throws BuildException {
460:                    throw new BuildException(
461:                            "preserveintarget doesn't support the dir "
462:                                    + "attribute");
463:                }
464:
465:            }
466:
467:            /**
468:             * Pseudo-assert method.
469:             */
470:            private static void assertTrue(String message, boolean condition) {
471:                if (!condition) {
472:                    throw new BuildException("Assertion Error: " + message);
473:                }
474:            }
475:
476:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.