001package org.apache.archiva.policies; 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.archiva.checksum.UpdateStatus; 025import org.apache.archiva.repository.storage.StorageAsset; 026import org.apache.commons.lang3.StringUtils; 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029import org.springframework.stereotype.Service; 030 031import java.io.IOException; 032import java.nio.file.Files; 033import java.nio.file.Path; 034import java.util.ArrayList; 035import java.util.Arrays; 036import java.util.List; 037import java.util.Properties; 038 039/** 040 * ChecksumPolicy - a policy applied after the download to see if the file has been downloaded 041 * successfully and completely (or not). 042 * 043 * 044 */ 045@Service( "postDownloadPolicy#checksum" ) 046public class ChecksumPolicy 047 extends AbstractPolicy implements PostDownloadPolicy 048{ 049 private Logger log = LoggerFactory.getLogger( ChecksumPolicy.class ); 050 051 private static final String ID = "checksum"; 052 053 /** 054 * The IGNORE policy indicates that if the checksum policy is ignored, and 055 * the state of, contents of, or validity of the checksum files are not 056 * checked. 057 */ 058 public static final ChecksumOption IGNORE = ChecksumOption.IGNORE; 059 060 /** 061 * The FAIL policy indicates that if the checksum does not match the 062 * downloaded file, then remove the downloaded artifact, and checksum 063 * files, and fail the transfer to the client side. 064 */ 065 public static final ChecksumOption FAIL = ChecksumOption.FAIL; 066 067 /** 068 * The FIX policy indicates that if the checksum does not match the 069 * downloaded file, then fix the checksum file locally, and return 070 * to the client side the corrected checksum. 071 */ 072 public static final ChecksumOption FIX = ChecksumOption.FIX; 073 074 private List<ChecksumAlgorithm> algorithms = Arrays.asList( ChecksumAlgorithm.SHA256, ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5 ); 075 076 private List<PolicyOption> options = new ArrayList<>( 3 ); 077 078 public ChecksumPolicy() 079 { 080 super(); 081 options.add( FAIL ); 082 options.add( FIX ); 083 options.add( IGNORE ); 084 } 085 086 @Override 087 public void applyPolicy( PolicyOption policySetting, Properties request, StorageAsset localFile ) 088 throws PolicyViolationException, PolicyConfigurationException 089 { 090 if ( "resource".equals( request.getProperty( "filetype" ) ) ) 091 { 092 return; 093 } 094 095 if ( !options.contains( policySetting ) ) 096 { 097 // Not a valid code. 098 throw new PolicyConfigurationException( 099 "Unknown checksum policy setting [" + policySetting + "], valid settings are [" + StringUtils.join( 100 options.iterator(), "," ) + "]" ); 101 } 102 103 if ( IGNORE.equals( policySetting ) ) 104 { 105 // Ignore. 106 log.debug( "Checksum policy set to IGNORE." ); 107 return; 108 } 109 110 if ( !localFile.exists() ) 111 { 112 // Local File does not exist. 113 throw new PolicyViolationException( 114 "Checksum policy failure, local file " + localFile.getPath() + " does not exist to check." ); 115 } 116 117 if ( FAIL.equals( policySetting ) && localFile.isFileBased() ) 118 { 119 ChecksummedFile checksum = new ChecksummedFile( localFile.getFilePath() ); 120 if ( checksum.isValidChecksums( algorithms ) ) 121 { 122 return; 123 } 124 125 for ( ChecksumAlgorithm algorithm : algorithms ) 126 { 127 Path file = checksum.getChecksumFile( algorithm ); 128 try 129 { 130 Files.deleteIfExists( file ); 131 } 132 catch ( IOException e ) 133 { 134 log.error("Could not delete file {}", file); 135 } 136 } 137 138 try 139 { 140 localFile.getStorage().removeAsset( localFile ); 141 } 142 catch ( IOException e ) 143 { 144 log.error("Could not delete file {}", localFile); 145 } 146 throw new PolicyViolationException( 147 "Checksums do not match, policy set to FAIL, " + "deleting checksum files and local file " 148 + localFile.getPath() + "." ); 149 } 150 151 if ( FIX.equals( policySetting ) && localFile.isFileBased()) 152 { 153 ChecksummedFile checksum = new ChecksummedFile( localFile.getFilePath() ); 154 if ( checksum.fixChecksums( algorithms ).getTotalStatus() != UpdateStatus.ERROR ) 155 { 156 log.debug( "Checksum policy set to FIX, checksum files have been updated." ); 157 return; 158 } 159 else 160 { 161 throw new PolicyViolationException( 162 "Checksum policy set to FIX, " + "yet unable to update checksums for local file " 163 + localFile.getPath() + "." ); 164 } 165 } 166 167 throw new PolicyConfigurationException( 168 "Unable to process checksum policy of [" + policySetting + "], please file a bug report." ); 169 } 170 171 @Override 172 public PolicyOption getDefaultOption() 173 { 174 return FIX; 175 } 176 177 @Override 178 public String getId() 179 { 180 return ID; 181 } 182 183 @Override 184 public List<PolicyOption> getOptions() 185 { 186 return options; 187 } 188}