Package org.cipango.callflow.diameter

Source Code of org.cipango.callflow.diameter.JmxMessageLogger$LogIterator

// ========================================================================
// Copyright 2010 NEXCOM Systems
// ------------------------------------------------------------------------
// Licensed 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.
// ========================================================================
package org.cipango.callflow.diameter;

import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;

import org.apache.commons.jexl.Expression;
import org.apache.commons.jexl.ExpressionFactory;
import org.apache.commons.jexl.JexlContext;
import org.apache.commons.jexl.JexlHelper;
import org.cipango.callflow.diameter.DiameterMessageFormator.Output;
import org.cipango.diameter.Dictionary;
import org.cipango.diameter.base.Accounting;
import org.cipango.diameter.base.Common;
import org.cipango.diameter.ims.Cx;
import org.cipango.diameter.ims.IMS;
import org.cipango.diameter.ims.Sh;
import org.cipango.diameter.io.Codecs;
import org.cipango.diameter.log.DiameterMessageListener;
import org.cipango.diameter.node.DiameterAnswer;
import org.cipango.diameter.node.DiameterConnection;
import org.cipango.diameter.node.DiameterMessage;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;

public class JmxMessageLogger extends AbstractLifeCycle implements DiameterMessageListener
{
  private static final int DEFAULT_MAX_MESSAGES = 50;
  public enum Direction { IN, OUT };
 
  private MessageInfo[] _messages;
  private int _maxMessages = DEFAULT_MAX_MESSAGES;
  private int _cursor;
 
  public int getMaxMessages()
  {
    return _maxMessages;
  }

