This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.transaction;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.archiva.checksum.ChecksumAlgorithm;
023import org.apache.archiva.checksum.ChecksummedFile;
024import org.apache.commons.io.FileUtils;
025
026import java.io.IOException;
027import java.nio.charset.Charset;
028import java.nio.file.Files;
029import java.nio.file.Path;
030import java.nio.file.Paths;
031import java.util.ArrayList;
032import java.util.Collections;
033import java.util.HashMap;
034import java.util.Iterator;
035import java.util.List;
036import java.util.Map;
037import java.util.stream.Stream;
038
039/**
040 * Abstract class for the TransactionEvents
041 *
042 *
043 */
044public abstract class AbstractTransactionEvent
045    implements TransactionEvent
046{
047    private Map<Path, Path> backups = new HashMap<>();
048
049    private List<Path> createdDirs = new ArrayList<>();
050
051    private List<Path> createdFiles = new ArrayList<>();
052
053    private List<ChecksumAlgorithm> checksumAlgorithms;
054
055    protected AbstractTransactionEvent()
056    {
057        this( new ArrayList<ChecksumAlgorithm>( 0 ) );
058    }
059
060    protected AbstractTransactionEvent( List<ChecksumAlgorithm> checksumAlgorithms)
061    {
062        this.checksumAlgorithms = checksumAlgorithms;
063    }
064
065    protected List<ChecksumAlgorithm> getChecksumAlgorithms()
066    {
067        return checksumAlgorithms;
068    }
069
070    /**
071     * Method that creates a directory as well as all the parent directories needed
072     *
073     * @param dir The File directory to be created
074     * @throws IOException when an unrecoverable error occurred
075     */
076    protected void mkDirs( Path dir )
077        throws IOException
078    {
079        List<Path> createDirs = new ArrayList<>();
080
081        Path parent = dir;
082        while ( !Files.exists(parent) || !Files.isDirectory(parent) )
083        {
084            createDirs.add( parent );
085
086            parent = parent.getParent();
087        }
088
089        while ( !createDirs.isEmpty() )
090        {
091            Path directory = createDirs.remove( createDirs.size() - 1 );
092            Files.createDirectories(directory);
093            createdDirs.add( directory );
094        }
095    }
096
097    protected void revertMkDirs()
098        throws IOException
099    {
100        if ( createdDirs != null )
101        {
102            Collections.reverse( createdDirs );
103
104            while ( !createdDirs.isEmpty() )
105            {
106                Path dir = createdDirs.remove( 0 );
107
108                if ( Files.isDirectory(dir))
109                {
110                    try(Stream<Path> str = Files.list(dir)) {
111                        if (str.count()==0) {
112                            org.apache.archiva.common.utils.FileUtils.deleteDirectory(dir);
113                        }
114                    }
115                }
116                else
117                {
118                    //cannot rollback created directory if it still contains files
119                    break;
120                }
121            }
122        }
123    }
124
125    protected void revertFilesCreated()
126        throws IOException
127    {
128        Iterator<Path> it = createdFiles.iterator();
129        while ( it.hasNext() )
130        {
131            Path file = it.next();
132            Files.deleteIfExists(file);
133            it.remove();
134        }
135    }
136
137    protected void createBackup( Path file )
138        throws IOException
139    {
140        if ( Files.exists(file) && Files.isRegularFile(file) )
141        {
142            Path backup = Files.createTempFile( "temp-", ".backup" );
143
144            FileUtils.copyFile( file.toFile(), backup.toFile() );
145
146            backup.toFile().deleteOnExit();
147
148            backups.put( file, backup );
149        }
150    }
151
152    protected void restoreBackups()
153        throws IOException
154    {
155        for ( Map.Entry<Path, Path> entry : backups.entrySet() )
156        {
157            FileUtils.copyFile( entry.getValue().toFile(), entry.getKey().toFile() );
158        }
159    }
160
161    protected void restoreBackup( Path file )
162        throws IOException
163    {
164        Path backup = backups.get( file );
165        if ( backup != null )
166        {
167            FileUtils.copyFile( backup.toFile(), file.toFile() );
168        }
169    }
170
171    /**
172     * Create checksums of file using all digesters defined at construction time.
173     *
174     * @param file
175     * @param force whether existing checksums should be overwritten or not
176     * @throws IOException
177     */
178    protected void createChecksums( Path file, boolean force )
179        throws IOException
180    {
181        for ( ChecksumAlgorithm checksumAlgorithm : getChecksumAlgorithms() )
182        {
183            Path checksumFile = Paths.get( file.toAbsolutePath( ) + "." + getChecksumFileExtension( checksumAlgorithm ) );
184            if ( Files.exists( checksumFile ) )
185            {
186                if ( !force )
187                {
188                    continue;
189                }
190                createBackup( checksumFile );
191            }
192            else
193            {
194                createdFiles.add( checksumFile );
195            }
196        }
197        ChecksummedFile csFile = new ChecksummedFile( file );
198        csFile.fixChecksums( getChecksumAlgorithms() );
199    }
200
201    /**
202     * TODO: Remove in favor of using FileUtils directly.
203     */
204    protected void writeStringToFile( Path file, String content )
205        throws IOException
206    {
207        org.apache.archiva.common.utils.FileUtils.writeStringToFile( file, Charset.defaultCharset(), content );
208    }
209
210    /**
211     * File extension for checksums
212     * TODO should be moved to plexus-digester ?
213     */
214    protected String getChecksumFileExtension( ChecksumAlgorithm algorithm )
215    {
216        return algorithm.getExt().get(0);
217    }
218
219}