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.napi.gsfret.source.support;
042:
043: import java.beans.PropertyChangeEvent;
044: import java.beans.PropertyChangeListener;
045: import java.util.ArrayList;
046: import java.util.Arrays;
047: import java.util.Collection;
048: import java.util.Collections;
049: import java.util.HashMap;
050: import java.util.LinkedList;
051: import java.util.List;
052: import java.util.Map;
053: import java.util.logging.Level;
054: import java.util.logging.Logger;
055: import javax.swing.JEditorPane;
056: import javax.swing.event.ChangeEvent;
057: import javax.swing.event.ChangeListener;
058: import javax.swing.text.Document;
059: import javax.swing.text.JTextComponent;
060: import org.netbeans.api.editor.EditorRegistry;
061: import org.netbeans.editor.Registry;
062: import org.netbeans.modules.gsf.LanguageRegistry;
063: import org.netbeans.napi.gsfret.source.Source;
064: import org.openide.filesystems.FileObject;
065: import org.openide.filesystems.FileUtil;
066: import org.openide.loaders.DataObject;
067: import org.openide.util.Parameters;
068:
069: /**
070: * This file is originally from Retouche, the Java Support
071: * infrastructure in NetBeans. I have modified the file as little
072: * as possible to make merging Retouche fixes back as simple as
073: * possible.
074: *
075: *
076: * @author Jan Lahoda
077: */
078: class OpenedEditors implements PropertyChangeListener {
079:
080: private List<JTextComponent> visibleEditors = new ArrayList<JTextComponent>();
081: private Map<JTextComponent, FileObject> visibleEditors2Files = new HashMap<JTextComponent, FileObject>();
082: private List<ChangeListener> listeners = new ArrayList<ChangeListener>();
083:
084: private static OpenedEditors DEFAULT;
085:
086: private OpenedEditors() {
087: EditorRegistry
088: .addPropertyChangeListener(new PropertyChangeListener() {
089: public void propertyChange(PropertyChangeEvent evt) {
090: stateChanged();
091: }
092: });
093: }
094:
095: public static synchronized OpenedEditors getDefault() {
096: if (DEFAULT == null) {
097: DEFAULT = new OpenedEditors();
098: }
099:
100: return DEFAULT;
101: }
102:
103: public synchronized void addChangeListener(ChangeListener l) {
104: listeners.add(l);
105: }
106:
107: public synchronized void removeChangeListener(ChangeListener l) {
108: listeners.remove(l);
109: }
110:
111: private void fireChangeEvent() {
112: ChangeEvent e = new ChangeEvent(this );
113: List<ChangeListener> listenersCopy = null;
114:
115: synchronized (this ) {
116: listenersCopy = new ArrayList(listeners);
117: }
118:
119: for (ChangeListener l : listenersCopy) {
120: l.stateChanged(e);
121: }
122: }
123:
124: public synchronized List<JTextComponent> getVisibleEditors() {
125: return Collections.unmodifiableList(visibleEditors);
126: }
127:
128: public synchronized Collection<FileObject> getVisibleEditorsFiles() {
129: return Collections.unmodifiableCollection(visibleEditors2Files
130: .values());
131: }
132:
133: public synchronized void stateChanged() {
134: for (JTextComponent c : visibleEditors) {
135: c.removePropertyChangeListener(this );
136: visibleEditors2Files.remove(c);
137: }
138:
139: visibleEditors.clear();
140:
141: JTextComponent editor = EditorRegistry.lastFocusedComponent();
142:
143: FileObject fo = editor != null ? getFileObject(editor) : null;
144: if (editor instanceof JEditorPane && fo != null
145: && Source.forFileObject(fo) != null) {
146: visibleEditors.add(editor);
147: }
148:
149: for (JTextComponent c : visibleEditors) {
150: c.addPropertyChangeListener(this );
151: visibleEditors2Files.put(c, getFileObject(c));
152: }
153:
154: fireChangeEvent();
155: }
156:
157: public synchronized void propertyChange(PropertyChangeEvent evt) {
158: JTextComponent c = (JTextComponent) evt.getSource();
159: FileObject originalFile = visibleEditors2Files.get(c);
160: FileObject nueFile = getFileObject(c);
161:
162: if (originalFile != nueFile) {
163: visibleEditors2Files.put(c, nueFile);
164: fireChangeEvent();
165: }
166: }
167:
168: static FileObject getFileObject(JTextComponent pane) {
169: Object source = pane.getDocument().getProperty(
170: Document.StreamDescriptionProperty);
171:
172: if (!(source instanceof DataObject)) {
173: return null;
174: }
175:
176: DataObject file = (DataObject) source;
177:
178: if (file != null) {
179: return file.getPrimaryFile();
180: }
181:
182: return null;
183: }
184:
185: /**Checks if the given file is supported. See {@link #filterSupportedMIMETypes}
186: * for more details.
187: *
188: * @param file to check
189: * @param type the type to check for the {@link SupportedMimeTypes} annotation
190: * @return true if and only if the given file is supported (see {@link #filterSupportedMIMETypes})
191: * @throws NullPointerException if <code>file == null</code> or <code>type == null</code>
192: */
193: public static boolean isSupported(FileObject file,
194: String... mimeTypes) throws NullPointerException {
195: Parameters.notNull("files", file);
196:
197: return !filterSupportedMIMETypes(
198: Collections.singletonList(file), mimeTypes).isEmpty();
199: }
200:
201: /**Filter unsupported files from the <code>files</code> parameter. A supported file
202: * <code>f</code> is defined as follows:
203: * <ul>
204: * <li><code>JavaSource.forFileObject(f) != null</code></li>
205: * <li>If the <code>type</code> is annotated with the {@link SupportedMimeTypes} annotation,
206: * the file is supported if <code>type.getAnnotation(SupportedMimeTypes.class).value()</code>
207: * contains <code>FileUtil.getMIMEType(f)</code>.
208: * </li>
209: * <li>If the <code>type</code> is not annotated with the {@link SupportedMimeTypes} annotation,
210: * the file is supported if <code>FileUtil.getMIMEType(f) == "text/x-java"</code>.
211: * </ul>
212: *
213: * @param files the list of files to filter
214: * @param type the type to check for the {@link SupportedMimeTypes} annotation
215: * @return list of files that are supported (see above).
216: * @throws NullPointerException if <code>files == null</code> or <code>type == null</code>
217: */
218: public static List<FileObject> filterSupportedMIMETypes(
219: Collection<FileObject> files, String... mimeTypes)
220: throws NullPointerException {
221: Parameters.notNull("files", files);
222:
223: // BEGIN TOR MODIFICATIONS
224: List<FileObject> result = new LinkedList<FileObject>();
225: for (FileObject f : files) {
226: Logger.getLogger(OpenedEditors.class.getName()).log(
227: Level.FINER, "analyzing={0}", f);
228:
229: if (!LanguageRegistry.getInstance().isSupported(
230: f.getMIMEType())) {
231: continue;
232: }
233: if (Source.forFileObject(f) == null)
234: continue;
235:
236: result.add(f);
237: continue;
238: }
239: // END TOR MODIFICATIONS
240:
241: return result;
242: }
243:
244: // static {
245: // SourceSupportAccessor.ACCESSOR = new SourceSupportAccessor() {
246: // public Collection<FileObject> getVisibleEditorsFiles() {
247: // return OpenedEditors.getDefault().getVisibleEditorsFiles();
248: // }
249: // };
250: // }
251: }
|