  public void setMaxMessages(int maxMessages)
  {
    if (maxMessages <= 0)
      throw new IllegalArgumentException("Max message must be greater than 0");
   
    synchronized (this)
    {
      if (isRunning() && maxMessages != _maxMessages)
      {
        MessageInfo[] messages = new MessageInfo[maxMessages];
        ListIterator<MessageInfo> it = iterate(false);
        int index = maxMessages;
        while (it.hasPrevious())
        {
          messages[--index] = it.previous();
          if (index == 0)
            break;
       
        _cursor = 0;
        _messages = messages;
      }
      _maxMessages = maxMessages;
    }
  }

  protected void doStart() throws Exception
  {
    _messages = new MessageInfo[_maxMessages];
    _cursor = 0;
    super.doStart();
  }

  protected void doStop() throws Exception
  {
    _messages = null;
    super.doStop();
  }
 

  public void messageReceived(DiameterMessage message, DiameterConnection connection)
  {
    doLog(message, Direction.IN, connection);
  }

  public void messageSent(DiameterMessage message, DiameterConnection connection)
  {
    doLog(message, Direction.OUT, connection);
  }

  public void doLog(DiameterMessage message, Direction direction, DiameterConnection connection)
  {
    if (_messages != null)
    {       
      synchronized (this)
      {
        _messages[_cursor] = new MessageInfo(message, direction, connection);
        _cursor = getNextCursor();
      }
     
    }
  }
   
  public Object[][] getMessages(Integer maxMessages) throws Exception
  {
    return getMessages(maxMessages, null);
  }
 
  private ListIterator<MessageInfo> iterate(boolean start)
  {
    return new LogIterator(start);
  }
 
 
  private int getNextCursor()
  {
    return _cursor + 1 == _maxMessages ? 0 : _cursor + 1;
  }
 
  public void clear()
  {
    if (_messages == null)
      return;
   
    synchronized (this)
    {
      for (int i = 0; i < _messages.length; i++)
        _messages[i] = null;
      _cursor = 0;
    }
  }
 
  public Object[][] getMessages(Integer maxMessages, String msgFilter) throws Exception
  {
    List<MessageInfo> messages = getMessageList(maxMessages, msgFilter);
    Object[][] tab = new Object[messages.size()][5];
    for (int i = 0; i < tab.length; i++)
    {
      MessageInfo info = (MessageInfo) messages.get(i);
      tab[i][0] = generateInfoLine(info);
      Output output = DiameterMessageFormator.getPretty().newOutput();
      output.add(info.getMessage());
      tab[i][1] = output.toString();
      tab[i][2] = info.getRemote();
    }
   
    return tab;
  }
 
  public String generateInfoLine(MessageInfo messageInfo)
  {
    StringBuilder sb = new StringBuilder();
    sb.append(messageInfo.getFormatedDate());
        if (messageInfo.getDirection() == Direction.IN)
          sb.append(" IN  ");
    else
      sb.append(" OUT ");
        sb.append(messageInfo.getConnection().getLocalAddr());
        sb.append(':');
        sb.append(messageInfo.getConnection().getLocalPort());
        sb.append((messageInfo.getDirection() == Direction.IN ? " < " : " > "));
        sb.append(messageInfo.getConnection().getRemoteAddr());
        sb.append(':');
        sb.append(messageInfo.getConnection().getRemotePort());
        sb.append('\n');
        return sb.toString();
  }
 
  @SuppressWarnings("unchecked")
  private List<MessageInfo> getMessageList(Integer maxMessages, String msgFilter) throws Exception
  {
    if (_messages == null)
      return null;
   
    synchronized (this)
    {
      JexlContext jc = JexlHelper.createContext();
      Expression msgExpression = null;
      if (msgFilter != null && !msgFilter.trim().equals(""))
      {
        Log.debug("Get messages with filter: " + msgFilter);
        msgExpression = ExpressionFactory.createExpression("log." + msgFilter);
      }
   
      List<MessageInfo> result = new ArrayList<MessageInfo>();
      ListIterator<MessageInfo> it = iterate(false);
     
      int i = 0;
      while (it.hasPrevious() && i < maxMessages)
      {
        MessageInfo info = it.previous();
        jc.getVars().put("log", info);
        jc.getVars().put("message", info.getMessage());
     
        if (msgExpression == null || ((Boolean) msgExpression.evaluate(jc)).booleanValue())
        {
          result.add(0, info);
          i++;
        }
      }
      return result;
    }
  }

  public static void main(String[] args) throws Exception
  {
    Dictionary.getInstance().load(Common.class);
    Dictionary.getInstance().load(Accounting.class);
    Dictionary.getInstance().load(IMS.class);
    Dictionary.getInstance().load(Cx.class);
    Dictionary.getInstance().load(Sh.class);
    JmxMessageLogger logger = new JmxMessageLogger();
    logger.start();
    DiameterMessage message = Codecs.__message.decode(load("mar.dat"));
    message.getAVPs().add(Cx.CX_APPLICATION_ID.getAVP());
    //((DiameterAnswer) message).setResultCode(Common.DIAMETER_SUCCESS);
    Output output  = DiameterMessageFormator.getPretty().newOutput();
    output.add(message);
    System.out.println(output.toString());
  }
 
  protected static Buffer load(String name) throws Exception
  {
    URL url = JmxMessageLogger.class.getClassLoader().getResource(name);
    File file = new File(url.toURI());
    FileInputStream fin = new FileInputStream(file);
    byte[] b = new byte[(int) file.length()];
    fin.read(b);
   
    return new ByteArrayBuffer(b);
  }
 
  private class LogIterator implements ListIterator<MessageInfo>
  {
    private int _itCursor;
    private boolean _start = true;
   
    public LogIterator(boolean start)
    {
      if (start)
        _itCursor = _messages[getNextCursor()] == null ? 0 : getNextCursor();
      else
        _itCursor = _cursor;
    }
   
    private int getNextItCursor()
    {
      return _itCursor + 1 == _maxMessages ? 0 : _itCursor + 1;
    }
    private int getPreviousItCursor()
    {
      return _itCursor == 0 ? _maxMessages - 1 : _itCursor - 1;
    }
   
    public boolean hasNext()
    {
      return _itCursor != _cursor && _messages[getNextItCursor()] != null;
    }

    public MessageInfo next()
    {
      if (!hasNext())
        throw new NoSuchElementException("No next");
      _itCursor = getNextItCursor();
      return _messages[_itCursor];
    }

    public void remove()
    {
      throw new UnsupportedOperationException("Read-only");
    }

    public void add(MessageInfo arg0)
    {
      throw new UnsupportedOperationException("Read-only");
    }

    public boolean hasPrevious()
    {
      return (_start || _itCursor != _cursor) && _messages[getPreviousItCursor()] != null;
    }

    public int nextIndex()
    {
      return 0;
    }

    public MessageInfo previous()
    {
      if (!hasPrevious())
        throw new NoSuchElementException("No previous");
      _start = false;
      _itCursor = getPreviousItCursor();
      return _messages[_itCursor];
    }

    public int previousIndex()
    {
      return 0;
    }

    public void set(MessageInfo arg0)
    {
      throw new UnsupportedOperationException("Read-only");
    }
  }

}



TOP

Related Classes of org.cipango.callflow.diameter.JmxMessageLogger$LogIterator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.