view src/org/eclipse/jetty/io/BufferCache.java @ 963:4b6216fa9cec

replace SelectChannelEndPoint._state with isDispatched
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 14 Oct 2016 00:15:28 -0600
parents 3ff59e08a1b7
children 74b9daf2826c
line wrap: on
line source

//
//  ========================================================================
//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.io;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;


/* ------------------------------------------------------------------------------- */
/** 
 * Stores a collection of {@link Buffer} objects.
 * Buffers are stored in an ordered collection and can retreived by index or value
 * 
 */
public class BufferCache
{
	private final HashMap _bufferMap=new HashMap();
	private final TreeMap _stringMap = new TreeMap();
	private final ArrayList _index= new ArrayList();

	/* ------------------------------------------------------------------------------- */
	/** Add a buffer to the cache at the specified index.
	 * @param value The content of the buffer.
	 */
	public CachedBuffer add(String value, int ordinal)
	{
		CachedBuffer buffer= new CachedBuffer(value, ordinal);
		_bufferMap.put(buffer, buffer);
		_stringMap.put(value.toLowerCase(), buffer);
		while ((ordinal - _index.size()) >= 0)
			_index.add(null);
		if (_index.get(ordinal)==null)
			_index.add(ordinal, buffer);
		return buffer;
	}

	public CachedBuffer get(int ordinal)
	{
		if (ordinal < 0 || ordinal >= _index.size())
			return null;
		return (CachedBuffer)_index.get(ordinal);
	}

	public CachedBuffer get(Buffer buffer)
	{
		return (CachedBuffer)_bufferMap.get(buffer);
	}

	public CachedBuffer get(String value)
	{
		return (CachedBuffer)_stringMap.get(value.toLowerCase());
	}

	public Buffer lookup(Buffer buffer)
	{
		if (buffer instanceof CachedBuffer)
			return buffer;
		
		Buffer b= get(buffer);
		if (b == null)
		{
			if (buffer instanceof Buffer.CaseInsensitve)
				return buffer;
			return new ByteArrayBuffer.CaseInsensitive(buffer.asArray(),0,buffer.length(),Buffer.IMMUTABLE);
		}

		return b;
	}
	
	public CachedBuffer getBest(byte[] value, int offset, int maxLength)
	{
		String key = new String(value,offset,maxLength).toLowerCase();
		CachedBuffer buffer = (CachedBuffer)_stringMap.get(key);
		if( buffer != null )
			return buffer;
		Map.Entry floor = _stringMap.floorEntry(key);
		Map.Entry ceiling = _stringMap.ceilingEntry(key);
		if( floor==null ) {
			if( ceiling==null )
				return null;
			String ceilingKey = (String)ceiling.getKey();
			return key.charAt(0) == ceilingKey.charAt(0) ? (CachedBuffer)ceiling.getValue() : null;
		} else {
			String floorKey = (String)floor.getKey();
			if( ceiling==null )
				return key.charAt(0) == floorKey.charAt(0) ? (CachedBuffer)floor.getValue() : null;
			String ceilingKey = (String)ceiling.getKey();
			int n = Math.min( key.length(), Math.min( floorKey.length(), ceilingKey.length() ) );
			int i = 0;
			while( ++i <= n && key.regionMatches(0,floorKey,0,i) && key.regionMatches(0,ceilingKey,0,i) );
			return key.regionMatches(0,floorKey,0,i) ? (CachedBuffer)floor.getValue() : key.regionMatches(0,ceilingKey,0,i) || i > 1 ? (CachedBuffer)ceiling.getValue() : null;
		}
/*
		Entry entry = _stringMap.getBestEntry(value, offset, maxLength);
		if (entry!=null)
			return (CachedBuffer)entry.getValue();
		return null;
*/
	}

	public Buffer lookup(String value)
	{
		Buffer b= get(value);
		if (b == null)
		{
			return new CachedBuffer(value,-1);
		}
		return b;
	}

	public String toString(Buffer buffer)
	{
		return lookup(buffer).toString();
	}

	public int getOrdinal(String value)
	{
		CachedBuffer buffer = (CachedBuffer)_stringMap.get(value.toLowerCase());
		return buffer==null?-1:buffer.getOrdinal();
	}
	
	public int getOrdinal(Buffer buffer)
	{
		if (buffer instanceof CachedBuffer)
			return ((CachedBuffer)buffer).getOrdinal();
		buffer=lookup(buffer);
		if (buffer!=null && buffer instanceof CachedBuffer)
			return ((CachedBuffer)buffer).getOrdinal();
		return -1;
	}
	
	public static class CachedBuffer extends ByteArrayBuffer.CaseInsensitive
	{
		private final int _ordinal;
		private HashMap _associateMap=null;
		
		public CachedBuffer(String value, int ordinal)
		{
			super(value);
			_ordinal= ordinal;
		}

		public int getOrdinal()
		{
			return _ordinal;
		}

		public CachedBuffer getAssociate(Object key)
		{
			if (_associateMap==null)
				return null;
			return (CachedBuffer)_associateMap.get(key);
		}

		// TODO Replace Associate with a mime encoding specific solution
		public void setAssociate(Object key, CachedBuffer associate)
		{
			if (_associateMap==null)
				_associateMap=new HashMap();
			_associateMap.put(key,associate);
		}
	}
	
	
	@Override
	public String toString()
	{
		return "CACHE["+
			"bufferMap="+_bufferMap+
			",stringMap="+_stringMap+
			",index="+_index+
			"]";
	}
}