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.server.output;
043:
044: import java.io.IOException;
045: import java.util.concurrent.atomic.AtomicLong;
046: import java.util.logging.Level;
047: import java.util.logging.Logger;
048: import org.netbeans.api.server.output.LineProcessor;
049: import org.netbeans.api.server.output.LineReader;
050: import org.netbeans.api.server.output.ReaderManager;
051: import org.openide.util.Parameters;
052:
053: /**
054: *
055: * This class is <i>ThreadSafe</i>.
056: * @author Petr Hejl
057: */
058: public class ReaderThread extends Thread {
059:
060: private static final Logger LOGGER = Logger
061: .getLogger(ReaderThread.class.getName());
062:
063: private static final int DELAY = 500;
064:
065: private static final AtomicLong THREAD_COUNTER = new AtomicLong(0);
066:
067: private final ReaderManager readerManager;
068:
069: private final LineReader lineReader;
070:
071: private final LineProcessor lineProcessor;
072:
073: public ReaderThread(ReaderManager readerManager,
074: LineReader lineReader) {
075: this (readerManager, lineReader, null);
076: }
077:
078: public ReaderThread(ReaderManager readerManager,
079: LineReader lineReader, LineProcessor lineProcessor) {
080:
081: super ("line_reader_thread_" + THREAD_COUNTER.incrementAndGet()); // NOI18N
082:
083: Parameters.notNull("readerManager", readerManager);
084: Parameters.notNull("lineReader", lineReader);
085:
086: this .setDaemon(true);
087: this .readerManager = readerManager;
088: this .lineReader = lineReader;
089: this .lineProcessor = lineProcessor;
090: }
091:
092: @Override
093: public void run() {
094: boolean interrupted = false;
095: try {
096: while (true) {
097: if (Thread.interrupted()) {
098: interrupted = true;
099: break;
100: }
101:
102: lineReader.readLines(lineProcessor, false);
103:
104: try {
105: // give the producer some time to write the output
106: Thread.sleep(DELAY);
107: } catch (InterruptedException e) {
108: interrupted = true;
109: break;
110: }
111: }
112:
113: lineReader.readLines(lineProcessor, true);
114: } catch (Exception ex) {
115: if (!interrupted && !Thread.currentThread().isInterrupted()) {
116: LOGGER.log(Level.INFO, null, ex);
117: }
118: } finally {
119: // perform cleanup
120: try {
121: lineReader.close();
122: } catch (IOException ex) {
123: LOGGER.log(Level.INFO, null, ex);
124: } finally {
125: Accessor.DEFAULT.notifyFinished(readerManager, this );
126: if (interrupted) {
127: Thread.currentThread().interrupt();
128: }
129: }
130: }
131: }
132:
133: /**
134: * The accessor pattern class.
135: */
136: public abstract static class Accessor {
137:
138: /** The default accessor. */
139: public static Accessor DEFAULT;
140:
141: static {
142: // invokes static initializer of ReaderManager.class
143: // that will assign value to the DEFAULT field above
144: Class c = ReaderManager.class;
145: try {
146: Class.forName(c.getName(), true, c.getClassLoader());
147: } catch (ClassNotFoundException ex) {
148: assert false : ex;
149: }
150: }
151:
152: /**
153: * Accessor to notify the manager about finished thread.
154: *
155: * @param manager the manager to notify
156: * @param thread the thread that was finished
157: */
158: public abstract void notifyFinished(ReaderManager manager,
159: ReaderThread thread);
160:
161: }
162: }
|