This project has retired. For details please refer to its Attic page.
AbstractTransactionEvent xref
View Javadoc
1   package org.apache.archiva.transaction;
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 org.apache.commons.io.FileUtils;
23  import org.codehaus.plexus.digest.Digester;
24  import org.codehaus.plexus.digest.DigesterException;
25  
26  import java.io.File;
27  import java.io.IOException;
28  import java.util.ArrayList;
29  import java.util.Collections;
30  import java.util.HashMap;
31  import java.util.Iterator;
32  import java.util.List;
33  import java.util.Map;
34  
35  /**
36   * Abstract class for the TransactionEvents
37   *
38   *
39   */
40  public abstract class AbstractTransactionEvent
41      implements TransactionEvent
42  {
43      private Map<File, File> backups = new HashMap<>();
44  
45      private List<File> createdDirs = new ArrayList<>();
46  
47      private List<File> createdFiles = new ArrayList<>();
48  
49      /**
50       * {@link List}&lt;{@link Digester}&gt;
51       */
52      private List<? extends Digester> digesters;
53  
54      protected AbstractTransactionEvent()
55      {
56          this( new ArrayList<Digester>( 0 ) );
57      }
58  
59      protected AbstractTransactionEvent( List<? extends Digester> digesters )
60      {
61          this.digesters = digesters;
62      }
63  
64      protected List<? extends Digester> getDigesters()
65      {
66          return digesters;
67      }
68  
69      /**
70       * Method that creates a directory as well as all the parent directories needed
71       *
72       * @param dir The File directory to be created
73       * @throws IOException when an unrecoverable error occurred
74       */
75      protected void mkDirs( File dir )
76          throws IOException
77      {
78          List<File> createDirs = new ArrayList<>();
79  
80          File parent = dir;
81          while ( !parent.exists() || !parent.isDirectory() )
82          {
83              createDirs.add( parent );
84  
85              parent = parent.getParentFile();
86          }
87  
88          while ( !createDirs.isEmpty() )
89          {
90              File directory = createDirs.remove( createDirs.size() - 1 );
91  
92              if ( directory.mkdir() )
93              {
94                  createdDirs.add( directory );
95              }
96              else
97              {
98                  throw new IOException( "Failed to create directory: " + directory.getAbsolutePath() );
99              }
100         }
101     }
102 
103     protected void revertMkDirs()
104         throws IOException
105     {
106         if ( createdDirs != null )
107         {
108             Collections.reverse( createdDirs );
109 
110             while ( !createdDirs.isEmpty() )
111             {
112                 File dir = (File) createdDirs.remove( 0 );
113 
114                 if ( dir.isDirectory() && dir.list().length == 0 )
115                 {
116                     FileUtils.deleteDirectory( dir );
117                 }
118                 else
119                 {
120                     //cannot rollback created directory if it still contains files
121                     break;
122                 }
123             }
124         }
125     }
126 
127     protected void revertFilesCreated()
128         throws IOException
129     {
130         Iterator<File> it = createdFiles.iterator();
131         while ( it.hasNext() )
132         {
133             File file = (File) it.next();
134             file.delete();
135             it.remove();
136         }
137     }
138 
139     protected void createBackup( File file )
140         throws IOException
141     {
142         if ( file.exists() && file.isFile() )
143         {
144             File backup = File.createTempFile( "temp-", ".backup" );
145 
146             FileUtils.copyFile( file, backup );
147 
148             backup.deleteOnExit();
149 
150             backups.put( file, backup );
151         }
152     }
153 
154     protected void restoreBackups()
155         throws IOException
156     {
157         for ( Map.Entry<File, File> entry : backups.entrySet() )
158         {
159             FileUtils.copyFile( entry.getValue(), entry.getKey() );
160         }
161     }
162 
163     protected void restoreBackup( File file )
164         throws IOException
165     {
166         File backup = (File) backups.get( file );
167         if ( backup != null )
168         {
169             FileUtils.copyFile( backup, file );
170         }
171     }
172 
173     /**
174      * Create checksums of file using all digesters defined at construction time.
175      *
176      * @param file
177      * @param force whether existing checksums should be overwritten or not
178      * @throws IOException
179      */
180     protected void createChecksums( File file, boolean force )
181         throws IOException
182     {
183         for ( Digester digester : getDigesters() )
184         {
185             File checksumFile = new File( file.getAbsolutePath() + "." + getDigesterFileExtension( digester ) );
186             if ( checksumFile.exists() )
187             {
188                 if ( !force )
189                 {
190                     continue;
191                 }
192                 createBackup( checksumFile );
193             }
194             else
195             {
196                 createdFiles.add( checksumFile );
197             }
198 
199             try
200             {
201                 writeStringToFile( checksumFile, digester.calc( file ) );
202             }
203             catch ( DigesterException e )
204             {
205                 throw (IOException) e.getCause();
206             }
207         }
208     }
209 
210     /**
211      * TODO: Remove in favor of using FileUtils directly.
212      */
213     protected void writeStringToFile( File file, String content )
214         throws IOException
215     {
216         FileUtils.writeStringToFile( file, content );
217     }
218 
219     /**
220      * File extension for checksums
221      * TODO should be moved to plexus-digester ?
222      */
223     protected String getDigesterFileExtension( Digester digester )
224     {
225         return digester.getAlgorithm().toLowerCase().replaceAll( "-", "" );
226     }
227 
228 }