All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.tomcat5.util.ServerLog Maven / Gradle / Ivy

There is a newer version: RELEASE230
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/*
 * ServerLog.java
 *
 * Created on September 13, 2004, 7:13 PM
 */

package org.netbeans.modules.tomcat5.util;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.extexecution.input.InputProcessors;
import org.netbeans.api.extexecution.input.InputReaderTask;
import org.netbeans.api.extexecution.input.InputReaders;
import org.netbeans.api.extexecution.input.LineProcessor;
import org.openide.modules.InstalledFileLocator;
import org.openide.util.NbBundle;
import org.openide.windows.InputOutput;
import org.openide.windows.OutputWriter;
import org.netbeans.api.java.classpath.GlobalPathRegistry;
import org.netbeans.modules.j2ee.deployment.plugins.api.UISupport;
import org.netbeans.modules.tomcat5.deploy.TomcatManager;
import org.netbeans.modules.tomcat5.util.LogSupport.LineInfo;
import org.openide.util.Exceptions;

/**
 * Tomcat server log reads from the Tomcat standard and error output and 
 * writes to output window.
 */ 
class ServerLog {
    private final InputOutput io;
    private final OutputWriter writer;
    private final OutputWriter errorWriter;
    private final InputReaderTask inReader;
    private final InputReaderTask errReader;
    private final boolean autoFlush;
    private final boolean takeFocus;
    private final ServerLogSupport logSupport;
    private final TomcatManager tomcatManager;
    private final AtomicInteger runningTasks = new AtomicInteger(2);

    /* GuardedBy("this") */
    private ExecutorService service;

    /**
     * Tomcat server log reads from the Tomcat standard and error output and 
     * writes to output window.
     * 
     * @param tomcatManager Tomcat deployment manager
     * @param displayName output window display name.
     * @param in Tomcat standard output reader.
     * @param err Tomcat error output reader.
     * @param autoFlush should we flush after a change?
     * @param takeFocus should be the output window made visible after each
     *        changed?
     */
    public ServerLog(TomcatManager tomcatManager, String displayName, Reader in, Reader err, boolean autoFlush,
            boolean takeFocus) {
        inReader = InputReaderTask.newDrainingTask(InputReaders.forReader(in),
                InputProcessors.bridge(new AnalyzingLineProcessor()));

        errReader = InputReaderTask.newDrainingTask(InputReaders.forReader(err),
                InputProcessors.bridge(new AnalyzingLineProcessor()));
        this.autoFlush = autoFlush;
        this.takeFocus = takeFocus;
        this.tomcatManager = tomcatManager;
        io = UISupport.getServerIO(tomcatManager.getUri());
        try {
            io.getOut().reset();
        } 
        catch (IOException e) {
            Logger.getLogger(ServerLog.class.getName()).log(Level.INFO, null, e);
        }
        writer = io.getOut();
        errorWriter = io.getErr();
        io.select();
        logSupport = new ServerLogSupport();
    }

    public void start() {
        synchronized (this) {
            service = Executors.newFixedThreadPool(2);
            service.submit(inReader);
            service.submit(errReader);
        }
    }
    
    /**
     * Test whether ServerLog thread is still running.
     *
     * @return true if the thread is still running, false
     *         otherwise.
     */
    public boolean isRunning() {
        synchronized (this) {
            return !service.isShutdown();
        }
    }
    
    /**
     * Make the log tab visible.
     */
    public void takeFocus() {
        io.select();
    }

    public void stop() {
        AccessController.doPrivileged( (PrivilegedAction) () -> {
            synchronized (ServerLog.this) {
                service.shutdownNow();
            }
            return null;
        });
    }
    
    /**
     * Support class for Tomcat server output log line analyzation and for 
     * creating links in the output window.
     */
    static class ServerLogSupport extends LogSupport {
        private String prevMessage;
        private GlobalPathRegistry globalPathRegistry = GlobalPathRegistry.getDefault();
        
