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.0KB

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