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-2006 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: package org.netbeans.modules.vmd.palette;
042:
043: import org.netbeans.api.java.classpath.ClassPath;
044: import org.netbeans.api.java.project.JavaProjectConstants;
045: import org.netbeans.api.java.source.ClasspathInfo;
046: import org.netbeans.api.java.source.CompilationController;
047: import org.netbeans.api.java.source.JavaSource;
048: import org.netbeans.api.java.source.Task;
049: import org.netbeans.api.project.Project;
050: import org.netbeans.api.project.SourceGroup;
051: import org.netbeans.modules.vmd.api.io.ProjectUtils;
052: import org.netbeans.modules.vmd.api.model.*;
053: import org.netbeans.modules.vmd.api.model.common.ActiveDocumentSupport;
054: import org.openide.filesystems.*;
055: import org.openide.util.Lookup;
056: import org.openide.util.WeakListeners;
057: import javax.swing.*;
058: import java.beans.PropertyChangeEvent;
059: import java.beans.PropertyChangeListener;
060: import java.io.IOException;
061: import java.lang.ref.WeakReference;
062: import java.util.*;
063: import java.util.concurrent.atomic.AtomicBoolean;
064: import org.openide.util.RequestProcessor;
065:
066: /**
067: *
068: * @author David Kaspar, Anton Chechel
069: */
070: public final class PaletteMap implements
071: ActiveDocumentSupport.Listener, DescriptorRegistryListener,
072: PropertyChangeListener {
073:
074: private static final PaletteMap INSTANCE = new PaletteMap();
075:
076: private final WeakHashMap<String, WeakReference<PaletteKit>> kitMap = new WeakHashMap<String, WeakReference<PaletteKit>>();
077: private String activeProjectID;
078: private DescriptorRegistry registeredRegistry;
079: private final AtomicBoolean requiresPaletteUpdate = new AtomicBoolean(
080: false);
081: private final Set<String> registeredProjects = new HashSet<String>();
082: private static RequestProcessor updateRP = new RequestProcessor(
083: "Update paletteKit"); // NOI18N
084:
085: private PaletteMap() {
086: ActiveDocumentSupport.getDefault().addActiveDocumentListener(
087: this );
088: }
089:
090: public static PaletteMap getInstance() {
091: return INSTANCE;
092: }
093:
094: public void activeDocumentChanged(
095: DesignDocument deactivatedDocument,
096: DesignDocument activatedDocument) {
097: if (activatedDocument == null) {
098: return;
099: }
100:
101: DescriptorRegistry currentRegistry = activatedDocument
102: .getDescriptorRegistry();
103: if (registeredRegistry != currentRegistry) {
104: if (registeredRegistry != null) {
105: registeredRegistry.removeRegistryListener(this );
106: }
107: registeredRegistry = currentRegistry;
108: if (registeredRegistry != null) {
109: registeredRegistry.addRegistryListener(this );
110: }
111: }
112:
113: String oldProjectID;
114: synchronized (this ) {
115: oldProjectID = activeProjectID;
116: activeProjectID = activatedDocument.getDocumentInterface()
117: .getProjectID();
118: }
119:
120: boolean isProjectIDChanged = !activeProjectID
121: .equals(oldProjectID);
122: if (isProjectIDChanged) {
123: registerClassPathListener(activatedDocument);
124: }
125:
126: updatePalette(activatedDocument, isProjectIDChanged);
127: }
128:
129: public void activeComponentsChanged(
130: Collection<DesignComponent> activeComponents) {
131: }
132:
133: public void descriptorRegistryUpdated() {
134: updatePalette(ActiveDocumentSupport.getDefault()
135: .getActiveDocument(), false);
136: }
137:
138: private void updatePalette(DesignDocument document,
139: boolean isProjectIDChanged) {
140: if (isProjectIDChanged) {
141: for (WeakReference<PaletteKit> kitReference : kitMap
142: .values()) {
143: PaletteKit kit = kitReference.get();
144: if (kit != null) {
145: kit.clearNodesStateCache();
146: }
147: }
148: }
149:
150: if (document == null) {
151: return;
152: }
153: WeakReference<PaletteKit> kitReference = kitMap.get(document
154: .getDocumentInterface().getProjectType());
155: if (kitReference == null) {
156: return;
157: }
158: PaletteKit kit = kitReference.get();
159: if (kit == null) {
160: return;
161: }
162: kit.setActiveDocument(document);
163: if (isProjectIDChanged) {
164: scheduleUpdateAfteCPScanned(document, kit);
165: } else {
166: kit.init();
167: }
168: }
169:
170: public synchronized PaletteKit getPaletteKitForProjectType(
171: String projectType) {
172: WeakReference<PaletteKit> reference = kitMap.get(projectType);
173: PaletteKit kit = reference != null ? reference.get() : null;
174: if (kit == null) {
175: kit = new PaletteKit(projectType);
176: kitMap.put(projectType, new WeakReference<PaletteKit>(kit));
177: }
178: return kit;
179: }
180:
181: void checkValidity(String projectType, Lookup lookup) {
182: WeakReference<PaletteKit> kitReference = kitMap
183: .get(projectType);
184: PaletteKit kit = kitReference != null ? kitReference.get()
185: : null;
186: if (kit == null) {
187: PaletteItemDataNode node = lookup
188: .lookup(PaletteItemDataNode.class);
189: if (node != null) {
190: node.setNeedCheck(false);
191: node.setValid(true);
192: }
193: } else {
194: kit.checkValidity(lookup);
195: }
196: }
197:
198: public void propertyChange(PropertyChangeEvent evt) {
199: schedulePaletteUpdate();
200: }
201:
202: private void scheduleUpdateAfteCPScanned(DesignDocument document,
203: final PaletteKit kit) {
204: final Project project = ProjectUtils.getProject(document);
205: final ClasspathInfo info = getClasspathInfo(project);
206: if (info == null) {
207: return;
208: }
209:
210: class UpdateTask implements Runnable,
211: Task<CompilationController> {
212:
213: public void run() {
214: try {
215: JavaSource.create(info).runWhenScanFinished(this ,
216: true);
217: } catch (IOException ex) {
218: Debug.warning(ex);
219: }
220: }
221:
222: public void run(CompilationController controller)
223: throws Exception {
224: kit.init();
225: }
226: }
227: updateRP.post(new UpdateTask());
228: }
229:
230: private void registerClassPathListener(DesignDocument document) {
231: final Project project = ProjectUtils.getProject(document);
232: final ClasspathInfo info = getClasspathInfo(project);
233: if (info == null) {
234: return;
235: }
236:
237: String projID = document.getDocumentInterface().getProjectID();
238: if (!registeredProjects.contains(projID)) {
239: Task<CompilationController> ct = new ListenerCancellableTask(
240: info);
241: try {
242: JavaSource.create(info).runUserActionTask(ct, true);
243: registeredProjects.add(projID);
244: } catch (IOException ex) {
245: Debug.warning(ex);
246: }
247: }
248: }
249:
250: private ClasspathInfo getClasspathInfo(Project project) {
251: if (project == null) {
252: return null;
253: }
254: SourceGroup group = getSourceGroup(project);
255: if (group == null) {
256: return null;
257: }
258: FileObject fileObject = group.getRootFolder();
259: return ClasspathInfo.create(fileObject);
260: }
261:
262: private SourceGroup getSourceGroup(Project project) {
263: SourceGroup[] sourceGroups = org.netbeans.api.project.ProjectUtils
264: .getSources(project).getSourceGroups(
265: JavaProjectConstants.SOURCES_TYPE_JAVA);
266: if (sourceGroups == null || sourceGroups.length < 1) {
267: return null;
268: }
269: return sourceGroups[0];
270: }
271:
272: private void schedulePaletteUpdate() {
273: if (requiresPaletteUpdate.getAndSet(true)) {
274: return;
275: }
276:
277: SwingUtilities.invokeLater(new Runnable() {
278:
279: public void run() {
280: while (requiresPaletteUpdate.getAndSet(false)) {
281: for (WeakReference<PaletteKit> kitReference : kitMap
282: .values()) {
283: PaletteKit kit = kitReference.get();
284: if (kit == null) {
285: continue;
286: }
287: kit.clearNodesStateCache();
288: // HINT refresh only visible palette
289: kit.refreshPaletteController();
290: }
291: }
292: }
293: });
294: }
295:
296: private final class ListenerCancellableTask implements
297: Task<CompilationController> {
298:
299: private ClasspathInfo info;
300:
301: public ListenerCancellableTask(ClasspathInfo info) {
302: this .info = info;
303: }
304:
305: public void run(CompilationController controller)
306: throws Exception {
307: ClassPath cp = info
308: .getClassPath(ClasspathInfo.PathKind.BOOT);
309: PropertyChangeListener wcl = WeakListeners.propertyChange(
310: PaletteMap.this, cp);
311: cp.addPropertyChangeListener(wcl);
312: }
313: }
314: }
|