        public LineInfo analyzeLine(String logLine) {
            String path = null;
            int line = -1;
            String message = null;
            boolean error = false;
            boolean accessible = false;

            logLine = logLine.trim();
            int lineLenght = logLine.length();

            // look for unix file links (e.g. /foo/bar.java:51: 'error msg')
            if (logLine.startsWith("/")) {
                error = true;
                int colonIdx = logLine.indexOf(":");
                if (colonIdx > -1) {
                    path = logLine.substring(0, colonIdx);
                    accessible = true;
                    if (lineLenght > colonIdx) {
                        int nextColonIdx = logLine.indexOf(":", colonIdx + 1);
                        if (nextColonIdx > -1) {
                            String lineNum = logLine.substring(colonIdx + 1, nextColonIdx);
                            try {
                                line = Integer.valueOf(lineNum);
                            } catch(NumberFormatException nfe) { 
                                // ignore it
                                Logger.getLogger(ServerLog.class.getName()).log(Level.INFO, null, nfe);
                            }
                            if (lineLenght > nextColonIdx) {
                                message = logLine.substring(nextColonIdx + 1, lineLenght); 
                            }
                        }
                    }
                }
            }
            // look for windows file links (e.g. c:\foo\bar.java:51: 'error msg')
            else if (lineLenght > 3 && Character.isLetter(logLine.charAt(0))
                        && (logLine.charAt(1) == ':') && (logLine.charAt(2) == '\\')) {
                error = true;
                int secondColonIdx = logLine.indexOf(":", 2);
                if (secondColonIdx > -1) {
                    path = logLine.substring(0, secondColonIdx);
                    accessible = true;
                    if (lineLenght > secondColonIdx) {
                        int thirdColonIdx = logLine.indexOf(":", secondColonIdx + 1);
                        if (thirdColonIdx > -1) {
                            String lineNum = logLine.substring(secondColonIdx + 1, thirdColonIdx);
                            try {
                                line = Integer.valueOf(lineNum);
                            } catch(NumberFormatException nfe) { 
                                // ignore it
                                Logger.getLogger(ServerLog.class.getName()).log(Level.INFO, null, nfe);
                            }
                            if (lineLenght > thirdColonIdx) {
                                message = logLine.substring(thirdColonIdx + 1, lineLenght);
                            }
                        }
                    }
                }
            }
            // look for stacktrace links (e.g. at java.lang.Thread.run(Thread.java:595)
            //                                 at t.HyperlinkTest$1.run(HyperlinkTest.java:24))
            else if (logLine.startsWith("at ") && lineLenght > 3) {
                error = true;
                int parenthIdx = logLine.indexOf("(");
                if (parenthIdx > -1) {
                    String classWithMethod = logLine.substring(3, parenthIdx);
                    int lastDotIdx = classWithMethod.lastIndexOf(".");
                    if (lastDotIdx > -1) {  
                        int lastParenthIdx = logLine.lastIndexOf(")");
                        String content = null;
                        if (lastParenthIdx > -1) {
                            content = logLine.substring(parenthIdx + 1, lastParenthIdx);
                        }
                        if (content != null) {
                            int lastColonIdx = content.lastIndexOf(":");
                            if (lastColonIdx > -1) {
                                String lineNum = content.substring(lastColonIdx + 1);
                                try {
                                    line = Integer.valueOf(lineNum);
                                } catch(NumberFormatException nfe) {
                                    // ignore it
                                    Logger.getLogger(ServerLog.class.getName()).log(Level.INFO, null, nfe);
                                }
                                message = prevMessage;
                            }
                        }
                        int firstDolarIdx = classWithMethod.indexOf("$"); // > -1 for inner classes
                        String className = classWithMethod.substring(0, firstDolarIdx > -1 ? firstDolarIdx : lastDotIdx);
                        path = className.replace('.','/') + ".java"; // NOI18N
                        accessible = globalPathRegistry.findResource(path) != null;
                    }
                }
            }
            // every other message treat as normal info message
            else {
                prevMessage = logLine;
            }
            return new LineInfo(path, line, message, error, accessible);
        }
    }
    
    private class AnalyzingLineProcessor implements LineProcessor {

        @Override
        public void processLine(String line) {
            ServerLogSupport.LineInfo lineInfo = logSupport.analyzeLine(line);
            if (lineInfo.isError()) {
                if (lineInfo.isAccessible()) {
                    try {
                        errorWriter.println(line, logSupport.getLink(lineInfo.message() , lineInfo.path(), lineInfo.line()));
                    } catch (IOException ex) {
                        Exceptions.printStackTrace(ex);
                    }
                } else {
                    errorWriter.println(line);
                }
            } else {
                writer.println(line);
                if (line.startsWith("SEVERE: WSSERVLET11: failed to parse runtime descriptor: java.lang.LinkageError:")) { // NOI18N
                    File jaxwsApi = InstalledFileLocator.getDefault().locate("modules/ext/jaxws22/api/jakarta.xml.ws-api.jar", null, false); // NOI18N
                    File jaxbApi  = InstalledFileLocator.getDefault().locate("modules/ext/jaxb/api/jaxb-api.jar", null, false); // NOI18N
                    File endoresedDir = tomcatManager.getTomcatProperties().getJavaEndorsedDir();
                    if (jaxwsApi != null && jaxbApi != null) {
                        writer.println(NbBundle.getMessage(ServerLog.class, "MSG_WSSERVLET11", jaxwsApi.getParent(), jaxbApi.getParent(), endoresedDir));
                    } else {
                        writer.println(NbBundle.getMessage(ServerLog.class, "MSG_WSSERVLET11_NOJAR", endoresedDir));
                    }
                }
            }
            if (autoFlush) {
                writer.flush();
                errorWriter.flush();
            }
            if (takeFocus) {
                io.select();
            }
        }

        @Override
        public void close() {
            int running = runningTasks.decrementAndGet();
            if (running == 0) {
                logSupport.detachAnnotation();
                writer.close();
                errorWriter.close();                    
            }
        }
        
        @Override
        public void reset() {
            // noop
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy