587
|
1 |
/*
|
628
|
2 |
* Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
|
|
3 |
* All rights reserved.
|
|
4 |
* This component and the accompanying materials are made available
|
|
5 |
* under the terms of the License "Eclipse Public License v1.0"
|
|
6 |
* which accompanies this distribution, and is available
|
|
7 |
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
8 |
*
|
|
9 |
* Initial Contributors:
|
|
10 |
* Nokia Corporation - initial contribution.
|
|
11 |
*
|
|
12 |
* Contributors:
|
|
13 |
*
|
|
14 |
* Description:
|
|
15 |
*
|
|
16 |
*/
|
|
17 |
|
587
|
18 |
package com.nokia.ant.taskdefs;
|
|
19 |
|
|
20 |
import java.io.File;
|
|
21 |
import java.io.IOException;
|
|
22 |
import java.util.Enumeration;
|
628
|
23 |
import java.util.Vector;
|
587
|
24 |
|
628
|
25 |
import org.apache.tools.ant.BuildException;
|
587
|
26 |
import org.apache.tools.ant.Project;
|
628
|
27 |
import org.apache.tools.ant.taskdefs.Copy;
|
587
|
28 |
import org.apache.tools.ant.types.FilterSet;
|
|
29 |
import org.apache.tools.ant.types.FilterSetCollection;
|
|
30 |
|
|
31 |
/**
|
628
|
32 |
* Copies a file(s) or directory(s) to a new file(s) or directory(s) using parallel threads. Number
|
|
33 |
* of parallel threads can be defined by threadCount. Files are only copied if the source file is
|
|
34 |
* newer than the destination file, or when the destination file does not exist. It is possible to
|
|
35 |
* explicitly overwrite existing files.</p>
|
|
36 |
*
|
|
37 |
*
|
587
|
38 |
* @ant.task category="Filesystem"
|
|
39 |
* @since Helium 0.21
|
628
|
40 |
*
|
|
41 |
*/
|
|
42 |
public class CopyParallelTask extends Copy {
|
587
|
43 |
|
|
44 |
static final String LINE_SEPARATOR = System.getProperty("line.separator");
|
|
45 |
private int copyThreadCount;
|
|
46 |
private int maxThreadCount;
|
628
|
47 |
|
587
|
48 |
/**
|
|
49 |
* CopyParallelTask task constructor.
|
|
50 |
*/
|
628
|
51 |
public CopyParallelTask() {
|
587
|
52 |
setTaskName("copy-parallel");
|
|
53 |
}
|
|
54 |
|
|
55 |
/**
|
|
56 |
* Perform the copy operation in parallel.
|
628
|
57 |
*
|
587
|
58 |
* @exception BuildException if an error occurs.
|
|
59 |
*/
|
628
|
60 |
public final void execute() {
|
|
61 |
super.execute();
|
|
62 |
// wait until all copy threads are dead
|
|
63 |
while (copyThreadCount > 0) {
|
587
|
64 |
try {
|
|
65 |
Thread.sleep(500);
|
628
|
66 |
}
|
|
67 |
catch (InterruptedException e) {
|
587
|
68 |
if (failonerror) {
|
628
|
69 |
throw new BuildException("Copy parallel task has been interrupted "
|
|
70 |
+ e.getMessage());
|
587
|
71 |
}
|
|
72 |
log("Copy parallel task has been interrupted " + e.getMessage(), Project.MSG_ERR);
|
|
73 |
}
|
588
|
74 |
}
|
628
|
75 |
|
587
|
76 |
}
|
|
77 |
|
|
78 |
/**
|
|
79 |
* Set maximum number of thread.
|
628
|
80 |
*
|
587
|
81 |
* @param threadCount maximum number of threads
|
|
82 |
*/
|
628
|
83 |
public final void setThreadCount(final int threadCount) {
|
|
84 |
// Limit max. threads to 8 otherwise we experience freezing when using the fastcopy task on
|
|
85 |
// 8 processor build machines
|
|
86 |
if (threadCount > 8) {
|
|
87 |
this.maxThreadCount = 8;
|
|
88 |
}
|
|
89 |
else {
|
587
|
90 |
this.maxThreadCount = threadCount;
|
|
91 |
}
|
|
92 |
}
|
|
93 |
|
628
|
94 |
/**
|
|
95 |
* Actually does the file (and possibly empty directory) copies. This is a good method for
|
|
96 |
* subclasses to override.
|
587
|
97 |
*/
|
628
|
98 |
protected final void doFileOperations() {
|
587
|
99 |
Vector filterSets = getFilterSets();
|
628
|
100 |
|
587
|
101 |
// set default thread count to 1 if it is not set
|
628
|
102 |
if (maxThreadCount < 1) {
|
|
103 |
maxThreadCount = 1;
|
|
104 |
}
|
|
105 |
|
|
106 |
if (fileCopyMap.size() > 0) {
|
|
107 |
log("Copying " + fileCopyMap.size() + " file" + (fileCopyMap.size() == 1 ? "" : "s")
|
|
108 |
+ " to " + destDir.getAbsolutePath() + " using " + maxThreadCount
|
587
|
109 |
+ " threads in parallel.");
|
|
110 |
|
588
|
111 |
Enumeration fileEnum = fileCopyMap.keys();
|
628
|
112 |
while (fileEnum.hasMoreElements()) {
|
588
|
113 |
String fromFile = (String) fileEnum.nextElement();
|
587
|
114 |
String[] toFiles = (String[]) fileCopyMap.get(fromFile);
|
|
115 |
|
|
116 |
for (int i = 0; i < toFiles.length; i++) {
|
|
117 |
String toFile = toFiles[i];
|
|
118 |
|
|
119 |
if (fromFile.equals(toFile)) {
|
|
120 |
log("Skipping self-copy of " + fromFile, verbosity);
|
|
121 |
continue;
|
|
122 |
}
|
|
123 |
log("Copying " + fromFile + " to " + toFile, verbosity);
|
|
124 |
|
|
125 |
FilterSetCollection executionFilters = new FilterSetCollection();
|
628
|
126 |
if (filtering) {
|
587
|
127 |
executionFilters.addFilterSet(getProject().getGlobalFilterSet());
|
|
128 |
}
|
628
|
129 |
for (Enumeration filterEnum = filterSets.elements(); filterEnum.hasMoreElements();) {
|
|
130 |
executionFilters.addFilterSet((FilterSet) filterEnum.nextElement());
|
|
131 |
}
|
|
132 |
|
|
133 |
while (true) {
|
|
134 |
if (copyThreadCount < maxThreadCount) {
|
588
|
135 |
CopyThread copyThread = new CopyThread(fromFile, toFile, executionFilters);
|
|
136 |
copyThread.start();
|
|
137 |
copyThreadCount++;
|
|
138 |
break;
|
|
139 |
}
|
587
|
140 |
}
|
|
141 |
}
|
|
142 |
}
|
|
143 |
}
|
|
144 |
if (includeEmpty) {
|
588
|
145 |
Enumeration dirEnum = dirCopyMap.elements();
|
587
|
146 |
int createCount = 0;
|
588
|
147 |
while (dirEnum.hasMoreElements()) {
|
|
148 |
String[] dirs = (String[]) dirEnum.nextElement();
|
587
|
149 |
for (int i = 0; i < dirs.length; i++) {
|
588
|
150 |
File file = new File(dirs[i]);
|
|
151 |
if (!file.exists()) {
|
|
152 |
if (!file.mkdirs()) {
|
628
|
153 |
log("Unable to create directory " + file.getAbsolutePath(), Project.MSG_ERR);
|
|
154 |
}
|
|
155 |
else {
|
587
|
156 |
createCount++;
|
|
157 |
}
|
|
158 |
}
|
|
159 |
}
|
|
160 |
}
|
|
161 |
if (createCount > 0) {
|
628
|
162 |
log("Copied " + dirCopyMap.size() + " empty director"
|
|
163 |
+ (dirCopyMap.size() == 1 ? "y" : "ies") + " to " + createCount
|
|
164 |
+ " empty director" + (createCount == 1 ? "y" : "ies") + " under "
|
587
|
165 |
+ destDir.getAbsolutePath());
|
|
166 |
}
|
|
167 |
}
|
|
168 |
}
|
|
169 |
|
|
170 |
/**
|
628
|
171 |
* private class to start a new thread to copy a single file or or directory.
|
587
|
172 |
*/
|
628
|
173 |
private class CopyThread extends Thread {
|
587
|
174 |
private String fromFile;
|
|
175 |
private String toFile;
|
|
176 |
private FilterSetCollection executionFilters;
|
|
177 |
private Vector filterChains;
|
|
178 |
private String inputEncoding;
|
|
179 |
private String outputEncoding;
|
628
|
180 |
|
|
181 |
public CopyThread(String fromFile, String toFile, FilterSetCollection executionFilters) {
|
587
|
182 |
this.fromFile = fromFile;
|
|
183 |
this.toFile = toFile;
|
|
184 |
this.executionFilters = executionFilters;
|
|
185 |
this.filterChains = getFilterChains();
|
|
186 |
this.inputEncoding = getEncoding();
|
|
187 |
this.outputEncoding = getOutputEncoding();
|
|
188 |
}
|
|
189 |
|
628
|
190 |
public void run() {
|
587
|
191 |
try {
|
628
|
192 |
fileUtils.copyFile(fromFile, toFile, executionFilters, filterChains, forceOverwrite, preserveLastModified, inputEncoding, outputEncoding, getProject());
|
|
193 |
}
|
|
194 |
catch (IOException e) {
|
587
|
195 |
log("Problem found in parallel copy " + e.toString(), Project.MSG_ERR);
|
|
196 |
}
|
|
197 |
copyThreadCount--;
|
|
198 |
}
|
|
199 |
}
|
|
200 |
|
|
201 |
}
|