TrackingFileManager { public Properties update( File file, Map<String, String> updates ) { Properties props = new Properties(); synchronized ( getLock( file ) ) { File directory = file.getParentFile(); if ( !directory.mkdirs() && !directory.exists() ) { logger.warn( "Failed to create parent directories for resolution tracking file " + file ); return props; } RandomAccessFile raf = null; FileLock lock = null; try { raf = new RandomAccessFile( file, "rw" ); lock = lock( raf.getChannel(), Math.max( 1, raf.length() ), false ); if ( file.canRead() ) { byte[] buffer = new byte[(int) raf.length()]; raf.readFully( buffer ); ByteArrayInputStream stream = new ByteArrayInputStream( buffer ); props.load( stream ); } for ( Map.Entry<String, String> update : updates.entrySet() ) { if ( update.getValue() == null ) { props.remove( update.getKey() ); } else { props.setProperty( update.getKey(), update.getValue() ); } } ByteArrayOutputStream stream = new ByteArrayOutputStream( 1024 * 2 ); logger.debug( "Writing resolution tracking file " + file ); props.store( stream, "NOTE: This is an internal implementation file" + ", its format can be changed without prior notice." ); raf.seek( 0 ); raf.write( stream.toByteArray() ); raf.setLength( raf.getFilePointer() ); } catch ( IOException e ) { logger.warn( "Failed to write resolution tracking file " + file, e ); } finally { release( lock, file ); close( raf, file ); } } return props; }  TrackingFileManager setLogger( Logger logger ); Properties read( File file ); Properties update( File file, Map<String, String> updates );  }
@Test public void testUpdate() throws Exception { TrackingFileManager tfm = new TrackingFileManager(); File propFile = TestFileUtils.createTempFile( "key1=value1\nkey2 : value2\n".getBytes( "UTF-8" ), 1000 ); Map<String, String> updates = new HashMap<String, String>(); updates.put( "key1", "v" ); updates.put( "key2", null ); tfm.update( propFile, updates ); Properties props = tfm.read( propFile ); assertNotNull( props ); assertEquals( String.valueOf( props ), 1, props.size() ); assertEquals( "v", props.get( "key1" ) ); assertNull( String.valueOf( props.get( "key2" ) ), props.get( "key2" ) ); }
@Test public void testUpdateNoFileLeak() throws Exception { TrackingFileManager tfm = new TrackingFileManager(); Map<String, String> updates = new HashMap<String, String>(); updates.put( "k", "v" ); for ( int i = 0; i < 1000; i++ ) { File propFile = TestFileUtils.createTempFile( "#COMMENT\nkey1=value1\nkey2 : value2" ); assertNotNull( tfm.update( propFile, updates ) ); assertTrue( "Leaked file: " + propFile, propFile.delete() ); } }