package org.apache.archiva.transaction; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.commons.io.FileUtils; import org.codehaus.plexus.digest.Digester; import org.codehaus.plexus.digest.DigesterException; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * Abstract class for the TransactionEvents * * */ public abstract class AbstractTransactionEvent implements TransactionEvent { private Map<File, File> backups = new HashMap<>(); private List<File> createdDirs = new ArrayList<>(); private List<File> createdFiles = new ArrayList<>(); /** * {@link List}<{@link Digester}> */ private List<? extends Digester> digesters; protected AbstractTransactionEvent() { this( new ArrayList<Digester>( 0 ) ); } protected AbstractTransactionEvent( List<? extends Digester> digesters ) { this.digesters = digesters; } protected List<? extends Digester> getDigesters() { return digesters; } /** * Method that creates a directory as well as all the parent directories needed * * @param dir The File directory to be created * @throws IOException when an unrecoverable error occurred */ protected void mkDirs( File dir ) throws IOException { List<File> createDirs = new ArrayList<>(); File parent = dir; while ( !parent.exists() || !parent.isDirectory() ) { createDirs.add( parent ); parent = parent.getParentFile(); } while ( !createDirs.isEmpty() ) { File directory = createDirs.remove( createDirs.size() - 1 ); if ( directory.mkdir() ) { createdDirs.add( directory ); } else { throw new IOException( "Failed to create directory: " + directory.getAbsolutePath() ); } } } protected void revertMkDirs() throws IOException { if ( createdDirs != null ) { Collections.reverse( createdDirs ); while ( !createdDirs.isEmpty() ) { File dir = (File) createdDirs.remove( 0 ); if ( dir.isDirectory() && dir.list().length == 0 ) { FileUtils.deleteDirectory( dir ); } else { //cannot rollback created directory if it still contains files break; } } } } protected void revertFilesCreated() throws IOException { Iterator<File> it = createdFiles.iterator(); while ( it.hasNext() ) { File file = (File) it.next(); file.delete(); it.remove(); } } protected void createBackup( File file ) throws IOException { if ( file.exists() && file.isFile() ) { File backup = File.createTempFile( "temp-", ".backup" ); FileUtils.copyFile( file, backup ); backup.deleteOnExit(); backups.put( file, backup ); } } protected void restoreBackups() throws IOException { for ( Map.Entry<File, File> entry : backups.entrySet() ) { FileUtils.copyFile( entry.getValue(), entry.getKey() ); } } protected void restoreBackup( File file ) throws IOException { File backup = (File) backups.get( file ); if ( backup != null ) { FileUtils.copyFile( backup, file ); } } /** * Create checksums of file using all digesters defined at construction time. * * @param file * @param force whether existing checksums should be overwritten or not * @throws IOException */ protected void createChecksums( File file, boolean force ) throws IOException { for ( Digester digester : getDigesters() ) { File checksumFile = new File( file.getAbsolutePath() + "." + getDigesterFileExtension( digester ) ); if ( checksumFile.exists() ) { if ( !force ) { continue; } createBackup( checksumFile ); } else { createdFiles.add( checksumFile ); } try { writeStringToFile( checksumFile, digester.calc( file ) ); } catch ( DigesterException e ) { throw (IOException) e.getCause(); } } } /** * TODO: Remove in favor of using FileUtils directly. */ protected void writeStringToFile( File file, String content ) throws IOException { FileUtils.writeStringToFile( file, content ); } /** * File extension for checksums * TODO should be moved to plexus-digester ? */ protected String getDigesterFileExtension( Digester digester ) { return digester.getAlgorithm().toLowerCase().replaceAll( "-", "" ); } }