Line 0
Link Here
|
|
|
1 |
/* |
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 |
* |
4 |
* Copyright 2013 Oracle and/or its affiliates. All rights reserved. |
5 |
* |
6 |
* Oracle and Java are registered trademarks of Oracle and/or its affiliates. |
7 |
* Other names may be trademarks of their respective owners. |
8 |
* |
9 |
* The contents of this file are subject to the terms of either the GNU |
10 |
* General Public License Version 2 only ("GPL") or the Common |
11 |
* Development and Distribution License("CDDL") (collectively, the |
12 |
* "License"). You may not use this file except in compliance with the |
13 |
* License. You can obtain a copy of the License at |
14 |
* http://www.netbeans.org/cddl-gplv2.html |
15 |
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the |
16 |
* specific language governing permissions and limitations under the |
17 |
* License. When distributing the software, include this License Header |
18 |
* Notice in each file and include the License file at |
19 |
* nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this |
20 |
* particular file as subject to the "Classpath" exception as provided |
21 |
* by Oracle in the GPL Version 2 section of the License file that |
22 |
* accompanied this code. If applicable, add the following below the |
23 |
* License Header, with the fields enclosed by brackets [] replaced by |
24 |
* your own identifying information: |
25 |
* "Portions Copyrighted [year] [name of copyright owner]" |
26 |
* |
27 |
* If you wish your version of this file to be governed by only the CDDL |
28 |
* or only the GPL Version 2, indicate your decision by adding |
29 |
* "[Contributor] elects to include this software in this distribution |
30 |
* under the [CDDL or GPL Version 2] license." If you do not indicate a |
31 |
* single choice of license, a recipient has the option to distribute |
32 |
* your version of this file under either the CDDL, the GPL Version 2 or |
33 |
* to extend the choice of license to its licensees as provided above. |
34 |
* However, if you add GPL Version 2 code and therefore, elected the GPL |
35 |
* Version 2 license, then the option applies only if the new code is |
36 |
* made subject to such option by the copyright holder. |
37 |
* |
38 |
* Contributor(s): |
39 |
* |
40 |
* Portions Copyrighted 2013 Sun Microsystems, Inc. |
41 |
*/ |
42 |
|
43 |
package org.netbeans.modules.java.api.common.project; |
44 |
|
45 |
import java.io.File; |
46 |
import java.io.IOException; |
47 |
import java.text.MessageFormat; |
48 |
import java.util.ArrayList; |
49 |
import java.util.Collections; |
50 |
import java.util.HashMap; |
51 |
import java.util.HashSet; |
52 |
import java.util.List; |
53 |
import java.util.Map; |
54 |
import java.util.Properties; |
55 |
import java.util.Set; |
56 |
import java.util.logging.Level; |
57 |
import java.util.logging.Logger; |
58 |
import org.apache.tools.ant.module.api.support.ActionUtils; |
59 |
import org.netbeans.api.annotations.common.NonNull; |
60 |
import org.netbeans.api.annotations.common.NullAllowed; |
61 |
import org.netbeans.api.project.FileOwnerQuery; |
62 |
import org.netbeans.api.project.Project; |
63 |
import org.netbeans.api.project.ProjectInformation; |
64 |
import org.netbeans.api.project.ProjectManager; |
65 |
import org.netbeans.api.project.ProjectUtils; |
66 |
import org.netbeans.modules.java.api.common.SourceRoots; |
67 |
import org.netbeans.modules.java.api.common.ant.UpdateHelper; |
68 |
import org.netbeans.modules.java.api.common.util.CommonProjectUtils; |
69 |
import org.netbeans.spi.project.CopyOperationImplementation; |
70 |
import org.netbeans.spi.project.DataFilesProviderImplementation; |
71 |
import org.netbeans.spi.project.DeleteOperationImplementation; |
72 |
import org.netbeans.spi.project.MoveOrRenameOperationImplementation; |
73 |
import org.netbeans.spi.project.support.ant.AntProjectHelper; |
74 |
import org.netbeans.spi.project.support.ant.EditableProperties; |
75 |
import org.netbeans.spi.project.support.ant.PropertyEvaluator; |
76 |
import org.netbeans.spi.project.support.ant.PropertyUtils; |
77 |
import org.netbeans.spi.project.support.ant.ReferenceHelper; |
78 |
import org.openide.filesystems.FileObject; |
79 |
import org.openide.filesystems.FileSystem; |
80 |
import org.openide.filesystems.FileUtil; |
81 |
import org.openide.util.Exceptions; |
82 |
import org.openide.util.NbBundle; |
83 |
import org.openide.util.Pair; |
84 |
import org.openide.util.Parameters; |
85 |
import org.openide.util.Utilities; |
86 |
|
87 |
/** |
88 |
* Support for default project operations for Ant based project. |
89 |
* @author Tomas Zezula |
90 |
* @author Jan Lahoda |
91 |
* @since 1.65 |
92 |
*/ |
93 |
public final class ProjectOperations { |
94 |
|
95 |
private static final Logger LOG = Logger.getLogger(ProjectOperations.class.getName()); |
96 |
private static final String TARGET_CLEAN = "clean"; |
97 |
|
98 |
private ProjectOperations() { |
99 |
throw new IllegalStateException("No instance allowed."); //NOI18N |
100 |
} |
101 |
|
102 |
/** |
103 |
* Creates a builder for creating {@link DeleteOperationImplementation}, |
104 |
* {@link MoveOrRenameOperationImplementation}, {@link CopyOperationImplementation} |
105 |
* implementation. |
106 |
* @param project the project to create project operations for |
107 |
* @param eval the project's {@link PropertyEvaluator} |
108 |
* @param helper the project's {@link UpdateHelper} |
109 |
* @param refHelper the project's {@link ReferenceHelper} |
110 |
* @param sources the project's source roots |
111 |
* @param tests the project's test roots |
112 |
* @return a builder for project operations |
113 |
*/ |
114 |
@NonNull |
115 |
public static ProjectOperationsBuilder createBuilder( |
116 |
@NonNull final Project project, |
117 |
@NonNull final PropertyEvaluator eval, |
118 |
@NonNull final UpdateHelper helper, |
119 |
@NonNull final ReferenceHelper refHelper, |
120 |
@NonNull final SourceRoots sources, |
121 |
@NonNull final SourceRoots tests) { |
122 |
return new ProjectOperationsBuilder( |
123 |
project, |
124 |
eval, |
125 |
helper, |
126 |
refHelper, |
127 |
sources, |
128 |
tests); |
129 |
} |
130 |
|
131 |
/** |
132 |
* Callback for project operations. |
133 |
* The callback is called before and after each project operation. |
134 |
* The callback is registered by {@link ProjectOperationsBuilder#setCallback} method. |
135 |
*/ |
136 |
public static interface Callback { |
137 |
/** |
138 |
* The type of project operation. |
139 |
*/ |
140 |
enum Operation { |
141 |
/** |
142 |
* Project delete. |
143 |
*/ |
144 |
DELETE, |
145 |
/** |
146 |
* Project copy. |
147 |
*/ |
148 |
COPY, |
149 |
/** |
150 |
* Project move. |
151 |
*/ |
152 |
MOVE, |
153 |
/** |
154 |
* Project rename. |
155 |
*/ |
156 |
RENAME; |
157 |
} |
158 |
|
159 |
/** |
160 |
* Called at the beginning of the project operation. |
161 |
* @param operation the operation being performed |
162 |
*/ |
163 |
void beforeOperation(@NonNull final Operation operation); |
164 |
|
165 |
/** |
166 |
* Called at the end of the project operation. |
167 |
* @param operation the operation being performed |
168 |
* @param newName the new project's name or null when not applicable, eg. delete |
169 |
* @param oldProject the old project or null when not applicable, eg. delete, move, rename |
170 |
*/ |
171 |
void afterOperation( |
172 |
@NonNull final Operation operation, |
173 |
@NullAllowed String newName, |
174 |
@NullAllowed Pair<File,Project> oldProject); |
175 |
} |
176 |
|
177 |
|
178 |
/** |
179 |
* The builder for projects operations. |
180 |
*/ |
181 |
public static final class ProjectOperationsBuilder { |
182 |
|
183 |
private final Project project; |
184 |
private final PropertyEvaluator eval; |
185 |
private final UpdateHelper helper; |
186 |
private final ReferenceHelper refHelper; |
187 |
private final SourceRoots sources; |
188 |
private final SourceRoots tests; |
189 |
private final List<String> additionalMetadataFiles; |
190 |
private final List<String> additionalDataFiles; |
191 |
private final List<String> cleanTargets; |
192 |
private final Set<String> privateProps; |
193 |
private final Map<String,Pair<String,Boolean>> updatedProps; |
194 |
private Callback callback; |
195 |
private String buildScriptProperty = ProjectProperties.BUILD_SCRIPT; |
196 |
|
197 |
private ProjectOperationsBuilder( |
198 |
@NonNull final Project project, |
199 |
@NonNull final PropertyEvaluator eval, |
200 |
@NonNull final UpdateHelper helper, |
201 |
@NonNull final ReferenceHelper refHelper, |
202 |
@NonNull final SourceRoots sources, |
203 |
@NonNull final SourceRoots tests) { |
204 |
Parameters.notNull("project", project); //NOI18N |
205 |
Parameters.notNull("eval", eval); //NOI18N |
206 |
Parameters.notNull("helper", helper); //NOI18N |
207 |
Parameters.notNull("refHelper", refHelper); //NOI18N |
208 |
Parameters.notNull("sources", sources); //NOI18N |
209 |
Parameters.notNull("tests", tests); //NOI18N |
210 |
this.project = project; |
211 |
this.eval = eval; |
212 |
this.helper = helper; |
213 |
this.refHelper = refHelper; |
214 |
this.sources = sources; |
215 |
this.tests = tests; |
216 |
this.additionalMetadataFiles = new ArrayList<>(); |
217 |
this.additionalDataFiles = new ArrayList<>(); |
218 |
this.cleanTargets = new ArrayList<>(); |
219 |
this.privateProps = new HashSet<>(); |
220 |
this.updatedProps = new HashMap<>(); |
221 |
} |
222 |
|
223 |
/** |
224 |
* Sets the name of property referencing the project build script. |
225 |
* @param propertyName the name of property holding the name of project's build script. |
226 |
* @return the {@link ProjectOperationsBuilder} |
227 |
*/ |
228 |
@NonNull |
229 |
public ProjectOperationsBuilder setBuildScriptProperty(@NonNull final String propertyName) { |
230 |
Parameters.notNull("propertyName", propertyName); //NOI18N |
231 |
this.buildScriptProperty = propertyName; |
232 |
return this; |
233 |
} |
234 |
|
235 |
/** |
236 |
* Adds build script targets to the list of clean targets. |
237 |
* All the added targets are executed before project operation, when no |
238 |
* clean target is set the default one "clean" is used. |
239 |
* @param cleanTargets the clean targets |
240 |
* @return the {@link ProjectOperationsBuilder} |
241 |
*/ |
242 |
@NonNull |
243 |
public ProjectOperationsBuilder addCleanTargets(@NonNull String... cleanTargets) { |
244 |
Parameters.notNull("cleanTargets", cleanTargets); //NOI18N |
245 |
Collections.addAll(this.cleanTargets, cleanTargets); |
246 |
return this; |
247 |
} |
248 |
|
249 |
/** |
250 |
* Adds additional files to the list of project metadata. |
251 |
* The "nbproject" and project build script are already included. |
252 |
* @param paths the metadata file paths, relative to project directory |
253 |
* @return the {@link ProjectOperationsBuilder} |
254 |
*/ |
255 |
@NonNull |
256 |
public ProjectOperationsBuilder addMetadataFiles(@NonNull final String... paths) { |
257 |
Parameters.notNull("paths", paths); //NOI18N |
258 |
Collections.addAll(additionalMetadataFiles, paths); |
259 |
return this; |
260 |
} |
261 |
|
262 |
/** |
263 |
* Adds additional files to the list of project data files. |
264 |
* The source roots, test roots and library definitions are already included. |
265 |
* @param paths the data file paths, relative to project directory |
266 |
* @return the {@link ProjectOperationsBuilder} |
267 |
*/ |
268 |
@NonNull |
269 |
public ProjectOperationsBuilder addDataFiles(@NonNull final String... paths) { |
270 |
Parameters.notNull("paths", paths); //NOI18N |
271 |
Collections.addAll(additionalDataFiles, paths); |
272 |
return this; |
273 |
} |
274 |
|
275 |
/** |
276 |
* Adds private properties which should be retained during copy, move or rename of project. |
277 |
* @param properties the private properties to be retained |
278 |
* @return the {@link ProjectOperationsBuilder} |
279 |
*/ |
280 |
@NonNull |
281 |
public ProjectOperationsBuilder addPreservedPrivateProperties(@NonNull final String... properties) { |
282 |
Parameters.notNull("properties", properties); //NOI18N |
283 |
Collections.addAll(privateProps, properties); |
284 |
return this; |
285 |
} |
286 |
|
287 |
/** |
288 |
* Adds a project property which should be updated by a new project name after rename or copy of project. |
289 |
* @param propertyName the project property name |
290 |
* @param propertyPattern the {@link MessageFormat} pattern of the property value, the "{0}" |
291 |
* is replaced by the new project name |
292 |
* @param antName when true the project name is converted into Ant friendly name before substitution |
293 |
* @return the {@link ProjectOperationsBuilder} |
294 |
*/ |
295 |
@NonNull |
296 |
public ProjectOperationsBuilder addUpdatedNameProperty( |
297 |
@NonNull final String propertyName, |
298 |
@NullAllowed String propertyPattern, |
299 |
final boolean antName) { |
300 |
Parameters.notNull("propertyName", propertyName); //NOI18N |
301 |
if (propertyPattern == null) { |
302 |
propertyPattern = "{0}"; //NOI18N |
303 |
} |
304 |
updatedProps.put(propertyName, Pair.<String,Boolean>of(propertyPattern, antName)); |
305 |
return this; |
306 |
} |
307 |
|
308 |
/** |
309 |
* Sets the project operation callback. |
310 |
* @param callback the callback |
311 |
* @return the {@link ProjectOperationsBuilder} |
312 |
*/ |
313 |
@NonNull |
314 |
public ProjectOperationsBuilder setCallback(@NonNull final Callback callback) { |
315 |
Parameters.notNull("callback", callback); //NOI18N |
316 |
this.callback = callback; |
317 |
return this; |
318 |
} |
319 |
|
320 |
/** |
321 |
* Creates a new configured {@link CopyOperationImplementation}, |
322 |
* {@link DeleteOperationImplementation} and {@link MoveOrRenameOperationImplementation} |
323 |
* instance. |
324 |
* @return the project operations implementation |
325 |
*/ |
326 |
@NonNull |
327 |
public DataFilesProviderImplementation build() { |
328 |
if (cleanTargets.isEmpty()) { |
329 |
cleanTargets.add(TARGET_CLEAN); |
330 |
} |
331 |
return new Operations( |
332 |
project, |
333 |
eval, |
334 |
helper, |
335 |
refHelper, |
336 |
sources, |
337 |
tests, |
338 |
buildScriptProperty, |
339 |
additionalMetadataFiles, |
340 |
additionalDataFiles, |
341 |
cleanTargets, |
342 |
privateProps, |
343 |
updatedProps, |
344 |
callback); |
345 |
} |
346 |
} |
347 |
|
348 |
|
349 |
private static class Operations implements DataFilesProviderImplementation, |
350 |
DeleteOperationImplementation, |
351 |
CopyOperationImplementation, MoveOrRenameOperationImplementation { |
352 |
|
353 |
private final Project project; |
354 |
private final PropertyEvaluator eval; |
355 |
private final UpdateHelper helper; |
356 |
private final ReferenceHelper refHelper; |
357 |
private final SourceRoots sources; |
358 |
private final SourceRoots tests; |
359 |
private final String buildScriptProperty; |
360 |
private final List<? extends String> additionalMetadataFiles; |
361 |
private final List<? extends String> additionalDataFiles; |
362 |
private final List<? extends String> cleanTargets; |
363 |
private final Set<? extends String> privateProps; |
364 |
private final Map<String,Pair<String,Boolean>> updatedProps; |
365 |
private final Callback callback; |
366 |
|
367 |
|
368 |
//RELY: Valid only on original project after the notifyMoving or notifyCopying was called |
369 |
private final Map<String,String> privatePropsToRestore = new HashMap<>(); |
370 |
//RELY: Valid only on original project after the notifyMoving or notifyCopying was called |
371 |
private String absolutesRelPath; |
372 |
//RELY: Valid only on original project after the notifyMoving or notifyCopying was called |
373 |
private String libraryPath; |
374 |
//RELY: Valid only on original project after the notifyMoving or notifyCopying was called |
375 |
private File libraryFile; |
376 |
//RELY: Valid only on original project after the notifyMoving or notifyCopying was called |
377 |
private boolean libraryWithinProject; |
378 |
//RELY: Valid only on original project after the notifyMoving or notifyCopying was called |
379 |
private FileSystem configs; |
380 |
|
381 |
Operations( |
382 |
@NonNull final Project project, |
383 |
@NonNull final PropertyEvaluator eval, |
384 |
@NonNull final UpdateHelper helper, |
385 |
@NonNull final ReferenceHelper refHelper, |
386 |
@NonNull final SourceRoots sources, |
387 |
@NonNull final SourceRoots tests, |
388 |
@NonNull final String buildScriptProperty, |
389 |
@NonNull final List<? extends String> additionalMetadataFiles, |
390 |
@NonNull final List<? extends String> additionalDataFiles, |
391 |
@NonNull final List<? extends String> cleanTargets, |
392 |
@NonNull final Set<? extends String> privateProps, |
393 |
@NonNull final Map<String,Pair<String,Boolean>> updatedProps, |
394 |
@NullAllowed final Callback callback) { |
395 |
Parameters.notNull("project", project); //NOI18N |
396 |
Parameters.notNull("eval", eval); //NOI18N |
397 |
Parameters.notNull("helper", helper); //NOI18N |
398 |
Parameters.notNull("refHelper", refHelper); //NOI18N |
399 |
Parameters.notNull("sources", sources); //NOI18N |
400 |
Parameters.notNull("tests", tests); //NOI18N |
401 |
Parameters.notNull("buildScriptProperty", buildScriptProperty); //NOI18N |
402 |
Parameters.notNull("additionalMetadataFiles", additionalMetadataFiles); //NOI18N |
403 |
Parameters.notNull("additionalDataFiles", additionalDataFiles); //NOI18N |
404 |
Parameters.notNull("cleanTargets", cleanTargets); //NOI18N |
405 |
Parameters.notNull("privateProps", privateProps); //NOI18N |
406 |
Parameters.notNull("updatedProps", updatedProps); //NOI18N |
407 |
this.project = project; |
408 |
this.eval = eval; |
409 |
this.helper = helper; |
410 |
this.refHelper = refHelper; |
411 |
this.sources = sources; |
412 |
this.tests = tests; |
413 |
this.buildScriptProperty = buildScriptProperty; |
414 |
this.additionalMetadataFiles = additionalMetadataFiles; |
415 |
this.additionalDataFiles = additionalDataFiles; |
416 |
this.cleanTargets = cleanTargets; |
417 |
this.privateProps = privateProps; |
418 |
this.updatedProps = updatedProps; |
419 |
this.callback = callback; |
420 |
} |
421 |
|
422 |
@Override |
423 |
public void notifyDeleting() throws IOException { |
424 |
before(Callback.Operation.DELETE); |
425 |
clean(); |
426 |
} |
427 |
|
428 |
@Override |
429 |
public void notifyDeleted() throws IOException { |
430 |
helper.getAntProjectHelper().notifyDeleted(); |
431 |
after(Callback.Operation.DELETE, null, null); |
432 |
} |
433 |
|
434 |
@Override |
435 |
public List<FileObject> getMetadataFiles() { |
436 |
final FileObject projectDirectory = project.getProjectDirectory(); |
437 |
final List<FileObject> files = new ArrayList<>(); |
438 |
addFile(projectDirectory, "nbproject", files); // NOI18N |
439 |
addFile(projectDirectory, CommonProjectUtils.getBuildXmlName(eval, buildScriptProperty), files); |
440 |
for (String amf : additionalMetadataFiles) { |
441 |
addFile(projectDirectory, amf, files); |
442 |
} |
443 |
return files; |
444 |
} |
445 |
|
446 |
@Override |
447 |
public List<FileObject> getDataFiles() { |
448 |
final FileObject projectDirectory = project.getProjectDirectory(); |
449 |
final List<FileObject> files = new ArrayList<>(); |
450 |
//add source & test roots |
451 |
Collections.addAll(files, sources.getRoots()); |
452 |
Collections.addAll(files, tests.getRoots()); |
453 |
// add libraries folder if it is within project: |
454 |
final AntProjectHelper aph = helper.getAntProjectHelper(); |
455 |
if (aph.getLibrariesLocation() != null) { |
456 |
File f = aph.resolveFile(aph.getLibrariesLocation()); |
457 |
if (f != null && f.exists()) { |
458 |
FileObject libFolder = FileUtil.toFileObject(f).getParent(); |
459 |
if (FileUtil.isParentOf(projectDirectory, libFolder)) { |
460 |
files.add(libFolder); |
461 |
} |
462 |
} |
463 |
} |
464 |
//add additional files |
465 |
for (String adf : additionalDataFiles) { |
466 |
addFile(projectDirectory, adf, files); |
467 |
} |
468 |
return files; |
469 |
} |
470 |
|
471 |
@Override |
472 |
public void notifyCopying() throws IOException { |
473 |
before(Callback.Operation.COPY); |
474 |
rememberLibraryLocation(); |
475 |
readPrivateProperties(); |
476 |
rememberConfigurations(); |
477 |
} |
478 |
|
479 |
@Override |
480 |
public void notifyCopied(Project original, File originalPath, String nueName) throws IOException { |
481 |
if (original == null) { |
482 |
//do nothing for the original project. |
483 |
return ; |
484 |
} |
485 |
final Operations origOperations = original.getLookup().lookup(Operations.class); |
486 |
fixLibraryLocation(origOperations); |
487 |
fixPrivateProperties(origOperations); |
488 |
updateProjectProperties(nueName); |
489 |
refHelper.fixReferences(originalPath); |
490 |
restoreConfigurations(origOperations); |
491 |
after(Callback.Operation.COPY, nueName, null); |
492 |
} |
493 |
|
494 |
@Override |
495 |
public void notifyRenaming() throws IOException { |
496 |
if (!this.helper.requestUpdate()) { |
497 |
throw new IOException(NbBundle.getMessage( |
498 |
ProjectOperations.class, |
499 |
"MSG_OldProjectMetadata")); |
500 |
} |
501 |
before(Callback.Operation.RENAME); |
502 |
clean(); |
503 |
} |
504 |
|
505 |
@Override |
506 |
public void notifyRenamed(String nueName) throws IOException { |
507 |
updateProjectProperties(nueName); |
508 |
after(Callback.Operation.RENAME, nueName, null); |
509 |
} |
510 |
|
511 |
@Override |
512 |
public void notifyMoving() throws IOException { |
513 |
if (!this.helper.requestUpdate()) { |
514 |
throw new IOException (NbBundle.getMessage( |
515 |
ProjectOperations.class, |
516 |
"MSG_OldProjectMetadata")); |
517 |
} |
518 |
before(Callback.Operation.MOVE); |
519 |
rememberLibraryLocation(); |
520 |
readPrivateProperties (); |
521 |
rememberConfigurations(); |
522 |
clean(); |
523 |
} |
524 |
|
525 |
@Override |
526 |
public void notifyMoved(Project original, File originalPath, String nueName) throws IOException { |
527 |
if (original == null) { |
528 |
helper.getAntProjectHelper().notifyDeleted(); |
529 |
return ; |
530 |
} |
531 |
final Operations origOperations = original.getLookup().lookup(Operations.class); |
532 |
fixLibraryLocation(origOperations); |
533 |
fixPrivateProperties (origOperations); |
534 |
updateProjectProperties(nueName); |
535 |
refHelper.fixReferences(originalPath); |
536 |
restoreConfigurations(origOperations); |
537 |
after(Callback.Operation.MOVE, nueName, Pair.<File, Project>of(originalPath,original)); |
538 |
} |
539 |
|
540 |
private void clean() throws IOException { |
541 |
final Properties p = new Properties(); |
542 |
final String buildXmlName = CommonProjectUtils.getBuildXmlName(eval, buildScriptProperty); |
543 |
final FileObject buildXML = project.getProjectDirectory().getFileObject(buildXmlName); |
544 |
if (buildXML != null) { |
545 |
ActionUtils.runTarget( |
546 |
buildXML, |
547 |
cleanTargets.toArray(new String[cleanTargets.size()]), |
548 |
p).waitFinished(); |
549 |
} else { |
550 |
LOG.log( |
551 |
Level.INFO, |
552 |
"Not cleaning the project: {0}, the build file: {1} does not exist.", //NOI18N |
553 |
new Object[] { |
554 |
ProjectUtils.getInformation(project).getDisplayName(), |
555 |
buildXmlName |
556 |
}); |
557 |
} |
558 |
} |
559 |
|
560 |
private void rememberLibraryLocation() { |
561 |
libraryWithinProject = false; |
562 |
absolutesRelPath = null; |
563 |
libraryPath = helper.getAntProjectHelper().getLibrariesLocation(); |
564 |
if (libraryPath != null) { |
565 |
File prjRoot = FileUtil.toFile(project.getProjectDirectory()); |
566 |
libraryFile = PropertyUtils.resolveFile(prjRoot, libraryPath); |
567 |
if (FileOwnerQuery.getOwner(Utilities.toURI(libraryFile)) == project && |
568 |
libraryFile.getAbsolutePath().startsWith(prjRoot.getAbsolutePath())) { |
569 |
//do not update the relative path if within the project.. |
570 |
libraryWithinProject = true; |
571 |
FileObject fo = FileUtil.toFileObject(libraryFile); |
572 |
if (new File(libraryPath).isAbsolute() && fo != null) { |
573 |
// if absolte path within project, it will get moved/copied.. |
574 |
absolutesRelPath = FileUtil.getRelativePath(project.getProjectDirectory(), fo); |
575 |
} |
576 |
} |
577 |
} |
578 |
} |
579 |
|
580 |
private void readPrivateProperties () { |
581 |
ProjectManager.mutex().readAccess(new Runnable() { |
582 |
public void run () { |
583 |
privatePropsToRestore.clear(); |
584 |
for (String privateProp : privateProps) { |
585 |
backUpPrivateProp(privateProp); |
586 |
} |
587 |
} |
588 |
}); |
589 |
} |
590 |
//where |
591 |
/** |
592 |
* Threading: Has to be called under project mutex |
593 |
*/ |
594 |
private void backUpPrivateProp(String propName) { |
595 |
assert ProjectManager.mutex().isReadAccess() || ProjectManager.mutex().isWriteAccess(); |
596 |
final String tmp = helper.getProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH).getProperty(propName); |
597 |
if (tmp != null) { |
598 |
privatePropsToRestore.put(propName, tmp); |
599 |
} |
600 |
} |
601 |
|
602 |
private void rememberConfigurations () { |
603 |
FileObject fo = project.getProjectDirectory().getFileObject(ProjectConfigurations.CONFIG_PROPS_PATH); |
604 |
if (fo != null) { |
605 |
//Has configurations |
606 |
try { |
607 |
FileSystem fs = FileUtil.createMemoryFileSystem(); |
608 |
FileUtil.copyFile(fo, fs.getRoot(),fo.getName()); |
609 |
fo = project.getProjectDirectory().getFileObject("nbproject/private/configs"); //NOI18N |
610 |
if (fo != null && fo.isFolder()) { |
611 |
FileObject cfgs = fs.getRoot().createFolder("configs"); //NOI18N |
612 |
for (FileObject child : fo.getChildren()) { |
613 |
FileUtil.copyFile(child, cfgs, child.getName()); |
614 |
} |
615 |
} |
616 |
configs = fs; |
617 |
} catch (IOException ioe) { |
618 |
Exceptions.printStackTrace(ioe); |
619 |
} |
620 |
} |
621 |
} |
622 |
|
623 |
private void fixLibraryLocation(Operations original) throws IllegalArgumentException { |
624 |
String libPath = original.libraryPath; |
625 |
if (libPath != null) { |
626 |
if (!new File(libPath).isAbsolute()) { |
627 |
//relative path to libraries |
628 |
if (!original.libraryWithinProject) { |
629 |
File file = original.libraryFile; |
630 |
if (file == null) { |
631 |
// could happen in some rare cases, but in that case the original project was already broken, don't fix. |
632 |
return; |
633 |
} |
634 |
String relativized = PropertyUtils.relativizeFile(FileUtil.toFile(project.getProjectDirectory()), file); |
635 |
if (relativized != null) { |
636 |
helper.getAntProjectHelper().setLibrariesLocation(relativized); |
637 |
} else { |
638 |
//cannot relativize, use absolute path |
639 |
helper.getAntProjectHelper().setLibrariesLocation(file.getAbsolutePath()); |
640 |
} |
641 |
} else { |
642 |
//got copied over to new location.. the relative path is the same.. |
643 |
} |
644 |
} else { |
645 |
|
646 |
//absolute path to libraries.. |
647 |
if (original.libraryWithinProject) { |
648 |
if (original.absolutesRelPath != null) { |
649 |
helper.getAntProjectHelper().setLibrariesLocation(PropertyUtils.resolveFile(FileUtil.toFile(project.getProjectDirectory()), original.absolutesRelPath).getAbsolutePath()); |
650 |
} |
651 |
} else { |
652 |
// absolute path to an external folder stays the same. |
653 |
} |
654 |
} |
655 |
} |
656 |
} |
657 |
|
658 |
private void fixPrivateProperties (final Operations original) { |
659 |
if (original != null && !original.privatePropsToRestore.isEmpty()) { |
660 |
ProjectManager.mutex().writeAccess(new Runnable () { |
661 |
public void run () { |
662 |
final EditableProperties ep = helper.getProperties (AntProjectHelper.PRIVATE_PROPERTIES_PATH); |
663 |
for (Map.Entry<String,String> entry : original.privatePropsToRestore.entrySet()) { |
664 |
ep.put(entry.getKey(), entry.getValue()); |
665 |
} |
666 |
helper.putProperties(AntProjectHelper.PRIVATE_PROPERTIES_PATH, ep); |
667 |
} |
668 |
}); |
669 |
} |
670 |
} |
671 |
|
672 |
private void restoreConfigurations (final Operations original) { |
673 |
final FileSystem fs = original.configs; |
674 |
original.configs = null; |
675 |
if (fs != null) { |
676 |
try { |
677 |
FileObject fo = fs.getRoot().getFileObject("config.properties"); //NOI18N |
678 |
if (fo != null) { |
679 |
FileObject privateFolder = FileUtil.createFolder(project.getProjectDirectory(), "nbproject/private"); //NOI18N |
680 |
if (privateFolder != null) { |
681 |
// #131857: SyncFailedException : check for file existence before FileUtil.copyFile |
682 |
FileObject oldFile = privateFolder.getFileObject(fo.getName(), fo.getExt()); |
683 |
if (oldFile != null) { |
684 |
//Probably delete outside of IDE + move. First try to repair FS cache |
685 |
privateFolder.refresh(); |
686 |
oldFile = privateFolder.getFileObject(fo.getName(), fo.getExt()); |
687 |
if (oldFile != null) { |
688 |
//The file still exists, delete it. |
689 |
oldFile.delete(); |
690 |
} |
691 |
} |
692 |
|
693 |
FileUtil.copyFile(fo, privateFolder, fo.getName()); |
694 |
} |
695 |
} |
696 |
fo = fs.getRoot().getFileObject("configs"); //NOI18N |
697 |
if (fo != null) { |
698 |
FileObject configsFolder = FileUtil.createFolder(project.getProjectDirectory(), "nbproject/private/configs"); //NOI18N |
699 |
if (configsFolder != null) { |
700 |
for (FileObject child : fo.getChildren()) { |
701 |
FileUtil.copyFile(child, configsFolder, child.getName()); |
702 |
} |
703 |
} |
704 |
} |
705 |
} catch (IOException ioe) { |
706 |
Exceptions.printStackTrace(ioe); |
707 |
} |
708 |
} |
709 |
} |
710 |
|
711 |
private void updateProjectProperties(@NonNull final String newName) { |
712 |
if (!updatedProps.isEmpty()) { |
713 |
final ProjectInformation pi = ProjectUtils.getInformation(project); |
714 |
final String oldName = pi.getDisplayName(); |
715 |
final EditableProperties ep = helper.getProperties (AntProjectHelper.PROJECT_PROPERTIES_PATH); |
716 |
for (Map.Entry<String,Pair<String,Boolean>> e : updatedProps.entrySet()) { |
717 |
final String propName = e.getKey(); |
718 |
final String format = e.getValue().first(); |
719 |
final boolean antName = e.getValue().second(); |
720 |
final String oldProp = MessageFormat.format( |
721 |
format, |
722 |
antName ? |
723 |
PropertyUtils.getUsablePropertyName(oldName) : |
724 |
oldName); |
725 |
final String propValue = ep.getProperty(propName); |
726 |
if (oldProp.equals (propValue)) { |
727 |
final String newProp = MessageFormat.format( |
728 |
format, |
729 |
antName ? |
730 |
PropertyUtils.getUsablePropertyName(newName) : |
731 |
newName); |
732 |
ep.put (propName, newProp); |
733 |
} |
734 |
} |
735 |
helper.putProperties (AntProjectHelper.PROJECT_PROPERTIES_PATH,ep); |
736 |
} |
737 |
} |
738 |
|
739 |
private void before(@NonNull final Callback.Operation operation) { |
740 |
if (callback != null) { |
741 |
callback.beforeOperation(operation); |
742 |
} |
743 |
} |
744 |
|
745 |
private void after( |
746 |
@NonNull final Callback.Operation operation, |
747 |
@NullAllowed final String newName, |
748 |
@NullAllowed final Pair<File,Project> oldProject) { |
749 |
if (callback != null) { |
750 |
callback.afterOperation(operation, newName, oldProject); |
751 |
} |
752 |
} |
753 |
|
754 |
private static void addFile(FileObject projectDirectory, String fileName, List<FileObject> result) { |
755 |
final FileObject file = projectDirectory.getFileObject(fileName); |
756 |
if (file != null) { |
757 |
result.add(file); |
758 |
} |
759 |
} |
760 |
|
761 |
} |
762 |
|
763 |
} |