You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LegacyArtifactDiscoverer.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. package org.apache.maven.repository.discovery;
  2. /*
  3. * Copyright 2001-2005 The Apache Software Foundation.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. import org.apache.maven.artifact.Artifact;
  18. import org.apache.maven.artifact.factory.ArtifactFactory;
  19. import org.codehaus.plexus.util.StringUtils;
  20. import java.io.File;
  21. import java.util.ArrayList;
  22. import java.util.Collections;
  23. import java.util.Iterator;
  24. import java.util.LinkedList;
  25. import java.util.List;
  26. import java.util.StringTokenizer;
  27. /**
  28. * Artifact discoverer for the legacy repository layout (Maven 1.x).
  29. *
  30. * @author John Casey
  31. * @author Brett Porter
  32. */
  33. public class LegacyArtifactDiscoverer
  34. extends AbstractArtifactDiscoverer
  35. {
  36. private ArtifactFactory artifactFactory;
  37. public List discoverArtifacts( File repositoryBase, String blacklistedPatterns, boolean includeSnapshots )
  38. {
  39. List artifacts = new ArrayList();
  40. String[] artifactPaths = scanForArtifactPaths( repositoryBase, blacklistedPatterns );
  41. for ( int i = 0; i < artifactPaths.length; i++ )
  42. {
  43. String path = artifactPaths[i];
  44. Artifact artifact = buildArtifact( path );
  45. if ( artifact != null )
  46. {
  47. if ( includeSnapshots || !artifact.isSnapshot() )
  48. {
  49. artifacts.add( artifact );
  50. }
  51. }
  52. }
  53. return artifacts;
  54. }
  55. private Artifact buildArtifact( String path )
  56. {
  57. StringTokenizer tokens = new StringTokenizer( path, "/\\" );
  58. int numberOfTokens = tokens.countTokens();
  59. if ( numberOfTokens != 3 )
  60. {
  61. addKickedOutPath( path );
  62. return null;
  63. }
  64. String groupId = tokens.nextToken();
  65. String type = tokens.nextToken();
  66. if ( type.endsWith( "s" ) )
  67. {
  68. type = type.substring( 0, type.length() - 1 );
  69. }
  70. // contains artifactId, version, classifier, and extension.
  71. String avceGlob = tokens.nextToken();
  72. LinkedList avceTokenList = new LinkedList();
  73. StringTokenizer avceTokenizer = new StringTokenizer( avceGlob, "-" );
  74. while ( avceTokenizer.hasMoreTokens() )
  75. {
  76. avceTokenList.addLast( avceTokenizer.nextToken() );
  77. }
  78. String lastAvceToken = (String) avceTokenList.removeLast();
  79. if ( lastAvceToken.endsWith( ".tar.gz" ) )
  80. {
  81. type = "distribution-tgz";
  82. lastAvceToken = lastAvceToken.substring( 0, lastAvceToken.length() - ".tar.gz".length() );
  83. avceTokenList.addLast( lastAvceToken );
  84. }
  85. else if ( lastAvceToken.endsWith( "sources.jar" ) )
  86. {
  87. type = "java-source";
  88. lastAvceToken = lastAvceToken.substring( 0, lastAvceToken.length() - ".jar".length() );
  89. avceTokenList.addLast( lastAvceToken );
  90. }
  91. else if ( lastAvceToken.endsWith( ".zip" ) )
  92. {
  93. type = "distribution-zip";
  94. lastAvceToken = lastAvceToken.substring( 0, lastAvceToken.length() - ".zip".length() );
  95. avceTokenList.addLast( lastAvceToken );
  96. }
  97. else
  98. {
  99. int extPos = lastAvceToken.lastIndexOf( '.' );
  100. if ( extPos > 0 )
  101. {
  102. String ext = lastAvceToken.substring( extPos + 1 );
  103. if ( type.equals( ext ) )
  104. {
  105. lastAvceToken = lastAvceToken.substring( 0, extPos );
  106. avceTokenList.addLast( lastAvceToken );
  107. }
  108. else
  109. {
  110. addKickedOutPath( path );
  111. return null;
  112. }
  113. }
  114. }
  115. // TODO: this is obscene - surely a better way?
  116. String validVersionParts = "([Dd][Ee][Vv][_.0-9]*)|" + "([Ss][Nn][Aa][Pp][Ss][Hh][Oo][Tt])|" +
  117. "([0-9][_.0-9a-zA-Z]*)|" + "([Gg]?[_.0-9ab]*([Pp][Rr][Ee]|[Rr][Cc]|[Gg]|[Mm])[_.0-9]*)|" +
  118. "([Aa][Ll][Pp][Hh][Aa][_.0-9]*)|" + "([Bb][Ee][Tt][Aa][_.0-9]*)|" + "([Rr][Cc][_.0-9]*)|" +
  119. "([Tt][Ee][Ss][Tt][_.0-9]*)|" + "([Dd][Ee][Bb][Uu][Gg][_.0-9]*)|" +
  120. "([Uu][Nn][Oo][Ff][Ff][Ii][Cc][Ii][Aa][Ll][_.0-9]*)|" + "([Cc][Uu][Rr][Rr][Ee][Nn][Tt])|" +
  121. "([Ll][Aa][Tt][Ee][Ss][Tt])|" + "([Ff][Cc][Ss])|" + "([Rr][Ee][Ll][Ee][Aa][Ss][Ee][_.0-9]*)|" +
  122. "([Nn][Ii][Gg][Hh][Tt][Ll][Yy])|" + "([AaBb][_.0-9]*)";
  123. // let's discover the version, and whatever's leftover will be either
  124. // a classifier, or part of the artifactId, depending on position.
  125. // Since version is at the end, we have to move in from the back.
  126. Collections.reverse( avceTokenList );
  127. StringBuffer classifierBuffer = new StringBuffer();
  128. StringBuffer versionBuffer = new StringBuffer();
  129. boolean firstVersionTokenEncountered = false;
  130. boolean firstToken = true;
  131. int tokensIterated = 0;
  132. for ( Iterator it = avceTokenList.iterator(); it.hasNext(); )
  133. {
  134. String token = (String) it.next();
  135. boolean tokenIsVersionPart = token.matches( validVersionParts );
  136. StringBuffer bufferToUpdate;
  137. // NOTE: logic in code is reversed, since we're peeling off the back
  138. // Any token after the last versionPart will be in the classifier.
  139. // Any token UP TO first non-versionPart is part of the version.
  140. if ( !tokenIsVersionPart )
  141. {
  142. if ( firstVersionTokenEncountered )
  143. {
  144. break;
  145. }
  146. else
  147. {
  148. bufferToUpdate = classifierBuffer;
  149. }
  150. }
  151. else
  152. {
  153. firstVersionTokenEncountered = true;
  154. bufferToUpdate = versionBuffer;
  155. }
  156. if ( firstToken )
  157. {
  158. firstToken = false;
  159. }
  160. else
  161. {
  162. bufferToUpdate.insert( 0, '-' );
  163. }
  164. bufferToUpdate.insert( 0, token );
  165. tokensIterated++;
  166. }
  167. getLogger().debug( "After parsing loop, state of buffers:\no Version Buffer: \'" + versionBuffer +
  168. "\'\no Classifier Buffer: \'" + classifierBuffer + "\'\no Number of Tokens Iterated: " + tokensIterated );
  169. // Now, restore the proper ordering so we can build the artifactId.
  170. Collections.reverse( avceTokenList );
  171. getLogger().debug(
  172. "Before repairing bad version and/or cleaning up used tokens, avce token list is:\n" + avceTokenList );
  173. // if we didn't find a version, then punt. Use the last token
  174. // as the version, and set the classifier empty.
  175. if ( versionBuffer.length() < 1 )
  176. {
  177. if ( avceTokenList.size() > 1 )
  178. {
  179. int lastIdx = avceTokenList.size() - 1;
  180. versionBuffer.append( avceTokenList.get( lastIdx ) );
  181. avceTokenList.remove( lastIdx );
  182. }
  183. else
  184. {
  185. getLogger().debug( "Cannot parse version from artifact path: \'" + path + "\'." );
  186. getLogger().debug(
  187. "artifact-version-classifier-extension remaining tokens is: \'" + avceTokenList + "\'" );
  188. }
  189. classifierBuffer.setLength( 0 );
  190. }
  191. else
  192. {
  193. getLogger().debug( "Removing " + tokensIterated + " tokens from avce token list." );
  194. // if everything is kosher, then pop off all the classifier and
  195. // version tokens, leaving the naked artifact id in the list.
  196. avceTokenList = new LinkedList( avceTokenList.subList( 0, avceTokenList.size() - tokensIterated ) );
  197. }
  198. getLogger().debug( "Now, remainder of avce token list is:\n" + avceTokenList );
  199. StringBuffer artifactIdBuffer = new StringBuffer();
  200. firstToken = true;
  201. for ( Iterator it = avceTokenList.iterator(); it.hasNext(); )
  202. {
  203. String token = (String) it.next();
  204. if ( firstToken )
  205. {
  206. firstToken = false;
  207. }
  208. else
  209. {
  210. artifactIdBuffer.append( '-' );
  211. }
  212. artifactIdBuffer.append( token );
  213. }
  214. String artifactId = artifactIdBuffer.toString();
  215. int lastVersionCharIdx = versionBuffer.length() - 1;
  216. if ( lastVersionCharIdx > -1 && versionBuffer.charAt( lastVersionCharIdx ) == '-' )
  217. {
  218. versionBuffer.setLength( lastVersionCharIdx );
  219. }
  220. String version = versionBuffer.toString();
  221. if ( version.length() < 1 )
  222. {
  223. version = null;
  224. }
  225. getLogger().debug( "Extracted artifact information from path:\n" + "groupId: \'" + groupId + "\'\n" +
  226. "artifactId: \'" + artifactId + "\'\n" + "type: \'" + type + "\'\n" + "version: \'" + version + "\'\n" +
  227. "classifier: \'" + classifierBuffer + "\'" );
  228. Artifact result = null;
  229. if ( classifierBuffer.length() > 0 )
  230. {
  231. getLogger().debug( "Creating artifact with classifier." );
  232. result = artifactFactory.createArtifactWithClassifier( groupId, artifactId, version, type,
  233. classifierBuffer.toString() );
  234. }
  235. else
  236. {
  237. if ( StringUtils.isNotEmpty( groupId ) && StringUtils.isNotEmpty( artifactId ) &&
  238. StringUtils.isNotEmpty( version ) && StringUtils.isNotEmpty( type ) )
  239. {
  240. result = artifactFactory.createArtifact( groupId, artifactId, version, Artifact.SCOPE_RUNTIME, type );
  241. }
  242. }
  243. if ( result != null )
  244. {
  245. result.setFile( new File( path ) );
  246. }
  247. return result;
  248. }
  249. }