Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.projectapi.nb;

import java.beans.PropertyChangeListener;
import javax.swing.Icon;
import javax.swing.event.ChangeListener;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.Sources;
import org.netbeans.spi.project.support.GenericSources;
import org.netbeans.spi.project.support.LookupProviderSupport;
import org.openide.filesystems.FileObject;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;

final class FallbackProject implements Project, ProjectInformation, Sources {
private static final String DASHNAME = "org-netbeans-modules-project-fallback"; // NOI18N
private static final String ICON = "org/netbeans/modules/projectapi/nb/fallback.svg"; // NOI18N

private final FileObject dir;
private final Lookup lkp;
private final SourceGroup genericGroup;

public FallbackProject(FileObject dir) {
this.dir = dir;
this.genericGroup = GenericSources.group(
this, dir,
Sources.TYPE_GENERIC, getDisplayName(),
getIcon(), getIcon()
);
Lookup basicLookup = Lookups.fixed(
this,
dir,
LookupProviderSupport.createActionProviderMerger()
);
this.lkp = LookupProviderSupport.createCompositeLookup(basicLookup, "Projects/" + DASHNAME + "/Lookup");
}

@Override
public FileObject getProjectDirectory() {
return dir;
}

@Override
public Lookup getLookup() {
return lkp;
}

@Override
public String getName() {
return dir.getNameExt();
}

@Override
@NbBundle.Messages({
"# {0} - name of the folder",
"CTL_FallbackProjectDisplayName=Folder {0}"
})
public String getDisplayName() {
return Bundle.CTL_FallbackProjectDisplayName(getName());
}

@Override
public Icon getIcon() {
Icon icon = ImageUtilities.loadIcon(ICON);
assert icon != null;
return icon;
}

@Override
public Project getProject() {
return this;
}

@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
}

@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
}

@Override
public SourceGroup[] getSourceGroups(String type) {
if (Sources.TYPE_GENERIC.equals(type)) {
return new SourceGroup[] { genericGroup };
} else {
return new SourceGroup[0];
}
}

@Override
public void addChangeListener(ChangeListener listener) {
}

@Override
public void removeChangeListener(ChangeListener listener) {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
* @author Jesse Glick
*/
@ServiceProvider(service = ProjectManagerImplementation.class, position = 1000)
public final class NbProjectManager implements ProjectManagerImplementation {
public final class NbProjectManager implements ProjectManagerImplementation.WithFallback {

// XXX need to figure out how to convince the system that a Project object is modified
// so that Save All and the exit dialog work... could temporarily use a DataLoader
Expand All @@ -90,7 +90,7 @@ public void resultChanged(LookupEvent e) {
}
});
}

private static enum LoadStatus {
/**
* Marker for a directory which is known to not be a project.
Expand Down Expand Up @@ -212,6 +212,17 @@ public Mutex getMutex(
*/
@Override
public Project findProject(final FileObject projectDirectory) throws IOException, IllegalArgumentException {
return findProjectImpl(projectDirectory, false);
}

@Override
public Project findProjectOrFallback(FileObject projectDirectory) throws IOException, IllegalArgumentException {
var found = findProjectImpl(projectDirectory, true);
assert found != null;
return found;
}

private Project findProjectImpl(FileObject projectDirectory, boolean fallback) throws IOException, IllegalArgumentException {
Parameters.notNull("projectDirectory", projectDirectory); //NOI18N
try {
return getMutex().readAccess(new Mutex.ExceptionAction<Project>() {
Expand Down Expand Up @@ -250,11 +261,17 @@ public Project run() throws IOException {
assert !LoadStatus.LOADING_PROJECT.is(o);
wasSomeSuchProject = LoadStatus.SOME_SUCH_PROJECT.is(o);
if (LoadStatus.NO_SUCH_PROJECT.is(o)) {
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "findProject({0}) in {1}: NO_SUCH_PROJECT", new Object[] {projectDirectory, Thread.currentThread().getName()});
if (fallback) {
// treat a not checked project yet
o = null;
} else {
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "findProject({0}) in {1}: NO_SUCH_PROJECT", new Object[]{projectDirectory, Thread.currentThread().getName()});
}
return null;
}
return null;
} else if (o != null && !LoadStatus.SOME_SUCH_PROJECT.is(o)) {
}
if (o != null && !LoadStatus.SOME_SUCH_PROJECT.is(o)) {
Project p = o.first().get();
if (p != null) {
if (LOG.isLoggable(Level.FINE)) {
Expand Down Expand Up @@ -285,7 +302,7 @@ public Project run() throws IOException {
}
boolean resetLP = false;
try {
Project p = createProject(projectDirectory);
Project p = createProject(projectDirectory, fallback);
//Thread.dumpStack();
synchronized (dir2Proj) {
dir2Proj.notifyAll();
Expand Down Expand Up @@ -366,7 +383,7 @@ public Project run() throws IOException {
* @return a project made from it, or null if it is not recognized
* @throws IOException if there was a problem loading the project
*/
private Project createProject(FileObject dir) throws IOException {
private Project createProject(FileObject dir, boolean fallback) throws IOException {
assert dir != null;
assert dir.isFolder();
assert getMutex().isReadAccess();
Expand All @@ -384,7 +401,14 @@ private Project createProject(FileObject dir) throws IOException {
return p;
}
}
return null;
if (fallback) {
FallbackProject p = new FallbackProject(dir);
proj2Factory.put(p, null);
state.attach(p);
return p;
} else {
return null;
}
}


Expand Down Expand Up @@ -489,11 +513,28 @@ public void clearNonProjectCache() {
LoadStatus.NO_SUCH_PROJECT.wrap(),
LoadStatus.SOME_SUCH_PROJECT.wrap(),
}));
// XXX remove everything too? but then e.g. AntProjectFactorySingleton
// will stay while its delegates are changed, which does no good
// XXX should there be any way to signal that a particular
// folder should be "reloaded" by a new factory?
}
MUTEX.postReadRequest(() -> {
synchronized (dir2Proj) {
// check if FallbackProject is still needed

Iterator<Map.Entry<FileObject, Union2<Reference<Project>, LoadStatus>>> it = dir2Proj.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<FileObject, Union2<Reference<Project>, LoadStatus>> entry = it.next();
if (entry.getValue().hasFirst() && entry.getValue().first().get() instanceof FallbackProject fallback) {
Result result = checkForProject(fallback.getProjectDirectory());
if (result != null) {
it.remove();
}
}
}
}
});

// XXX remove everything too? but then e.g. AntProjectFactorySingleton
// will stay while its delegates are changed, which does no good
// XXX should there be any way to signal that a particular
// folder should be "reloaded" by a new factory?
}

private final class ProjectStateImpl implements ProjectState {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading