1 package org.apache.archiva.repository.content.maven2; 2 3 /* 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 22 import org.apache.archiva.model.ArtifactReference; 23 import org.apache.archiva.repository.ManagedRepositoryContent; 24 import org.apache.archiva.repository.content.PathParser; 25 import org.apache.archiva.repository.layout.LayoutException; 26 import org.apache.archiva.repository.metadata.MetadataTools; 27 import org.apache.commons.lang.StringUtils; 28 29 /** 30 * RepositoryRequest is used to determine the type of request that is incoming, and convert it to an appropriate 31 * ArtifactReference. 32 */ 33 public class RepositoryRequest 34 { 35 private PathParser defaultPathParser = new DefaultPathParser(); 36 37 public RepositoryRequest() 38 { 39 // no op 40 } 41 42 /** 43 * Takes an incoming requested path (in "/" format) and gleans the layout 44 * and ArtifactReference appropriate for that content. 45 * 46 * @param requestedPath the relative path to the content. 47 * @return the ArtifactReference for the requestedPath. 48 * @throws org.apache.archiva.repository.layout.LayoutException if the request path is not layout valid. 49 */ 50 public ArtifactReference toArtifactReference( String requestedPath ) 51 throws LayoutException 52 { 53 if ( StringUtils.isBlank( requestedPath ) ) 54 { 55 throw new LayoutException( "Blank request path is not a valid." ); 56 } 57 58 String path = requestedPath; 59 while ( path.startsWith( "/" ) ) 60 { 61 path = path.substring( 1 ); 62 63 // Only slash? that's bad, mmm-kay? 64 if ( "/".equals( path ) ) 65 { 66 throw new LayoutException( "Invalid request path: Slash only." ); 67 } 68 } 69 70 if ( isDefault( path ) ) 71 { 72 return defaultPathParser.toArtifactReference( path ); 73 } 74 else if ( isLegacy( path ) ) 75 { 76 throw new LayoutException( "Legacy Maven1 repository not supported anymore." ); 77 } 78 else 79 { 80 throw new LayoutException( "Not a valid request path layout, too short." ); 81 } 82 } 83 84 /** 85 * <p> 86 * Tests the path to see if it conforms to the expectations of a metadata request. 87 * </p> 88 * <p> 89 * NOTE: This does a cursory check on the path's last element. A result of true 90 * from this method is not a guarantee that the metadata is in a valid format, or 91 * that it even contains data. 92 * </p> 93 * 94 * @param requestedPath the path to test. 95 * @return true if the requestedPath is likely a metadata request. 96 */ 97 public boolean isMetadata( String requestedPath ) 98 { 99 return requestedPath.endsWith( "/" + MetadataTools.MAVEN_METADATA ); 100 } 101 102 /** 103 * @param requestedPath 104 * @return true if the requestedPath is likely an archetype catalog request. 105 */ 106 public boolean isArchetypeCatalog( String requestedPath ) 107 { 108 return requestedPath.endsWith( "/" + MetadataTools.MAVEN_ARCHETYPE_CATALOG ); 109 } 110 111 /** 112 * <p> 113 * Tests the path to see if it conforms to the expectations of a support file request. 114 * </p> 115 * <p> 116 * Tests for <code>.sha1</code>, <code>.md5</code>, <code>.asc</code>, and <code>.php</code>. 117 * </p> 118 * <p> 119 * NOTE: This does a cursory check on the path's extension only. A result of true 120 * from this method is not a guarantee that the support resource is in a valid format, or 121 * that it even contains data. 122 * </p> 123 * 124 * @param requestedPath the path to test. 125 * @return true if the requestedPath is likely that of a support file request. 126 */ 127 public boolean isSupportFile( String requestedPath ) 128 { 129 int idx = requestedPath.lastIndexOf( '.' ); 130 if ( idx <= 0 ) 131 { 132 return false; 133 } 134 135 String ext = requestedPath.substring( idx ); 136 return ( ".sha1".equals( ext ) || ".md5".equals( ext ) || ".asc".equals( ext ) || ".pgp".equals( ext ) ); 137 } 138 139 public boolean isMetadataSupportFile( String requestedPath ) 140 { 141 if ( isSupportFile( requestedPath ) ) 142 { 143 String basefilePath = StringUtils.substring( requestedPath, 0, requestedPath.lastIndexOf( '.' ) ); 144 if ( isMetadata( basefilePath ) ) 145 { 146 return true; 147 } 148 } 149 150 return false; 151 } 152 153 /** 154 * <p> 155 * Tests the path to see if it conforms to the expectations of a default layout request. 156 * </p> 157 * <p> 158 * NOTE: This does a cursory check on the count of path elements only. A result of 159 * true from this method is not a guarantee that the path sections are valid and 160 * can be resolved to an artifact reference. use {@link #toArtifactReference(String)} 161 * if you want a more complete analysis of the validity of the path. 162 * </p> 163 * 164 * @param requestedPath the path to test. 165 * @return true if the requestedPath is likely that of a default layout request. 166 */ 167 public boolean isDefault( String requestedPath ) 168 { 169 if ( StringUtils.isBlank( requestedPath ) ) 170 { 171 return false; 172 } 173 174 String pathParts[] = StringUtils.splitPreserveAllTokens( requestedPath, '/' ); 175 if ( pathParts.length > 3 ) 176 { 177 return true; 178 } 179 else if ( pathParts.length == 3 ) 180 { 181 // check if artifact-level metadata (ex. eclipse/jdtcore/maven-metadata.xml) 182 if ( isMetadata( requestedPath ) ) 183 { 184 return true; 185 } 186 else 187 { 188 // check if checksum of artifact-level metadata (ex. eclipse/jdtcore/maven-metadata.xml.sha1) 189 int idx = requestedPath.lastIndexOf( '.' ); 190 if ( idx > 0 ) 191 { 192 String base = requestedPath.substring( 0, idx ); 193 if ( isMetadata( base ) && isSupportFile( requestedPath ) ) 194 { 195 return true; 196 } 197 } 198 199 return false; 200 } 201 } 202 else 203 { 204 return false; 205 } 206 } 207 208 /** 209 * <p> 210 * Tests the path to see if it conforms to the expectations of a legacy layout request. 211 * </p> 212 * <p> 213 * NOTE: This does a cursory check on the count of path elements only. A result of 214 * true from this method is not a guarantee that the path sections are valid and 215 * can be resolved to an artifact reference. use {@link #toArtifactReference(String)} 216 * if you want a more complete analysis of the validity of the path. 217 * </p> 218 * 219 * @param requestedPath the path to test. 220 * @return true if the requestedPath is likely that of a legacy layout request. 221 */ 222 public boolean isLegacy( String requestedPath ) 223 { 224 if ( StringUtils.isBlank( requestedPath ) ) 225 { 226 return false; 227 } 228 229 String pathParts[] = StringUtils.splitPreserveAllTokens( requestedPath, '/' ); 230 return pathParts.length == 3; 231 } 232 233 /** 234 * Adjust the requestedPath to conform to the native layout of the provided {@link org.apache.archiva.repository.ManagedRepositoryContent}. 235 * 236 * @param requestedPath the incoming requested path. 237 * @param repository the repository to adjust to. 238 * @return the adjusted (to native) path. 239 * @throws org.apache.archiva.repository.layout.LayoutException if the path cannot be parsed. 240 */ 241 public String toNativePath( String requestedPath, ManagedRepositoryContent repository ) 242 throws LayoutException 243 { 244 if ( StringUtils.isBlank( requestedPath ) ) 245 { 246 throw new LayoutException( "Request Path is blank." ); 247 } 248 249 String referencedResource = requestedPath; 250 // No checksum by default. 251 String supportfile = ""; 252 253 // Figure out support file, and actual referencedResource. 254 if ( isSupportFile( requestedPath ) ) 255 { 256 int idx = requestedPath.lastIndexOf( '.' ); 257 referencedResource = requestedPath.substring( 0, idx ); 258 supportfile = requestedPath.substring( idx ); 259 } 260 261 if ( isMetadata( referencedResource ) ) 262 { 263 /* Nothing to translate. 264 * Default layout is the only layout that can contain maven-metadata.xml files, and 265 * if the managedRepository is layout legacy, this request would never occur. 266 */ 267 return requestedPath; 268 } 269 270 // Treat as an artifact reference. 271 ArtifactReference ref = toArtifactReference( referencedResource ); 272 String adjustedPath = repository.toPath( ref ); 273 return adjustedPath + supportfile; 274 } 275 }