001package org.apache.archiva.repository.content.maven2; 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.utils.VersionUtil; 023 024import java.util.regex.Matcher; 025import java.util.regex.Pattern; 026 027/** 028 * Generic Filename Parser for use with layout routines. 029 * 030 * 031 */ 032public class FilenameParser 033{ 034 private String name; 035 036 private String extension; 037 038 private int offset; 039 040 private static final Pattern mavenPluginPattern = Pattern.compile( "(maven-.*-plugin)|(.*-maven-plugin)" ); 041 042 private static final Pattern extensionPattern = 043 Pattern.compile( "(\\.tar\\.gz$)|(\\.tar\\.bz2$)|(\\.[\\-a-z0-9]*$)", Pattern.CASE_INSENSITIVE ); 044 045 private static final Pattern SNAPSHOT_PATTERN = Pattern.compile( "^([0-9]{8}\\.[0-9]{6}-[0-9]+)(.*)$" ); 046 047 private static final Pattern section = Pattern.compile( "([^-]*)" ); 048 049 private Matcher matcher; 050 051 public FilenameParser( String filename ) 052 { 053 this.name = filename; 054 055 Matcher mat = extensionPattern.matcher( name ); 056 if ( mat.find() ) 057 { 058 extension = filename.substring( mat.start() + 1 ); 059 name = name.substring( 0, name.length() - extension.length() - 1 ); 060 } 061 062 matcher = section.matcher( name ); 063 064 reset(); 065 } 066 067 public void reset() 068 { 069 offset = 0; 070 } 071 072 public String next() 073 { 074 // Past the end of the string. 075 if ( offset > name.length() ) 076 { 077 return null; 078 } 079 080 // Return the next section. 081 if ( matcher.find( offset ) ) 082 { 083 // Return found section. 084 offset = matcher.end() + 1; 085 return matcher.group(); 086 } 087 088 // Nothing to return. 089 return null; 090 } 091 092 protected String expect( String expected ) 093 { 094 String value = null; 095 096 if ( name.startsWith( expected, offset ) ) 097 { 098 value = expected; 099 } 100 else if ( VersionUtil.isGenericSnapshot( expected ) ) 101 { 102 String version = name.substring( offset ); 103 104 // check it starts with the same version up to the snapshot part 105 int leadingLength = expected.length() - 9; 106 if ( leadingLength > 0 && version.startsWith( expected.substring( 0, leadingLength ) ) && 107 version.length() > leadingLength ) 108 { 109 // If we expect a non-generic snapshot - look for the timestamp 110 Matcher m = SNAPSHOT_PATTERN.matcher( version.substring( leadingLength + 1 ) ); 111 if ( m.matches() ) 112 { 113 value = version.substring( 0, leadingLength + 1 ) + m.group( 1 ); 114 } 115 } 116 } 117 118 if ( value != null ) 119 { 120 // Potential hit. check for '.' or '-' at end of expected. 121 int seperatorOffset = offset + value.length(); 122 123 // Test for "out of bounds" first. 124 if ( seperatorOffset >= name.length() ) 125 { 126 offset = name.length(); 127 return value; 128 } 129 130 // Test for seperator char. 131 char seperatorChar = name.charAt( seperatorOffset ); 132 if ( ( seperatorChar == '-' ) || ( seperatorChar == '.' ) ) 133 { 134 offset = seperatorOffset + 1; 135 return value; 136 } 137 } 138 139 return null; 140 } 141 142 /** 143 * Get the current seperator character. 144 * 145 * @return the seperator character (either '.' or '-'), or 0 if no seperator character available. 146 */ 147 protected char seperator() 148 { 149 // Past the end of the string? 150 if ( offset >= name.length() ) 151 { 152 return 0; 153 } 154 155 // Before the start of the string? 156 if ( offset <= 0 ) 157 { 158 return 0; 159 } 160 161 return name.charAt( offset - 1 ); 162 } 163 164 protected String getName() 165 { 166 return name; 167 } 168 169 public String getExtension() 170 { 171 return extension; 172 } 173 174 public String remaining() 175 { 176 if ( offset >= name.length() ) 177 { 178 return null; 179 } 180 181 String end = name.substring( offset ); 182 offset = name.length(); 183 return end; 184 } 185 186 public String nextNonVersion() 187 { 188 boolean done = false; 189 190 StringBuilder ver = new StringBuilder(); 191 192 // Any text upto the end of a special case is considered non-version. 193 Matcher specialMat = mavenPluginPattern.matcher( name ); 194 if ( specialMat.find() ) 195 { 196 ver.append( name.substring( offset, specialMat.end() ) ); 197 offset = specialMat.end() + 1; 198 } 199 200 while ( !done ) 201 { 202 int initialOffset = offset; 203 String section = next(); 204 if ( section == null ) 205 { 206 done = true; 207 } 208 else if ( !VersionUtil.isVersion( section ) ) 209 { 210 if ( ver.length() > 0 ) 211 { 212 ver.append( '-' ); 213 } 214 ver.append( section ); 215 } 216 else 217 { 218 offset = initialOffset; 219 done = true; 220 } 221 } 222 223 return ver.toString(); 224 } 225 226 protected String nextVersion() 227 { 228 boolean done = false; 229 230 StringBuilder ver = new StringBuilder(); 231 232 while ( !done ) 233 { 234 int initialOffset = offset; 235 String section = next(); 236 if ( section == null ) 237 { 238 done = true; 239 } 240 else if ( VersionUtil.isVersion( section ) ) 241 { 242 if ( ver.length() > 0 ) 243 { 244 ver.append( '-' ); 245 } 246 ver.append( section ); 247 } 248 else 249 { 250 offset = initialOffset; 251 done = true; 252 } 253 } 254 255 return ver.toString(); 256 } 257 258 259}