gt: 			return( toIntern );
context: /*
  
   * Created on Jun 8, 2007
   * Created by Paul Gardner
   * Copyright (C) Azureus Software, Inc, All Rights Reserved.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
   * This program 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 General Public License for more details.
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   *
   */
  
  
  package com.biglybt.core.util;
  
  import java.io.File;
  import java.lang.ref.ReferenceQueue;
  import java.lang.ref.WeakReference;
  import java.net.URL;
  import java.util.*;
  import java.util.concurrent.locks.ReadWriteLock;
  import java.util.concurrent.locks.ReentrantReadWriteLock;
  
  
  public class
  StringInterner
  {
  	/**
  	 * Can't be final as set true for a few specific apps
  	 */
  
  	@SuppressWarnings("CanBeFinal")
  	public static boolean DISABLE_INTERNING = System.getProperty("stringinterner.disable", "0").equals("1");
  
  	private static final int SCHEDULED_CLEANUP_INTERVAL = 60*1000;
  
  	private static final boolean TRACE_CLEANUP = false;
  	private static final boolean TRACE_MULTIHITS = false;
  
  
  	private static final int IMMEDIATE_CLEANUP_TRIGGER = 2000;
  	private static final int IMMEDIATE_CLEANUP_GOAL = 1500;
  	private static final int SCHEDULED_CLEANUP_TRIGGER = 1500;
  	private static final int SCHEDULED_CLEANUP_GOAL = 1000;
  	private static final int SCHEDULED_AGING_THRESHOLD = 750;
  
  	private static final LightHashSet managedInterningSet = new LightHashSet(800);
  	private static final LightHashSet unmanagedInterningSet = new LightHashSet();
  	static final ReadWriteLock managedSetLock = new ReentrantReadWriteLock();
  
  	private final static ReferenceQueue managedRefQueue = new ReferenceQueue();
  	private final static ReferenceQueue unmanagedRefQueue = new ReferenceQueue();
  
  	private static final String[] COMMON_KEYS = {
  		"src","port","prot","ip","udpport","azver","httpport","downloaded",
  		"Content","Refresh On","path.utf-8","uploaded","completed","persistent","attributes","encoding",
  		"azureus_properties","stats.download.added.time","networks","p1","resume data","dndflags","blocks","resume",
  		"primaryfile","resumecomplete","data","peersources","name.utf-8","valid","torrent filename","parameters",
  		"secrets","timesincedl","tracker_cache","filedownloaded","timesinceul","tracker_peers","trackerclientextensions","GlobalRating",
  		"comment.utf-8","Count","String","stats.counted","Thumbnail","Plugin.<internal>.DDBaseTTTorrent::sha1","type","Title",
  		"displayname","Publisher","Creation Date","Revision Date","Content Hash","flags","stats.download.completed.time","Description",
  		"Progressive","Content Type","QOS Class","DRM","hash","ver","id",
  		"body","seed","eip","rid","iip","dp2","tp","orig",
  		"dp","Quality","private","dht_backup_enable","max.uploads","filelinks","Speed Bps","cdn_properties",
  		"sha1","ed2k","DRM Key","Plugin.aeseedingengine.attributes","initial_seed","dht_backup_requested","ta","size",
  		"DIRECTOR PUBLISH","Plugin.azdirector.ContentMap","dateadded","bytesin","announces","status","bytesout","scrapes",
  		"passive",
  	};
  
  	private static final ByteArrayHashMap	byte_map = new ByteArrayHashMap( COMMON_KEYS.length );
  
  	static{
  		try{
  			for (int i=0;i<COMMON_KEYS.length;i++){
  
  				byte_map.put( COMMON_KEYS[i].getBytes(Constants.BYTE_ENCODING_CHARSET), COMMON_KEYS[i] );
  				managedInterningSet.add(new WeakStringEntry(COMMON_KEYS[i]));
  			}
  		}catch( Throwable e ){
  
  			e.printStackTrace();
  		}
  
  			// initialisation nightmare - we have to create periodic event async to avoid
  			// circular class loading issues when azureus.config is borkified
  
  		new AEThread2( "asyncify", true )
  		{
  			@Override
  			public void
  			run()
  			{
  				SimpleTimer.addPeriodicEvent("StringInterner:cleaner", SCHEDULED_CLEANUP_INTERVAL, new TimerEventPerformer() {
  					@Override
  					public void perform(TimerEvent event) {
  						managedSetLock.writeLock().lock();
  						try {
  							sanitize(true);
  						} finally {
  							managedSetLock.writeLock().unlock();
  						}
  
  
  						sanitizeLight();
  					}
  				});
  			}
  		}.start();
  	}
  
  	// private final static ReferenceQueue queue = new ReferenceQueue();
  
  
  	public static String
  	intern(
  		byte[]	bytes )
  	{
  		String res = (String)byte_map.get( bytes );
  
  		// System.out.println( new String( bytes ) + " -> " + res );
  
  		return( res );
  	}
  
  	/**
  	 * A generic interning facilty for heavyweight or frequently duplicated
  	 * Objects that have a reasonable <code>equals()</code> implementation.<br>
  	 * <br>
  	 * Important: The objects should have a limited lifespan, the interning set
  	 * used by this method is unmanaged, i.e. does not clean out old entries!
  	 * Entries without strong references are still removed.
  	 *
  	 */
  	public static Object internObject(Object toIntern)
  	{
  		if ( DISABLE_INTERNING ){
  			return( toIntern );
  		}
  
  		if(toIntern == null)
  			return null;
  
  		Object internedItem;
  
  		WeakEntry checkEntry = new WeakEntry(toIntern,unmanagedRefQueue);
  
  		synchronized( unmanagedInterningSet ){
  
  			WeakEntry internedEntry = (WeakEntry) unmanagedInterningSet.get(checkEntry);
  
  			if (internedEntry == null || (internedItem = (internedEntry.get())) == null)
  			{
  				internedItem = toIntern;
  				if(!unmanagedInterningSet.add(checkEntry))
  					System.out.println("unexpected modification"); // should not happen
  			}
  
  			sanitizeLight();
  		}
  
  		// should not happen
  		if(!toIntern.equals(internedItem))
  			System.err.println("mismatch");
  
  		return internedItem;
  	}
  
  	public static String intern(String toIntern) {
  
  		if ( DISABLE_INTERNING ){
  			return( toIntern );
  		}
  
  		if(toIntern == null)
  			return null;
  
  		String internedString;
  
  		WeakStringEntry checkEntry = new WeakStringEntry(toIntern);
  
  		WeakStringEntry internedEntry = null;
  		boolean hit = false;
  
  		managedSetLock.readLock().lock();
  		try {
  
  			internedEntry = (WeakStringEntry) managedInterningSet.get(checkEntry);
  
  			if (internedEntry != null && (internedString = internedEntry.getString()) != null)
  				hit = true;
  			else
  			{
  				managedSetLock.readLock().unlock();
  				managedSetLock.writeLock().lock();
  				try{
  					sanitize(false);
  
  					// get again, weakrefs might have expired and been added by another thread concurrently
  					internedEntry = (WeakStringEntry) managedInterningSet.get(checkEntry);
  
  					if (internedEntry != null && (internedString = internedEntry.getString()) != null)
  						hit = true;
  					else {
  						toIntern = new String( toIntern );	// this trims any baggage that might be included in the original string due to char[] sharing for substrings etc
  						checkEntry = new WeakStringEntry( toIntern );
  						managedInterningSet.add(checkEntry);
  						internedString = toIntern;
  					}
  				}finally{
  					managedSetLock.readLock().lock();
  					managedSetLock.writeLock().unlock();
  				}
  			}
  		} finally {
  			managedSetLock.readLock().unlock();
  		}
  
  		if(hit) {
  			internedEntry.incHits();
  			checkEntry.destroy();
  			if(TRACE_MULTIHITS && internedEntry.hits % 10 == 0)
  				System.out.println("multihit "+internedEntry);
  		}
  
  
  		return internedString;
  	}
  
  	public static char[] intern(char[] toIntern) {
  
  		if ( DISABLE_INTERNING ){
  			return( toIntern );
  		}
  
  		if(toIntern == null)
  			return null;
  
  		char[] internedCharArray;
  
  		WeakCharArrayEntry checkEntry = new WeakCharArrayEntry(toIntern);
  
  		WeakCharArrayEntry internedEntry = null;
  		boolean hit = false;
  
  		managedSetLock.readLock().lock();
  		try {
  
  			internedEntry = (WeakCharArrayEntry) managedInterningSet.get(checkEntry);
  
  			if (internedEntry != null && (internedCharArray = internedEntry.getCharArray()) != null)
  				hit = true;
  			else
  			{
  				managedSetLock.readLock().unlock();
  				managedSetLock.writeLock().lock();
  				try{
  					sanitize(false);
  
  					// get again, weakrefs might have expired and been added by another thread concurrently
  					internedEntry = (WeakCharArrayEntry) managedInterningSet.get(checkEntry);
  
  					if (internedEntry != null && (internedCharArray = internedEntry.getCharArray()) != null)
  						hit = true;
  					else {
  						managedInterningSet.add(checkEntry);
  						internedCharArray = toIntern;
  					}
  				}finally{
  					managedSetLock.readLock().lock();
  					managedSetLock.writeLock().unlock();
  				}
  			}
  		} finally {
  			managedSetLock.readLock().unlock();
  		}
  
  		if(hit) {
  			System.out.println( "hit for " + new String(toIntern ));
  			internedEntry.incHits();
  			checkEntry.destroy();
  			if(TRACE_MULTIHITS && internedEntry.hits % 10 == 0)
  				System.out.println("multihit "+internedEntry);
  		}
  
  
  		return internedCharArray;
  	}
  
  
  
  
  	public static byte[] internBytes(byte[] toIntern) {
  
  		if ( DISABLE_INTERNING ){
  