Lines 40-163
Link Here
|
40 |
* Portions Copyrighted 2008 Sun Microsystems, Inc. |
40 |
* Portions Copyrighted 2008 Sun Microsystems, Inc. |
41 |
*/ |
41 |
*/ |
42 |
|
42 |
|
43 |
package org.netbeans.modules.maven.queries; |
43 |
package org.netbeans.modules.maven; |
44 |
|
44 |
|
45 |
import java.beans.PropertyChangeEvent; |
45 |
import java.beans.PropertyChangeEvent; |
46 |
import java.beans.PropertyChangeListener; |
46 |
import java.beans.PropertyChangeListener; |
47 |
import java.io.File; |
47 |
import java.io.File; |
48 |
import java.net.URI; |
|
|
49 |
import java.util.ArrayList; |
50 |
import java.util.HashSet; |
51 |
import java.util.Iterator; |
52 |
import java.util.List; |
53 |
import java.util.Set; |
54 |
import java.util.logging.Level; |
48 |
import java.util.logging.Level; |
55 |
import java.util.logging.Logger; |
49 |
import java.util.logging.Logger; |
56 |
import javax.swing.event.ChangeListener; |
50 |
import javax.swing.event.ChangeListener; |
57 |
import org.netbeans.modules.maven.NbMavenProjectImpl; |
51 |
import org.apache.maven.artifact.Artifact; |
58 |
import org.netbeans.modules.maven.api.NbMavenProject; |
52 |
import org.apache.maven.artifact.repository.ArtifactRepository; |
59 |
import org.netbeans.api.project.Project; |
53 |
import org.netbeans.api.project.FileOwnerQuery; |
60 |
import org.netbeans.api.project.ProjectManager; |
|
|
61 |
import org.netbeans.spi.project.FileOwnerQueryImplementation; |
62 |
import org.netbeans.spi.project.SubprojectProvider; |
63 |
import org.openide.filesystems.FileObject; |
64 |
import org.openide.filesystems.FileUtil; |
54 |
import org.openide.filesystems.FileUtil; |
65 |
import org.openide.util.ChangeSupport; |
55 |
import org.openide.util.ChangeSupport; |
66 |
import org.openide.util.Lookup; |
|
|
67 |
import org.openide.util.Mutex.Action; |
68 |
import org.openide.util.lookup.ServiceProvider; |
69 |
|
70 |
|
56 |
|
71 |
/** |
57 |
/** |
72 |
* A global implementation of FileOwnerQueryImplementation, is required to link together the maven project |
58 |
* Links the Maven project with its artifact in the local repository. |
73 |
* and it's artifact in the maven repository. any other files shall be handled by the |
|
|
74 |
* default netbeans implementation. |
75 |
* |
76 |
* @author Milos Kleint |
77 |
*/ |
59 |
*/ |
78 |
@ServiceProvider(service=FileOwnerQueryImplementation.class, position=97) |
60 |
public class MavenFileOwner { |
79 |
public class MavenFileOwnerQueryImpl implements FileOwnerQueryImplementation { |
|
|
80 |
|
61 |
|
81 |
private Set<NbMavenProjectImpl> set; |
62 |
private final PropertyChangeListener projectListener; |
82 |
private final Object setLock = new Object(); |
|
|
83 |
|
84 |
private Set<NbMavenProjectImpl> cachedProjects; |
85 |
private Set<NbMavenProjectImpl> projectsToAddToCache; |
86 |
private final Object cacheLock = new Object(); |
87 |
|
88 |
private PropertyChangeListener projectListener; |
89 |
private final ChangeSupport cs = new ChangeSupport(this); |
63 |
private final ChangeSupport cs = new ChangeSupport(this); |
90 |
|
64 |
|
91 |
private static final Logger LOG = Logger.getLogger(MavenFileOwnerQueryImpl.class.getName()); |
65 |
private static final Logger LOG = Logger.getLogger(MavenFileOwner.class.getName()); |
92 |
|
66 |
|
93 |
public MavenFileOwnerQueryImpl() { |
67 |
private MavenFileOwner() { |
94 |
set = new HashSet<NbMavenProjectImpl>(); |
|
|
95 |
cachedProjects = null; |
96 |
projectsToAddToCache = null; |
97 |
projectListener = new PropertyChangeListener() { |
68 |
projectListener = new PropertyChangeListener() { |
98 |
public @Override void propertyChange(PropertyChangeEvent evt) { |
69 |
public @Override void propertyChange(PropertyChangeEvent evt) { |
99 |
if (NbMavenProjectImpl.PROP_PROJECT.equals(evt.getPropertyName())) { |
70 |
if (NbMavenProjectImpl.PROP_PROJECT.equals(evt.getPropertyName())) { |
100 |
Object evtSource = evt.getSource(); |
71 |
fireChange(); |
101 |
if (evtSource instanceof NbMavenProjectImpl) { |
|
|
102 |
// try adding the changed project and its subprojects again to cache |
103 |
// new subprojects might have been added/activated for the changed project |
104 |
synchronized (cacheLock) { |
105 |
if (null == projectsToAddToCache) { |
106 |
projectsToAddToCache = new HashSet<NbMavenProjectImpl>(1); |
107 |
} |
108 |
projectsToAddToCache.add((NbMavenProjectImpl) evtSource); |
109 |
} |
110 |
} |
111 |
} |
72 |
} |
112 |
} |
73 |
} |
113 |
}; |
74 |
}; |
114 |
} |
75 |
} |
115 |
|
76 |
|
116 |
public static MavenFileOwnerQueryImpl getInstance() { |
77 |
private static final MavenFileOwner IMPL = new MavenFileOwner(); |
117 |
Lookup.Result<FileOwnerQueryImplementation> implementations = |
78 |
public static MavenFileOwner getInstance() { |
118 |
Lookup.getDefault().lookup(new Lookup.Template<FileOwnerQueryImplementation>(FileOwnerQueryImplementation.class)); |
79 |
return IMPL; |
119 |
Iterator<? extends FileOwnerQueryImplementation> it = implementations.allInstances().iterator(); |
|
|
120 |
while (it.hasNext()) { |
121 |
FileOwnerQueryImplementation obj = it.next(); |
122 |
if (obj instanceof MavenFileOwnerQueryImpl) { |
123 |
return (MavenFileOwnerQueryImpl)obj; |
124 |
} |
125 |
} |
126 |
return null; |
127 |
} |
80 |
} |
128 |
|
81 |
|
129 |
public void addMavenProject(NbMavenProjectImpl project) { |
82 |
public void addMavenProject(NbMavenProjectImpl project) { |
130 |
synchronized (setLock) { |
83 |
Artifact art = project.getOriginalMavenProject().getArtifact(); |
131 |
if (!set.contains(project)) { |
84 |
if (art != null) { |
132 |
LOG.log(Level.FINE, "Adding Maven project:{0}", project.getArtifactRelativeRepositoryPath()); |
85 |
File f = art.getFile(); |
133 |
set.add(project); |
86 |
if (f == null) { // XXX seems to be the normal case - why? |
134 |
NbMavenProject.addPropertyChangeListener(project, projectListener); |
87 |
ArtifactRepository repo = project.getEmbedder().getLocalRepository(); |
|
|
88 |
f = new File(repo.getBasedir(), repo.pathOf(art)); |
135 |
} |
89 |
} |
|
|
90 |
File allArtifacts = FileUtil.normalizeFile(f.getParentFile()); |
91 |
LOG.log(Level.FINE, "registering {0} for {1}", new Object[] {allArtifacts, art}); |
92 |
FileOwnerQuery.markExternalOwner(allArtifacts.toURI(), project, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT); |
93 |
// Also claim other versions, though another project with that exact version might override you: |
94 |
FileOwnerQuery.markExternalOwner(allArtifacts.getParentFile().toURI(), project, FileOwnerQuery.EXTERNAL_ALGORITHM_TRANSIENT); |
95 |
} else { |
96 |
LOG.log(Level.WARNING, "no artifact for {0}", project); |
136 |
} |
97 |
} |
137 |
synchronized (cacheLock) { |
98 |
project.getProjectWatcher().removePropertyChangeListener(projectListener); |
138 |
// add the new project to cache incrementally if it has not been |
99 |
project.getProjectWatcher().addPropertyChangeListener(projectListener); |
139 |
// added to cache already from "set" where we added it just above |
|
|
140 |
if (null != cachedProjects && !cachedProjects.contains(project)) { |
141 |
if (null == projectsToAddToCache) { |
142 |
projectsToAddToCache = new HashSet<NbMavenProjectImpl>(1); |
143 |
} |
144 |
projectsToAddToCache.add(project); |
145 |
} |
146 |
} |
147 |
|
148 |
fireChange(); |
149 |
} |
150 |
public void removeMavenProject(NbMavenProjectImpl project) { |
151 |
synchronized (setLock) { |
152 |
if (set.contains(project)) { |
153 |
LOG.log(Level.FINE, "Removing Maven project:{0}", project.getArtifactRelativeRepositoryPath()); |
154 |
set.remove(project); |
155 |
NbMavenProject.removePropertyChangeListener(project, projectListener); |
156 |
} |
157 |
} |
158 |
synchronized (cacheLock) { |
159 |
cachedProjects = null; |
160 |
} |
161 |
fireChange(); |
100 |
fireChange(); |
162 |
} |
101 |
} |
163 |
|
102 |
|
Lines 173-312
Link Here
|
173 |
cs.fireChange(); |
112 |
cs.fireChange(); |
174 |
} |
113 |
} |
175 |
|
114 |
|
176 |
/** |
|
|
177 |
* get the list of currently opened maven projects.. kind of hack, but well.. |
178 |
*/ |
179 |
public Set<Project> getOpenedProjects() { |
180 |
synchronized (setLock) { |
181 |
return new HashSet<Project>(set); |
182 |
} |
183 |
} |
184 |
|
185 |
public @Override Project getOwner(URI uri) { |
186 |
LOG.log(Level.FINEST, "getOwner of uri={0}", uri); |
187 |
if (uri.getScheme() != null && "file".equals(uri.getScheme())) { //NOI18N |
188 |
File file = new File(uri); |
189 |
return getOwner(file); |
190 |
} |
191 |
return null; |
192 |
} |
193 |
|
194 |
public @Override Project getOwner(FileObject fileObject) { |
195 |
LOG.log(Level.FINEST, "getOwner of fileobject={0}", fileObject); |
196 |
File file = FileUtil.toFile(fileObject); |
197 |
if (file != null) { |
198 |
//logger.fatal("getOwner of fileobject=" + fileObject.getNameExt()); |
199 |
return getOwner(file); |
200 |
} |
201 |
return null; |
202 |
} |
203 |
|
204 |
private Project getOwner(File file) { |
205 |
//TODO check if the file is from local repo ?? |
206 |
LOG.log(Level.FINE, "Looking for owner of {0}", file); |
207 |
boolean passBasicCheck = false; |
208 |
String nm = file.getName(); |
209 |
File parentVer = file.getParentFile(); |
210 |
if (parentVer != null) { |
211 |
File parentArt = parentVer.getParentFile(); |
212 |
if (parentArt != null) { |
213 |
if (nm.startsWith(parentArt.getName() + "-" + parentVer.getName())) { |
214 |
passBasicCheck = true; |
215 |
} |
216 |
} |
217 |
} |
218 |
if (!passBasicCheck) { |
219 |
LOG.fine(" exiting early, not from local repository."); |
220 |
return null; |
221 |
} |
222 |
Set<NbMavenProjectImpl> currentProjects = getAllKnownProjects(); |
223 |
|
224 |
Iterator<NbMavenProjectImpl> it = currentProjects.iterator(); |
225 |
String filepath = file.getAbsolutePath().replace('\\', '/'); |
226 |
while (it.hasNext()) { |
227 |
NbMavenProjectImpl project = it.next(); |
228 |
String path = project.getArtifactRelativeRepositoryPath(); |
229 |
LOG.log(Level.FINEST, "matching againts known project {0}", path); |
230 |
if (filepath.endsWith(path)) { |
231 |
return project; |
232 |
} |
233 |
path = project.getTestArtifactRelativeRepositoryPath(); |
234 |
LOG.log(Level.FINEST, "matching againts known project''s test {0}", path); |
235 |
if (filepath.endsWith(path)) { |
236 |
return project; |
237 |
} |
238 |
} |
239 |
return null; |
240 |
|
241 |
} |
242 |
|
243 |
|
244 |
private Set<NbMavenProjectImpl> getAllKnownProjects() { |
245 |
return ProjectManager.mutex().readAccess(new Action<Set<NbMavenProjectImpl>>() { |
246 |
public @Override Set<NbMavenProjectImpl> run() { |
247 |
synchronized (cacheLock) { |
248 |
// is cachedProjects up-to-date? |
249 |
if (cachedProjects != null && null == projectsToAddToCache) { |
250 |
return new HashSet<NbMavenProjectImpl>(cachedProjects); |
251 |
} |
252 |
// cachedProjects empty? |
253 |
if (null == cachedProjects) { |
254 |
// full build of the cache |
255 |
Set<NbMavenProjectImpl> currentProjects; |
256 |
List<NbMavenProjectImpl> iterating; |
257 |
synchronized (setLock) { |
258 |
currentProjects = new HashSet<NbMavenProjectImpl>(set); |
259 |
iterating = new ArrayList<NbMavenProjectImpl>(set); |
260 |
} |
261 |
int index = 0; |
262 |
// iterate all opened projects and figure their subprojects.. |
263 |
// consider these as well. do so recursively. |
264 |
while (index < iterating.size()) { |
265 |
NbMavenProjectImpl prj = iterating.get(index); |
266 |
addSubProjects(currentProjects, iterating, prj); |
267 |
index = index + 1; |
268 |
} |
269 |
cachedProjects = currentProjects; |
270 |
projectsToAddToCache = null; |
271 |
} |
272 |
// non-empty projectsToAddToCache? |
273 |
if (null != projectsToAddToCache) { |
274 |
// incrementally adding to the cache |
275 |
Set<NbMavenProjectImpl> currentProjects; |
276 |
List<NbMavenProjectImpl> iterating; |
277 |
currentProjects = new HashSet<NbMavenProjectImpl>(cachedProjects); |
278 |
currentProjects.addAll(projectsToAddToCache); |
279 |
iterating = new ArrayList<NbMavenProjectImpl>(projectsToAddToCache); |
280 |
int index = 0; |
281 |
// iterate all new or changed (after propChange) projects |
282 |
// and figure their subprojects.. |
283 |
// consider these as well. do so recursively. |
284 |
while (index < iterating.size()) { |
285 |
NbMavenProjectImpl prj = iterating.get(index); |
286 |
addSubProjects(currentProjects, iterating, prj); |
287 |
index = index + 1; |
288 |
} |
289 |
cachedProjects = currentProjects; |
290 |
projectsToAddToCache = null; |
291 |
} |
292 |
return new HashSet<NbMavenProjectImpl>(cachedProjects); |
293 |
} |
294 |
} |
295 |
}); |
296 |
} |
297 |
|
298 |
private void addSubProjects(Set<NbMavenProjectImpl> finalset, List<NbMavenProjectImpl> iteratinglist, NbMavenProjectImpl prj) { |
299 |
SubprojectProvider sub = prj.getLookup().lookup(SubprojectProvider.class); |
300 |
if (sub != null) { |
301 |
Set<? extends Project> subs = sub.getSubprojects(); |
302 |
for (Project p : subs) { |
303 |
if (p instanceof NbMavenProjectImpl) { |
304 |
finalset.add((NbMavenProjectImpl) p); |
305 |
if (!iteratinglist.contains((NbMavenProjectImpl)p)) { |
306 |
iteratinglist.add((NbMavenProjectImpl) p); |
307 |
} |
308 |
} |
309 |
} |
310 |
} |
311 |
} |
312 |
} |
115 |
} |