001/*
002 *  Copyright 2012 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.runtime.plugins.admin.jvmstatus;
017
018import java.io.IOException;
019import java.lang.management.ManagementFactory;
020import java.lang.management.ThreadInfo;
021import java.util.HashMap;
022import java.util.Map;
023
024import org.apache.avalon.framework.parameters.Parameters;
025import org.apache.cocoon.ProcessingException;
026import org.apache.cocoon.environment.ObjectModelHelper;
027import org.apache.cocoon.environment.Response;
028import org.apache.cocoon.environment.SourceResolver;
029import org.apache.cocoon.reading.AbstractReader;
030import org.xml.sax.SAXException;
031
032/**
033 * Send a report on thread 
034 */
035public class ThreadLogReader extends AbstractReader
036{
037    /** The servlet response */
038    protected Response _response;
039    
040    @Override
041    public String getMimeType()
042    {
043        return "text/plain";
044    }
045    
046    @Override
047    public void setup(SourceResolver pResolver, Map pObjectModel, String pSrc, Parameters pPar) throws ProcessingException, SAXException, IOException
048    {
049        super.setup(pResolver, pObjectModel, pSrc, pPar);
050        _response = ObjectModelHelper.getResponse(pObjectModel);
051    }
052    
053    public void generate() throws IOException, SAXException, ProcessingException
054    {
055        if (getLogger().isInfoEnabled())
056        {
057            getLogger().info("Administrator is download deadlocked threads'report");
058        }
059        
060        _response.setHeader("Content-Disposition", "attachment");
061        
062        long[] deadlockedThreadsIds = ManagementFactory.getThreadMXBean().findMonitorDeadlockedThreads();
063        if (deadlockedThreadsIds == null)
064        {
065            if (getLogger().isInfoEnabled())
066            {
067                getLogger().info("Report is empty");
068            }
069            out.write("No thread in deadlock.\n".getBytes("UTF-8"));
070        }
071        else
072        {
073            if (getLogger().isInfoEnabled())
074            {
075                getLogger().info("Report contains " + deadlockedThreadsIds.length + " deadlocked threads");
076            }
077            out.write((deadlockedThreadsIds.length + " threads in deadlock.\n").getBytes("UTF-8"));
078            
079            Map<Thread, StackTraceElement[]> threads = Thread.getAllStackTraces();
080            Map<Long, StackTraceElement[]> stackTraces = new HashMap<>();
081            for (Thread thread : threads.keySet())
082            {
083                long id = thread.getId();
084                stackTraces.put(id, threads.get(thread));
085            }
086            
087            ThreadInfo[] deadlockedThread = ManagementFactory.getThreadMXBean().getThreadInfo(deadlockedThreadsIds);
088            for (ThreadInfo info : deadlockedThread)
089            {
090                out.write("\n".getBytes("UTF-8"));
091                out.write(("THREAD '" + info.getThreadId() + "' - '" + info.getThreadName() + "'\n").getBytes("UTF-8"));
092                out.write(("locked on monitor " + info.getLockName() + " by thread '" + info.getLockOwnerId() + "' - '" + info.getLockOwnerName() + "'\n").getBytes("UTF-8"));
093
094                
095                StackTraceElement[] stes = stackTraces.get(info.getThreadId()); // car info.getStackTrace(); renvoie vide
096                for (StackTraceElement ste : stes)
097                {
098                    String line = "at " + ste.getClassName()  + "." + ste.getMethodName() + " (" + ste.getFileName() + ":" + ste.getLineNumber() + ")\n";
099                    out.write(line.getBytes("UTF-8"));
100                }
101            }
102        }
103    }
104}