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