Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.nettyhttpserver.server; import com.nettyhttpserver.domain.ConnectionInfoDTO; import com.nettyhttpserver.service.serverrequest.ServerRequestService; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.traffic.ChannelTrafficShapingHandler; import io.netty.handler.traffic.TrafficCounter; import java.net.InetSocketAddress; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * * @author McKey */ public class NettyChannelTrafficShapingHandler extends ChannelTrafficShapingHandler { private final ApplicationContext context; private final ServerRequestService service; /** * List of last 16 connections. */ private static List<ConnectionInfoDTO> serverConnectionList = Collections .synchronizedList(new ArrayList<ConnectionInfoDTO>()); /** * Instance of {@link vlt.hamster.netty.status.ServerConnectionRecord * ServerConnectionRecord} used for accounting one channel. */ private ConnectionInfoDTO connectionInfo = new ConnectionInfoDTO(); public NettyChannelTrafficShapingHandler(long checkInterval) { super(checkInterval); context = new ClassPathXmlApplicationContext("nettyBeans.xml"); service = context.getBean(ServerRequestService.class); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { connectionInfo.setIp(((InetSocketAddress) ctx.channel().remoteAddress()).getHostString()); connectionInfo.setTimestamp(new Timestamp(System.currentTimeMillis())); super.channelActive(ctx); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if (msg instanceof HttpRequest) { /* * Traffic accounting is recorded in ServerConnectionRecord instance */ String uri = ((HttpRequest) msg).getUri(); connectionInfo.setUri(uri); trafficAccounting(); } super.channelRead(ctx, msg); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { trafficAccounting(); if (connectionInfo.getUri() == null) { connectionInfo.setUri("No URI Accessed"); } super.channelInactive(ctx); } /** * If there are more than 16 connections in list, removes the first one and * adds new one to the end. */ private void addToConnectionList() { serverConnectionList.add(connectionInfo); if (serverConnectionList.size() > 16) { serverConnectionList.remove(0); } } /** * * @return the backwards (from the last element) iterator of the list */ public static ListIterator<ConnectionInfoDTO> getServerConnectionListIterator() { /* * The list copy is returned so no Concurrency exceptions will be thrown * wgile iterating over changing list. */ List<ConnectionInfoDTO> list = new ArrayList<>(serverConnectionList); return list.listIterator(list.size()); } private void trafficAccounting() { TrafficCounter tc = trafficCounter(); connectionInfo.setRecivedBytes(Math.abs(tc.cumulativeReadBytes())); connectionInfo.setSentBytes(tc.cumulativeWrittenBytes()); connectionInfo.setSpeed(tc.lastWrittenBytes() * 1000 / (tc.checkInterval())); connectionInfo.setTimestamp(new Timestamp(System.currentTimeMillis())); /* * Instance is added to List on last place (the last the newest) */ if (serverConnectionList.contains(connectionInfo)) { serverConnectionList.remove(connectionInfo); addToConnectionList(); } else { addToConnectionList(); } } }