Index: src/main/java/org/codehaus/mevenide/netbeans/FileUtilities.java =================================================================== --- src/main/java/org/codehaus/mevenide/netbeans/FileUtilities.java (revision 4369) +++ src/main/java/org/codehaus/mevenide/netbeans/FileUtilities.java (working copy) @@ -51,8 +51,16 @@ return null; } - + public static URI convertStringToUri(String str) { + if (str != null) { + File fil = new File(str); + fil = FileUtil.normalizeFile(fil); + return fil.toURI(); + } + return null; + } + private static final Pattern RELATIVE_SLASH_SEPARATED_PATH = Pattern.compile("[^:/\\\\.][^:/\\\\]*(/[^:/\\\\.][^:/\\\\]*)*"); // NOI18N Index: src/main/java/org/codehaus/mevenide/netbeans/execute/AbstractActionGoalProvider.java =================================================================== --- src/main/java/org/codehaus/mevenide/netbeans/execute/AbstractActionGoalProvider.java (revision 4369) +++ src/main/java/org/codehaus/mevenide/netbeans/execute/AbstractActionGoalProvider.java (working copy) @@ -41,6 +41,7 @@ import org.codehaus.mevenide.netbeans.execute.model.io.xpp3.NetbeansBuildActionXpp3Writer; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.netbeans.api.java.project.JavaProjectConstants; +import org.netbeans.api.project.PotentialSourceGroup; import org.netbeans.api.project.SourceGroup; import org.netbeans.api.project.Sources; import org.netbeans.spi.project.ActionProvider; @@ -87,6 +88,9 @@ Sources srcs = (Sources)project.getLookup().lookup(Sources.class); SourceGroup[] grp = srcs.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA); for (int i = 0; i < grp.length; i++) { + if (grp[i] instanceof PotentialSourceGroup) { + continue; + } relPath = FileUtil.getRelativePath(grp[i].getRootFolder(), fos[0]); if (relPath != null) { group = grp[i].getName(); Index: src/main/java/org/codehaus/mevenide/netbeans/nodes/SourcesNodeFactory.java =================================================================== --- src/main/java/org/codehaus/mevenide/netbeans/nodes/SourcesNodeFactory.java (revision 4369) +++ src/main/java/org/codehaus/mevenide/netbeans/nodes/SourcesNodeFactory.java (working copy) @@ -21,9 +21,9 @@ import java.util.List; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import org.codehaus.mevenide.netbeans.MavenSourcesImpl; import org.codehaus.mevenide.netbeans.NbMavenProject; import org.netbeans.api.java.project.JavaProjectConstants; +import org.netbeans.api.project.PotentialSourceGroup; import org.netbeans.api.project.Project; import org.netbeans.api.project.ProjectUtils; import org.netbeans.api.project.SourceGroup; @@ -31,6 +31,8 @@ import org.netbeans.spi.java.project.support.ui.PackageView; import org.netbeans.spi.project.ui.support.NodeFactory; import org.netbeans.spi.project.ui.support.NodeList; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; import org.openide.nodes.Node; /** @@ -59,12 +61,18 @@ Sources srcs = ProjectUtils.getSources(project); SourceGroup[] javagroup = srcs.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA); for (int i = 0; i < javagroup.length; i++) { - list.add(javagroup[i]); - } + list.add(javagroup[i]); + } return list; } public Node node(SourceGroup group) { + if (group instanceof PotentialSourceGroup) { + Node nd = new AbstractNode(Children.LEAF); + nd.setName(group.getName()); + nd.setDisplayName(group.getDisplayName()); + return nd; + } return PackageView.createPackageView(group); } Index: src/main/java/org/codehaus/mevenide/netbeans/MavenSourcesImpl.java =================================================================== --- src/main/java/org/codehaus/mevenide/netbeans/MavenSourcesImpl.java (revision 4369) +++ src/main/java/org/codehaus/mevenide/netbeans/MavenSourcesImpl.java (working copy) @@ -36,6 +36,7 @@ import org.netbeans.api.project.ProjectInformation; import org.netbeans.api.project.ProjectManager; import org.netbeans.api.project.SourceGroup; +import org.netbeans.api.project.PotentialSourceGroup; import org.netbeans.api.project.Sources; import org.netbeans.api.queries.SharabilityQuery; import org.netbeans.api.queries.VisibilityQuery; @@ -83,6 +84,9 @@ if (NbMavenProject.PROP_PROJECT.equals(event.getPropertyName())) { checkChanges(true); } + if (NbMavenProject.PROP_RESOURCE.equals(event.getPropertyName())) { + checkChanges(true); + } } }); } @@ -92,11 +96,13 @@ synchronized (lock) { MavenProject mp = project.getOriginalMavenProject(); if (mp != null) { - FileObject folder = FileUtilities.convertStringToFileObject(mp.getBuild().getSourceDirectory()); - changed = changed | checkJavaGroupCache(folder, NAME_SOURCE, NbBundle.getMessage(MavenSourcesImpl.class, "SG_Sources")); - folder = FileUtilities.convertStringToFileObject(mp.getBuild().getTestSourceDirectory()); - changed = changed | checkJavaGroupCache(folder, NAME_TESTSOURCE, NbBundle.getMessage(MavenSourcesImpl.class, "SG_Test_Sources")); +// FileObject folder = FileUtilities.convertStringToFileObject(mp.getBuild().getSourceDirectory()); + URI folderUri = FileUtilities.convertStringToUri(mp.getBuild().getSourceDirectory()); + changed = changed | checkJavaGroupCache(folderUri, NAME_SOURCE, NbBundle.getMessage(MavenSourcesImpl.class, "SG_Sources")); + folderUri = FileUtilities.convertStringToUri(mp.getBuild().getTestSourceDirectory()); + changed = changed | checkJavaGroupCache(folderUri, NAME_TESTSOURCE, NbBundle.getMessage(MavenSourcesImpl.class, "SG_Test_Sources")); URI[] uris = project.getGeneratedSourceRoots(); + FileObject folder; if (uris.length > 0) { try { folder = URLMapper.findFileObject(uris[0].toURL()); @@ -221,10 +227,19 @@ /** * consult the SourceGroup cache, return true if anything changed.. */ - private boolean checkJavaGroupCache(FileObject root, String name, String displayName) { + private boolean checkJavaGroupCache(URI root, String name, String displayName) { + FileObject fo = FileUtilities.convertURItoFileObject(root); SourceGroup group = javaGroup.get(name); if (root == null && group != null) { javaGroup.remove(name); + ProjectURLWatcher watch = project.getLookup().lookup(ProjectURLWatcher.class); + URI uri; + if (group instanceof PotentialSourceGroup) { + uri = ((PotentialSourceGroup)group).getPotencialRootFolder(); + } else { + uri = FileUtil.toFile(group.getRootFolder()).toURI(); + } + watch.removeWatchedPath(uri); return true; } if (root == null) { @@ -232,15 +247,42 @@ } boolean changed = false; if (group == null) { - group = GenericSources.group(project, root, name, displayName, null, null); + if (fo != null) { + group = GenericSources.group(project, fo, name, displayName, null, null); + } else { + group = new PotGroup(project, root, name, displayName); + } javaGroup.put(name, group); changed = true; + ProjectURLWatcher watch = project.getLookup().lookup(ProjectURLWatcher.class); + watch.addWatchedPath(root); } else { - if (!group.getRootFolder().equals(root)) { - group = GenericSources.group(project, root, name, displayName, null, null); + boolean pot = group instanceof PotGroup; + ProjectURLWatcher watch = project.getLookup().lookup(ProjectURLWatcher.class); + URI uri; + if (group instanceof PotentialSourceGroup) { + uri = ((PotentialSourceGroup)group).getPotencialRootFolder(); + } else { + uri = FileUtil.toFile(group.getRootFolder()).toURI(); + } + watch.removeWatchedPath(uri); + if ((fo != null && fo.isValid()) && (pot || !group.getRootFolder().equals(fo))) { + group = GenericSources.group(project, fo, name, displayName, null, null); javaGroup.put(name, group); changed = true; } + if ((fo == null || !fo.isValid())&& (!pot || !((PotGroup)group).getPotencialRootFolder().equals(root))) { + group = new PotGroup(project, root, name, displayName); + javaGroup.put(name, group); + changed = true; + } + if (group instanceof PotentialSourceGroup) { + uri = ((PotentialSourceGroup)group).getPotencialRootFolder(); + } else { + uri = FileUtil.toFile(group.getRootFolder()).toURI(); + } + watch.addWatchedPath(uri); + } return changed; } @@ -328,7 +370,6 @@ // Not on disk, include it. return true; } - } public void addPropertyChangeListener(PropertyChangeListener l) { @@ -340,4 +381,96 @@ } } + + public final class PotGroup implements PotentialSourceGroup { + + private final URI rootFolder; + private final String name; + private final String displayName; + private final Icon icon = null; + private final Icon openedIcon = null; + private NbMavenProject project; + private boolean fired = false; + + PotGroup(NbMavenProject p, URI rootFold, String nm, String displayNm/*, + Icon icn, Icon opened*/) { + project = p; + rootFolder = rootFold; + name = nm; + displayName = displayNm != null ? displayNm : NbBundle.getMessage(MavenSourcesImpl.class, "SG_Root_not_defined"); +// icon = icn; +// openedIcon = opened; } + + public FileObject getRootFolder() { + File fil = new File(rootFolder); + if (!fil.exists()) { + fil.mkdirs(); + if (!fired) { + fired = true; + Thread.dumpStack(); + RequestProcessor.getDefault().post(new Runnable() { + public void run() { + MavenSourcesImpl.this.checkChanges(true); + } + }); + } + } + return FileUtil.toFileObject(fil); + } + + public URI getPotencialRootFolder() { + return rootFolder; + } + + public String getName() { + return name; + } + + public String getDisplayName() { + return displayName; + } + + public Icon getIcon(boolean opened) { + return opened ? icon : openedIcon; + } + + public boolean contains(FileObject file) { + File fil = new File(rootFolder); + if (!fil.exists()) { + return false; + } + FileObject root = FileUtil.toFileObject(fil); + if (file != root && !FileUtil.isParentOf(root, file)) { + throw new IllegalArgumentException(); + } + if (project != null) { + if (file.isFolder() && file != project.getProjectDirectory() && ProjectManager.getDefault().isProject(file)) { + // #67450: avoid actually loading the nested project. + return false; + } + if (FileOwnerQuery.getOwner(file) != project) { + return false; + } + } + File f = FileUtil.toFile(file); + if (f != null) { + // MIXED, UNKNOWN, and SHARABLE -> include it + return SharabilityQuery.getSharability(f) != SharabilityQuery.NOT_SHARABLE; + } else { + // Not on disk, include it. + return true; + } + } + + public void addPropertyChangeListener(PropertyChangeListener l) { + // XXX should react to ProjectInformation changes + } + + public void removePropertyChangeListener(PropertyChangeListener l) { + // XXX + } + } + + +} Index: pom.xml =================================================================== --- pom.xml (revision 4369) +++ pom.xml (working copy) @@ -117,7 +117,7 @@ org.netbeans.api org-netbeans-modules-projectapi - ${netbeans.release} + RELEASE60-M10-SNAPSHOT org.netbeans.api