/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 */
package org.apache.log.output.jms;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.log.LogEvent;
import org.apache.log.ContextMap;
import org.apache.log.Logger;
import org.apache.log.util.StackIntrospector;
import java.io.StringWriter;
import java.io.PrintWriter;

/**
 * Basic message factory that stores LogEvent in Message.
 *
 * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
 */
public class TextMessageBuilder
    implements MessageBuilder
{
    private final static String  TYPE_CATEGORY_STR = "category";
    private final static String  TYPE_CONTEXT_STR = "context";
    private final static String  TYPE_MESSAGE_STR = "message";
    private final static String  TYPE_TIME_STR = "time";
    private final static String  TYPE_RELATIVE_TIME_STR = "rtime";
    private final static String  TYPE_THROWABLE_STR = "throwable";
    private final static String  TYPE_PRIORITY_STR = "priority";
    private final static String  TYPE_METHOD_STR = "method";
    private final static String  TYPE_THREAD_STR = "thread";

    public Message buildMessage( Session session, LogEvent event )
        throws JMSException
    {
        synchronized( session )
        {
            final TextMessage message = session.createTextMessage();
            message.setText( event.getMessage() );
            message.setStringProperty(TYPE_PRIORITY_STR, event.getPriority().getName());            
            message.setStringProperty(TYPE_CATEGORY_STR, event.getCategory());            
            message.setLongProperty(TYPE_TIME_STR, event.getTime());
            message.setLongProperty(TYPE_RELATIVE_TIME_STR, event.getRelativeTime());
            message.setStringProperty(TYPE_METHOD_STR, getMethod( event ) );            
            message.setStringProperty(TYPE_THREAD_STR, getThread( event ) );
            message.setStringProperty(TYPE_THROWABLE_STR, getStackTrace( event ) ); 

            return message;
        }
    }
    
    protected String getMethod( final LogEvent event)
    {
        final ContextMap map = event.getContextMap();
        if( null != map )
        {
            final Object object = map.get( "method" );
            if( null != object )
            {
                return object.toString();
            }
        }

        final String result = StackIntrospector.getCallerMethod( Logger.class );
        if( null == result )
        {
            return "UnknownMethod";
        }
        return result;
    }

    protected String getThread( final LogEvent event )
    {
        final ContextMap map = event.getContextMap();
        if( null != map )
        {
            final Object object = map.get( "thread" );
            if( null != object )
            {
                return object.toString();
            }
        }

        return Thread.currentThread().getName();
    }
    
    protected String getStackTrace( final LogEvent event )
    {        
        final Throwable throwable = event.getThrowable();
        final String result;
     
        if ( null != throwable )
        {
            final StringWriter stringWriter = new StringWriter();
            final PrintWriter printWriter = new PrintWriter( stringWriter );
            throwable.printStackTrace( printWriter );

            result = stringWriter.getBuffer().toString();                        
        }
        else 
        {
            result = "";
        }
        
        return result;
    }
}

