gt: 			if (validAtom.equalsIgnoreCase(ah.type)) {
context: /*
   * Created on Jan 19, 2011
   * 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.io.IOException;
  import java.io.RandomAccessFile;
  import java.util.HashSet;
  import java.util.Set;
  
  /*
   * The original code by Mike Melanson (melanson@pcisys.net) was placed in the
   * public domain and so is this Java port of it.
   */
  
  
  public class
  QTFastStartRAF
  {
  	private static final Set<String>	supported_extensions = new HashSet<>();
  
  	static{
  		supported_extensions.add( "mov" );
  		supported_extensions.add( "qt" );
  		supported_extensions.add( "mp4" );
  	}
  
  	private static final Set<String>	tested = new HashSet<>();
  
  	public static boolean
  	isSupportedExtension(
  		String		extension )
  	{
  		return( supported_extensions.contains( extension.toLowerCase()));
  	}
  
  	private static final String ATOM_FREE = "free";
  	private static final String ATOM_JUNK = "junk";
  	private static final String ATOM_MDAT = "mdat";
  	private static final String ATOM_MOOV = "moov";
  	private static final String ATOM_PNOT = "pnot";
  	private static final String ATOM_SKIP = "skip";
  	private static final String ATOM_WIDE = "wide";
  	private static final String ATOM_PICT = "PICT";
  	private static final String ATOM_FTYP = "ftyp";
  
  	private static final String ATOM_CMOV = "cmov";
  	private static final String ATOM_STCO = "stco";
  	private static final String ATOM_CO64 = "co64";
  
  	private static final String[] VALID_TOPLEVEL_ATOMS = {
  		ATOM_FREE, ATOM_JUNK, ATOM_MDAT, ATOM_MOOV,
  		ATOM_PNOT, ATOM_SKIP, ATOM_WIDE, ATOM_PICT,
  		ATOM_FTYP };
  
  	private final FileAccessor	input;
  
  	private boolean		transparent;
  
  	private byte[]		header;
  	private long		body_start;
  	private long		body_end;
  
  	private long		seek_position;
  
  	public
  	QTFastStartRAF(
  		File		file,
  		boolean		enable )
  
  		throws IOException
  	{
  		this( new RAFAccessor( file ), enable );
  	}
  
  	public
  	QTFastStartRAF(
  		FileAccessor	accessor,
  		boolean			enable )
  
  		throws IOException
  	{
  		input = accessor;
  
  		if ( enable ){
  
  			String	name = accessor.getName();
  
  			boolean	log;
  			String	fail	= null;
  
  			synchronized( tested ){
  
  				log = !tested.contains( name );
  
  				if ( log ){
  
  					tested.add( name );
  				}
  			}
  
  			try{
  				Atom ah = null;
  				Atom ftypAtom = null;
  
  				boolean gotFtyp = false;
  				boolean gotMdat = false;
  				boolean justCopy = false;
  
  				while (input.getFilePointer() < input.length()) {
  
  					ah = new Atom(input);
  
  					// System.out.println( "got " + ah.type +", size=" + ah.size );
  
  					if (!isValidTopLevelAtom(ah)) {
  						throw new IOException("Non top level QT atom found (" + ah.type + "). File invalid?");
  					}
  
  					if (gotFtyp && !gotMdat && ah.type.equalsIgnoreCase(ATOM_MOOV)) {
  						justCopy = true;
  						break;
  					}
  
  					// store ftyp atom to buffer
  					if (ah.type.equalsIgnoreCase(ATOM_FTYP)) {
  						ftypAtom = ah;
  						ftypAtom.fillBuffer(input);
  						gotFtyp = true;
  					} else if (ah.type.equalsIgnoreCase(ATOM_MDAT)) {
  						gotMdat = true;
  						input.skipBytes((int)ah.size);
  					} else {
  						input.skipBytes((int)ah.size);
  					}
  				}
  
  				if ( justCopy ){
  
  					transparent	= true;
  
  					return;
  				}
  
  				if ( ftypAtom == null ){
  
  					throw new IOException("No FTYP atom found");
  				}
  
  				if ( ah == null || !ah.type.equalsIgnoreCase(ATOM_MOOV)){
  
  					throw new IOException("Last QT atom was not the MOOV atom.");
  				}
  
  				input.seek(ah.offset);
  
  				Atom moovAtom = ah;
  
  				moovAtom.fillBuffer(input);
  
  				if (isCompressedMoovAtom(moovAtom)){
  
  					throw new IOException("Compressed MOOV qt atoms are not supported");
  				}
  
  				patchMoovAtom(moovAtom);
  
  				body_start 	= ftypAtom.offset+ftypAtom.size;
  				body_end	= moovAtom.offset;
  
  				header = new byte[ftypAtom.buffer.length + moovAtom.buffer.length];
  
  				System.arraycopy( ftypAtom.buffer, 0, header, 0, ftypAtom.buffer.length );
  				System.arraycopy( moovAtom.buffer, 0, header, ftypAtom.buffer.length, moovAtom.buffer.length );
  
  				if ( accessor.length() != header.length + ( body_end - body_start )){
  
  					throw( new IOException( "Inconsistent: file size has changed" ));
  				}
  
  			}catch( Throwable e ){
  
  				//e.printStackTrace();
  
  				fail = Debug.getNestedExceptionMessage( e );
  
  				transparent	= true;
  
  			}finally{
  
  				input.seek( 0 );
  
  				if ( log ){
  
  					String	message;
  
  					if ( fail == null ){
  
  						message = transparent?"Not required":"Required";
  
  					}else{
  
  						message = "Failed - " + fail;
  					}
  
  					Debug.outNoStack( "MOOV relocation for " + accessor.getName() + ": " + message );
  				}
  			}
  		}else{
  
  			transparent = true;
  		}
  	}
  
  	private boolean isCompressedMoovAtom(Atom moovAtom) {
  
  		byte[] cmovBuffer = copyOfRange(moovAtom.buffer, 12, 15);
  
  		if (new String(cmovBuffer).equalsIgnoreCase(ATOM_CMOV)) {
  			return true;
  		}
  
  		return false;
  	}
  
  	private boolean isValidTopLevelAtom(Atom ah) {
  
  		for (String validAtom: VALID_TOPLEVEL_ATOMS) {
  