PageRenderTime 58ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/projects/netbeans-7.3/cnd.makeproject/src/org/netbeans/modules/cnd/makeproject/api/configurations/Folder.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 1307 lines | 1089 code | 104 blank | 114 comment | 305 complexity | 8423376c7bd8c45d371df2b6e7987eb9 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2011 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. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. package org.netbeans.modules.cnd.makeproject.api.configurations;
  45. import java.io.File;
  46. import java.io.IOException;
  47. import java.util.ArrayList;
  48. import java.util.HashMap;
  49. import java.util.HashSet;
  50. import java.util.Iterator;
  51. import java.util.LinkedHashSet;
  52. import java.util.List;
  53. import java.util.Set;
  54. import java.util.concurrent.locks.ReentrantReadWriteLock;
  55. import java.util.logging.Level;
  56. import java.util.logging.Logger;
  57. import javax.swing.event.ChangeEvent;
  58. import javax.swing.event.ChangeListener;
  59. import org.netbeans.api.project.Project;
  60. import org.netbeans.api.queries.VisibilityQuery;
  61. import org.netbeans.modules.cnd.api.project.NativeFileItem;
  62. import org.netbeans.modules.cnd.api.project.NativeFileItemSet;
  63. import org.netbeans.modules.cnd.api.remote.RemoteFileUtil;
  64. import org.netbeans.modules.cnd.api.utils.CndFileVisibilityQuery;
  65. import org.netbeans.modules.cnd.makeproject.MakeProjectFileProviderFactory;
  66. import org.netbeans.modules.cnd.makeproject.ui.MakeLogicalViewProvider;
  67. import org.netbeans.modules.cnd.utils.CndPathUtilitities;
  68. import org.netbeans.modules.cnd.utils.CndUtils;
  69. import org.netbeans.modules.cnd.utils.FileFilterFactory;
  70. import org.netbeans.modules.cnd.utils.cache.CndFileUtils;
  71. import org.netbeans.modules.remote.spi.FileSystemProvider;
  72. import org.openide.filesystems.FileAttributeEvent;
  73. import org.openide.filesystems.FileChangeListener;
  74. import org.openide.filesystems.FileEvent;
  75. import org.openide.filesystems.FileObject;
  76. import org.openide.filesystems.FileRenameEvent;
  77. import org.openide.filesystems.FileSystem;
  78. import org.openide.loaders.DataObject;
  79. import org.openide.util.CharSequences;
  80. import org.openide.util.NbBundle;
  81. import org.openide.util.WeakSet;
  82. public class Folder implements FileChangeListener, ChangeListener {
  83. public enum Kind {
  84. ROOT,
  85. SOURCE_LOGICAL_FOLDER,
  86. SOURCE_DISK_FOLDER,
  87. IMPORTANT_FILES_FOLDER,
  88. TEST_LOGICAL_FOLDER,
  89. TEST
  90. };
  91. public static final String DEFAULT_FOLDER_NAME = "f"; // NOI18N
  92. public static final String DEFAULT_FOLDER_DISPLAY_NAME = getString("NewFolderName");
  93. public static final String DEFAULT_TEST_FOLDER_DISPLAY_NAME = getString("NewTestFolderName");
  94. private final MakeConfigurationDescriptor configurationDescriptor;
  95. private volatile boolean listenerAttached;
  96. private final String name;
  97. private String displayName;
  98. private final Folder parent;
  99. private final ArrayList<Object> items; // Folder or Item
  100. private final ReentrantReadWriteLock itemsLock = new ReentrantReadWriteLock();
  101. private HashMap<String, HashMap<Configuration, DeletedConfiguration>> deletedItems;
  102. private final Set<ChangeListener> changeListenerList = new WeakSet<ChangeListener>(1);
  103. private final boolean projectFiles;
  104. private String id = null;
  105. private String root;
  106. private volatile boolean removed;
  107. private final static Logger log = Logger.getLogger("makeproject.folder"); // NOI18N
  108. private static boolean checkedLogging = checkLogging();
  109. private final Kind kind;
  110. public Folder(MakeConfigurationDescriptor configurationDescriptor, Folder parent, String name, String displayName, boolean projectFiles, Kind kind) {
  111. this.configurationDescriptor = configurationDescriptor;
  112. this.parent = parent;
  113. this.name = name;
  114. this.displayName = displayName;
  115. this.projectFiles = projectFiles;
  116. if (kind == null) {
  117. if (parent.isDiskFolder()) {
  118. kind = Kind.SOURCE_DISK_FOLDER;
  119. } else if (parent.isTestLogicalFolder()) {
  120. kind = Kind.TEST_LOGICAL_FOLDER;
  121. } else {
  122. kind = Kind.SOURCE_LOGICAL_FOLDER;
  123. }
  124. }
  125. this.kind = kind;
  126. if (this.kind != Kind.SOURCE_DISK_FOLDER) {
  127. if (log.isLoggable(Level.FINE)) {
  128. log.log(Level.FINE, "------------Non Physical Folder {0}", getPath()); // NOI18N
  129. }
  130. }
  131. this.items = new ArrayList<Object>();
  132. }
  133. /**
  134. * For internal purpose. Method reduce folder items size
  135. */
  136. public void pack() {
  137. itemsLock.writeLock().lock();
  138. try {
  139. items.trimToSize();
  140. } finally {
  141. itemsLock.writeLock().unlock();
  142. }
  143. }
  144. public Kind getKind() {
  145. return kind;
  146. }
  147. public void setRoot(String root) {
  148. this.root = root;
  149. }
  150. public String getRoot() {
  151. return root;
  152. }
  153. public void refreshDiskFolderAfterRestoringOldScheme() {
  154. if (!UNCHANGED_PROJECT_MODE) {
  155. refreshDiskFolder(new HashSet<String>(), true);
  156. }
  157. }
  158. public void refreshDiskFolder() {
  159. if (!UNCHANGED_PROJECT_MODE) {
  160. refreshDiskFolder(new HashSet<String>(), false);
  161. }
  162. }
  163. private void refreshDiskFolder(Set<String> antiLoop, boolean useOldSchemeBehavior) {
  164. if (log.isLoggable(Level.FINEST)) {
  165. log.log(Level.FINEST, "----------refreshDiskFolder {0}", getPath()); // NOI18N
  166. }
  167. String rootPath = getRootPath();
  168. FileObject folderFile = getThisFolder();
  169. // Folders to be removed
  170. if (folderFile == null || !folderFile.isValid()
  171. || !folderFile.isFolder()
  172. || !VisibilityQuery.getDefault().isVisible(folderFile)
  173. || getConfigurationDescriptor().getFolderVisibilityQuery().isIgnored(folderFile)) {
  174. // Remove it plus all subfolders and items from project
  175. if (log.isLoggable(Level.FINE)) {
  176. log.log(Level.FINE, "------------removing folder {0} in {1}", new Object[]{getPath(), getParent().getPath()}); // NOI18N
  177. }
  178. getParent().removeFolderImpl(this, true, false);
  179. return;
  180. }
  181. // Items to be removed
  182. for (Item item : getItemsAsArray()) {
  183. FileObject fo = item.getFileObject();
  184. if (fo == null) {
  185. log.log(Level.INFO, "Null file object for {0}", item.getAbsolutePath()); //NOI18N
  186. continue;
  187. }
  188. if (!fo.isValid()
  189. || !fo.isData()
  190. || !VisibilityQuery.getDefault().isVisible(fo)
  191. || !CndFileVisibilityQuery.getDefault().isVisible(fo)) {
  192. if (log.isLoggable(Level.FINE)) {
  193. log.log(Level.FINE, "------------removing item {0} in {1} [{2}]", new Object[]{item.getPath(), getPath(), fo}); // NOI18N
  194. }
  195. removeItemImpl(item, true, false);
  196. }
  197. }
  198. try {
  199. String canonicalPath = RemoteFileUtil.getCanonicalPath(folderFile);
  200. if (antiLoop.contains(canonicalPath)) {
  201. // It seems we have recursive link
  202. log.log(Level.INFO, "Ignore recursive link {0} in folder {1}", new Object[]{canonicalPath, folderFile.getPath()});
  203. return;
  204. }
  205. antiLoop.add(canonicalPath);
  206. } catch (IOException ex) {
  207. log.log(Level.INFO, ex.getMessage(), ex);
  208. return;
  209. }
  210. // files/folders to be added
  211. FileObject files[] = folderFile.getChildren();
  212. if (files == null) {
  213. return;
  214. }
  215. List<FileObject> fileList = new ArrayList<FileObject>();
  216. ArrayList<CharSequence> otherFileList = new ArrayList<CharSequence>();
  217. for (int i = 0; i < files.length; i++) {
  218. if (!VisibilityQuery.getDefault().isVisible(files[i])) {
  219. continue;
  220. }
  221. if (files[i].isFolder()) {
  222. if (getConfigurationDescriptor().getFolderVisibilityQuery().isIgnored(files[i])) {
  223. continue;
  224. }
  225. } else {
  226. if (!CndFileVisibilityQuery.getDefault().isVisible(files[i])) {
  227. otherFileList.add(CharSequences.create(files[i].getNameExt()));
  228. continue;
  229. }
  230. }
  231. fileList.add(files[i]);
  232. }
  233. if (otherFileList.size() > 0) {
  234. otherFileList.trimToSize();
  235. }
  236. MakeProjectFileProviderFactory.updateSearchBase(configurationDescriptor.getProject(), this, otherFileList);
  237. for (FileObject file : fileList) {
  238. if (file.isFolder()) {
  239. try {
  240. String canonicalPath = RemoteFileUtil.getCanonicalPath(file);
  241. if (antiLoop.contains(canonicalPath)) {
  242. // It seems we have recursive link
  243. log.log(Level.INFO, "Ignore recursive link {0} in folder {1}", new Object[]{canonicalPath, folderFile.getPath()});
  244. continue;
  245. }
  246. } catch (IOException ex) {
  247. log.log(Level.INFO, ex.getMessage(), ex);
  248. continue;
  249. }
  250. Folder existingFolder = findFolderByName(file.getNameExt());
  251. if (existingFolder == null) {
  252. if (log.isLoggable(Level.FINE)) {
  253. log.log(Level.FINE, "------------adding folder {0} in {1}", new Object[]{file.getPath(), getPath()}); // NOI18N
  254. }
  255. getConfigurationDescriptor().addFilesFromRefreshedDir(this, file, true, true, null, useOldSchemeBehavior);
  256. } else {
  257. existingFolder.markRemoved(false);
  258. }
  259. } else {
  260. String path = rootPath + '/' + file.getNameExt();
  261. if (path.startsWith("./")) { // NOI18N
  262. path = path.substring(2);
  263. }
  264. if (findItemByPath(path) == null) {
  265. if (log.isLoggable(Level.FINE)) {
  266. log.log(Level.FINE, "------------adding {2} item {0} in {1}", new Object[]{file.getPath(), getPath(), useOldSchemeBehavior ? "included" : "excluded"}); // NOI18N
  267. }
  268. addItemFromRefreshDir(Item.createInFileSystem(configurationDescriptor.getBaseDirFileSystem(), path), true, true, useOldSchemeBehavior);
  269. }
  270. }
  271. }
  272. // Repeast for all sub folders
  273. List<Folder> subFolders = getFolders();
  274. for (Folder f : subFolders) {
  275. f.refreshDiskFolder(antiLoop, useOldSchemeBehavior);
  276. }
  277. }
  278. public String getDiskName() {
  279. String diskName = getAbsolutePath();
  280. if (diskName != null) {
  281. return CndPathUtilitities.getBaseName(diskName);
  282. }
  283. return null;
  284. }
  285. private static final boolean UNCHANGED_PROJECT_MODE = Boolean.getBoolean("cnd.unchanged.project"); // NOI18N
  286. public void attachListeners() {
  287. if (configurationDescriptor == null) {
  288. CndUtils.assertTrueInConsole(false, "null configurationDescriptor for " + this.name);
  289. return;
  290. }
  291. String rootPath = getRootPath();
  292. if (listenerAttached) {
  293. CndUtils.assertTrueInConsole(false, "listeners already attached to " + rootPath);
  294. return;
  295. }
  296. FileSystem fileSystem = configurationDescriptor.getBaseDirFileSystem();
  297. String absRootPath = CndPathUtilitities.toAbsolutePath(configurationDescriptor.getBaseDirFileObject(), rootPath);
  298. if (CndFileUtils.isLocalFileSystem(fileSystem)) {
  299. // TODO: Remove this check: it was keeped just because of code freeze
  300. File folderFile = new File(absRootPath);
  301. if (!folderFile.exists() || !folderFile.isDirectory()) {
  302. return;
  303. }
  304. }
  305. if (isDiskFolder() && getRoot() != null) {
  306. VisibilityQuery.getDefault().addChangeListener(this);
  307. CndFileVisibilityQuery.getDefault().addChangeListener(this);
  308. getConfigurationDescriptor().getFolderVisibilityQuery().addChangeListener(this);
  309. if (log.isLoggable(Level.FINER)) {
  310. log.log(Level.FINER, "-----------attachFilterListener {0}:{1} ({2})", new Object[] {getPath(), absRootPath, System.identityHashCode(this)}); // NOI18N
  311. }
  312. try {
  313. if (!UNCHANGED_PROJECT_MODE) {
  314. FileSystemProvider.addRecursiveListener(this, fileSystem, absRootPath);
  315. }
  316. listenerAttached = true;
  317. if (log.isLoggable(Level.FINER)) {
  318. log.log(Level.FINER, "-----------attachFileChangeListener {0}:{1} ({2})", new Object[] {getPath(), absRootPath, System.identityHashCode(this)}); // NOI18N
  319. }
  320. } catch (IllegalArgumentException iae) {
  321. // Can happen if trying to attach twice...
  322. if (log.isLoggable(Level.FINER)) {
  323. log.log(Level.FINER, "-----------attachFileChangeListener duplicate error {0}:{1} ({2})", new Object[] {getPath(), absRootPath, System.identityHashCode(this)}); // NOI18N
  324. }
  325. }
  326. return;
  327. }
  328. // Repeast for all sub folders
  329. List<Folder> subFolders = getFolders();
  330. for (Folder f : subFolders) {
  331. f.attachListeners();
  332. }
  333. }
  334. public void detachListener() {
  335. if (!listenerAttached) {
  336. if (isDiskFolder() && getRoot() != null && log.isLoggable(Level.FINER)) {
  337. log.log(Level.FINER, "----------- skip detaching FileChangeListener {0}: ({1})", new Object[]{getPath(), System.identityHashCode(this)}); // NOI18N
  338. }
  339. return;
  340. }
  341. if (configurationDescriptor == null) {
  342. CndUtils.assertTrueInConsole(false, "null configurationDescriptor for " + this.name);
  343. return;
  344. }
  345. String rootPath = getRootPath();
  346. FileSystem fileSystem = configurationDescriptor.getBaseDirFileSystem();
  347. String absRootPath = CndPathUtilitities.toAbsolutePath(configurationDescriptor.getBaseDirFileObject(), rootPath);
  348. if (log.isLoggable(Level.FINER)) {
  349. log.log(Level.FINER, "-----------detachFileChangeListener {0}:{1} ({2})", new Object[]{getPath(), absRootPath, System.identityHashCode(this)}); // NOI18N
  350. }
  351. try {
  352. if (!UNCHANGED_PROJECT_MODE) {
  353. FileSystemProvider.removeRecursiveListener(this, fileSystem, absRootPath);
  354. }
  355. } catch(IllegalArgumentException iae) {
  356. // Can happen if trying to detach twice or folder was GCed...
  357. log.log(Level.INFO, "-----------detachFileChangeListener not-attached error {0}:{1} ({2})", new Object[] {getPath(), absRootPath, System.identityHashCode(this)}); // NOI18N
  358. } finally {
  359. listenerAttached = false;
  360. }
  361. if (isDiskFolder() && getRoot() != null) {
  362. VisibilityQuery.getDefault().removeChangeListener(this);
  363. CndFileVisibilityQuery.getDefault().removeChangeListener(this);
  364. getConfigurationDescriptor().getFolderVisibilityQuery().removeChangeListener(this);
  365. if (log.isLoggable(Level.FINER)) {
  366. log.log(Level.FINER, "-----------detachFilterListener {0}:{1} ({2})", new Object[]{getPath(), absRootPath, System.identityHashCode(this)}); // NOI18N
  367. }
  368. }
  369. }
  370. public Folder getParent() {
  371. return parent;
  372. }
  373. public Project getProject() {
  374. return getConfigurationDescriptor().getProject();
  375. }
  376. public String getName() {
  377. return name;
  378. }
  379. private String getSortName() {
  380. return displayName;
  381. }
  382. public String getPath() {
  383. StringBuilder builder2 = new StringBuilder(32);
  384. reversePath(this, builder2, false);
  385. return builder2.toString();
  386. }
  387. public String getRootPath() {
  388. StringBuilder builder2 = new StringBuilder(32);
  389. reversePath(this, builder2, true);
  390. String path = builder2.toString();
  391. return path;
  392. }
  393. private void reversePath(Folder folder, StringBuilder builder, boolean fromRoot) {
  394. Folder aParent = folder.getParent();
  395. if (aParent != null && aParent.getParent() != null) {
  396. reversePath(aParent, builder, fromRoot);
  397. builder.append('/'); // NOI18N
  398. }
  399. if (fromRoot && folder.isDiskFolder() && folder.getRoot() != null) {
  400. builder.append(folder.getRoot());
  401. } else {
  402. builder.append(folder.getName());
  403. }
  404. }
  405. public String getDisplayName() {
  406. // This is dirty fix for #201152. Do not see other way to do this,
  407. // as Folders instances are always updated and it is impossible
  408. // to provide them with the right name.
  409. if (isDiskFolder() && getRoot() != null) {
  410. String diskName = getDiskName();
  411. if (diskName != null) {
  412. return diskName;
  413. }
  414. }
  415. return displayName;
  416. }
  417. public final boolean isRemoved() {
  418. return removed;
  419. }
  420. public final void markRemoved(boolean broken) {
  421. this.removed = broken;
  422. }
  423. public void setDisplayName(String displayName) {
  424. this.displayName = displayName;
  425. configurationDescriptor.setModified();
  426. getParent().reInsertElement(this);
  427. }
  428. public MakeConfigurationDescriptor getConfigurationDescriptor() {
  429. return configurationDescriptor;
  430. }
  431. public boolean isProjectFiles() {
  432. return projectFiles;
  433. }
  434. public boolean isDiskFolder() {
  435. return getKind() == Kind.SOURCE_DISK_FOLDER;
  436. }
  437. public boolean isTestLogicalFolder() {
  438. return getKind() == Kind.TEST_LOGICAL_FOLDER;
  439. }
  440. public boolean isTestRootFolder() {
  441. return isTestLogicalFolder() && getName().equals(MakeConfigurationDescriptor.TEST_FILES_FOLDER);
  442. }
  443. public boolean isTest() {
  444. return getKind() == Kind.TEST;
  445. }
  446. public List<Object> getElements() {
  447. itemsLock.readLock().lock();
  448. try {
  449. return new ArrayList<Object>(items);
  450. } finally {
  451. itemsLock.readLock().unlock();
  452. }
  453. }
  454. private void reInsertElement(Object element) {
  455. itemsLock.writeLock().lock();
  456. try {
  457. int index = items.indexOf(element);
  458. if (index < 0) {
  459. return;
  460. }
  461. items.remove(element);
  462. } finally {
  463. itemsLock.writeLock().unlock();
  464. }
  465. if (element instanceof Folder) {
  466. Folder inserted = insertFolderElement((Folder) element);
  467. inserted.markRemoved(false);
  468. } else if (element instanceof Item) {
  469. insertItemElement((Item) element);
  470. } else {
  471. assert false;
  472. }
  473. fireChangeEvent();
  474. }
  475. private Folder insertFolderElement(Folder element) {
  476. itemsLock.writeLock().lock();
  477. try {
  478. element.markRemoved(false);
  479. if (!element.isProjectFiles()) {
  480. // Insert last
  481. items.add(element);
  482. return element;
  483. }
  484. String name1 = element.getSortName();
  485. int indexAt = items.size() - 1;
  486. while (indexAt >= 0) {
  487. Object o = items.get(indexAt);
  488. if (!(o instanceof Folder)) {
  489. indexAt--;
  490. continue;
  491. }
  492. Folder f = (Folder) o;
  493. if (!f.isProjectFiles()) {
  494. indexAt--;
  495. continue;
  496. }
  497. String name2 = f.getSortName();
  498. int compareRes = name1.compareToIgnoreCase(name2);
  499. if (compareRes == 0) {
  500. if (isSameFolder(f, element)) {
  501. // already in list
  502. f.markRemoved(false);
  503. return f;
  504. }
  505. }
  506. if (compareRes < 0) {
  507. indexAt--;
  508. continue;
  509. }
  510. break;
  511. }
  512. items.add(indexAt + 1, element);
  513. return element;
  514. } finally {
  515. itemsLock.writeLock().unlock();
  516. }
  517. }
  518. private boolean isSameFolder(Folder f, Folder element) {
  519. assert f != null;
  520. assert element != null;
  521. return f.getKind() == element.getKind() && f.getRootPath().equals(element.getRootPath());
  522. }
  523. public static Item insertItemElementInList(ArrayList<Object> list, Item element) {
  524. String name1 = (element).getSortName();
  525. int indexAt = list.size() - 1;
  526. while (indexAt >= 0) {
  527. Object o = list.get(indexAt);
  528. if (!(o instanceof Item)) {
  529. //indexAt--;
  530. break;
  531. }
  532. String name2 = ((Item) o).getSortName();
  533. int compareRes = name1.compareTo(name2);
  534. if (compareRes < 0) {
  535. indexAt--;
  536. continue;
  537. }
  538. break;
  539. }
  540. list.add(indexAt + 1, element);
  541. return element;
  542. }
  543. private Item insertItemElement(Item element) {
  544. itemsLock.writeLock().lock();
  545. try {
  546. return insertItemElementInList(items, element);
  547. } finally {
  548. itemsLock.writeLock().unlock();
  549. }
  550. }
  551. private Object addElement(Object element, boolean setModified) { // FIXUP: shopuld be private
  552. // Always keep the vector sorted
  553. if (element instanceof Item) {
  554. element = insertItemElement((Item) element);
  555. } else if (element instanceof Folder) {
  556. element = insertFolderElement((Folder) element);
  557. } else {
  558. assert false;
  559. }
  560. fireChangeEvent(this, setModified);
  561. return element;
  562. }
  563. /**
  564. * add item and make sure it is included in all configurations
  565. *
  566. * @param item
  567. * @return
  568. */
  569. public Item addItemAction(Item item) {
  570. Item added = addItemActionImpl(item, true, false);
  571. if (added != null) {
  572. for (ItemConfiguration conf : added.getItemConfigurations()) {
  573. if (conf != null) {
  574. conf.getExcluded().setValue(false);
  575. }
  576. }
  577. MakeLogicalViewProvider.checkForChangedViewItemNodes(this.getProject(), this, added);
  578. }
  579. return added;
  580. }
  581. private Item addItemActionImpl(Item item, boolean setModified, boolean excludedByDefault) {
  582. final Item addedItem = addItemImpl(item, true, setModified, excludedByDefault);
  583. if (addedItem != item) {
  584. return addedItem; // Nothing new was added
  585. }
  586. ArrayList<NativeFileItem> list = new ArrayList<NativeFileItem>(1);
  587. list.add(item);
  588. configurationDescriptor.fireFilesAdded(list);
  589. return item;
  590. }
  591. public Item addItem(Item item) {
  592. return addItemImpl(item, true, true, false);
  593. }
  594. public Item addItemFromRefreshDir(Item item, boolean notify, boolean setModified, boolean useOldSchemeBehavior) {
  595. // in new scheme we restored "non-excluded" items => all new are treated as excluded by default
  596. // in old scheme we didn't store "non-excluded" items, we stored "excluded" instead
  597. // so to support projects with old scheme we need to consider all new files as "non-excluded"
  598. return addItemImpl(item, notify, setModified, !useOldSchemeBehavior);
  599. }
  600. private synchronized Item addItemImpl(Item item, boolean notify, boolean setModified, boolean excludedByDefault) {
  601. if (item == null) {
  602. return null;
  603. }
  604. // Check if already in project. Refresh if it's there.
  605. Item existingItem;
  606. if (isProjectFiles() && (existingItem = configurationDescriptor.findProjectItemByPath(item.getPath())) != null) {
  607. //System.err.println("Folder - addItem - item ignored, already added: " + item); // NOI18N // FIXUP: correct?
  608. fireChangeEvent(existingItem, setModified);
  609. return existingItem; // Nothing added
  610. }
  611. // Add it to the folder
  612. item.setFolder(this);
  613. item = (Item) addElement(item, setModified);
  614. // Add item to the dataObject's lookup
  615. if (isProjectFiles() && notify) {
  616. DataObject dao = item.getDataObject();
  617. NativeFileItemSet myNativeFileItemSet = (dao == null) ? null : dao.getLookup().lookup(NativeFileItemSet.class);
  618. if (myNativeFileItemSet != null) {
  619. myNativeFileItemSet.add(item);
  620. } else {
  621. if (log.isLoggable(Level.FINEST)) {
  622. log.log(Level.FINEST, "can not add NativeFileItem for folder''s {0} item {1} using {2}", new Object[]{this, item, dao}); // NOI18N
  623. }
  624. }
  625. }
  626. // Add it to project Items
  627. if (isProjectFiles()) {
  628. configurationDescriptor.addProjectItem(item);
  629. if (setModified) {
  630. final Project project = configurationDescriptor.getProject();
  631. if (project != null) {
  632. CharSequence itemPath = CharSequences.create(item.getAbsolutePath());
  633. MakeProjectFileProviderFactory.addToSearchBase(project, this, itemPath);
  634. }
  635. configurationDescriptor.setModified();
  636. }
  637. // Add configuration to all configurations
  638. if (configurationDescriptor.getConfs() == null) {
  639. return item;
  640. }
  641. HashMap<Configuration, DeletedConfiguration> map = null;
  642. if (deletedItems != null) {
  643. map = deletedItems.get(item.getPath());
  644. }
  645. Configuration[] configurations = configurationDescriptor.getConfs().toArray();
  646. for (int i = 0; i < configurations.length; i++) {
  647. // this is hack to initialize folder configuration
  648. FolderConfiguration folderConfiguration = getFolderConfiguration(configurations[i]);
  649. DeletedConfiguration old = null;
  650. if (map != null) {
  651. old = map.get(configurations[i]);
  652. }
  653. ItemConfiguration ic = new ItemConfiguration(configurations[i], item);
  654. ic.getExcluded().setValue(excludedByDefault);
  655. if (old != null && old.ic != null && old.aux != null) {
  656. ic.setTool(old.ic.getTool());
  657. ic.assignValues(old.aux);
  658. }
  659. configurations[i].addAuxObject(ic);
  660. }
  661. if (map != null && deletedItems != null) {
  662. deletedItems.remove(item.getPath());
  663. }
  664. }
  665. return item;
  666. }
  667. public Folder addFolder(Folder folder, boolean setModified) {
  668. Folder aFolder = this;
  669. while (aFolder != null) {
  670. if (aFolder.equals(folder)) {
  671. log.log(Level.INFO, "Folder {0} already was added.", folder.getDisplayName()); // NOI18N
  672. return folder;
  673. }
  674. aFolder = aFolder.getParent();
  675. }
  676. folder = (Folder) addElement(folder, setModified);
  677. if (isProjectFiles()) {
  678. // Add configuration to all configurations
  679. if (configurationDescriptor.getConfs() == null) {
  680. return folder;
  681. }
  682. Configuration[] configurations = configurationDescriptor.getConfs().toArray();
  683. for (int i = 0; i < configurations.length; i++) {
  684. folder.getFolderConfiguration(configurations[i]);
  685. }
  686. }
  687. return folder;
  688. }
  689. /**
  690. * Returns an unique id (String) used to retrive this object from the pool
  691. * of aux objects
  692. */
  693. public String getId() {
  694. if (id == null) {
  695. id = "f-" + getPath(); // NOI18N
  696. }
  697. return id;
  698. }
  699. public FolderConfiguration getFolderConfiguration(Configuration configuration) {
  700. FolderConfiguration folderConfiguration = null;
  701. if (isProjectFiles() || isTest() || isTestLogicalFolder()) {
  702. folderConfiguration = (FolderConfiguration) configuration.getAuxObject(getId());
  703. if (folderConfiguration == null) {
  704. CCompilerConfiguration parentCCompilerConfiguration;
  705. CCCompilerConfiguration parentCCCompilerConfiguration;
  706. FolderConfiguration parentFolderConfiguration = null;
  707. if (getParent() != null) {
  708. parentFolderConfiguration = getParent().getFolderConfiguration(configuration);
  709. }
  710. if (parentFolderConfiguration != null) {
  711. parentCCompilerConfiguration = parentFolderConfiguration.getCCompilerConfiguration();
  712. parentCCCompilerConfiguration = parentFolderConfiguration.getCCCompilerConfiguration();
  713. } else {
  714. parentCCompilerConfiguration = ((MakeConfiguration) configuration).getCCompilerConfiguration();
  715. parentCCCompilerConfiguration = ((MakeConfiguration) configuration).getCCCompilerConfiguration();
  716. }
  717. folderConfiguration = new FolderConfiguration(configuration, parentCCompilerConfiguration, parentCCCompilerConfiguration, this);
  718. configuration.addAuxObject(folderConfiguration);
  719. }
  720. }
  721. return folderConfiguration;
  722. }
  723. public FolderConfiguration[] getFolderConfigurations() {
  724. FolderConfiguration[] folderConfigurations;
  725. if (configurationDescriptor == null) {
  726. return new FolderConfiguration[0];
  727. }
  728. Configuration[] configurations = configurationDescriptor.getConfs().toArray();
  729. folderConfigurations = new FolderConfiguration[configurations.length];
  730. for (int i = 0; i < configurations.length; i++) {
  731. folderConfigurations[i] = getFolderConfiguration(configurations[i]);
  732. }
  733. return folderConfigurations;
  734. }
  735. public String suggestedNewTestFolderName() {
  736. return suggestedName(DEFAULT_TEST_FOLDER_DISPLAY_NAME);
  737. }
  738. public String suggestedNewFolderName() {
  739. return suggestedName(DEFAULT_FOLDER_DISPLAY_NAME);
  740. }
  741. public String suggestedName(String template) {
  742. String aNname;
  743. String aDisplayName;
  744. for (int i = 1;; i++) {
  745. aNname = DEFAULT_FOLDER_NAME + i;
  746. aDisplayName = template + " " + i; // NOI18N
  747. if (findFolderByName(aNname) == null) {
  748. break;
  749. }
  750. }
  751. return aDisplayName;
  752. }
  753. public Folder addNewFolder(boolean projectFiles) {
  754. return addNewFolder(projectFiles, getKind());
  755. }
  756. public Folder addNewFolder(boolean projectFiles, Kind kind) {
  757. String aNname;
  758. String aDisplayName;
  759. for (int i = 1;; i++) {
  760. aNname = DEFAULT_FOLDER_NAME + i;
  761. aDisplayName = DEFAULT_FOLDER_DISPLAY_NAME + " " + i; // NOI18N
  762. if (findFolderByName(aNname) == null) {
  763. break;
  764. }
  765. }
  766. return addNewFolder(aNname, aDisplayName, projectFiles, kind); // NOI18N
  767. }
  768. public Folder addNewFolder(String name, String displayName, boolean projectFiles, String kindText) {
  769. Kind k = null;
  770. if (kindText != null) {
  771. if (kindText.equals("IMPORTANT_FILES_FOLDER")) { // NOI18N
  772. k = Kind.IMPORTANT_FILES_FOLDER;
  773. } else if (kindText.equals("SOURCE_DISK_FOLDER")) { // NOI18N
  774. k = Kind.SOURCE_DISK_FOLDER;
  775. } else if (kindText.equals("SOURCE_LOGICAL_FOLDER")) { // NOI18N
  776. k = Kind.SOURCE_LOGICAL_FOLDER;
  777. } else if (kindText.equals("TEST")) { // NOI18N
  778. k = Kind.TEST;
  779. } else if (kindText.equals("TEST_LOGICAL_FOLDER")) { // NOI18N
  780. k = Kind.TEST_LOGICAL_FOLDER;
  781. }
  782. }
  783. return addNewFolder(name, displayName, projectFiles, k);
  784. }
  785. public Folder addNewFolder(String name, String displayName, boolean projectFiles, Kind kind) {
  786. Folder newFolder = new Folder(getConfigurationDescriptor(), this, name, displayName, projectFiles, kind);
  787. addFolder(newFolder, true);
  788. return newFolder;
  789. }
  790. public boolean removeItemAction(Item item) {
  791. ArrayList<NativeFileItem> list = new ArrayList<NativeFileItem>(1);
  792. list.add(item);
  793. boolean ret = removeItemImpl(item, true, true);
  794. if (isProjectFiles()) {
  795. configurationDescriptor.fireFilesRemoved(list);
  796. }
  797. return ret;
  798. }
  799. private boolean removePhysicalItem(Item item, boolean setModified) {
  800. ArrayList<NativeFileItem> list = new ArrayList<NativeFileItem>(1);
  801. list.add(item);
  802. boolean ret = removeItemImpl(item, setModified, false);
  803. if (isProjectFiles()) {
  804. configurationDescriptor.fireFilesRemoved(list);
  805. }
  806. return ret;
  807. }
  808. public void renameItemAction(String oldPath, Item newItem) {
  809. configurationDescriptor.fireFileRenamed(oldPath, newItem);
  810. }
  811. public boolean removeItem(Item item) {
  812. // shouldn't it be the same as removeItemAction?
  813. return removeItemImpl(item, true, true);
  814. }
  815. private boolean removeItemImpl(Item item, boolean setModified, boolean requestForCompleteRemove) {
  816. if (!requestForCompleteRemove && item.hasImportantAttributes()) {
  817. if (log.isLoggable(Level.FINE)) {
  818. log.log(Level.FINE, "------------removeItemImpl does NOT REMOVED attributed {0} in {1}", new Object[]{item, getPath()}); // NOI18N
  819. }
  820. return false;
  821. }
  822. boolean ret = false;
  823. if (item == null) {
  824. return false;
  825. }
  826. // Remove it from folder
  827. itemsLock.writeLock().lock();
  828. try {
  829. ret = items.remove(item);
  830. } finally {
  831. itemsLock.writeLock().unlock();
  832. }
  833. if (!ret) {
  834. fireChangeEvent(this, false);
  835. return ret;
  836. }
  837. // Remove item from the dataObject's lookup
  838. if (isProjectFiles()) {
  839. item.onClose();
  840. }
  841. // item.setFolder(null);
  842. if (isProjectFiles()) {
  843. // Remove it from project Items
  844. configurationDescriptor.removeProjectItem(item);
  845. if (setModified) {
  846. final Project project = configurationDescriptor.getProject();
  847. if (project != null) {
  848. CharSequence itemPath = CharSequences.create(item.getAbsolutePath());
  849. MakeProjectFileProviderFactory.removeFromSearchBase(project, this, itemPath);
  850. }
  851. configurationDescriptor.setModified();
  852. }
  853. // Remove it form all configurations
  854. if (deletedItems == null) {
  855. deletedItems = new HashMap<String, HashMap<Configuration, DeletedConfiguration>>();
  856. }
  857. HashMap<Configuration, DeletedConfiguration> map = new HashMap<Configuration, DeletedConfiguration>();
  858. deletedItems.put(item.getPath(), map);
  859. Configuration[] configurations = configurationDescriptor.getConfs().toArray();
  860. for (int i = 0; i < configurations.length; i++) {
  861. DeletedConfiguration del = new DeletedConfiguration();
  862. del.ic = item.getItemConfiguration(configurations[i]);
  863. del.aux = configurations[i].removeAuxObject(item.getId()/*ItemConfiguration.getId(item.getPath())*/);
  864. map.put(configurations[i], del);
  865. }
  866. }
  867. item.setFolder(null);
  868. fireChangeEvent(this, setModified);
  869. return ret;
  870. }
  871. public boolean removeFolderAction(Folder folder) {
  872. // this is request from user to remove folder completely
  873. boolean ret = removeFolderImpl(folder, true, true);
  874. configurationDescriptor.fireFilesRemoved(folder.getAllItemsAsList());
  875. return ret;
  876. }
  877. private boolean removeFolderImpl(Folder folder, boolean setModified, boolean requestForCompleteRemove) {
  878. boolean ret = false;
  879. if (folder != null) {
  880. for (Folder f : folder.getAllFolders(false)) {
  881. MakeProjectFileProviderFactory.updateSearchBase(configurationDescriptor.getProject(), f, null);
  882. }
  883. MakeProjectFileProviderFactory.updateSearchBase(configurationDescriptor.getProject(), folder, null);
  884. if (folder.isDiskFolder()) {
  885. folder.detachListener();
  886. }
  887. folder.removeAll(requestForCompleteRemove);
  888. folder.markRemoved(true);
  889. if (!requestForCompleteRemove && folder.hasAttributedItems()) {
  890. if (log.isLoggable(Level.FINE)) {
  891. log.log(Level.FINE, "------------removeFolderImpl does NOT REMOVED attributed {0} in {1}", new Object[]{folder, getPath()}); // NOI18N
  892. }
  893. fireChangeEvent(this, false);
  894. return false;
  895. }
  896. itemsLock.writeLock().lock();
  897. try {
  898. ret = items.remove(folder);
  899. } finally {
  900. itemsLock.writeLock().unlock();
  901. }
  902. if (isProjectFiles()) {
  903. // Remove it form all configurations
  904. Configuration[] configurations = configurationDescriptor.getConfs().toArray();
  905. for (int i = 0; i < configurations.length; i++) {
  906. configurations[i].removeAuxObject(folder.getId());
  907. }
  908. }
  909. }
  910. if (ret) {
  911. fireChangeEvent(this, setModified);
  912. }
  913. return ret;
  914. }
  915. /**
  916. * Remove all items and folders recursively
  917. */
  918. private void removeAll(boolean requestForCompleteRemove) {
  919. Item[] itemsToRemove = getItemsAsArray();
  920. Folder[] foldersToRemove = getFoldersAsArray();
  921. boolean setModified = requestForCompleteRemove;
  922. for (int i = 0; i < itemsToRemove.length; i++) {
  923. removeItemImpl(itemsToRemove[i], setModified, requestForCompleteRemove);
  924. }
  925. for (int i = 0; i < foldersToRemove.length; i++) {
  926. removeFolderImpl(foldersToRemove[i], setModified, requestForCompleteRemove);
  927. }
  928. }
  929. public void reset() {
  930. itemsLock.writeLock().lock();
  931. try {
  932. items.clear();
  933. } finally {
  934. itemsLock.writeLock().unlock();
  935. }
  936. fireChangeEvent();
  937. }
  938. public Item findItemByPath(String path) {
  939. if (path == null) {
  940. return null;
  941. }
  942. Item[] anItems = getItemsAsArray();
  943. for (int i = 0; i < anItems.length; i++) {
  944. if (path.equals(anItems[i].getPath())) {
  945. return anItems[i];
  946. }
  947. }
  948. return null;
  949. }
  950. public Item findItemByAbsolutePath(String path) {
  951. if (path == null) {
  952. return null;
  953. }
  954. Item[] anItems = getItemsAsArray();
  955. for (int i = 0; i < anItems.length; i++) {
  956. if (path.equals(anItems[i].getAbsolutePath())) {
  957. return anItems[i];
  958. }
  959. }
  960. return null;
  961. }
  962. public Item findItemByName(String name) {
  963. if (name == null) {
  964. return null;
  965. }
  966. Item[] anItems = getItemsAsArray();
  967. for (int i = 0; i < anItems.length; i++) {
  968. if (name.equals(anItems[i].getName())) {
  969. return anItems[i];
  970. }
  971. }
  972. return null;
  973. }
  974. public Folder findFolderByName(String name) {
  975. if (name == null) {
  976. return null;
  977. }
  978. Folder[] folders = getFoldersAsArray();
  979. for (int i = 0; i < folders.length; i++) {
  980. if (name.equals(folders[i].getName())) {
  981. return folders[i];
  982. }
  983. }
  984. return null;
  985. }
  986. public Folder findFolderByDisplayName(String name) {
  987. if (name == null) {
  988. return null;
  989. }
  990. Folder[] folders = getFoldersAsArray();
  991. for (int i = 0; i < folders.length; i++) {
  992. if (name.equals(folders[i].getDisplayName())) {
  993. return folders[i];
  994. }
  995. }
  996. return null;
  997. }
  998. public Folder findFolderByAbsolutePath(String path) {
  999. if (path == null) {
  1000. return null;
  1001. }
  1002. for (Folder folder : getFolders()) {
  1003. String absPath = folder.getAbsolutePath();
  1004. if (absPath != null && path.equals(absPath)) {
  1005. return folder;
  1006. }
  1007. }
  1008. return null;
  1009. }
  1010. public Folder findFolderByRelativePath(String path) {
  1011. if (path == null) {
  1012. return null;
  1013. }
  1014. for (Folder folder : getFolders()) {
  1015. String relPath = folder.getRoot();
  1016. if (relPath != null && path.equals(relPath)) {
  1017. return folder;
  1018. }
  1019. }
  1020. return null;
  1021. }
  1022. public String getAbsolutePath() {
  1023. String aRoot = getRoot();
  1024. if (aRoot != null) {
  1025. String absRootPath = CndPathUtilitities.toAbsolutePath(configurationDescriptor.getBaseDirFileObject(), getRoot());
  1026. absRootPath = RemoteFileUtil.normalizeAbsolutePath(absRootPath, getProject());
  1027. FileObject folderFile = RemoteFileUtil.getFileObject(absRootPath, getProject());
  1028. if (folderFile != null) {
  1029. return folderFile.getPath();
  1030. }
  1031. }
  1032. return null;
  1033. }
  1034. /*
  1035. * FIXUP: not sure this method is working as intended.....
  1036. */
  1037. public Folder findFolderByPath(String path) {
  1038. int i = path.indexOf('/');
  1039. if (i >= 0) {
  1040. String aName = path.substring(0, i);
  1041. Folder folder = findFolderByName(aName);
  1042. if (folder == null) {
  1043. return null;
  1044. }
  1045. return folder.findFolderByPath(path.substring(i + 1));
  1046. } else {
  1047. return findFolderByName(path);
  1048. }
  1049. }
  1050. public Item[] getItemsAsArray() {
  1051. ArrayList<Item> found = new ArrayList<Item>();
  1052. Iterator<?> iter = new ArrayList<Object>(getElements()).iterator();
  1053. while (iter.hasNext()) {
  1054. Object o = iter.next();
  1055. if (o instanceof Item) {
  1056. found.add((Item) o);
  1057. }
  1058. }
  1059. return found.toArray(new Item[found.size()]);
  1060. }
  1061. public boolean hasAttributedItems() {
  1062. if (!this.isDiskFolder()) {
  1063. return true;
  1064. }
  1065. if (this.getRoot() != null) {
  1066. return true;
  1067. }
  1068. Iterator<?> iter = new ArrayList<Object>(getElements()).iterator();
  1069. while (iter.hasNext()) {
  1070. Object o = iter.next();
  1071. if (o instanceof Item) {
  1072. if (((Item) o).hasImportantAttributes()) {
  1073. return true;
  1074. }
  1075. }
  1076. if (o instanceof Folder) {
  1077. if (((Folder) o).hasAttributedItems()) {
  1078. return true;
  1079. }
  1080. }
  1081. }
  1082. return false;
  1083. }
  1084. private List<NativeFileItem> getAllItemsAsList() {
  1085. ArrayList<NativeFileItem> found = new ArrayList<NativeFileItem>();
  1086. Iterator<?> iter = new ArrayList<Object>(getElements()).iterator();
  1087. while (iter.hasNext()) {
  1088. Object o = iter.next();
  1089. if (o instanceof Item) {
  1090. found.add((Item) o);
  1091. }
  1092. if (o instanceof Folder) {
  1093. List<NativeFileItem> anItems = ((Folder) o).getAllItemsAsList();
  1094. found.addAll(anItems);
  1095. }
  1096. }
  1097. return found;
  1098. }
  1099. public Item[] getAllItemsAsArray() {
  1100. List<NativeFileItem> list = getAllItemsAsList();
  1101. return list.toArray(new Item[list.size()]);
  1102. }
  1103. /*
  1104. * Returns a set of all files in this logical folder and subfolders as FileObjetc's
  1105. */
  1106. public Set<FileObject> getAllItemsAsFileObjectSet(boolean projectFilesOnly, FileObjectNameMatcher matcher) {
  1107. LinkedHashSet<FileObject> files = new LinkedHashSet<FileObject>();
  1108. getAllItemsAsFileObjectSet(files, projectFilesOnly, matcher);
  1109. return files;
  1110. }
  1111. private void getAllItemsAsFileObjectSet(Set<FileObject> files, boolean projectFilesOnly, FileObjectNameMatcher matcher) {
  1112. if (!projectFilesOnly || isProjectFiles()) {
  1113. if (matcher.isTerminated()) {
  1114. return;
  1115. }
  1116. Iterator<?> iter = new ArrayList<Object>(getElements()).iterator();
  1117. while (iter.hasNext()) {
  1118. if (matcher.isTerminated()) {
  1119. return;
  1120. }
  1121. Object item = iter.next();
  1122. if (item instanceof Item) {
  1123. FileObject fo = ((Item) item).getFileObject();
  1124. if (fo != null && (matcher == null || matcher.pathMatches(fo))) {
  1125. files.add(fo);
  1126. }
  1127. } else if (item instanceof Folder) {
  1128. ((Folder) item).getAllItemsAsFileObjectSet(files, projectFilesOnly, matcher);
  1129. }
  1130. }
  1131. }
  1132. }
  1133. /*
  1134. * Returns a set of all logical folder in this folder as an array
  1135. */
  1136. public Folder[] getFoldersAsArray() {
  1137. List<Folder> folders = getFolders();
  1138. return folders.toArray(new Folder[folders.size()]);
  1139. }
  1140. /*
  1141. * Returns a set of all logical folder in this folder
  1142. */
  1143. public List<Folder> getFolders() {
  1144. List<Folder> folders = new ArrayList<Folder>();
  1145. Iterator<?> iter = new ArrayList<Object>(getElements()).iterator();
  1146. while (iter.hasNext()) {
  1147. Object item = iter.next();
  1148. if (item instanceof Folder) {
  1149. folders.add((Folder) item);
  1150. }
  1151. }
  1152. return folders;
  1153. }
  1154. /*
  1155. * Returns a set of all logical folder and subfolders in this folder
  1156. */
  1157. public List<Folder> getAllFolders(boolean projectFilesOnly) {
  1158. List<Folder> folders = new ArrayList<Folder>();
  1159. getAllFolders(folders, projectFilesOnly);
  1160. return folders;
  1161. }
  1162. private void getAllFolders(List<Folder> folders, boolean projectFilesOnly) {
  1163. if (!projectFilesOnly || isProjectFiles()) {
  1164. Iterator<?> iter = new ArrayList<Object>(getElements()).iterator();
  1165. while (iter.hasNext()) {
  1166. Object item = iter.next();
  1167. if (item instanceof Folder) {
  1168. Folder folder = (Folder) item;
  1169. if (!projectFilesOnly || folder.isProjectFiles()) {
  1170. folders.add(folder);
  1171. folder.getAllFolders(folders, projectFilesOnly);
  1172. }
  1173. }
  1174. }
  1175. }
  1176. }
  1177. public List<Folder> getAllTests() {
  1178. List<Folder> list = new ArrayList<Folder>();
  1179. getTests(list);
  1180. return list;
  1181. }
  1182. /*
  1183. * recursive!
  1184. */
  1185. private void getTests(List<Folder> list) {
  1186. Iterator<?> iter = new ArrayList<Object>(getElements()).iterator();
  1187. while (iter.hasNext()) {
  1188. Object o = iter.next();
  1189. if (o instanceof Folder) {
  1190. if (((Folder) o).isTest()) {
  1191. list.add((Folder) o);
  1192. }
  1193. ((Folder) o).getTests(list);
  1194. }
  1195. }
  1196. }
  1197. public void addChangeListener(ChangeListener cl) {
  1198. synchronized (changeListenerList) {
  1199. changeListenerList.add(cl);
  1200. }
  1201. }
  1202. public void removeChangeListener(ChangeListener cl) {
  1203. synchroni