diff --git a/java.api.common/nbproject/project.xml b/java.api.common/nbproject/project.xml --- a/java.api.common/nbproject/project.xml +++ b/java.api.common/nbproject/project.xml @@ -30,6 +30,15 @@ 1 1.0 + + + + org.netbeans.api.progress + + + + 1 + 1.17 diff --git a/java.api.common/src/org/netbeans/modules/java/api/common/project/ui/wizards/Bundle.properties b/java.api.common/src/org/netbeans/modules/java/api/common/project/ui/wizards/Bundle.properties --- a/java.api.common/src/org/netbeans/modules/java/api/common/project/ui/wizards/Bundle.properties +++ b/java.api.common/src/org/netbeans/modules/java/api/common/project/ui/wizards/Bundle.properties @@ -42,3 +42,4 @@ CTL_RemoveFolder=Remove ACSD_FolderList=List of folders ACSD_NA=N/A +TXT_SearchingSourceRoots=Searching source roots diff --git a/java.api.common/src/org/netbeans/modules/java/api/common/project/ui/wizards/FolderList.java b/java.api.common/src/org/netbeans/modules/java/api/common/project/ui/wizards/FolderList.java --- a/java.api.common/src/org/netbeans/modules/java/api/common/project/ui/wizards/FolderList.java +++ b/java.api.common/src/org/netbeans/modules/java/api/common/project/ui/wizards/FolderList.java @@ -43,8 +43,13 @@ import java.awt.Component; import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.DefaultListModel; import javax.swing.DefaultListCellRenderer; import javax.swing.JFileChooser; @@ -52,11 +57,13 @@ import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionEvent; import org.netbeans.api.java.project.JavaProjectConstants; +import org.netbeans.api.progress.ProgressUtils; import org.netbeans.api.project.FileOwnerQuery; import org.netbeans.api.project.Project; import org.netbeans.api.project.SourceGroup; import org.netbeans.api.project.Sources; import org.netbeans.modules.java.api.common.project.ui.customizer.SourceRootsUi; +import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.util.NbBundle; @@ -229,24 +236,49 @@ chooser.setMultiSelectionEnabled(true); if (this.lastUsedFolder != null && this.lastUsedFolder.isDirectory()) { chooser.setCurrentDirectory (this.lastUsedFolder); - } + } else if (this.projectFolder != null && this.projectFolder.isDirectory()) { - chooser.setCurrentDirectory (this.projectFolder); - } + chooser.setCurrentDirectory (this.projectFolder); + } if (chooser.showOpenDialog(this)== JFileChooser.APPROVE_OPTION) { - File[] files = chooser.getSelectedFiles(); - int[] indecesToSelect = new int[files.length]; + final AtomicBoolean cancel = new AtomicBoolean(); + final File[] files = normalizeFiles(chooser.getSelectedFiles()); + final List toAdd = Collections.synchronizedList(new ArrayList()); + final Runnable task = new Runnable() { + public void run() { + for (File file : files) { + if (cancel.get()) { + return; + } + final Collection detectedRoots = JavadocAndSourceRootDetection.findSourceRoots(FileUtil.toFileObject(file),cancel); + if (detectedRoots.isEmpty()) { + toAdd.add(file); + } + else { + for (FileObject detectedRoot : detectedRoots) { + toAdd.add (FileUtil.toFile(detectedRoot)); + } + } + } + } + }; + ProgressUtils.runOffEventDispatchThread(task, NbBundle.getMessage(FolderList.class, "TXT_SearchingSourceRoots"), cancel, true); + File[] toAddArr; + synchronized (toAdd) { + toAddArr = cancel.get() ? files : toAdd.toArray(new File[toAdd.size()]); + } + int[] indecesToSelect = new int[toAdd.size()]; DefaultListModel model = (DefaultListModel)this.roots.getModel(); Set invalidRoots = new HashSet(); - File[] relatedFolders = this.relatedFolderList == null ? + File[] relatedFolders = this.relatedFolderList == null ? new File[0] : this.relatedFolderList.getFiles(); - for (int i=0, index=model.size(); i + + + Added JavadocAndSourceRootDetection.findSourceRoots method to find all source roots under the given folder + + + + + +

+ Added JavadocAndSourceRootDetection.findSourceRoots to find all source roots under the given folder. + This method is used by the import source roots in the new project wizards. +

+
+ + +
Added JavaRunner.PROP_RUNTIME_ENCODING property for COS Runner diff --git a/java.project/manifest.mf b/java.project/manifest.mf --- a/java.project/manifest.mf +++ b/java.project/manifest.mf @@ -3,7 +3,7 @@ OpenIDE-Module-Layer: org/netbeans/modules/java/project/layer.xml OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/java/project/Bundle.properties OpenIDE-Module-Needs: javax.script.ScriptEngine.freemarker -OpenIDE-Module-Specification-Version: 1.30 +OpenIDE-Module-Specification-Version: 1.31 OpenIDE-Module-Recommends: org.netbeans.spi.java.project.runner.JavaRunnerImplementation AutoUpdate-Show-In-Client: false diff --git a/java.project/src/org/netbeans/spi/java/project/support/JavadocAndSourceRootDetection.java b/java.project/src/org/netbeans/spi/java/project/support/JavadocAndSourceRootDetection.java --- a/java.project/src/org/netbeans/spi/java/project/support/JavadocAndSourceRootDetection.java +++ b/java.project/src/org/netbeans/spi/java/project/support/JavadocAndSourceRootDetection.java @@ -45,13 +45,21 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.annotations.common.NullAllowed; import org.netbeans.modules.classfile.ClassFile; import org.netbeans.modules.classfile.ClassName; import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; import org.openide.util.Exceptions; import org.openide.util.Parameters; @@ -103,7 +111,29 @@ } return null; } - + + /** + * Finds Java sources roots inside of given folder. + * + * @param folder to start search in; routine will traverse subfolders + * to find a Java file to detect package root; cannot be null; must be folder + * @param canceled if set to true the method immediatelly returns roots it has alredy found, + * may be null + * @return {@link Collection} of found package roots + * @since 1.31 + */ + public static Collection findSourceRoots(final @NonNull FileObject folder, final @NullAllowed AtomicBoolean canceled) { + Parameters.notNull("folder", folder); //NOI18N + if (!folder.isValid()) { + throw new IllegalArgumentException("Folder: " + FileUtil.getFileDisplayName(folder)+" is not valid."); //NOI18N + } + if (!folder.isFolder()) { + throw new IllegalArgumentException("The parameter: " + FileUtil.getFileDisplayName(folder) + " has to be a directory."); //NOI18N + } + final List result = new LinkedList(); + findAllSourceRoots(folder, result, canceled, 0); + return Collections.unmodifiableList(result); + } /** * Returns package root of the given java or class file. * @@ -120,6 +150,30 @@ } } + private static FileObject findAllSourceRoots(final FileObject folder, final Collection result, + final AtomicBoolean canceled, final int depth) { + if (depth == 50) { + return null; + } + final FileObject[] children = folder.getChildren(); + for (FileObject child : children) { + if (canceled != null && canceled.get()) { + return null; + } else if (child.isData() && "text/x-java".equals(FileUtil.getMIMEType(child, "text/x-java"))) { //NOI18N + final FileObject root = findPackageRoot(child); + if (root != null) { + result.add(root); + } + return root; + } else if (child.isFolder()) { + final FileObject upTo = findAllSourceRoots(child, result, canceled, depth+1); + if (upTo != null && !upTo.equals(child)) { + return upTo; + } + } + } + return null; + } private static FileObject findJavadocRoot(FileObject fo, int level) { FileObject fo1 = fo.getFileObject("package-list", null); // NOI18N diff --git a/java.project/test/unit/src/org/netbeans/spi/java/project/support/JavadocAndSourceRootDetectionTest.java b/java.project/test/unit/src/org/netbeans/spi/java/project/support/JavadocAndSourceRootDetectionTest.java --- a/java.project/test/unit/src/org/netbeans/spi/java/project/support/JavadocAndSourceRootDetectionTest.java +++ b/java.project/test/unit/src/org/netbeans/spi/java/project/support/JavadocAndSourceRootDetectionTest.java @@ -40,7 +40,14 @@ package org.netbeans.spi.java.project.support; import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; import java.net.URL; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; import java.util.regex.Matcher; import org.netbeans.junit.NbTestCase; import org.openide.filesystems.FileObject; @@ -110,6 +117,49 @@ assertParse("/*****/package foo;", false, "foo"); // would like to test stack overflow from #154894, but never managed to reproduce it in a unit test (only in standalone j2seproject) } + + + public void testFindAllSourceRoots() throws Exception { + FileUtil.setMIMEType("java", "text/x-java"); + final File wd = getWorkDir(); + final File root1 = new File (wd,"root1"); + final File root2 = new File (new File (wd,"foo"),"root2"); + final File root3 = new File (new File (new File (wd,"foo"),"test"),"root3"); + final File root4 = new File (wd,"root4"); + createJava(root1,"org.me.Test1","package org.me; class Test1{}"); + createJava(root2,"org.me.Test2","package org.me; class Test2{}"); + createJava(root3,"org.me.Test3","package org.me; class Test3{}"); + createJava(root4,"org.me.Test4","package org.me; class Test4{}"); + final FileObject wdFo = FileUtil.toFileObject(wd); + assertNotNull(wdFo); + final Collection result = JavadocAndSourceRootDetection.findSourceRoots(wdFo, null); + final Collection expected = Arrays.asList( + FileUtil.toFileObject(root1), + FileUtil.toFileObject(root2), + FileUtil.toFileObject(root3), + FileUtil.toFileObject(root4)); + assertEquals (expected, result); + } + + private static File createJava(final File root, final String fqn, final String content) throws IOException { + final File f = new File (root,fqn.replace('.', File.separatorChar)+".java"); + f.getParentFile().mkdirs(); + final PrintWriter out = new PrintWriter(new FileWriter(f)); + try { + out.println(content); + } finally { + out.close(); + } + return f; + } + + private void assertEquals(final Collection expected, final Collection result) { + assertEquals(expected.size(), result.size()); + final Set diff = new HashSet(expected); + diff.removeAll(result); + assertEquals(0, diff.size()); + } + private void assertParse(String text, boolean packageInfo, String expectedPackage) { Matcher m = (packageInfo ? JavadocAndSourceRootDetection.PACKAGE_INFO : JavadocAndSourceRootDetection.JAVA_FILE).matcher(text); assertEquals("Misparse of:\n" + text, expectedPackage, m.matches() ? m.group(1) : null);