001package org.apache.archiva.configuration; 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.common.FileTypeUtils; 023import org.apache.archiva.configuration.functors.FiletypeSelectionPredicate; 024import org.apache.archiva.configuration.io.registry.ConfigurationRegistryReader; 025import org.apache.archiva.configuration.util.PathMatcher; 026import org.apache.archiva.components.registry.Registry; 027import org.apache.archiva.components.registry.RegistryException; 028import org.apache.archiva.components.registry.RegistryListener; 029import org.apache.archiva.components.registry.commons.CommonsConfigurationRegistry; 030import org.apache.commons.collections4.CollectionUtils; 031import org.apache.commons.collections4.IterableUtils; 032import org.apache.commons.collections4.Predicate; 033import org.apache.commons.configuration.CombinedConfiguration; 034import org.springframework.stereotype.Service; 035 036import javax.annotation.PostConstruct; 037import javax.inject.Inject; 038import javax.inject.Named; 039import java.lang.reflect.Field; 040import java.util.ArrayList; 041import java.util.Collections; 042import java.util.HashMap; 043import java.util.List; 044import java.util.Map; 045 046/** 047 * FileTypes 048 */ 049@Service("fileTypes") 050public class FileTypes 051 implements RegistryListener 052{ 053 public static final String ARTIFACTS = "artifacts"; 054 055 public static final String AUTO_REMOVE = "auto-remove"; 056 057 public static final String INDEXABLE_CONTENT = "indexable-content"; 058 059 public static final String IGNORED = "ignored"; 060 061 @Inject 062 @Named(value = "archivaConfiguration#default") 063 private ArchivaConfiguration archivaConfiguration; 064 065 066 public FileTypes() { 067 068 } 069 070 /** 071 * Map of default values for the file types. 072 */ 073 private Map<String, List<String>> defaultTypeMap = new HashMap<>(); 074 075 private List<String> artifactPatterns; 076 077 /** 078 * Default exclusions from artifact consumers that are using the file types. Note that this is simplistic in the 079 * case of the support files (based on extension) as it is elsewhere - it may be better to match these to actual 080 * artifacts and exclude later during scanning. 081 * 082 * @deprecated 083 */ 084 public static final List<String> DEFAULT_EXCLUSIONS = FileTypeUtils.DEFAULT_EXCLUSIONS; 085 086 public void setArchivaConfiguration( ArchivaConfiguration archivaConfiguration ) 087 { 088 this.archivaConfiguration = archivaConfiguration; 089 } 090 091 /** 092 * Get the list of patterns for a specified filetype. 093 * You will always get a list. In this order. 094 * <ul> 095 * <li>The Configured List</li> 096 * <li>The Default List</li> 097 * <li>A single item list of <code>"**/*"</code></li> 098 * </ul> 099 * 100 * @param id the id to lookup. 101 * @return the list of patterns. 102 */ 103 public List<String> getFileTypePatterns( String id ) 104 { 105 Configuration config = archivaConfiguration.getConfiguration(); 106 Predicate selectedFiletype = new FiletypeSelectionPredicate( id ); 107 RepositoryScanningConfiguration repositoryScanningConfiguration = config.getRepositoryScanning(); 108 if ( repositoryScanningConfiguration != null ) 109 { 110 FileType filetype = 111 IterableUtils.find( config.getRepositoryScanning().getFileTypes(), selectedFiletype ); 112 113 if ( ( filetype != null ) && CollectionUtils.isNotEmpty( filetype.getPatterns() ) ) 114 { 115 return filetype.getPatterns(); 116 } 117 } 118 List<String> defaultPatterns = defaultTypeMap.get( id ); 119 120 if ( CollectionUtils.isEmpty( defaultPatterns ) ) 121 { 122 return Collections.singletonList( "**/*" ); 123 } 124 125 return defaultPatterns; 126 } 127 128 public synchronized boolean matchesArtifactPattern( String relativePath ) 129 { 130 // Correct the slash pattern. 131 relativePath = relativePath.replace( '\\', '/' ); 132 133 if ( artifactPatterns == null ) 134 { 135 artifactPatterns = getFileTypePatterns( ARTIFACTS ); 136 } 137 138 for ( String pattern : artifactPatterns ) 139 { 140 if ( PathMatcher.matchPath( pattern, relativePath, false ) ) 141 { 142 // Found match 143 return true; 144 } 145 } 146 147 // No match. 148 return false; 149 } 150 151 public boolean matchesDefaultExclusions( String relativePath ) 152 { 153 // Correct the slash pattern. 154 relativePath = relativePath.replace( '\\', '/' ); 155 156 for ( String pattern : DEFAULT_EXCLUSIONS ) 157 { 158 if ( PathMatcher.matchPath( pattern, relativePath, false ) ) 159 { 160 // Found match 161 return true; 162 } 163 } 164 165 // No match. 166 return false; 167 } 168 169 @PostConstruct 170 public void initialize() 171 { 172 // TODO: why is this done by hand? 173 174 // TODO: ideally, this would be instantiated by configuration instead, and not need to be a component 175 176 String errMsg = "Unable to load default archiva configuration for FileTypes: "; 177 178 try 179 { 180 CommonsConfigurationRegistry commonsRegistry = new CommonsConfigurationRegistry(); 181 182 // Configure commonsRegistry 183 Field fld = commonsRegistry.getClass().getDeclaredField( "configuration" ); 184 fld.setAccessible( true ); 185 fld.set( commonsRegistry, new CombinedConfiguration() ); 186 commonsRegistry.addConfigurationFromResource( "org/apache/archiva/configuration/default-archiva.xml" ); 187 188 // Read configuration as it was intended. 189 ConfigurationRegistryReader configReader = new ConfigurationRegistryReader(); 190 Configuration defaultConfig = configReader.read( commonsRegistry ); 191 192 initialiseTypeMap( defaultConfig ); 193 } 194 catch ( RegistryException e ) 195 { 196 throw new RuntimeException( errMsg + e.getMessage(), e ); 197 } 198 catch ( SecurityException e ) 199 { 200 throw new RuntimeException( errMsg + e.getMessage(), e ); 201 } 202 catch ( NoSuchFieldException e ) 203 { 204 throw new RuntimeException( errMsg + e.getMessage(), e ); 205 } 206 catch ( IllegalArgumentException e ) 207 { 208 throw new RuntimeException( errMsg + e.getMessage(), e ); 209 } 210 catch ( IllegalAccessException e ) 211 { 212 throw new RuntimeException( errMsg + e.getMessage(), e ); 213 } 214 215 this.archivaConfiguration.addChangeListener( this ); 216 } 217 218 private void initialiseTypeMap( Configuration configuration ) 219 { 220 defaultTypeMap.clear(); 221 222 // Store the default file type declaration. 223 List<FileType> filetypes = configuration.getRepositoryScanning().getFileTypes(); 224 for ( FileType filetype : filetypes ) 225 { 226 List<String> patterns = defaultTypeMap.get( filetype.getId() ); 227 if ( patterns == null ) 228 { 229 patterns = new ArrayList<>( filetype.getPatterns().size() ); 230 } 231 patterns.addAll( filetype.getPatterns() ); 232 233 defaultTypeMap.put( filetype.getId(), patterns ); 234 } 235 } 236 237 @Override 238 public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue ) 239 { 240 if ( propertyName.contains( "fileType" ) ) 241 { 242 artifactPatterns = null; 243 244 initialiseTypeMap( archivaConfiguration.getConfiguration() ); 245 } 246 } 247 248 @Override 249 public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue ) 250 { 251 /* nothing to do */ 252 } 253}