View Javadoc
1   package org.eclipse.aether.internal.test.util;
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 java.io.BufferedReader;
23  import java.io.IOException;
24  import java.io.InputStreamReader;
25  import java.io.Reader;
26  import java.io.StringReader;
27  import java.net.URL;
28  import java.util.ArrayList;
29  import java.util.Collection;
30  import java.util.HashMap;
31  import java.util.List;
32  import java.util.Locale;
33  import java.util.Map;
34  
35  import org.eclipse.aether.artifact.Artifact;
36  import org.eclipse.aether.artifact.DefaultArtifact;
37  import org.eclipse.aether.graph.Dependency;
38  import org.eclipse.aether.graph.Exclusion;
39  import org.eclipse.aether.repository.RemoteRepository;
40  
41  /**
42   * @see IniArtifactDescriptorReader
43   */
44  class IniArtifactDataReader
45  {
46  
47      private String prefix = "";
48  
49      /**
50       * Constructs a data reader with the prefix {@code ""}.
51       */
52      public IniArtifactDataReader()
53      {
54          this( "" );
55      }
56  
57      /**
58       * Constructs a data reader with the given prefix.
59       * 
60       * @param prefix the prefix to use for loading resources from the classpath.
61       */
62      public IniArtifactDataReader( String prefix )
63      {
64          this.prefix = prefix;
65  
66      }
67  
68      /**
69       * Load an artifact description from the classpath and parse it.
70       */
71      public ArtifactDescription parse( String resource )
72          throws IOException
73      {
74          URL res = this.getClass().getClassLoader().getResource( prefix + resource );
75  
76          if ( res == null )
77          {
78              throw new IOException( "cannot find resource: " + resource );
79          }
80          return parse( res );
81      }
82  
83      /**
84       * Open the given URL and parse ist.
85       */
86      public ArtifactDescription parse( URL res )
87          throws IOException
88      {
89          return parse( new InputStreamReader( res.openStream(), "UTF-8" ) );
90      }
91  
92      /**
93       * Parse the given String.
94       */
95      public ArtifactDescription parseLiteral( String description )
96          throws IOException
97      {
98          StringReader reader = new StringReader( description );
99          return parse( reader );
100     }
101 
102     private enum State
103     {
104         NONE, RELOCATION, DEPENDENCIES, MANAGEDDEPENDENCIES, REPOSITORIES
105     }
106 
107     private ArtifactDescription parse( Reader reader )
108         throws IOException
109     {
110         String line = null;
111 
112         State state = State.NONE;
113 
114         Map<State, List<String>> sections = new HashMap<State, List<String>>();
115 
116         BufferedReader in = new BufferedReader( reader );
117         try
118         {
119             while ( ( line = in.readLine() ) != null )
120             {
121 
122                 line = cutComment( line );
123                 if ( isEmpty( line ) )
124                 {
125                     continue;
126                 }
127 
128                 if ( line.startsWith( "[" ) )
129                 {
130                     try
131                     {
132                         String name = line.substring( 1, line.length() - 1 );
133                         name = name.replace( "-", "" ).toUpperCase( Locale.ENGLISH );
134                         state = State.valueOf( name );
135                         sections.put( state, new ArrayList<String>() );
136                     }
137                     catch ( IllegalArgumentException e )
138                     {
139                         throw new IOException( "unknown section: " + line );
140                     }
141                 }
142                 else
143                 {
144                     List<String> lines = sections.get( state );
145                     if ( lines == null )
146                     {
147                         throw new IOException( "missing section: " + line );
148                     }
149                     lines.add( line.trim() );
150                 }
151             }
152         }
153         finally
154         {
155             in.close();
156         }
157 
158         Artifact relocation = relocation( sections.get( State.RELOCATION ) );
159         List<Dependency> dependencies = dependencies( sections.get( State.DEPENDENCIES ), false );
160         List<Dependency> managedDependencies = dependencies( sections.get( State.MANAGEDDEPENDENCIES ), true );
161         List<RemoteRepository> repositories = repositories( sections.get( State.REPOSITORIES ) );
162 
163         ArtifactDescription description =
164             new ArtifactDescription( relocation, dependencies, managedDependencies, repositories );
165         return description;
166     }
167 
168     private List<RemoteRepository> repositories( List<String> list )
169     {
170         ArrayList<RemoteRepository> ret = new ArrayList<RemoteRepository>();
171         if ( list == null )
172         {
173             return ret;
174         }
175         for ( String coords : list )
176         {
177             String[] split = coords.split( ":", 3 );
178             String id = split[0];
179             String type = split[1];
180             String url = split[2];
181 
182             ret.add( new RemoteRepository.Builder( id, type, url ).build() );
183         }
184         return ret;
185     }
186 
187     private List<Dependency> dependencies( List<String> list, boolean managed )
188     {
189         List<Dependency> ret = new ArrayList<Dependency>();
190         if ( list == null )
191         {
192             return ret;
193         }
194 
195         Collection<Exclusion> exclusions = new ArrayList<Exclusion>();
196 
197         Boolean optional = null;
198         Artifact artifact = null;
199         String scope = null;
200 
201         for ( String coords : list )
202         {
203             if ( coords.startsWith( "-" ) )
204             {
205                 coords = coords.substring( 1 );
206                 String[] split = coords.split( ":" );
207                 exclusions.add( new Exclusion( split[0], split[1], "*", "*" ) );
208             }
209             else
210             {
211                 if ( artifact != null )
212                 {
213                     // commit dependency
214                     Dependency dep = new Dependency( artifact, scope, optional, exclusions );
215                     ret.add( dep );
216 
217                     exclusions = new ArrayList<Exclusion>();
218                 }
219 
220                 ArtifactDefinition def = new ArtifactDefinition( coords );
221 
222                 optional = managed ? def.getOptional() : Boolean.valueOf( Boolean.TRUE.equals( def.getOptional() ) );
223 
224                 scope = "".equals( def.getScope() ) && !managed ? "compile" : def.getScope();
225 
226                 artifact =
227                     new DefaultArtifact( def.getGroupId(), def.getArtifactId(), "", def.getExtension(),
228                                          def.getVersion() );
229             }
230         }
231         if ( artifact != null )
232         {
233             // commit dependency
234             Dependency dep = new Dependency( artifact, scope, optional, exclusions );
235             ret.add( dep );
236         }
237 
238         return ret;
239     }
240 
241     private Artifact relocation( List<String> list )
242     {
243         if ( list == null || list.isEmpty() )
244         {
245             return null;
246         }
247         String coords = list.get( 0 );
248         ArtifactDefinition def = new ArtifactDefinition( coords );
249         return new DefaultArtifact( def.getGroupId(), def.getArtifactId(), "", def.getExtension(), def.getVersion() );
250     }
251 
252     private static boolean isEmpty( String line )
253     {
254         return line == null || line.length() == 0;
255     }
256 
257     private static String cutComment( String line )
258     {
259         int idx = line.indexOf( '#' );
260 
261         if ( idx != -1 )
262         {
263             line = line.substring( 0, idx );
264         }
265 
266         return line;
267     }
268 
269     static class Definition
270     {
271         private String groupId;
272 
273         private String artifactId;
274 
275         private String extension;
276 
277         private String version;
278 
279         private String scope = "";
280 
281         private String definition;
282 
283         private String id = null;
284 
285         private String reference = null;
286 
287         private boolean optional = false;
288 
289         public Definition( String def )
290         {
291             this.definition = def.trim();
292 
293             if ( definition.startsWith( "(" ) )
294             {
295                 int idx = definition.indexOf( ')' );
296                 this.id = definition.substring( 1, idx );
297                 this.definition = definition.substring( idx + 1 );
298             }
299             else if ( definition.startsWith( "^" ) )
300             {
301                 this.reference = definition.substring( 1 );
302                 return;
303             }
304 
305             String[] split = definition.split( ":" );
306             if ( split.length < 4 )
307             {
308                 throw new IllegalArgumentException( "Need definition like 'gid:aid:ext:ver[:scope]', but was: "
309                     + definition );
310             }
311             groupId = split[0];
312             artifactId = split[1];
313             extension = split[2];
314             version = split[3];
315             if ( split.length > 4 )
316             {
317                 scope = split[4];
318             }
319             if ( split.length > 5 && "true".equalsIgnoreCase( split[5] ) )
320             {
321                 optional = true;
322             }
323         }
324 
325         public String getGroupId()
326         {
327             return groupId;
328         }
329 
330         public String getArtifactId()
331         {
332             return artifactId;
333         }
334 
335         public String getType()
336         {
337             return extension;
338         }
339 
340         public String getVersion()
341         {
342             return version;
343         }
344 
345         public String getScope()
346         {
347             return scope;
348         }
349 
350         @Override
351         public String toString()
352         {
353             return definition;
354         }
355 
356         public String getId()
357         {
358             return id;
359         }
360 
361         public String getReference()
362         {
363             return reference;
364         }
365 
366         public boolean isReference()
367         {
368             return reference != null;
369         }
370 
371         public boolean hasId()
372         {
373             return id != null;
374         }
375 
376         public boolean isOptional()
377         {
378             return optional;
379         }
380     }
381 
382 }