View Javadoc
1   package org.eclipse.aether.internal.impl;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.ByteArrayInputStream;
23  import java.io.ByteArrayOutputStream;
24  import java.io.Closeable;
25  import java.io.File;
26  import java.io.FileInputStream;
27  import java.io.IOException;
28  import java.io.RandomAccessFile;
29  import java.util.Map;
30  import java.util.Properties;
31  
32  import javax.inject.Named;
33  import javax.inject.Singleton;
34  
35  import org.slf4j.Logger;
36  import org.slf4j.LoggerFactory;
37  
38  /**
39   * Manages access to a properties file.
40   */
41  @Singleton
42  @Named
43  public final class DefaultTrackingFileManager
44      implements TrackingFileManager
45  {
46      private static final Logger LOGGER = LoggerFactory.getLogger( DefaultTrackingFileManager.class );
47  
48      @Override
49      public Properties read( File file )
50      {
51          FileInputStream stream = null;
52          try
53          {
54              if ( !file.exists() )
55              {
56                  return null;
57              }
58  
59              stream = new FileInputStream( file );
60  
61              Properties props = new Properties();
62              props.load( stream );
63  
64              return props;
65          }
66          catch ( IOException e )
67          {
68              LOGGER.warn( "Failed to read tracking file {}", file, e );
69          }
70          finally
71          {
72              close( stream, file );
73          }
74  
75          return null;
76      }
77  
78      @Override
79      public Properties update( File file, Map<String, String> updates )
80      {
81          Properties props = new Properties();
82  
83          File directory = file.getParentFile();
84          if ( !directory.mkdirs() && !directory.exists() )
85          {
86              LOGGER.warn( "Failed to create parent directories for tracking file {}", file );
87              return props;
88          }
89  
90          RandomAccessFile raf = null;
91          try
92          {
93              raf = new RandomAccessFile( file, "rw" );
94  
95              if ( file.canRead() )
96              {
97                  byte[] buffer = new byte[(int) raf.length()];
98  
99                  raf.readFully( buffer );
100 
101                 ByteArrayInputStream stream = new ByteArrayInputStream( buffer );
102 
103                 props.load( stream );
104             }
105 
106             for ( Map.Entry<String, String> update : updates.entrySet() )
107             {
108                 if ( update.getValue() == null )
109                 {
110                     props.remove( update.getKey() );
111                 }
112                 else
113                 {
114                     props.setProperty( update.getKey(), update.getValue() );
115                 }
116             }
117 
118             ByteArrayOutputStream stream = new ByteArrayOutputStream( 1024 * 2 );
119 
120             LOGGER.debug( "Writing tracking file {}", file );
121             props.store( stream, "NOTE: This is a Maven Resolver internal implementation file"
122                 + ", its format can be changed without prior notice." );
123 
124             raf.seek( 0 );
125             raf.write( stream.toByteArray() );
126             raf.setLength( raf.getFilePointer() );
127         }
128         catch ( IOException e )
129         {
130             LOGGER.warn( "Failed to write tracking file {}", file, e );
131         }
132         finally
133         {
134             close( raf, file );
135         }
136 
137         return props;
138     }
139 
140     private void close( Closeable closeable, File file )
141     {
142         if ( closeable != null )
143         {
144             try
145             {
146                 closeable.close();
147             }
148             catch ( IOException e )
149             {
150                 LOGGER.warn( "Error closing tracking file {}", file, e );
151             }
152         }
153     }
154 
155 }