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

org.xsocket.connection.ConnectionUtils Maven / Gradle / Ivy

There is a newer version: 2.8.15
Show newest version
/*
 *  Copyright (c) xsocket.org, 2006 - 2008. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
 * The latest copy of this software may be found on http://www.xsocket.org/
 */
package org.xsocket.connection;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.lang.management.ManagementFactory;
import java.net.SocketTimeoutException;
import java.nio.BufferUnderflowException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.xsocket.DataConverter;





/**
 * utility class for jmx support
 * 
 * @author [email protected]
 */
@SuppressWarnings("unchecked")
public final class ConnectionUtils {
	
	private static final Logger LOG = Logger.getLogger(ConnectionUtils.class.getName());
	
	public static final String DEFAULT_DOMAIN = "org.xsocket.connection";
	public static final String SERVER_TRHREAD_PREFIX = "xServer";


	private static String versionInfo = null;
	

	private ConnectionUtils() { }

	
	
	/**
	 * validate, based on a leading int length field. The length field will be removed
	 * 
	 * @param connection     the connection
	 * @return the length 
	 * @throws IOException if an exception occurs
	 * @throws BufferUnderflowException if not enough data is available
	 */
	public static int validateSufficientDatasizeByIntLengthField(INonBlockingConnection connection) throws IOException, BufferUnderflowException {

		connection.resetToReadMark();
		connection.markReadPosition();
		
		// check if enough data is available
		int length = connection.readInt();
		if (connection.available() < length) {
			if (LOG.isLoggable(Level.FINE)) {
				LOG.fine("[" + connection.getId() + "]insufficient data. require " + length + " got "  + connection.available());
			}
			throw new BufferUnderflowException();
	
		} else { 
			// ...yes, remove mark
			connection.removeReadMark();
			return length;
		}
	}  


	
	/**
	 * validate, based on a leading int length field, that enough data (getNumberOfAvailableBytes() >= length) is available. If not,
	 * an BufferUnderflowException will been thrown. Example:
	 * 
	 * //client
	 * connection.setAutoflush(false);  // avoid immediate write
	 * ...
	 * connection.markWritePosition();  // mark current position
	 * connection.write((int) 0);       // write "emtpy" length field
	 *  
	 * // write and count written size
	 * int written = connection.write(CMD_PUT);
	 * written += ...
	 *  
	 * connection.resetToWriteMark();  // return to length field position
	 * connection.write(written);      // and update it
	 * connection.flush(); // flush (marker will be removed implicit)
	 * ...
	 * 
	 * 
	 * // server
	 * class MyHandler implements IDataHandler {
	 *    ...
	 *    public boolean onData(INonBlockingConnection connection) throws IOException, BufferUnderflowException {
	 *       int length = ConnectionUtils.validateSufficientDatasizeByIntLengthField(connection);
	 *       
	 *       // enough data (BufferUnderflowException hasn`t been thrown)
	 *       byte cmd = connection.readByte();
	 *       ...
	 *    }
	 *  }      
	 * 
* * @param connection the connection * @param removeLengthField true, if length field should be removed * @return the length * @throws IOException if an exception occurs * @throws BufferUnderflowException if not enough data is available */ public static int validateSufficientDatasizeByIntLengthField(INonBlockingConnection connection, boolean removeLengthField) throws IOException, BufferUnderflowException { connection.resetToReadMark(); connection.markReadPosition(); // check if enough data is available int length = connection.readInt(); if (connection.available() < length) { if (LOG.isLoggable(Level.FINE)) { LOG.fine("[" + connection.getId() + "]insufficient data. require " + length + " got " + connection.available()); } throw new BufferUnderflowException(); } else { // ...yes, remove mark if (!removeLengthField) { connection.resetToReadMark(); } connection.removeReadMark(); return length; } } /** * starts the given server within a dedicated thread. This method blocks * until the server is open. If the server hasn't been started within * 60 sec a timeout exception will been thrown * * @param server the server to start * @throws SocketTimeoutException is the timeout has been reached */ public static void start(IServer server) throws SocketTimeoutException { start(server, 60); } /** * starts the given server within a dedicated thread. This method blocks * until the server is open. * * @param server the server to start * @param timeoutSec the maximum time to wait * * @throws SocketTimeoutException is the timeout has been reached */ public static void start(IServer server, int timeoutSec) throws SocketTimeoutException { final CountDownLatch startedSignal = new CountDownLatch(1); // create and add startup listener IServerListener startupListener = new IServerListener() { public void onInit() { startedSignal.countDown(); }; public void onDestroy() {}; }; server.addListener(startupListener); // start server within a dedicated thread Thread t = new Thread(server); t.setName("xServer"); t.start(); // wait until server has been started (onInit has been called) boolean isStarted = false; try { isStarted = startedSignal.await(timeoutSec, TimeUnit.SECONDS); } catch (InterruptedException e) { throw new RuntimeException("start signal doesn't occured. " + e.toString()); } // timeout occurred? if (!isStarted) { throw new SocketTimeoutException("start timeout (" + DataConverter.toFormatedDuration((long) timeoutSec * 1000) + ")"); } // update thread name t.setName(SERVER_TRHREAD_PREFIX + ":" + server.getLocalPort()); // remove the startup listener server.removeListener(startupListener); } /** * creates and registers a mbean for the given server on the platform MBeanServer * *

This is a xSocket preview functionality and subject to change. This * method could be removed by the final version * * @param server the server to register * @return the objectName * @throws JMException if an jmx exception occurs */ public static ObjectName registerMBean(IServer server) throws JMException { return registerMBean(server, DEFAULT_DOMAIN); } /** * creates and registers a mbean for the given server on the platform MBeanServer * under the given domain name * *

This is a xSocket preview functionality and subject to change. This * method could be removed by the final version * * @param server the server to register * @param domain the domain name to use * @return the objectName * @throws JMException if an jmx exception occurs */ public static ObjectName registerMBean(IServer server, String domain) throws JMException { return registerMBean(server, domain, ManagementFactory.getPlatformMBeanServer()); } /** * creates and registers a mbean for the given server on the given MBeanServer * under the given domain name * *

This is a xSocket preview functionality and subject to change. This * method could be removed by the final version * * @param mbeanServer the mbean server to use * @param server the server to register * @param domain the domain name to use * @return the objectName * @throws JMException if an jmx exception occurs */ public static ObjectName registerMBean(IServer server, String domain, MBeanServer mbeanServer) throws JMException { return ServerMBeanProxyFactory.createAndRegister(server, domain, mbeanServer); } /** * creates and registers a mbean for the given connection pool on the platform MBeanServer * *

This is a xSocket preview functionality and subject to change. This * method could be removed by the final version * * @param pool the pool to register * @return the objectName * @throws JMException if an jmx exception occurs */ @SuppressWarnings("unchecked") public static ObjectName registerMBean(IConnectionPool pool) throws JMException { return registerMBean(pool, DEFAULT_DOMAIN); } /** * creates and registers a mbean for the given connection pool on the platform MBeanServer * under the given domain name * *

This is a xSocket preview functionality and subject to change. This * method could be removed by the final version * * @param pool the pool to register * @param domain the domain name to use * @return the objectName * @throws JMException if an jmx exception occurs */ @SuppressWarnings("unchecked") public static ObjectName registerMBean(IConnectionPool pool, String domain) throws JMException { return registerMBean(pool, domain, ManagementFactory.getPlatformMBeanServer()); } /** * creates and registers a mbean for the given pool on the given MBeanServer * under the given domain name * *

This is a xSocket preview functionality and subject to change. This * method could be removed by the final version * * @param mbeanServer the mbean server to use * @param pool the pool to register * @param domain the domain name to use * @return the objectName * @throws JMException if an jmx exception occurs */ @SuppressWarnings("unchecked") public static ObjectName registerMBean(IConnectionPool pool, String domain, MBeanServer mbeanServer) throws JMException { return ConnectionPoolMBeanProxyFactory.createAndRegister(pool, domain, mbeanServer); } /** * get the version string of xSocket (core) * * @return the version string */ public static String getVersionInfo() { if (versionInfo == null) { versionInfo = ""; try { InputStreamReader isr = new InputStreamReader(ConnectionUtils.class.getResourceAsStream("/org/xsocket/version.txt")); if (isr != null) { LineNumberReader lnr = new LineNumberReader(isr); String line = null; do { line = lnr.readLine(); if (line != null) { if (line.startsWith("Implementation-Version=")) { versionInfo = line.substring("Implementation-Version=".length(), line.length()).trim(); } } } while (line != null); lnr.close(); } } catch (Exception ignore) { } } return versionInfo; } /** * creates a new bound cache * * @param the map value type * @param maxSize the max size of the cache * @return the new map cache */ public static Map newMapCache(int maxSize) { return new MapCache(maxSize); } @SuppressWarnings("unchecked") private static final class MapCache extends LinkedHashMap { private static final long serialVersionUID = 4513864504007457500L; private int maxSize = 0; MapCache(int maxSize) { this.maxSize = maxSize; } @Override protected boolean removeEldestEntry(Entry eldest) { return size() > maxSize; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy