1f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. 2f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 3f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * This program and the accompanying materials are made available under 4f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * the terms of the Common Public License v1.0 which accompanies this distribution, 5f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * and is available at http://www.eclipse.org/legal/cpl-v10.html 6f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 7f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * $Id: DataFactory.java,v 1.1.1.1.2.3 2004/07/16 23:32:29 vlad_r Exp $ 8f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 9f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpackage com.vladium.emma.data; 10f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 11f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.BufferedInputStream; 12f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.BufferedOutputStream; 13f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.DataInput; 14f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.DataInputStream; 15f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.DataOutput; 16f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.DataOutputStream; 17f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.File; 18f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.FileDescriptor; 19f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.FileInputStream; 20f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.FileOutputStream; 21f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.IOException; 22f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.ObjectInputStream; 23f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.ObjectOutputStream; 24f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.OutputStream; 25f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.RandomAccessFile; 26f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.net.URL; 27f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.net.URLConnection; 28f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 29f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.logging.Logger; 30f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.asserts.$assert; 31f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.IAppConstants; 32f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 33f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ---------------------------------------------------------------------------- 34f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/** 35f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @author Vlad Roubtsov, (C) 2003 36f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 37f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpublic 38f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectabstract class DataFactory 39f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project{ 40f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // public: ................................................................ 41f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 42f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: file compaction 43f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: file locking 44f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 45f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: what's the best place for these? 46f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 47f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static final byte TYPE_METADATA = 0x0; // must start with 0 48f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static final byte TYPE_COVERAGEDATA = 0x1; // must be consistent with mergeload() 49f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 50f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 51f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static IMergeable [] load (final File file) 52f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 53f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 54f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (file == null) throw new IllegalArgumentException ("null input: file"); 55f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 56f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return mergeload (file); 57f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 58f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 59f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static void persist (final IMetaData data, final File file, final boolean merge) 60f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 61f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 62f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (data == null) throw new IllegalArgumentException ("null input: data"); 63f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (file == null) throw new IllegalArgumentException ("null input: file"); 64f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 65f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! merge && file.exists ()) 66f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 67f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! file.delete ()) 68f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IOException ("could not delete file [" + file.getAbsolutePath () + "]"); 69f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 70f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 71f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project persist (data, TYPE_METADATA, file); 72f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 73f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 74f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static void persist (final ICoverageData data, final File file, final boolean merge) 75f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 76f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 77f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (data == null) throw new IllegalArgumentException ("null input: data"); 78f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (file == null) throw new IllegalArgumentException ("null input: file"); 79f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 80f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! merge && file.exists ()) 81f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 82f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! file.delete ()) 83f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IOException ("could not delete file [" + file.getAbsolutePath () + "]"); 84f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 85f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 86f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project persist (data, TYPE_COVERAGEDATA, file); 87f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 88f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 89f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static void persist (final ISessionData data, final File file, final boolean merge) 90f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 91f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 92f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (data == null) throw new IllegalArgumentException ("null input: data"); 93f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (file == null) throw new IllegalArgumentException ("null input: file"); 94f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 95f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! merge && file.exists ()) 96f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 97f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! file.delete ()) 98f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IOException ("could not delete file [" + file.getAbsolutePath () + "]"); 99f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project persist (data.getMetaData (), TYPE_METADATA, file); 102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project persist (data.getCoverageData (), TYPE_COVERAGEDATA, file); 103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static IMetaData newMetaData (final CoverageOptions options) 107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return new MetaData (options); 109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static ICoverageData newCoverageData () 112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return new CoverageData (); 114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static IMetaData readMetaData (final URL url) 117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException, ClassNotFoundException 118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ObjectInputStream oin = null; 120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project oin = new ObjectInputStream (new BufferedInputStream (url.openStream (), 32 * 1024)); 124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return (IMetaData) oin.readObject (); 126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (oin != null) try { oin.close (); } catch (Exception ignore) {} 130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static void writeMetaData (final IMetaData data, final OutputStream out) 134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ObjectOutputStream oout = new ObjectOutputStream (out); 137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project oout.writeObject (data); 138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static void writeMetaData (final IMetaData data, final URL url) 141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final URLConnection connection = url.openConnection (); 144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project connection.setDoOutput (true); 145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project OutputStream out = null; 147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out = connection.getOutputStream (); 150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project writeMetaData (data, out); 152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.flush (); 153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (out != null) try { out.close (); } catch (Exception ignore) {} 157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static ICoverageData readCoverageData (final URL url) 161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException, ClassNotFoundException 162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ObjectInputStream oin = null; 164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project oin = new ObjectInputStream (new BufferedInputStream (url.openStream (), 32 * 1024)); 168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return (ICoverageData) oin.readObject (); 170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (oin != null) try { oin.close (); } catch (Exception ignore) {} 174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static void writeCoverageData (final ICoverageData data, final OutputStream out) 178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: prevent concurrent modification problems here 181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ObjectOutputStream oout = new ObjectOutputStream (out); 183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project oout.writeObject (data); 184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static int [] readIntArray (final DataInput in) 187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int length = in.readInt (); 190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (length == NULL_ARRAY_LENGTH) 191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return null; 192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int [] result = new int [length]; 195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // read array in reverse order: 197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int i = length; -- i >= 0; ) 198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project result [i] = in.readInt (); 200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return result; 203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static boolean [] readBooleanArray (final DataInput in) 207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int length = in.readInt (); 210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (length == NULL_ARRAY_LENGTH) 211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return null; 212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean [] result = new boolean [length]; 215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // read array in reverse order: 217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int i = length; -- i >= 0; ) 218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project result [i] = in.readBoolean (); 220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return result; 223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static void writeIntArray (final int [] array, final DataOutput out) 227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (array == null) 230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeInt (NULL_ARRAY_LENGTH); 231f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 232f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 233f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int length = array.length; 234f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeInt (length); 235f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 236f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // write array in reverse order: 237f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int i = length; -- i >= 0; ) 238f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 239f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeInt (array [i]); 240f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 241f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 242f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 243f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 244f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static void writeBooleanArray (final boolean [] array, final DataOutput out) 245f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 246f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 247f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (array == null) 248f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeInt (NULL_ARRAY_LENGTH); 249f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 250f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 251f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int length = array.length; 252f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeInt (length); 253f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 254f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // write array in reverse order: 255f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int i = length; -- i >= 0; ) 256f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 257f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeBoolean (array [i]); 258f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 259f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 260f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 261f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 262f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // protected: ............................................................. 263f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 264f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // package: ............................................................... 265f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 266f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // private: ............................................................... 267f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 268f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 269f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final class UCFileInputStream extends FileInputStream 270f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 271f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public void close () 272f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 273f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 274f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 275f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project UCFileInputStream (final FileDescriptor fd) 276f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 277f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (fd); 278f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 279f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (fd.valid (), "UCFileInputStream.<init>: FD invalid"); 280f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 281f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 282f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 283f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 284f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final class UCFileOutputStream extends FileOutputStream 285f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 286f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public void close () 287f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 288f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 289f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 290f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project UCFileOutputStream (final FileDescriptor fd) 291f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 292f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (fd); 293f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 294f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (fd.valid (), "UCFileOutputStream.<init>: FD invalid"); 295f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 296f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 297f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 298f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 299f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 300f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final class RandomAccessFileInputStream extends BufferedInputStream 301f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 302f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final int read () throws IOException 303f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 304f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int rc = super.read (); 305f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (rc >= 0) ++ m_count; 306f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 307f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return rc; 308f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 309f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 310f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final int read (final byte [] b, final int off, final int len) 311f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 312f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 313f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int rc = super.read (b, off, len); 314f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (rc >= 0) m_count += rc; 315f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 316f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return rc; 317f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 318f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 319f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final int read (final byte [] b) throws IOException 320f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 321f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int rc = super.read (b); 322f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (rc >= 0) m_count += rc; 323f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 324f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return rc; 325f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 326f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 327f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public void close () 328f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 329f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 330f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 331f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 332f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RandomAccessFileInputStream (final RandomAccessFile raf, final int bufSize) 333f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 334f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 335f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (new UCFileInputStream (raf.getFD ()), bufSize); 336f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 337f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 338f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long getCount () 339f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 340f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return m_count; 341f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 342f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 343f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private long m_count; 344f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 345f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 346f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 347f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final class RandomAccessFileOutputStream extends BufferedOutputStream 348f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 349f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final void write (final byte [] b, final int off, final int len) throws IOException 350f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 351f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super.write (b, off, len); 352f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_count += len; 353f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 354f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 355f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final void write (final byte [] b) throws IOException 356f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 357f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super.write (b); 358f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_count += b.length; 359f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 360f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 361f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final void write (final int b) throws IOException 362f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 363f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super.write (b); 364f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ++ m_count; 365f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 366f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 367f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public void close () 368f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 369f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 370f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 371f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 372f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RandomAccessFileOutputStream (final RandomAccessFile raf, final int bufSize) 373f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 374f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 375f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super (new UCFileOutputStream (raf.getFD ()), bufSize); 376f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 377f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 378f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long getCount () 379f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 380f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return m_count; 381f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 382f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 383f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private long m_count; 384f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 385f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 386f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 387f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 388f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private DataFactory () {} // prevent subclassing 389f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 390f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /* 391f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * input checked by the caller 392f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 393f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static IMergeable [] mergeload (final File file) 394f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 395f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 396f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger log = Logger.getLogger (); 397f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean trace1 = log.atTRACE1 (); 398f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean trace2 = log.atTRACE2 (); 399f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String method = "mergeload"; 400f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 401f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project long start = 0, end; 402f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 403f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace1) start = System.currentTimeMillis (); 404f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 405f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IMergeable [] result = new IMergeable [2]; 406f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 407f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! file.exists ()) 408f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 409f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IOException ("input file does not exist: [" + file.getAbsolutePath () + "]"); 410f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 411f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 412f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 413f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RandomAccessFile raf = null; 414f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 415f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 416f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf = new RandomAccessFile (file, "r"); 417f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 418f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // 'file' is a valid existing file, but it could still be of 0 length or otherwise corrupt: 419f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long length = raf.length (); 420f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace1) log.trace1 (method, "[" + file + "]: file length = " + length); 421f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 422f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (length < FILE_HEADER_LENGTH) 423f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 424f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IOException ("file [" + file.getAbsolutePath () + "] is corrupt or was not created by " + IAppConstants.APP_NAME); 425f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 426f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 427f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 428f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: data version checks parallel to persist() 429f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 430f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (length > FILE_HEADER_LENGTH) // return {null, null} in case of equality 431f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 432f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf.seek (FILE_HEADER_LENGTH); 433f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 434f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [assertion: file length > FILE_HEADER_LENGTH] 435f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 436f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // read entries until the first corrupt entry or the end of the file: 437f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 438f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project long position = FILE_HEADER_LENGTH; 439f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project long entryLength; 440f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 441f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project long entrystart = 0; 442f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 443f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project while (true) 444f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 445f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) log.trace2 (method, "[" + file + "]: position " + raf.getFilePointer ()); 446f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (position >= length) break; 447f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 448f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project entryLength = raf.readLong (); 449f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 450f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((entryLength <= 0) || (position + entryLength + ENTRY_HEADER_LENGTH > length)) 451f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 452f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 453f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 454f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final byte type = raf.readByte (); 455f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((type < 0) || (type >= result.length)) 456f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 457f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 458f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) log.trace2 (method, "[" + file + "]: found valid entry of size " + entryLength + " and type " + type); 459f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 460f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) entrystart = System.currentTimeMillis (); 461f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IMergeable data = readEntry (raf, type, entryLength); 462f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) log.trace2 (method, "entry read in " + (System.currentTimeMillis () - entrystart) + " ms"); 463f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 464f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IMergeable current = result [type]; 465f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 466f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (current == null) 467f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project result [type] = data; 468f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 469f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project result [type] = current.merge (data); // note: later entries overrides earlier entries 470f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 471f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 472f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project position += entryLength + ENTRY_HEADER_LENGTH; 473f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 474f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (raf.getFD ().valid (), "FD invalid"); 475f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf.seek (position); 476f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 477f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 478f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 479f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 480f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 481f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 482f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 483f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (raf != null) try { raf.close (); } catch (Throwable ignore) {} 484f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf = null; 485f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 486f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 487f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 488f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace1) 489f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 490f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project end = System.currentTimeMillis (); 491f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 492f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.trace1 (method, "[" + file + "]: file processed in " + (end - start) + " ms"); 493f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 494f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 495f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return result; 496f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 497f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 498f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 499f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /* 500f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * input checked by the caller 501f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 502f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static void persist (final IMergeable data, final byte type, final File file) 503f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 504f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 505f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger log = Logger.getLogger (); 506f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean trace1 = log.atTRACE1 (); 507f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean trace2 = log.atTRACE2 (); 508f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String method = "persist"; 509f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 510f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project long start = 0, end; 511f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 512f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace1) start = System.currentTimeMillis (); 513f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 514f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: 1.4 adds some interesting RAF open mode options as well 515f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: will this benefit from extra buffering? 516f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 517f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: data version checks 518f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 519f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RandomAccessFile raf = null; 520f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 521f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 522f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean overwrite = false; 523f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean truncate = false; 524f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 525f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (file.exists ()) 526f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 527f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // 'file' exists: 528f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 529f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! file.isFile ()) throw new IOException ("can persist in normal files only: " + file.getAbsolutePath ()); 530f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 531f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf = new RandomAccessFile (file, "rw"); 532f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 533f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // 'file' is a valid existing file, but it could still be of 0 length or otherwise corrupt: 534f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long length = raf.length (); 535f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace1) log.trace1 (method, "[" + file + "]: existing file length = " + length); 536f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 537f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 538f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (length < 4) 539f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 540f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project overwrite = true; 541f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project truncate = (length > 0); 542f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 543f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 544f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 545f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [assertion: file length >= 4] 546f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 547f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // check header info before reading further: 548f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int magic = raf.readInt (); 549f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (magic != MAGIC) 550f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IOException ("cannot overwrite [" + file.getAbsolutePath () + "]: not created by " + IAppConstants.APP_NAME); 551f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 552f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (length < FILE_HEADER_LENGTH) 553f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 554f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // it's our file, but the header is corrupt: overwrite 555f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project overwrite = true; 556f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project truncate = true; 557f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 558f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 559f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 560f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [assertion: file length >= FILE_HEADER_LENGTH] 561f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 562f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// if (! append) 563f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// { 564f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// // overwrite any existing data: 565f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// 566f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// raf.seek (FILE_HEADER_LENGTH); 567f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// writeEntry (raf, FILE_HEADER_LENGTH, data, type); 568f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// } 569f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// else 570f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 571f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // check data format version info: 572f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long dataVersion = raf.readLong (); 573f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 574f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (dataVersion != IAppConstants.DATA_FORMAT_VERSION) 575f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 576f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // read app version info for the error message: 577f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 578f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int major = 0, minor = 0, build = 0; 579f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean gotAppVersion = false; 580f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 581f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 582f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project major = raf.readInt (); 583f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project minor = raf.readInt (); 584f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project build = raf.readInt (); 585f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 586f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project gotAppVersion = true; 587f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 588f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (Throwable ignore) {} 589f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 590f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code here? 591f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (gotAppVersion) 592f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 593f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IOException ("cannot merge new data into [" + file.getAbsolutePath () + "]: created by another " + IAppConstants.APP_NAME + " version [" + makeAppVersion (major, minor, build) + "]"); 594f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 595f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 596f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 597f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IOException ("cannot merge new data into [" + file.getAbsolutePath () + "]: created by another " + IAppConstants.APP_NAME + " version"); 598f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 599f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 600f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 601f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 602f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [assertion: file header is valid and data format version is consistent] 603f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 604f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf.seek (FILE_HEADER_LENGTH); 605f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 606f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (length == FILE_HEADER_LENGTH) 607f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 608f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // no previous data entries: append 'data' 609f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 610f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project writeEntry (log, raf, FILE_HEADER_LENGTH, data, type); 611f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 612f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 613f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 614f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [assertion: file length > FILE_HEADER_LENGTH] 615f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 616f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // write 'data' starting with the first corrupt entry or the end of the file: 617f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 618f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project long position = FILE_HEADER_LENGTH; 619f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project long entryLength; 620f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 621f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project while (true) 622f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 623f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) log.trace2 (method, "[" + file + "]: position " + raf.getFilePointer ()); 624f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (position >= length) break; 625f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 626f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project entryLength = raf.readLong (); 627f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 628f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((entryLength <= 0) || (position + entryLength + ENTRY_HEADER_LENGTH > length)) 629f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 630f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 631f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 632f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) log.trace2 (method, "[" + file + "]: found valid entry of size " + entryLength); 633f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 634f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project position += entryLength + ENTRY_HEADER_LENGTH; 635f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf.seek (position); 636f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 637f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 638f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 639f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace2) log.trace2 (method, "[" + file + "]: adding entry at position " + position); 640f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project writeEntry (log, raf, position, data, type); 641f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 642f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 643f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 644f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 645f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 646f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 647f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 648f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 649f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // 'file' does not exist: 650f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 651f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace1) log.trace1 (method, "[" + file + "]: creating a new file"); 652f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 653f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File parent = file.getParentFile (); 654f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (parent != null) parent.mkdirs (); 655f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 656f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf = new RandomAccessFile (file, "rw"); 657f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 658f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project overwrite = true; 659f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 660f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 661f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 662f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (overwrite) 663f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 664f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // persist starting from 0 offset: 665f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 666f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (raf != null, "raf = null"); 667f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 668f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (truncate) raf.seek (0); 669f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project writeFileHeader (raf); 670f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (raf.getFilePointer () == FILE_HEADER_LENGTH, "invalid header length: " + raf.getFilePointer ()); 671f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 672f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project writeEntry (log, raf, FILE_HEADER_LENGTH, data, type); 673f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 674f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 675f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 676f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 677f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (raf != null) try { raf.close (); } catch (Throwable ignore) {} 678f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf = null; 679f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 680f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 681f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (trace1) 682f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 683f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project end = System.currentTimeMillis (); 684f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 685f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.trace1 (method, "[" + file + "]: file processed in " + (end - start) + " ms"); 686f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 687f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 688f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 689f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static void writeFileHeader (final DataOutput out) 690f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 691f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 692f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeInt (MAGIC); 693f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 694f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeLong (IAppConstants.DATA_FORMAT_VERSION); 695f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 696f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeInt (IAppConstants.APP_MAJOR_VERSION); 697f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeInt (IAppConstants.APP_MINOR_VERSION); 698f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeInt (IAppConstants.APP_BUILD_ID); 699f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 700f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 701f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static void writeEntryHeader (final DataOutput out, final byte type) 702f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 703f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 704f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeLong (UNKNOWN); // length placeholder 705f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.writeByte (type); 706f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 707f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 708f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static void writeEntry (final Logger log, final RandomAccessFile raf, final long marker, final IMergeable data, final byte type) 709f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 710f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 711f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [unfinished] entry header: 712f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project writeEntryHeader (raf, type); 713f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 714f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // serialize 'data' starting with the current raf position: 715f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RandomAccessFileOutputStream rafout = new RandomAccessFileOutputStream (raf, IO_BUF_SIZE); // note: no new file descriptors created here 716f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 717f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ObjectOutputStream oout = new ObjectOutputStream (rafout); 718f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// 719f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// oout.writeObject (data); 720f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// oout.flush (); 721f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// oout = null; 722f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 723f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project DataOutputStream dout = new DataOutputStream (rafout); 724f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project switch (type) 725f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 726f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case TYPE_METADATA: MetaData.writeExternal ((MetaData) data, dout); 727f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 728f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 729f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project default /* TYPE_COVERAGEDATA */: CoverageData.writeExternal ((CoverageData) data, dout); 730f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 731f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 732f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of switch 733f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project dout.flush (); 734f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project dout = null; 735f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 736f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // truncate: 737f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf.setLength (raf.getFilePointer ()); 738f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 739f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 740f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // transact this entry [finish the header]: 741f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf.seek (marker); 742f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf.writeLong (rafout.getCount ()); 743f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (DO_FSYNC) raf.getFD ().sync (); 744f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 745f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atTRACE2 ()) log.trace2 ("writeEntry", "entry [" + data.getClass ().getName () + "] length: " + rafout.getCount ()); 746f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 747f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 748f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static IMergeable readEntry (final RandomAccessFile raf, final byte type, final long entryLength) 749f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 750f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 751f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Object data; 752f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 753f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RandomAccessFileInputStream rafin = new RandomAccessFileInputStream (raf, IO_BUF_SIZE); // note: no new file descriptors created here 754f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 755f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ObjectInputStream oin = new ObjectInputStream (rafin); 756f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// 757f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// try 758f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// { 759f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// data = oin.readObject (); 760f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// } 761f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// catch (ClassNotFoundException cnfe) 762f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// { 763f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// // TODO: EMMA exception here 764f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// throw new IOException ("could not read data entry: " + cnfe.toString ()); 765f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// } 766f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 767f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project DataInputStream din = new DataInputStream (rafin); 768f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project switch (type) 769f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 770f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project case TYPE_METADATA: data = MetaData.readExternal (din); 771f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 772f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 773f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project default /* TYPE_COVERAGEDATA */: data = CoverageData.readExternal (din); 774f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 775f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 776f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of switch 777f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 778f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 779f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (rafin.getCount () == entryLength, "entry length mismatch: " + rafin.getCount () + " != " + entryLength); 780f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 781f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return (IMergeable) data; 782f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 783f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 784f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 785f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /* 786f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * This is cloned from EMMAProperties by design, to eliminate a CONSTANT_Class_info 787f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * dependency between this and EMMAProperties classes. 788f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 789f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static String makeAppVersion (final int major, final int minor, final int build) 790f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 791f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final StringBuffer buf = new StringBuffer (); 792f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 793f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.append (major); 794f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.append ('.'); 795f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.append (minor); 796f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.append ('.'); 797f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project buf.append (build); 798f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 799f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return buf.toString (); 800f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 801f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 802f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 803f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int NULL_ARRAY_LENGTH = -1; 804f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 805f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int MAGIC = 0x454D4D41; // "EMMA" 806f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final long UNKNOWN = 0L; 807f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int FILE_HEADER_LENGTH = 4 + 8 + 3 * 4; // IMPORTANT: update on writeFileHeader() changes 808f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int ENTRY_HEADER_LENGTH = 8 + 1; // IMPORTANT: update on writeEntryHeader() changes 809f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final boolean DO_FSYNC = true; 810f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int IO_BUF_SIZE = 32 * 1024; 811f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 812f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project} // end of class 813f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ---------------------------------------------------------------------------- 814