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