001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.cnd.modelimpl.csm.core;
043:
044: import java.io.File;
045: import java.util.ArrayList;
046: import java.util.Collection;
047: import java.util.HashMap;
048: import java.util.HashSet;
049: import java.util.List;
050: import java.util.Map;
051: import java.util.Set;
052: import org.netbeans.modules.cnd.api.model.CsmProject;
053: import org.netbeans.modules.cnd.api.project.NativeFileItem;
054: import org.netbeans.modules.cnd.api.project.NativeProject;
055: import org.netbeans.modules.cnd.api.project.NativeProjectItemsListener;
056: import org.netbeans.modules.cnd.modelimpl.cache.CacheManager;
057: import org.netbeans.modules.cnd.modelimpl.debug.TraceFlags;
058: import org.netbeans.modules.cnd.modelimpl.repository.RepositoryUtils;
059: import org.openide.filesystems.FileChangeAdapter;
060: import org.openide.filesystems.FileEvent;
061: import org.openide.filesystems.FileObject;
062: import org.openide.filesystems.FileUtil;
063:
064: /**
065: * Implementation of the NativeProjectItemsListener interface
066: * @author Vladimir Kvashin
067: */
068: // package-local
069: class NativeProjectListenerImpl implements NativeProjectItemsListener {
070:
071: private final ModelImpl model;
072:
073: public NativeProjectListenerImpl(ModelImpl model) {
074: this .model = model;
075: }
076:
077: public void fileAdded(NativeFileItem fileItem) {
078: onProjectItemAdded(fileItem);
079: }
080:
081: public void filesAdded(List<NativeFileItem> fileItems) {
082: for (List<NativeFileItem> list : divideByProjects(fileItems)) {
083: onProjectItemAdded(list);
084: }
085: }
086:
087: public void fileRemoved(NativeFileItem fileItem) {
088: onProjectItemRemoved(fileItem);
089: }
090:
091: public void filesRemoved(List<NativeFileItem> fileItems) {
092: for (List<NativeFileItem> list : divideByProjects(fileItems)) {
093: onProjectItemRemoved(list);
094: }
095: }
096:
097: public void fileRenamed(String oldPath, NativeFileItem newFileIetm) {
098: onProjectItemRenamed(oldPath, newFileIetm);
099: }
100:
101: public void filePropertiesChanged(NativeFileItem fileItem) {
102: onProjectItemChanged(fileItem);
103: }
104:
105: public void filesPropertiesChanged(
106: final List<NativeFileItem> fileItems) {
107: // FIXUP for #109425
108: ModelImpl.instance().enqueueModelTask(new Runnable() {
109: public void run() {
110: for (List<NativeFileItem> list : divideByProjects(fileItems)) {
111: onProjectItemChanged(list);
112: }
113: }
114: }, "Applying property changes"); // NOI18N
115:
116: }
117:
118: public void filesPropertiesChanged() {
119: // FIXUP for #109425
120: ModelImpl.instance().enqueueModelTask(new Runnable() {
121: public void run() {
122: for (NativeProject project : getNativeProjects()) {
123: ArrayList<NativeFileItem> list = new ArrayList<NativeFileItem>();
124: for (NativeFileItem item : project.getAllFiles()) {
125: if (!item.isExcluded()) {
126: switch (item.getLanguage()) {
127: case C:
128: case CPP:
129: list.add(item);
130: break;
131: default:
132: break;
133: }
134: }
135: }
136: filesPropertiesChanged(list);
137: }
138: }
139: }, "Applying property changes"); // NOI18N
140: }
141:
142: public void projectDeleted(NativeProject nativeProject) {
143: RepositoryUtils.onProjectDeleted(nativeProject);
144: }
145:
146: private Collection<List<NativeFileItem>> divideByProjects(
147: List<NativeFileItem> fileItems) {
148: Map<NativeProject, List<NativeFileItem>> res = new HashMap<NativeProject, List<NativeFileItem>>();
149: for (NativeFileItem item : fileItems) {
150: NativeProject nativeProject = item.getNativeProject();
151: if (nativeProject != null) {
152: List<NativeFileItem> list = res.get(nativeProject);
153: if (list == null) {
154: list = new ArrayList<NativeFileItem>();
155: res.put(nativeProject, list);
156: }
157: list.add(item);
158: }
159: }
160: return res.values();
161: }
162:
163: protected void onProjectItemAdded(final NativeFileItem item) {
164: try {
165: final ProjectBase project = getProject(item, true);
166: if (project != null) {
167: project.onFileAdded(item);
168: }
169: } catch (Exception e) {
170: e.printStackTrace(System.err);
171: }
172: }
173:
174: protected void onProjectItemAdded(final List<NativeFileItem> items) {
175: if (items.size() > 0) {
176: try {
177: final ProjectBase project = getProject(items.get(0),
178: true);
179: if (project != null) {
180: project.onFileAdded(items);
181: }
182: } catch (Exception e) {
183: e.printStackTrace(System.err);
184: }
185: }
186: }
187:
188: protected void onProjectItemRemoved(final NativeFileItem item) {
189: try {
190: final ProjectBase project = getProject(item, false);
191: if (project != null) {
192: final File file = item.getFile();
193: FileObject fo = FileUtil.toFileObject(file);
194: if (fo != null) {
195: fo
196: .addFileChangeListener(FileUtil
197: .weakFileChangeListener(
198: new FileDeleteListener(
199: project), fo));
200: }
201: project.onFileRemoved(file);
202: }
203: } catch (Exception e) {
204: //TODO: FIX (most likely in Makeproject: path == null in this situation,
205: //this cause NPE
206: e.printStackTrace(System.err);
207: }
208: }
209:
210: protected void onProjectItemRemoved(final List<NativeFileItem> items) {
211: if (items.size() > 0) {
212: try {
213: final ProjectBase project = getProject(items.get(0),
214: false);
215: if (project != null) {
216: project.onFileRemoved(items);
217: }
218: } catch (Exception e) {
219: e.printStackTrace(System.err);
220: }
221: }
222: }
223:
224: protected void onProjectItemRenamed(String oldPath,
225: NativeFileItem newFileIetm) {
226: try {
227: final ProjectBase project = getProject(newFileIetm, false);
228: if (project != null) {
229: File file = FileUtil.normalizeFile(new File(oldPath));
230: project.onFileRemoved(file);
231: project.onFileAdded(newFileIetm);
232: }
233: } catch (Exception e) {
234: //TODO: FIX (most likely in Makeproject: path == null in this situation,
235: //this cause NPE
236: e.printStackTrace(System.err);
237: }
238: }
239:
240: protected void onProjectItemChanged(final NativeFileItem item) {
241: // invalidate cache for this file
242: if (TraceFlags.USE_AST_CACHE) {
243: CacheManager.getInstance().invalidate(
244: item.getFile().getAbsolutePath());
245: } else {
246: // do not need to invalidate APT, it is preprocessor neutral
247: }
248: try {
249: final ProjectBase project = getProject(item, false);
250: if (project != null) {
251: project.onFilePropertyChanged(item);
252: }
253: } catch (Exception e) {
254: //TODO: FIX (most likely in Makeproject: path == null in this situation,
255: //this cause NPE
256: e.printStackTrace(System.err);
257: }
258: }
259:
260: protected void onProjectItemChanged(final List<NativeFileItem> items) {
261: if (items.size() > 0) {
262: try {
263: final ProjectBase project = getProject(items.get(0),
264: true);
265: if (project != null && project.isValid()) {
266: if (project instanceof ProjectImpl) {
267: LibraryManager.getInstance()
268: .onProjectPropertyChanged(
269: project.getUID());
270: }
271: project.onFilePropertyChanged(items);
272: }
273: } catch (Exception e) {
274: e.printStackTrace(System.err);
275: }
276: }
277: }
278:
279: private ProjectBase getProject(NativeFileItem nativeFile,
280: boolean createIfNeeded) {
281: assert nativeFile != null : "must not be null";
282: assert nativeFile.getFile() != null : "must be associated with valid file";
283: assert nativeFile.getNativeProject() != null : "must have container project";
284: ProjectBase csmProject = null;
285: try {
286: NativeProject nativeProject = nativeFile.getNativeProject();
287: assert (nativeProject != null) : "NativeFileItem should never return null NativeProject";
288: if (nativeProject != null) {
289: csmProject = createIfNeeded ? (ProjectBase) model
290: ._getProject(nativeProject)
291: : (ProjectBase) model
292: .findProject(nativeProject);
293: }
294: } catch (NullPointerException ex) {
295: ex.printStackTrace();
296: }
297: return csmProject;
298: }
299:
300: private Collection<NativeProject> getNativeProjects() {
301: Set<NativeProject> res = new HashSet<NativeProject>();
302: for (CsmProject project : model.projects()) {
303: Object prj = project.getPlatformProject();
304: if (prj instanceof NativeProject) {
305: res.add((NativeProject) prj);
306: }
307: }
308: return res;
309: }
310:
311: private static class FileDeleteListener extends FileChangeAdapter {
312: private final ProjectBase project;
313:
314: public FileDeleteListener(ProjectBase project) {
315: this .project = project;
316: }
317:
318: @Override
319: public void fileDeleted(FileEvent fe) {
320: FileObject fo = fe.getFile();
321: project.onFileRemoved(FileUtil.toFile(fo));
322: fo.removeFileChangeListener(this);
323: }
324: };
325:
326: }
|