2929import java .io .FileInputStream ;
3030import java .io .IOException ;
3131import java .io .RandomAccessFile ;
32- import java .nio .channels .FileChannel ;
33- import java .nio .channels .FileLock ;
34- import java .nio .channels .OverlappingFileLockException ;
3532import java .util .Map ;
3633import java .util .Properties ;
3734
3835/**
39- * Manages potentially concurrent accesses to a properties file.
36+ * Manages access to a properties file.
4037 */
4138class TrackingFileManager
4239{
@@ -45,35 +42,28 @@ class TrackingFileManager
4542
4643 public Properties read ( File file )
4744 {
48- synchronized ( getLock ( file ) )
45+ FileInputStream stream = null ;
46+ try
4947 {
50- FileLock lock = null ;
51- FileInputStream stream = null ;
52- try
48+ if ( !file .exists () )
5349 {
54- if ( !file .exists () )
55- {
56- return null ;
57- }
50+ return null ;
51+ }
5852
59- stream = new FileInputStream ( file );
53+ stream = new FileInputStream ( file );
6054
61- lock = lock ( stream .getChannel (), Math .max ( 1 , file .length () ), true );
55+ Properties props = new Properties ();
56+ props .load ( stream );
6257
63- Properties props = new Properties ();
64- props .load ( stream );
65-
66- return props ;
67- }
68- catch ( IOException e )
69- {
70- LOGGER .warn ( "Failed to read tracking file {}" , file , e );
71- }
72- finally
73- {
74- release ( lock , file );
75- close ( stream , file );
76- }
58+ return props ;
59+ }
60+ catch ( IOException e )
61+ {
62+ LOGGER .warn ( "Failed to read tracking file {}" , file , e );
63+ }
64+ finally
65+ {
66+ close ( stream , file );
7767 }
7868
7969 return null ;
@@ -83,82 +73,61 @@ public Properties update( File file, Map<String, String> updates )
8373 {
8474 Properties props = new Properties ();
8575
86- synchronized ( getLock ( file ) )
76+ File directory = file .getParentFile ();
77+ if ( !directory .mkdirs () && !directory .exists () )
8778 {
88- File directory = file .getParentFile ();
89- if ( !directory .mkdirs () && !directory .exists () )
90- {
91- LOGGER .warn ( "Failed to create parent directories for tracking file {}" , file );
92- return props ;
93- }
79+ LOGGER .warn ( "Failed to create parent directories for tracking file {}" , file );
80+ return props ;
81+ }
9482
95- RandomAccessFile raf = null ;
96- FileLock lock = null ;
97- try
83+ RandomAccessFile raf = null ;
84+ try
85+ {
86+ raf = new RandomAccessFile ( file , "rw" );
87+
88+ if ( file .canRead () )
9889 {
99- raf = new RandomAccessFile ( file , "rw" );
100- lock = lock ( raf .getChannel (), Math .max ( 1 , raf .length () ), false );
90+ byte [] buffer = new byte [(int ) raf .length ()];
10191
102- if ( file .canRead () )
103- {
104- byte [] buffer = new byte [(int ) raf .length ()];
92+ raf .readFully ( buffer );
10593
106- raf . readFully ( buffer );
94+ ByteArrayInputStream stream = new ByteArrayInputStream ( buffer );
10795
108- ByteArrayInputStream stream = new ByteArrayInputStream ( buffer );
96+ props .load ( stream );
97+ }
10998
110- props .load ( stream );
99+ for ( Map .Entry <String , String > update : updates .entrySet () )
100+ {
101+ if ( update .getValue () == null )
102+ {
103+ props .remove ( update .getKey () );
111104 }
112-
113- for ( Map .Entry <String , String > update : updates .entrySet () )
105+ else
114106 {
115- if ( update .getValue () == null )
116- {
117- props .remove ( update .getKey () );
118- }
119- else
120- {
121- props .setProperty ( update .getKey (), update .getValue () );
122- }
107+ props .setProperty ( update .getKey (), update .getValue () );
123108 }
109+ }
124110
125- ByteArrayOutputStream stream = new ByteArrayOutputStream ( 1024 * 2 );
111+ ByteArrayOutputStream stream = new ByteArrayOutputStream ( 1024 * 2 );
126112
127- LOGGER .debug ( "Writing tracking file {}" , file );
128- props .store ( stream , "NOTE: This is a Maven Resolver internal implementation file"
129- + ", its format can be changed without prior notice." );
113+ LOGGER .debug ( "Writing tracking file {}" , file );
114+ props .store ( stream , "NOTE: This is a Maven Resolver internal implementation file"
115+ + ", its format can be changed without prior notice." );
130116
131- raf .seek ( 0 );
132- raf .write ( stream .toByteArray () );
133- raf .setLength ( raf .getFilePointer () );
134- }
135- catch ( IOException e )
136- {
137- LOGGER .warn ( "Failed to write tracking file {}" , file , e );
138- }
139- finally
140- {
141- release ( lock , file );
142- close ( raf , file );
143- }
117+ raf .seek ( 0 );
118+ raf .write ( stream .toByteArray () );
119+ raf .setLength ( raf .getFilePointer () );
144120 }
145-
146- return props ;
147- }
148-
149- private void release ( FileLock lock , File file )
150- {
151- if ( lock != null )
121+ catch ( IOException e )
152122 {
153- try
154- {
155- lock .release ();
156- }
157- catch ( IOException e )
158- {
159- LOGGER .warn ( "Error releasing lock for tracking file {}" , file , e );
160- }
123+ LOGGER .warn ( "Failed to write tracking file {}" , file , e );
161124 }
125+ finally
126+ {
127+ close ( raf , file );
128+ }
129+
130+ return props ;
162131 }
163132
164133 private void close ( Closeable closeable , File file )
@@ -176,61 +145,4 @@ private void close( Closeable closeable, File file )
176145 }
177146 }
178147
179- private Object getLock ( File file )
180- {
181- /*
182- * NOTE: Locks held by one JVM must not overlap and using the canonical path is our best bet, still another
183- * piece of code might have locked the same file (unlikely though) or the canonical path fails to capture file
184- * identity sufficiently as is the case with Java 1.6 and symlinks on Windows.
185- */
186- try
187- {
188- return file .getCanonicalPath ().intern ();
189- }
190- catch ( IOException e )
191- {
192- LOGGER .warn ( "Failed to canonicalize path {}" , file , e );
193- // TODO This is code smell and deprecated
194- return file .getAbsolutePath ().intern ();
195- }
196- }
197-
198- @ SuppressWarnings ( { "checkstyle:magicnumber" } )
199- private FileLock lock ( FileChannel channel , long size , boolean shared )
200- throws IOException
201- {
202- FileLock lock = null ;
203-
204- for ( int attempts = 8 ; attempts >= 0 ; attempts -- )
205- {
206- try
207- {
208- lock = channel .lock ( 0 , size , shared );
209- break ;
210- }
211- catch ( OverlappingFileLockException e )
212- {
213- if ( attempts <= 0 )
214- {
215- throw new IOException ( e );
216- }
217- try
218- {
219- Thread .sleep ( 50L );
220- }
221- catch ( InterruptedException e1 )
222- {
223- Thread .currentThread ().interrupt ();
224- }
225- }
226- }
227-
228- if ( lock == null )
229- {
230- throw new IOException ( "Could not lock file" );
231- }
232-
233- return lock ;
234- }
235-
236148}
0 commit comments