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.search;
043:
044: import java.awt.EventQueue;
045: import java.io.IOException;
046: import java.nio.channels.ClosedByInterruptException;
047: import org.openide.filesystems.FileObject;
048: import org.openide.filesystems.FileUtil;
049: import org.openide.util.RequestProcessor;
050:
051: /**
052: * Fetches text from an Item off the event thread and passes it to a
053: * TextReceiever on the event thread.
054: *
055: * @author Tim Boudreau
056: */
057: final class TextFetcher implements Runnable {
058:
059: private final Item source;
060: private final TextDisplayer textDisplayer;
061: private final RequestProcessor.Task task;
062:
063: /** */
064: private TextDetail location; //accessed only from the event DT
065: /** */
066: private boolean done = false; //accessed only from the event DT
067: /** */
068: private boolean cancelled = false; //accessed only from the event DT
069:
070: /** */
071: private volatile String text = null;
072:
073: /**
074: */
075: TextFetcher(Item source, TextDisplayer receiver, RequestProcessor rp) {
076: assert EventQueue.isDispatchThread();
077:
078: this .source = source;
079: this .textDisplayer = receiver;
080: this .location = source.getLocation();
081: task = rp.post(this , 50);
082: }
083:
084: void cancel() {
085: assert EventQueue.isDispatchThread();
086:
087: cancelled = true;
088: task.cancel();
089: }
090:
091: public void run() {
092: if (EventQueue.isDispatchThread()) {
093: if (cancelled) {
094: return;
095: }
096:
097: FileObject fob = FileUtil.toFileObject(source.matchingObj
098: .getFile());
099: String mimeType = fob.getMIMEType();
100: //We don't want the swing html editor kit, and even if we
101: //do get it, it will frequently throw a random NPE
102: //in StyleSheet.removeHTMLTags that appears to be a swing bug
103: if ("text/html".equals(mimeType)) { //NOI18N
104: mimeType = "text/plain"; //NOI18N
105: }
106: textDisplayer.setText(text, fob.getMIMEType(),
107: getLocation());
108: done = true;
109: } else {
110:
111: /* called from the request processor's thread */
112:
113: if (Thread.interrupted()) {
114: return;
115: }
116:
117: String invalidityDescription = source.matchingObj
118: .getInvalidityDescription();
119: if (invalidityDescription != null) {
120: text = invalidityDescription;
121: } else {
122: try {
123: text = source.matchingObj.getText();
124: } catch (ClosedByInterruptException cbie) {
125: cancelled = true;
126: return;
127: } catch (IOException ioe) {
128: text = ioe.getLocalizedMessage();
129:
130: // cancel();
131: }
132: }
133:
134: if (Thread.interrupted()) {
135: return;
136: }
137:
138: EventQueue.invokeLater(this );
139: }
140: }
141:
142: /**
143: * If a new request comes to display the same file, just possibly at a
144: * different location, simply change the location we're scheduled to
145: * display and return true, else return false (in which case we'll be
146: * cancelled and a new request will be scheduled).
147: *
148: * @param item item to be shown
149: * @param receiver displayer that will actually show the item in the UI
150: * @return {@code true} if the previous item has not been shown yet
151: * and we are about to show the same file, just at a possible
152: * different location;
153: * {@code false} otherwise
154: */
155: boolean replaceLocation(Item item, TextDisplayer textDisplayer) {
156: assert EventQueue.isDispatchThread();
157:
158: if (done || (textDisplayer != this .textDisplayer)) {
159: return false;
160: }
161:
162: boolean result = source.matchingObj.getFile().equals(
163: item.matchingObj.getFile());
164: if (result) {
165: setLocation(item.getLocation());
166: task.schedule(50);
167: }
168: return result;
169: }
170:
171: private synchronized void setLocation(TextDetail location) {
172: assert EventQueue.isDispatchThread();
173:
174: this .location = location;
175: }
176:
177: private synchronized TextDetail getLocation() {
178: assert EventQueue.isDispatchThread();
179:
180: return location;
181: }
182: }
|