You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AbstractTransactionEvent.java 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. package org.apache.archiva.transaction;
  2. /*
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. */
  20. import org.apache.commons.io.FileUtils;
  21. import org.codehaus.plexus.digest.Digester;
  22. import org.codehaus.plexus.digest.DigesterException;
  23. import java.io.IOException;
  24. import java.nio.charset.Charset;
  25. import java.nio.file.Files;
  26. import java.nio.file.Path;
  27. import java.nio.file.Paths;
  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. import java.util.stream.Stream;
  35. /**
  36. * Abstract class for the TransactionEvents
  37. *
  38. *
  39. */
  40. public abstract class AbstractTransactionEvent
  41. implements TransactionEvent
  42. {
  43. private Map<Path, Path> backups = new HashMap<>();
  44. private List<Path> createdDirs = new ArrayList<>();
  45. private List<Path> createdFiles = new ArrayList<>();
  46. /**
  47. * {@link List}&lt;{@link Digester}&gt;
  48. */
  49. private List<? extends Digester> digesters;
  50. protected AbstractTransactionEvent()
  51. {
  52. this( new ArrayList<Digester>( 0 ) );
  53. }
  54. protected AbstractTransactionEvent( List<? extends Digester> digesters )
  55. {
  56. this.digesters = digesters;
  57. }
  58. protected List<? extends Digester> getDigesters()
  59. {
  60. return digesters;
  61. }
  62. /**
  63. * Method that creates a directory as well as all the parent directories needed
  64. *
  65. * @param dir The File directory to be created
  66. * @throws IOException when an unrecoverable error occurred
  67. */
  68. protected void mkDirs( Path dir )
  69. throws IOException
  70. {
  71. List<Path> createDirs = new ArrayList<>();
  72. Path parent = dir;
  73. while ( !Files.exists(parent) || !Files.isDirectory(parent) )
  74. {
  75. createDirs.add( parent );
  76. parent = parent.getParent();
  77. }
  78. while ( !createDirs.isEmpty() )
  79. {
  80. Path directory = createDirs.remove( createDirs.size() - 1 );
  81. Files.createDirectories(directory);
  82. createdDirs.add( directory );
  83. }
  84. }
  85. protected void revertMkDirs()
  86. throws IOException
  87. {
  88. if ( createdDirs != null )
  89. {
  90. Collections.reverse( createdDirs );
  91. while ( !createdDirs.isEmpty() )
  92. {
  93. Path dir = createdDirs.remove( 0 );
  94. if ( Files.isDirectory(dir))
  95. {
  96. try(Stream<Path> str = Files.list(dir)) {
  97. if (str.count()==0) {
  98. org.apache.archiva.common.utils.FileUtils.deleteDirectory(dir);
  99. }
  100. }
  101. }
  102. else
  103. {
  104. //cannot rollback created directory if it still contains files
  105. break;
  106. }
  107. }
  108. }
  109. }
  110. protected void revertFilesCreated()
  111. throws IOException
  112. {
  113. Iterator<Path> it = createdFiles.iterator();
  114. while ( it.hasNext() )
  115. {
  116. Path file = it.next();
  117. Files.deleteIfExists(file);
  118. it.remove();
  119. }
  120. }
  121. protected void createBackup( Path file )
  122. throws IOException
  123. {
  124. if ( Files.exists(file) && Files.isRegularFile(file) )
  125. {
  126. Path backup = Files.createTempFile( "temp-", ".backup" );
  127. FileUtils.copyFile( file.toFile(), backup.toFile() );
  128. backup.toFile().deleteOnExit();
  129. backups.put( file, backup );
  130. }
  131. }
  132. protected void restoreBackups()
  133. throws IOException
  134. {
  135. for ( Map.Entry<Path, Path> entry : backups.entrySet() )
  136. {
  137. FileUtils.copyFile( entry.getValue().toFile(), entry.getKey().toFile() );
  138. }
  139. }
  140. protected void restoreBackup( Path file )
  141. throws IOException
  142. {
  143. Path backup = backups.get( file );
  144. if ( backup != null )
  145. {
  146. FileUtils.copyFile( backup.toFile(), file.toFile() );
  147. }
  148. }
  149. /**
  150. * Create checksums of file using all digesters defined at construction time.
  151. *
  152. * @param file
  153. * @param force whether existing checksums should be overwritten or not
  154. * @throws IOException
  155. */
  156. protected void createChecksums( Path file, boolean force )
  157. throws IOException
  158. {
  159. for ( Digester digester : getDigesters() )
  160. {
  161. Path checksumFile = Paths.get(file.toAbsolutePath() + "." + getDigesterFileExtension( digester ) );
  162. if ( Files.exists(checksumFile) )
  163. {
  164. if ( !force )
  165. {
  166. continue;
  167. }
  168. createBackup( checksumFile );
  169. }
  170. else
  171. {
  172. createdFiles.add( checksumFile );
  173. }
  174. try
  175. {
  176. writeStringToFile( checksumFile, digester.calc( file.toFile() ) );
  177. }
  178. catch ( DigesterException e )
  179. {
  180. throw (IOException) e.getCause();
  181. }
  182. }
  183. }
  184. /**
  185. * TODO: Remove in favor of using FileUtils directly.
  186. */
  187. protected void writeStringToFile( Path file, String content )
  188. throws IOException
  189. {
  190. org.apache.archiva.common.utils.FileUtils.writeStringToFile( file, Charset.defaultCharset(), content );
  191. }
  192. /**
  193. * File extension for checksums
  194. * TODO should be moved to plexus-digester ?
  195. */
  196. protected String getDigesterFileExtension( Digester digester )
  197. {
  198. return digester.getAlgorithm().toLowerCase().replaceAll( "-", "" );
  199. }
  200. }