diff --git a/java.j2seplatform/nbproject/project.xml b/java.j2seplatform/nbproject/project.xml
--- a/java.j2seplatform/nbproject/project.xml
+++ b/java.j2seplatform/nbproject/project.xml
@@ -87,6 +87,15 @@
1
+
+
+
+ org.netbeans.modules.java.project
+
+
+
+ 1
+ 1.20
diff --git a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SELibrarySourceForBinaryQuery.java b/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SELibrarySourceForBinaryQuery.java
--- a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SELibrarySourceForBinaryQuery.java
+++ b/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SELibrarySourceForBinaryQuery.java
@@ -52,6 +52,7 @@
import org.netbeans.api.java.queries.SourceForBinaryQuery;
import org.netbeans.api.project.libraries.Library;
import org.netbeans.api.project.libraries.LibraryManager;
+import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection;
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation2;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
@@ -160,9 +161,15 @@
if (this.lib.getContent(J2SELibraryTypeProvider.VOLUME_TYPE_CLASSPATH).contains(entry)) {
List result = new ArrayList();
for (URL u : lib.getContent(J2SELibraryTypeProvider.VOLUME_TYPE_SRC)) {
- FileObject sourceRootURL = URLMapper.findFileObject(u);
- if (sourceRootURL!=null) {
- result.add (sourceRootURL);
+ FileObject sourceRoot = URLMapper.findFileObject(u);
+ if (sourceRoot != null) {
+ FileObject fo2 = JavadocAndSourceRootDetection.findSourcesRoot(sourceRoot, false);
+ if (fo2 != null) {
+ sourceRoot = fo2;
+ }
+ }
+ if (sourceRoot!=null) {
+ result.add (sourceRoot);
}
}
this.cache = result.toArray(new FileObject[result.size()]);
diff --git a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SEVolumeCustomizer.form b/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SEVolumeCustomizer.form
--- a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SEVolumeCustomizer.form
+++ b/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SEVolumeCustomizer.form
@@ -9,6 +9,7 @@
+
diff --git a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SEVolumeCustomizer.java b/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SEVolumeCustomizer.java
--- a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SEVolumeCustomizer.java
+++ b/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/J2SEVolumeCustomizer.java
@@ -62,6 +62,7 @@
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileFilter;
import org.netbeans.api.project.ant.FileChooser;
+import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection;
import org.netbeans.spi.project.libraries.LibraryCustomizerContext;
import org.openide.DialogDisplayer;
import org.openide.ErrorManager;
@@ -374,7 +375,7 @@
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
try {
lastFolder = chooser.getCurrentDirectory();
- addFiles (chooser.getSelectedPaths(), area != null ? area.getLocation() : null);
+ addFiles (chooser.getSelectedPaths(), area != null ? area.getLocation() : null, this.volumeType);
} catch (MalformedURLException mue) {
ErrorManager.getDefault().notify(mue);
} catch (IOException ex) {
@@ -405,7 +406,7 @@
// }
- private void addFiles (String[] fileNames, URL libraryLocation) throws MalformedURLException {
+ private void addFiles (String[] fileNames, URL libraryLocation, String volume) throws MalformedURLException {
int firstIndex = this.model.getSize();
for (int i = 0; i < fileNames.length; i++) {
File f = new File(fileNames[i]);
@@ -419,6 +420,7 @@
new File(URI.create(area.getLocation().toExternalForm())).getParentFile(), f.getPath()));
}
}
+ checkFile(realFile, volume);
if (FileUtil.isArchiveFile(realFile.toURI().toURL())) {
uri = LibrariesSupport.getArchiveRoot(uri);
} else if (!uri.toString().endsWith("/")){
@@ -431,6 +433,7 @@
model.addResource(uri);
} else {
assert f.isAbsolute() : f.getPath();
+ checkFile(f, volume);
URL url = FileUtil.normalizeFile(f).toURI().toURL();
if (FileUtil.isArchiveFile(url)) {
url = FileUtil.getArchiveRoot(url);
@@ -438,14 +441,6 @@
url = new URL(url.toExternalForm()+"/");
}
model.addResource(url);
- }
- if (this.volumeType.equals(J2SELibraryTypeProvider.VOLUME_TYPE_JAVADOC)
- && !JavadocForBinaryQueryLibraryImpl.isValidLibraryJavadocRoot (
- LibrariesSupport.resolveLibraryEntryURI(libraryLocation, uri).toURL())) {
- DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(
- NbBundle.getMessage(J2SEVolumeCustomizer.class,"TXT_InvalidJavadocRoot", f.getPath()),
- NotifyDescriptor.ERROR_MESSAGE));
- continue;
}
}
int lastIndex = this.model.getSize()-1;
@@ -459,6 +454,31 @@
if (this.volumeType.equals(J2SELibraryTypeProvider.VOLUME_TYPE_CLASSPATH)) {
if (impl != null) {
impl.setContent(J2SELibraryTypeProvider.VOLUME_TYPE_MAVEN_POM, Collections.emptyList());
+ }
+ }
+ }
+
+ private void checkFile(File f, String volume) {
+ FileObject fo = FileUtil.toFileObject(f);
+ if (volume.equals(J2SELibraryTypeProvider.VOLUME_TYPE_JAVADOC)) {
+ if (fo != null) {
+ if (fo.isData()) {
+ fo = FileUtil.getArchiveRoot(fo);
+ }
+ if (JavadocAndSourceRootDetection.findJavadocRoot(fo, true) == null) {
+ DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(
+ NbBundle.getMessage(J2SEVolumeCustomizer.class,"TXT_InvalidJavadocRoot", f.getPath()),
+ NotifyDescriptor.ERROR_MESSAGE));
+ }
+ }
+ } else if (volume.equals(J2SELibraryTypeProvider.VOLUME_TYPE_SRC)) {
+ if (fo != null) {
+ if (fo.isData()) {
+ fo = FileUtil.getArchiveRoot(fo);
+ }
+ if (JavadocAndSourceRootDetection.findSourcesRoot(fo, true) == null) {
+ // TODO: warn user that no source root was found
+ }
}
}
}
diff --git a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/JavadocForBinaryQueryLibraryImpl.java b/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/JavadocForBinaryQueryLibraryImpl.java
--- a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/JavadocForBinaryQueryLibraryImpl.java
+++ b/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/libraries/JavadocForBinaryQueryLibraryImpl.java
@@ -52,6 +52,7 @@
import org.netbeans.api.java.queries.JavadocForBinaryQuery;
import org.netbeans.api.project.libraries.Library;
import org.netbeans.api.project.libraries.LibraryManager;
+import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection;
import org.netbeans.spi.java.queries.JavadocForBinaryQueryImplementation;
import org.openide.ErrorManager;
import org.openide.util.WeakListeners;
@@ -90,7 +91,7 @@
if (this.cachedRoots == null) {
List result = new ArrayList();
for (URL u : lib.getContent(J2SELibraryTypeProvider.VOLUME_TYPE_JAVADOC)) {
- result.add (getIndexFolder(u));
+ result.add (getIndexFolder(u, false));
}
this.cachedRoots = result.toArray(new URL[result.size()]);
}
@@ -179,60 +180,27 @@
/**
- * Tests if the query accepts the root as valid JavadocRoot,
- * the query accepts the JavaDoc root, if it can find the index-files
- * or index-all.html in the root.
- * @param rootURL the javadoc root
- * @return true if the root is a valid Javadoc root
- */
- static boolean isValidLibraryJavadocRoot (final URL rootURL) {
- assert rootURL != null && rootURL.toExternalForm().endsWith("/");
- final FileObject root = URLMapper.findFileObject(rootURL);
- if (root == null) {
- return false;
- }
- return findIndexFolder (root,1) != null;
- }
-
- /**
* Search for the actual root of the Javadoc containing the index-all.html or
* index-files. In case when it is not able to find it, it returns the given Javadoc folder/file.
* @param URL Javadoc folder/file
* @return URL either the URL of folder containg the index or the given parameter if the index was not found.
*/
- private static URL getIndexFolder (URL rootURL) {
- if (rootURL == null) {
+ private static URL getIndexFolder (URL rootURL, boolean strict) {
+ FileObject fo = URLMapper.findFileObject(rootURL);
+ if (fo != null) {
+ fo = JavadocAndSourceRootDetection.findJavadocRoot(fo, false);
+ if (fo != null) {
+ URL url2 = URLMapper.findURL(fo, URLMapper.EXTERNAL);
+ if (url2 != null) {
+ return url2;
+ }
+ }
+ }
+ if (strict) {
return null;
- }
- FileObject root = URLMapper.findFileObject(rootURL);
- if (root == null) {
- return rootURL;
- }
- FileObject result = findIndexFolder (root,1);
- try {
- return result == null ? rootURL : result.getURL();
- } catch (FileStateInvalidException e) {
- ErrorManager.getDefault().notify(e);
+ } else {
return rootURL;
}
}
- private static FileObject findIndexFolder (FileObject fo, int depth) {
- if (depth > MAX_DEPTH) {
- return null;
- }
- if (fo.getFileObject("index-files",null)!=null || fo.getFileObject("index-all.html",null)!=null) { //NOI18N
- return fo;
- }
- for (FileObject child : fo.getChildren()) {
- if (child.isFolder()) {
- FileObject result = findIndexFolder(child, depth+1);
- if (result != null) {
- return result;
- }
- }
- }
- return null;
- }
-
}
diff --git a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/DefaultClassPathProvider.java b/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/DefaultClassPathProvider.java
--- a/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/DefaultClassPathProvider.java
+++ b/java.j2seplatform/src/org/netbeans/modules/java/j2seplatform/platformdefinition/DefaultClassPathProvider.java
@@ -43,7 +43,6 @@
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
-import java.io.*;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.net.URL;
@@ -53,7 +52,6 @@
import java.util.Set;
import java.util.Iterator;
import java.util.HashSet;
-import java.util.StringTokenizer;
import java.util.WeakHashMap;
import java.util.Collections;
import org.netbeans.api.java.classpath.ClassPath;
@@ -66,9 +64,8 @@
import org.netbeans.spi.java.classpath.ClassPathImplementation;
import org.netbeans.spi.java.classpath.ClassPathFactory;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
-import org.netbeans.modules.classfile.ClassFile;
-import org.netbeans.modules.classfile.ClassName;
import org.netbeans.spi.java.classpath.PathResourceImplementation;
+import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection;
import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileStateInvalidException;
@@ -80,16 +77,10 @@
*/
public class DefaultClassPathProvider implements ClassPathProvider {
- /** Name of package keyword. */
- private static final String PACKAGE = "package"; //NOI18N
/**Java file extension */
private static final String JAVA_EXT = "java"; //NOI18N
/**Class file extension*/
private static final String CLASS_EXT = "class"; //NOI18N
-
- private static final int TYPE_JAVA = 1;
-
- private static final int TYPE_CLASS = 2;
private /*WeakHash*/Map> sourceRootsCache = new WeakHashMap>();
private /*WeakHash*/Map> sourceClasPathsCache = new WeakHashMap>();
@@ -194,7 +185,7 @@
Reference foRef = this.sourceRootsCache.get (file);
FileObject execRoot = null;
if (foRef == null || (execRoot = foRef.get()) == null ) {
- execRoot = getRootForFile (file, TYPE_CLASS);
+ execRoot = JavadocAndSourceRootDetection.findPackageRoot(file);
if (execRoot == null) {
return null;
}
@@ -215,336 +206,6 @@
}
return null;
}
-
- private static FileObject getRootForFile (final FileObject fo, int type) {
- String pkg;
- if (type == TYPE_JAVA) {
- pkg = findJavaPackage (fo);
- }
- else {
- pkg = findClassPackage (fo);
- }
- FileObject packageRoot = null;
- if (pkg == null) {
- packageRoot = fo.getParent();
- }
- else {
- List elements = new ArrayList ();
- for (StringTokenizer tk = new StringTokenizer(pkg,"."); tk.hasMoreTokens();) {
- elements.add(tk.nextToken());
- }
- FileObject tmp = fo;
- for (int i=elements.size()-1; i>=0; i--) {
- String name = elements.get(i);
- tmp = tmp.getParent();
- if (tmp == null || !tmp.getName().equals(name)) {
- tmp = fo;
- break;
- }
- }
- packageRoot = tmp.getParent();
- }
- return packageRoot;
- }
-
-
- /**
- * Find java package in side .class file.
- *
- * @return package or null if not found
- */
- private static final String findClassPackage (FileObject file) {
- try {
- InputStream in = file.getInputStream();
- try {
- ClassFile cf = new ClassFile(in,false);
- ClassName cn = cf.getName();
- return cn.getPackage();
- } finally {
- in.close ();
- }
- } catch (FileNotFoundException fnf) {
- //Ignore it
- // The file was removed after checking it for isValid
- } catch (IOException e) {
- ErrorManager.getDefault().notify(e);
- }
- return null;
- }
-
- /**
- * Find java package in side .java file.
- *
- * @return package or null if not found
- */
- private static String findJavaPackage(FileObject file) {
- String pkg = ""; // NOI18N
- boolean packageKnown = false;
-
- // Try to find the package name and then infer a directory to mount.
- BufferedReader rd = null;
-
- try {
- int pckgPos; // found package position
-
- rd = new BufferedReader(new SourceReader(file.getInputStream()));
-
- // Check for unicode byte watermarks.
- rd.mark(2);
- char[] cbuf = new char[2];
- rd.read(cbuf, 0, 2);
-
- if (cbuf[0] == 255 && cbuf[1] == 254) {
- rd.close();
- rd = new BufferedReader(new SourceReader(file.getInputStream(), "Unicode")); // NOI18N
- } else {
- rd.reset();
- }
-
- while (!packageKnown) {
- String line = rd.readLine();
- if (line == null) {
- packageKnown = true; // i.e. valid termination of search, default pkg
- //break;
- return pkg;
- }
-
- pckgPos = line.indexOf(PACKAGE);
- if (pckgPos == -1) {
- continue;
- }
- StringTokenizer tok = new StringTokenizer(line, " \t;"); // NOI18N
- boolean gotPackage = false;
- while (tok.hasMoreTokens()) {
- String theTok = tok.nextToken ();
- if (gotPackage) {
- // Hopefully the package name, but first a sanity check...
- StringTokenizer ptok = new StringTokenizer(theTok, "."); // NOI18N
- boolean ok = ptok.hasMoreTokens();
- while (ptok.hasMoreTokens()) {
- String component = ptok.nextToken();
- if (component.length() == 0) {
- ok = false;
- break;
- }
- if (!Character.isJavaIdentifierStart(component.charAt(0))) {
- ok = false;
- break;
- }
- for (int pos = 1; pos < component.length(); pos++) {
- if (!Character.isJavaIdentifierPart(component.charAt(pos))) {
- ok = false;
- break;
- }
- }
- }
- if (ok) {
- pkg = theTok;
- packageKnown = true;
- //break;
- return pkg;
- } else {
- // Keep on looking for valid package statement.
- gotPackage = false;
- continue;
- }
- } else if (theTok.equals (PACKAGE)) {
- gotPackage = true;
- } else if (theTok.equals ("{")) { // NOI18N
- // Most likely we can stop if hit opening brace of class def.
- // Usually people leave spaces around it.
- packageKnown = true; // valid end of search, default pkg
- // break;
- return pkg;
- }
- }
- }
- } catch (FileNotFoundException fnf) {
- //Ignore it
- //The file was probably removed after it was checked for isValid
- }
- catch (IOException e1) {
- ErrorManager.getDefault().notify(e1);
- } finally {
- try {
- if (rd != null) {
- rd.close();
- }
- } catch (IOException e2) {
- ErrorManager.getDefault().notify(e2);
- }
- }
-
- return null;
- }
-
- /**
- * Filtered reader for Java sources - it simply excludes
- * comments and some useless whitespaces from the original stream.
- */
- public static class SourceReader extends InputStreamReader {
- private int preRead = -1;
- private boolean inString = false;
- private boolean backslashLast = false;
- private boolean separatorLast = false;
- static private final char separators[] = {'.'}; // dot is enough here...
- static private final char whitespaces[] = {' ', '\t', '\r', '\n'};
-
- public SourceReader(InputStream in) {
- super(in);
- }
-
- public SourceReader(InputStream in, String encoding) throws UnsupportedEncodingException {
- super(in, encoding);
- }
-
- /** Reads chars from input reader and filters them. */
- public int read(char[] data, int pos, int len) throws IOException {
- int numRead = 0;
- int c;
- char[] onechar = new char[1];
-
- while (numRead < len) {
- if (preRead != -1) {
- c = preRead;
- preRead = -1;
- } else {
- c = super.read(onechar, 0, 1);
- if (c == -1) { // end of stream reached
- return (numRead > 0) ? numRead : -1;
- }
- c = onechar[0];
- }
-
- if (c == '/' && !inString) { // a comment could start here
- preRead = super.read(onechar, 0, 1);
- if (preRead == 1) {
- preRead = onechar[0];
- }
- if (preRead != '*' && preRead != '/') { // it's not a comment
- data[pos++] = (char) c;
- numRead++;
- if (preRead == -1) { // end of stream reached
- return numRead;
- }
- } else { // we have run into the comment - skip it
- if (preRead == '*') { // comment started with /*
- preRead = -1;
- do {
- c = moveToChar('*');
- if (c == 0) {
- c = super.read(onechar, 0, 1);
- if (c == 1) {
- c = onechar[0];
- }
- if (c == '*') {
- preRead = c;
- }
- }
- } while (c != '/' && c != -1);
- } else { // comment started with //
- preRead = -1;
- c = moveToChar('\n');
- if (c == 0) {
- preRead = '\n';
- }
- }
- if (c == -1) { // end of stream reached
- return -1;
- }
- }
- } else { // normal valid character
- if (!inString) { // not inside a string " ... "
- if (isWhitespace(c)) { // reduce some whitespaces
- while (true) {
- preRead = super.read(onechar, 0, 1);
- if (preRead == -1) { // end of stream reached
- return (numRead > 0) ? numRead : -1;
- }
- preRead = onechar[0];
-
- if (isSeparator(preRead)) {
- c = preRead;
- preRead = -1;
- break;
- } else if (!isWhitespace(preRead)) {
- if (separatorLast) {
- c = preRead;
- preRead = -1;
- }
- break;
- }
- }
- }
-
- if (c == '\"' || c == '\'') {
- inString = true;
- separatorLast = false;
- } else {
- separatorLast = isSeparator(c);
- }
- } else { // we are just in a string
- if (c == '\"' || c == '\'') {
- if (!backslashLast) {
- inString = false;
- } else {
- backslashLast = false;
- }
- } else {
- backslashLast = (c == '\\');
- }
- }
-
- data[pos++] = (char) c;
- numRead++;
- }
- }
- return numRead;
- }
-
- private int moveToChar(int c) throws IOException {
- int cc;
- char[] onechar = new char[1];
-
- if (preRead != -1) {
- cc = preRead;
- preRead = -1;
- } else {
- cc = super.read(onechar, 0, 1);
- if (cc == 1) {
- cc = onechar[0];
- }
- }
-
- while (cc != -1 && cc != c) {
- cc = super.read(onechar, 0, 1);
- if (cc == 1) {
- cc = onechar[0];
- }
- }
-
- return (cc == -1) ? -1 : 0;
- }
-
- static private boolean isSeparator(int c) {
- for (int i=0; i < separators.length; i++) {
- if (c == separators[i]) {
- return true;
- }
- }
- return false;
- }
-
- static private boolean isWhitespace(int c) {
- for (int i=0; i < whitespaces.length; i++) {
- if (c == whitespaces[i]) {
- return true;
- }
- }
- return false;
- }
- } // End of class SourceReader.
-
private static class RecursionException extends IllegalStateException {}
diff --git a/java.j2seproject/nbproject/project.xml b/java.j2seproject/nbproject/project.xml
--- a/java.j2seproject/nbproject/project.xml
+++ b/java.j2seproject/nbproject/project.xml
@@ -148,7 +148,7 @@
1
- 1.19
+ 1.20
diff --git a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/ClassPathUiSupport.java b/java.j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/ClassPathUiSupport.java
--- a/java.j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/ClassPathUiSupport.java
+++ b/java.j2seproject/src/org/netbeans/modules/java/j2seproject/ui/customizer/ClassPathUiSupport.java
@@ -53,8 +53,12 @@
import org.netbeans.api.project.libraries.LibrariesCustomizer;
import org.netbeans.api.project.libraries.Library;
import org.netbeans.modules.java.j2seproject.classpath.ClassPathSupport;
+import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection;
import org.netbeans.spi.java.project.support.ui.EditJarSupport;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
+import org.netbeans.spi.project.support.ant.PropertyUtils;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
import org.openide.util.NbCollections;
/**
@@ -147,6 +151,33 @@
if (eji != null) {
item.setJavadocFilePath(eji.getJavadocFile());
item.setSourceFilePath(eji.getSourceFile());
+ if (eji.getJavadocFile() != null) {
+ String val = helper.getStandardPropertyEvaluator().evaluate(eji.getJavadocFile());
+ File f = PropertyUtils.resolveFile(FileUtil.toFile(helper.getProjectDirectory()), val);
+ FileObject fo = FileUtil.toFileObject(f);
+ if (fo != null) {
+ if (fo.isData()) {
+ fo = FileUtil.getArchiveRoot(fo);
+ }
+ if (JavadocAndSourceRootDetection.findJavadocRoot(fo, true) == null) {
+ // TODO: warn user that no Javadoc was found
+ }
+ }
+ }
+ if (eji.getSourceFile() != null) {
+ String val = helper.getStandardPropertyEvaluator().evaluate(eji.getSourceFile());
+ File f = PropertyUtils.resolveFile(FileUtil.toFile(helper.getProjectDirectory()), val);
+ FileObject fo = FileUtil.toFileObject(f);
+ if (fo != null) {
+ if (fo.isData()) {
+ fo = FileUtil.getArchiveRoot(fo);
+ }
+ if (JavadocAndSourceRootDetection.findSourcesRoot(fo, true) == null) {
+ // TODO: warn user that no source root was found
+ }
+ }
+ }
+
}
}
if (item.getType() == ClassPathSupport.Item.TYPE_LIBRARY) {
diff --git a/java.project/manifest.mf b/java.project/manifest.mf
--- a/java.project/manifest.mf
+++ b/java.project/manifest.mf
@@ -3,6 +3,6 @@
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.19
+OpenIDE-Module-Specification-Version: 1.20
AutoUpdate-Show-In-Client: false
diff --git a/java.project/nbproject/project.xml b/java.project/nbproject/project.xml
--- a/java.project/nbproject/project.xml
+++ b/java.project/nbproject/project.xml
@@ -89,6 +89,14 @@
1
1.9
+
+
+
+ org.netbeans.modules.classfile
+
+
+
+ 1
diff --git a/java.project/src/org/netbeans/modules/java/project/ExtraProjectJavadocForBinaryQueryImpl.java b/java.project/src/org/netbeans/modules/java/project/ExtraProjectJavadocForBinaryQueryImpl.java
--- a/java.project/src/org/netbeans/modules/java/project/ExtraProjectJavadocForBinaryQueryImpl.java
+++ b/java.project/src/org/netbeans/modules/java/project/ExtraProjectJavadocForBinaryQueryImpl.java
@@ -57,9 +57,12 @@
import javax.swing.event.ChangeListener;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
+import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection;
import org.netbeans.spi.java.queries.JavadocForBinaryQueryImplementation;
import org.netbeans.spi.project.ui.ProjectOpenedHook;
+import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
+import org.openide.filesystems.URLMapper;
import org.openide.util.ChangeSupport;
import org.openide.util.Exceptions;
@@ -224,6 +227,16 @@
if (FileUtil.isArchiveFile(url)) {
url = FileUtil.getArchiveRoot(url);
}
+ FileObject fo = URLMapper.findFileObject(url);
+ if (fo != null) {
+ fo = JavadocAndSourceRootDetection.findJavadocRoot(fo, false);
+ if (fo != null) {
+ URL url2 = URLMapper.findURL(fo, URLMapper.EXTERNAL);
+ if (url2 != null) {
+ url = url2;
+ }
+ }
+ }
return new URL[] { url };
} catch ( MalformedURLException ex )
{
diff --git a/java.project/src/org/netbeans/modules/java/project/ExtraProjectSourceForBinaryQueryImpl.java b/java.project/src/org/netbeans/modules/java/project/ExtraProjectSourceForBinaryQueryImpl.java
--- a/java.project/src/org/netbeans/modules/java/project/ExtraProjectSourceForBinaryQueryImpl.java
+++ b/java.project/src/org/netbeans/modules/java/project/ExtraProjectSourceForBinaryQueryImpl.java
@@ -56,6 +56,7 @@
import org.netbeans.api.java.queries.SourceForBinaryQuery;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
+import org.netbeans.spi.java.project.support.JavadocAndSourceRootDetection;
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation2;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.PropertyEvaluator;
@@ -230,6 +231,12 @@
url = FileUtil.getArchiveRoot(url);
}
FileObject fo = URLMapper.findFileObject(url);
+ if (fo != null) {
+ FileObject fo2 = JavadocAndSourceRootDetection.findSourcesRoot(fo, false);
+ if (fo2 != null) {
+ fo = fo2;
+ }
+ }
if ( fo != null )
{
return new FileObject[]{fo};
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
new file mode 100644
--- /dev/null
+++ b/java.project/src/org/netbeans/spi/java/project/support/JavadocAndSourceRootDetection.java
@@ -0,0 +1,568 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2008 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.spi.java.project.support;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.logging.Logger;
+import org.netbeans.modules.classfile.ClassFile;
+import org.netbeans.modules.classfile.ClassName;
+import org.openide.ErrorManager;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.URLMapper;
+import org.openide.util.Exceptions;
+import org.openide.util.NbPreferences;
+
+/**
+ * Miscellaneous helper utils to detect Javadoc root folder, source root folder or
+ * package of the given java or class file.
+ *
+ * @since org.netbeans.modules.java.project/1 1.20
+ */
+public class JavadocAndSourceRootDetection {
+
+ private static final int HOW_MANY_DIRS_TO_TRAVERSE_DEEP = 5;
+
+ /** Name of package keyword. */
+ private static final String PACKAGE = "package"; //NOI18N
+
+ private static final Logger LOG = Logger.getLogger(JavadocAndSourceRootDetection.class.getName());
+
+ private JavadocAndSourceRootDetection() {
+ }
+
+ /**
+ * Finds Javadoc root inside of given folder.
+ *
+ * @param fo base folder to start search in; routine will traverse 5 folders
+ * deep before giving up; cannot be null; must be folder
+ * @param ignoreCache any successful found value is cached and will be used
+ * if possible to avoid potentially slow folder search; set to true to ignore it
+ * @return found Javadoc root or null if none found
+ */
+ public static FileObject findJavadocRoot(FileObject baseFolder, boolean ignoreCache) {
+ if (!baseFolder.isFolder()) {
+ throw new IllegalStateException("baseFolder must be folder - "+baseFolder); // NOI18N
+ }
+ String key = null;
+ try {
+ key = URLMapper.findURL(baseFolder, URLMapper.EXTERNAL).toURI().toString();
+ } catch (URISyntaxException ex) {
+ Exceptions.printStackTrace(ex);
+ ignoreCache = true;
+ }
+ if (!ignoreCache) {
+ String value = NbPreferences.forModule(JavadocAndSourceRootDetection.class).get("javadoc."+key, null); // NOI18N
+ if (value != null) {
+ FileObject fo1;
+ try {
+ fo1 = URLMapper.findFileObject(URI.create(value).toURL());
+ if (fo1 != null) {
+ return fo1;
+ }
+ } catch (MalformedURLException ex) {
+ LOG.info("cached value '"+value+"' cannot be parsed: "+ex.toString()); // NOI18N
+ }
+ }
+ }
+ FileObject root = findJavadocRoot(baseFolder, 0);
+ String value = null;
+ if (root != null) {
+ try {
+ value = URLMapper.findURL(root, URLMapper.EXTERNAL).toURI().toString();
+ } catch (URISyntaxException ex) {
+ Exceptions.printStackTrace(ex);
+ value = null;
+ }
+ }
+ if (value == null) {
+ NbPreferences.forModule(JavadocAndSourceRootDetection.class).remove("javadoc."+key); // NOI18N
+ } else {
+ NbPreferences.forModule(JavadocAndSourceRootDetection.class).put("javadoc."+key, value); // NOI18N
+ }
+ return root;
+ }
+
+ /**
+ * Finds Java sources root inside of given folder.
+ *
+ * @param fo base 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 ignoreCache any successful found value is cached and will be used
+ * if possible to avoid potentially slow folder search; set to true to ignore it
+ * @return found package root of first Java file found or null if none found
+ */
+ public static FileObject findSourcesRoot(FileObject fo, boolean ignoreCache) {
+ if (!fo.isFolder()) {
+ throw new IllegalStateException("fo must be folder - "+fo); // NOI18N
+ }
+ String key = null;
+ try {
+ key = URLMapper.findURL(fo, URLMapper.EXTERNAL).toURI().toString();
+ } catch (URISyntaxException ex) {
+ Exceptions.printStackTrace(ex);
+ ignoreCache = true;
+ }
+ if (!ignoreCache) {
+ String value = NbPreferences.forModule(JavadocAndSourceRootDetection.class).get("sources."+key, null); // NOI18N
+ if (value != null) {
+ FileObject fo1;
+ try {
+ fo1 = URLMapper.findFileObject(URI.create(value).toURL());
+ if (fo1 != null) {
+ return fo1;
+ }
+ } catch (MalformedURLException ex) {
+ LOG.info("cached value '"+value+"' cannot be parsed: "+ex.toString()); // NOI18N
+ }
+ }
+ }
+ FileObject root = findJavaSourceFile(fo, 0);
+ if (root != null) {
+ root = findPackageRoot(root);
+ }
+ String value = null;
+ if (root != null) {
+ try {
+ value = URLMapper.findURL(root, URLMapper.EXTERNAL).toURI().toString();
+ } catch (URISyntaxException ex) {
+ Exceptions.printStackTrace(ex);
+ value = null;
+ }
+ }
+ if (value == null) {
+ NbPreferences.forModule(JavadocAndSourceRootDetection.class).remove("sources."+key); // NOI18N
+ } else {
+ NbPreferences.forModule(JavadocAndSourceRootDetection.class).put("sources."+key, value); // NOI18N
+ }
+ return root;
+ }
+
+ /**
+ * Returns package root of the given java or class file.
+ *
+ * @param fo either .java or .class file; never null
+ * @return package root of the given file
+ */
+ public static FileObject findPackageRoot(final FileObject fo) {
+ String pkg;
+ if ("java".equals(fo.getExt())) { // NOI18N
+ pkg = findJavaPackage (fo);
+ } else if ("class".equals(fo.getExt())) { // NOI18N
+ pkg = findClassPackage (fo);
+ } else {
+ throw new IllegalStateException("only java or class files accepted "+fo); // NOI18N
+ }
+ FileObject packageRoot = null;
+ if (pkg == null) {
+ packageRoot = fo.getParent();
+ }
+ else {
+ List elements = new ArrayList ();
+ for (StringTokenizer tk = new StringTokenizer(pkg,"."); tk.hasMoreTokens();) { // NOI18N
+ elements.add(tk.nextToken());
+ }
+ FileObject tmp = fo;
+ for (int i=elements.size()-1; i>=0; i--) {
+ String name = elements.get(i);
+ tmp = tmp.getParent();
+ if (tmp == null || !tmp.getName().equals(name)) {
+ tmp = fo;
+ break;
+ }
+ }
+ packageRoot = tmp.getParent();
+ }
+ return packageRoot;
+ }
+
+
+ private static FileObject findJavadocRoot(FileObject fo, int level) {
+ FileObject fo1 = fo.getFileObject("package-list", null); // NOI18N
+ if (fo1 != null) {
+ return fo;
+ }
+ if (level == HOW_MANY_DIRS_TO_TRAVERSE_DEEP) {
+ return null;
+ }
+ for (FileObject fo2 : fo.getChildren()) {
+ if (!fo2.isFolder()) {
+ continue;
+ }
+ fo2 = findJavadocRoot(fo2, level+1);
+ if (fo2 != null) {
+ return fo2;
+ }
+ }
+ return null;
+ }
+
+ private static FileObject findJavaSourceFile(FileObject fo, int level) {
+ if (level == 999) { // ignore for now
+ return null;
+ }
+ // go through files first:
+ for (FileObject fo2 : fo.getChildren()) {
+ if (fo2.isData() && "java".equals(fo2.getExt())) { // NOI18N
+ return fo2;
+ }
+ }
+ // now check sunfolders:
+ for (FileObject fo2 : fo.getChildren()) {
+ if (fo2.isFolder()) {
+ fo2 = findJavaSourceFile(fo2, level+1);
+ if (fo2 != null) {
+ return fo2;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find java package in side .class file.
+ *
+ * @return package or null if not found
+ */
+ private static final String findClassPackage (FileObject file) {
+ try {
+ InputStream in = file.getInputStream();
+ try {
+ ClassFile cf = new ClassFile(in,false);
+ ClassName cn = cf.getName();
+ return cn.getPackage();
+ } finally {
+ in.close ();
+ }
+ } catch (FileNotFoundException fnf) {
+ //Ignore it
+ // The file was removed after checking it for isValid
+ } catch (IOException e) {
+ ErrorManager.getDefault().notify(e);
+ }
+ return null;
+ }
+
+ /**
+ * Find java package in side .java file.
+ *
+ * @return package or null if not found
+ */
+ private static String findJavaPackage(FileObject file) {
+ String pkg = ""; // NOI18N
+ boolean packageKnown = false;
+
+ // Try to find the package name and then infer a directory to mount.
+ BufferedReader rd = null;
+
+ try {
+ int pckgPos; // found package position
+
+ rd = new BufferedReader(new SourceReader(file.getInputStream()));
+
+ // Check for unicode byte watermarks.
+ rd.mark(2);
+ char[] cbuf = new char[2];
+ rd.read(cbuf, 0, 2);
+
+ if (cbuf[0] == 255 && cbuf[1] == 254) {
+ rd.close();
+ rd = new BufferedReader(new SourceReader(file.getInputStream(), "Unicode")); // NOI18N
+ } else {
+ rd.reset();
+ }
+
+ while (!packageKnown) {
+ String line = rd.readLine();
+ if (line == null) {
+ packageKnown = true; // i.e. valid termination of search, default pkg
+ //break;
+ return pkg;
+ }
+
+ pckgPos = line.indexOf(PACKAGE);
+ if (pckgPos == -1) {
+ continue;
+ }
+ StringTokenizer tok = new StringTokenizer(line, " \t;"); // NOI18N
+ boolean gotPackage = false;
+ while (tok.hasMoreTokens()) {
+ String theTok = tok.nextToken ();
+ if (gotPackage) {
+ // Hopefully the package name, but first a sanity check...
+ StringTokenizer ptok = new StringTokenizer(theTok, "."); // NOI18N
+ boolean ok = ptok.hasMoreTokens();
+ while (ptok.hasMoreTokens()) {
+ String component = ptok.nextToken();
+ if (component.length() == 0) {
+ ok = false;
+ break;
+ }
+ if (!Character.isJavaIdentifierStart(component.charAt(0))) {
+ ok = false;
+ break;
+ }
+ for (int pos = 1; pos < component.length(); pos++) {
+ if (!Character.isJavaIdentifierPart(component.charAt(pos))) {
+ ok = false;
+ break;
+ }
+ }
+ }
+ if (ok) {
+ pkg = theTok;
+ packageKnown = true;
+ //break;
+ return pkg;
+ } else {
+ // Keep on looking for valid package statement.
+ gotPackage = false;
+ continue;
+ }
+ } else if (theTok.equals (PACKAGE)) {
+ gotPackage = true;
+ } else if (theTok.equals ("{")) { // NOI18N
+ // Most likely we can stop if hit opening brace of class def.
+ // Usually people leave spaces around it.
+ packageKnown = true; // valid end of search, default pkg
+ // break;
+ return pkg;
+ }
+ }
+ }
+ } catch (FileNotFoundException fnf) {
+ //Ignore it
+ //The file was probably removed after it was checked for isValid
+ }
+ catch (IOException e1) {
+ ErrorManager.getDefault().notify(e1);
+ } finally {
+ try {
+ if (rd != null) {
+ rd.close();
+ }
+ } catch (IOException e2) {
+ ErrorManager.getDefault().notify(e2);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Filtered reader for Java sources - it simply excludes
+ * comments and some useless whitespaces from the original stream.
+ */
+ public static class SourceReader extends InputStreamReader {
+ private int preRead = -1;
+ private boolean inString = false;
+ private boolean backslashLast = false;
+ private boolean separatorLast = false;
+ static private final char separators[] = {'.'}; // dot is enough here...
+ static private final char whitespaces[] = {' ', '\t', '\r', '\n'};
+
+ public SourceReader(InputStream in) {
+ super(in);
+ }
+
+ public SourceReader(InputStream in, String encoding) throws UnsupportedEncodingException {
+ super(in, encoding);
+ }
+
+ /** Reads chars from input reader and filters them. */
+ public int read(char[] data, int pos, int len) throws IOException {
+ int numRead = 0;
+ int c;
+ char[] onechar = new char[1];
+
+ while (numRead < len) {
+ if (preRead != -1) {
+ c = preRead;
+ preRead = -1;
+ } else {
+ c = super.read(onechar, 0, 1);
+ if (c == -1) { // end of stream reached
+ return (numRead > 0) ? numRead : -1;
+ }
+ c = onechar[0];
+ }
+
+ if (c == '/' && !inString) { // a comment could start here
+ preRead = super.read(onechar, 0, 1);
+ if (preRead == 1) {
+ preRead = onechar[0];
+ }
+ if (preRead != '*' && preRead != '/') { // it's not a comment
+ data[pos++] = (char) c;
+ numRead++;
+ if (preRead == -1) { // end of stream reached
+ return numRead;
+ }
+ } else { // we have run into the comment - skip it
+ if (preRead == '*') { // comment started with /*
+ preRead = -1;
+ do {
+ c = moveToChar('*');
+ if (c == 0) {
+ c = super.read(onechar, 0, 1);
+ if (c == 1) {
+ c = onechar[0];
+ }
+ if (c == '*') {
+ preRead = c;
+ }
+ }
+ } while (c != '/' && c != -1);
+ } else { // comment started with //
+ preRead = -1;
+ c = moveToChar('\n');
+ if (c == 0) {
+ preRead = '\n';
+ }
+ }
+ if (c == -1) { // end of stream reached
+ return -1;
+ }
+ }
+ } else { // normal valid character
+ if (!inString) { // not inside a string " ... "
+ if (isWhitespace(c)) { // reduce some whitespaces
+ while (true) {
+ preRead = super.read(onechar, 0, 1);
+ if (preRead == -1) { // end of stream reached
+ return (numRead > 0) ? numRead : -1;
+ }
+ preRead = onechar[0];
+
+ if (isSeparator(preRead)) {
+ c = preRead;
+ preRead = -1;
+ break;
+ } else if (!isWhitespace(preRead)) {
+ if (separatorLast) {
+ c = preRead;
+ preRead = -1;
+ }
+ break;
+ }
+ }
+ }
+
+ if (c == '\"' || c == '\'') {
+ inString = true;
+ separatorLast = false;
+ } else {
+ separatorLast = isSeparator(c);
+ }
+ } else { // we are just in a string
+ if (c == '\"' || c == '\'') {
+ if (!backslashLast) {
+ inString = false;
+ } else {
+ backslashLast = false;
+ }
+ } else {
+ backslashLast = (c == '\\');
+ }
+ }
+
+ data[pos++] = (char) c;
+ numRead++;
+ }
+ }
+ return numRead;
+ }
+
+ private int moveToChar(int c) throws IOException {
+ int cc;
+ char[] onechar = new char[1];
+
+ if (preRead != -1) {
+ cc = preRead;
+ preRead = -1;
+ } else {
+ cc = super.read(onechar, 0, 1);
+ if (cc == 1) {
+ cc = onechar[0];
+ }
+ }
+
+ while (cc != -1 && cc != c) {
+ cc = super.read(onechar, 0, 1);
+ if (cc == 1) {
+ cc = onechar[0];
+ }
+ }
+
+ return (cc == -1) ? -1 : 0;
+ }
+
+ static private boolean isSeparator(int c) {
+ for (int i=0; i < separators.length; i++) {
+ if (c == separators[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static private boolean isWhitespace(int c) {
+ for (int i=0; i < whitespaces.length; i++) {
+ if (c == whitespaces[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+ } // End of class SourceReader.
+
+
+}
diff --git a/java.project/test/unit/data/javadoc-and-sources-detection/build.xml b/java.project/test/unit/data/javadoc-and-sources-detection/build.xml
new file mode 100644
--- /dev/null
+++ b/java.project/test/unit/data/javadoc-and-sources-detection/build.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+ Builds, tests, and runs the project JavaApplication22.
+
+
+
diff --git a/java.project/test/unit/data/javadoc-and-sources-detection/manifest.mf b/java.project/test/unit/data/javadoc-and-sources-detection/manifest.mf
new file mode 100644
--- /dev/null
+++ b/java.project/test/unit/data/javadoc-and-sources-detection/manifest.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
diff --git a/java.project/test/unit/data/javadoc-and-sources-detection/nbproject/build-impl.xml b/java.project/test/unit/data/javadoc-and-sources-detection/nbproject/build-impl.xml
new file mode 100644
--- /dev/null
+++ b/java.project/test/unit/data/javadoc-and-sources-detection/nbproject/build-impl.xml
@@ -0,0 +1,661 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set src.dir
+ Must set test.src.dir
+ Must set build.dir
+ Must set dist.dir
+ Must set build.classes.dir
+ Must set dist.javadoc.dir
+ Must set build.test.classes.dir
+ Must set build.test.results.dir
+ Must set build.classes.excludes
+ Must set dist.jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+
+
+
+
+
+ java -cp "${run.classpath.with.dist.jar}" ${main.class}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To run this application from the command line without Ant, try:
+
+ java -jar "${dist.jar.resolved}"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set run.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set debug.class
+
+
+
+
+ Must set fix.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set javac.includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+
+
+
+
+ Must select some files in the IDE or set test.includes
+
+
+
+ Some tests failed; see details above.
+
+
+
+
+ Must select one file in the IDE or set test.class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+ Must select one file in the IDE or set applet.url
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/java.project/test/unit/data/javadoc-and-sources-detection/nbproject/genfiles.properties b/java.project/test/unit/data/javadoc-and-sources-detection/nbproject/genfiles.properties
new file mode 100644
--- /dev/null
+++ b/java.project/test/unit/data/javadoc-and-sources-detection/nbproject/genfiles.properties
@@ -0,0 +1,8 @@
+build.xml.data.CRC32=53c593e8
+build.xml.script.CRC32=d9a08ab5
+build.xml.stylesheet.CRC32=be360661
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=53c593e8
+nbproject/build-impl.xml.script.CRC32=7b015764
+nbproject/build-impl.xml.stylesheet.CRC32=61b4e419
diff --git a/java.project/test/unit/data/javadoc-and-sources-detection/nbproject/project.properties b/java.project/test/unit/data/javadoc-and-sources-detection/nbproject/project.properties
new file mode 100644
--- /dev/null
+++ b/java.project/test/unit/data/javadoc-and-sources-detection/nbproject/project.properties
@@ -0,0 +1,64 @@
+build.classes.dir=${build.dir}/classes
+build.classes.excludes=**/*.java,**/*.form
+# This directory is removed when the project is cleaned:
+build.dir=build
+build.generated.dir=${build.dir}/generated
+# Only compile against the classpath explicitly listed here:
+build.sysclasspath=ignore
+build.test.classes.dir=${build.dir}/test/classes
+build.test.results.dir=${build.dir}/test/results
+# Uncomment to specify the preferred debugger connection transport:
+#debug.transport=dt_socket
+debug.classpath=\
+ ${run.classpath}
+debug.test.classpath=\
+ ${run.test.classpath}
+# This directory is removed when the project is cleaned:
+dist.dir=dist
+dist.jar=${dist.dir}/JavaApplication22.jar
+dist.javadoc.dir=${dist.dir}/javadoc
+excludes=
+includes=**
+jar.compress=false
+javac.classpath=
+# Space-separated list of extra javac options
+javac.compilerargs=
+javac.deprecation=false
+javac.source=1.5
+javac.target=1.5
+javac.test.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}:\
+ ${libs.junit.classpath}:\
+ ${libs.junit_4.classpath}
+javadoc.additionalparam=
+javadoc.author=false
+javadoc.encoding=${source.encoding}
+javadoc.noindex=false
+javadoc.nonavbar=false
+javadoc.notree=false
+javadoc.private=false
+javadoc.splitindex=true
+javadoc.use=true
+javadoc.version=false
+javadoc.windowtitle=
+main.class=javaapplication22.Main
+manifest.file=manifest.mf
+meta.inf.dir=${src.dir}/META-INF
+platform.active=default_platform
+quick.run=true
+quick.run.single=true
+quick.test.single=true
+run.classpath=\
+ ${javac.classpath}:\
+ ${build.classes.dir}
+# Space-separated list of JVM arguments used when running the project
+# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
+# or test-sys-prop.name=value to set system properties for unit tests):
+run.jvmargs=
+run.test.classpath=\
+ ${javac.test.classpath}:\
+ ${build.test.classes.dir}
+source.encoding=UTF-8
+src.dir=src
+test.src.dir=test
diff --git a/java.project/test/unit/data/javadoc-and-sources-detection/nbproject/project.xml b/java.project/test/unit/data/javadoc-and-sources-detection/nbproject/project.xml
new file mode 100644
--- /dev/null
+++ b/java.project/test/unit/data/javadoc-and-sources-detection/nbproject/project.xml
@@ -0,0 +1,19 @@
+
+
+ org.netbeans.modules.java.j2seproject
+
+
+ JavaApplication22
+ 1.6.5
+
+
+
+
+
+
+
+
+ ./lib/nblibraries.properties
+
+
+
diff --git a/java.project/test/unit/data/javadoc-and-sources-detection/src/org/netbeans/testmodule/Main.java b/java.project/test/unit/data/javadoc-and-sources-detection/src/org/netbeans/testmodule/Main.java
new file mode 100644
--- /dev/null
+++ b/java.project/test/unit/data/javadoc-and-sources-detection/src/org/netbeans/testmodule/Main.java
@@ -0,0 +1,24 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.netbeans.testmodule;
+
+/**
+ * Main class.
+ *
+ * @author David Konecny
+ */
+public class Main {
+
+ /**
+ * Start Application.
+ *
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ // TODO code application logic here
+ }
+
+}
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
new file mode 100644
--- /dev/null
+++ b/java.project/test/unit/src/org/netbeans/spi/java/project/support/JavadocAndSourceRootDetectionTest.java
@@ -0,0 +1,114 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2008 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.spi.java.project.support;
+
+import java.io.File;
+import java.io.IOException;
+import org.netbeans.junit.NbTestCase;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+
+/**
+ *
+ */
+public class JavadocAndSourceRootDetectionTest extends NbTestCase {
+
+ public JavadocAndSourceRootDetectionTest(String testName) {
+ super(testName);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ clearWorkDir();
+ }
+
+ public static FileObject copyFolderRecursively(FileObject sourceFolder, FileObject destination) throws IOException {
+ assert sourceFolder.isFolder() : sourceFolder;
+ assert destination.isFolder() : destination;
+ FileObject destinationSubFolder = destination.getFileObject(sourceFolder.getName());
+ if (destinationSubFolder == null) {
+ destinationSubFolder = destination.createFolder(sourceFolder.getName());
+ }
+ for (FileObject fo : sourceFolder.getChildren()) {
+ if (fo.isFolder()) {
+ copyFolderRecursively(fo, destinationSubFolder);
+ } else {
+ FileObject foExists = destinationSubFolder.getFileObject(fo.getName(), fo.getExt());
+ if (foExists != null) {
+ foExists.delete();
+ }
+ FileObject newFO = FileUtil.copyFile(fo, destinationSubFolder, fo.getName(), fo.getExt());
+ }
+ }
+ return destinationSubFolder;
+ }
+
+ public void testFindJavadocRoot() throws Exception {
+ FileObject root = copyFolderRecursively(FileUtil.toFileObject(new File(getDataDir(), "javadoc-and-sources-detection")), FileUtil.toFileObject(getWorkDir()));
+ FileObject javadocRoot = JavadocAndSourceRootDetection.findJavadocRoot(root, true);
+ assertNotNull(javadocRoot);
+ assertEquals(new File(getWorkDir(), "javadoc-and-sources-detection/dist/javadoc").getPath(), FileUtil.toFile(javadocRoot).getPath());
+
+ FileObject sourcesRoot = JavadocAndSourceRootDetection.findSourcesRoot(root, true);
+ assertNotNull(sourcesRoot);
+ assertEquals(new File(getWorkDir(), "javadoc-and-sources-detection/src").getPath(), FileUtil.toFile(sourcesRoot).getPath());
+
+ // removing these files should fail detection unless data are read from cache:
+ javadocRoot.getFileObject("package-list", null).delete();
+ sourcesRoot.getFileObject("org", null).delete();
+
+ javadocRoot = JavadocAndSourceRootDetection.findJavadocRoot(root, false);
+ assertNotNull(javadocRoot);
+ assertEquals(new File(getWorkDir(), "javadoc-and-sources-detection/dist/javadoc").getPath(), FileUtil.toFile(javadocRoot).getPath());
+
+ sourcesRoot = JavadocAndSourceRootDetection.findSourcesRoot(root, false);
+ assertNotNull(sourcesRoot);
+ assertEquals(new File(getWorkDir(), "javadoc-and-sources-detection/src").getPath(), FileUtil.toFile(sourcesRoot).getPath());
+
+ // force to ignore cache:
+ javadocRoot = JavadocAndSourceRootDetection.findJavadocRoot(root, true);
+ assertNull(javadocRoot);
+
+ sourcesRoot = JavadocAndSourceRootDetection.findSourcesRoot(root, true);
+ assertNull(sourcesRoot);
+ }
+
+}
\ No newline at end of file