View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.internal.test.util;
20  
21  import java.io.BufferedReader;
22  import java.io.IOException;
23  import java.io.InputStreamReader;
24  import java.io.Reader;
25  import java.io.StringReader;
26  import java.net.URL;
27  import java.nio.charset.StandardCharsets;
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      private final String prefix;
47  
48      /**
49       * Constructs a data reader with the given prefix.
50       *
51       * @param prefix the prefix to use for loading resources from the classpath
52       */
53      IniArtifactDataReader(String prefix) {
54          this.prefix = prefix;
55      }
56  
57      /**
58       * Load an artifact description from the classpath and parse it.
59       */
60      ArtifactDescription parse(String resource) throws IOException {
61          URL res = this.getClass().getClassLoader().getResource(prefix + resource);
62  
63          if (res == null) {
64              throw new IOException("cannot find resource: " + resource);
65          }
66          return parse(res);
67      }
68  
69      /**
70       * Open the given URL and parse it.
71       */
72      private ArtifactDescription parse(URL res) throws IOException {
73          return parse(new InputStreamReader(res.openStream(), StandardCharsets.UTF_8));
74      }
75  
76      /**
77       * Parse the given String.
78       */
79      ArtifactDescription parseLiteral(String description) throws IOException {
80          StringReader reader = new StringReader(description);
81          return parse(reader);
82      }
83  
84      private enum State {
85          NONE,
86          RELOCATION,
87          DEPENDENCIES,
88          MANAGEDDEPENDENCIES,
89          REPOSITORIES
90      }
91  
92      private ArtifactDescription parse(Reader reader) throws IOException {
93          String line = null;
94  
95          State state = State.NONE;
96  
97          Map<State, List<String>> sections = new HashMap<>();
98  
99          BufferedReader in = null;
100         try {
101             in = new BufferedReader(reader);
102             while ((line = in.readLine()) != null) {
103 
104                 line = cutComment(line);
105                 if (isEmpty(line)) {
106                     continue;
107                 }
108 
109                 if (line.startsWith("[")) {
110                     try {
111                         String name = line.substring(1, line.length() - 1);
112                         name = name.replace("-", "").toUpperCase(Locale.ENGLISH);
113                         state = State.valueOf(name);
114                         sections.put(state, new ArrayList<>());
115                     } catch (IllegalArgumentException e) {
116                         throw new IOException("unknown section: " + line);
117                     }
118                 } else {
119                     List<String> lines = sections.get(state);
120                     if (lines == null) {
121                         throw new IOException("missing section: " + line);
122                     }
123                     lines.add(line.trim());
124                 }
125             }
126 
127             in.close();
128             in = null;
129         } finally {
130             try {
131                 if (in != null) {
132                     in.close();
133                 }
134             } catch (final IOException e) {
135                 // Suppressed due to an exception already thrown in the try block.
136             }
137         }
138 
139         Artifact relocation = relocation(sections.get(State.RELOCATION));
140         List<Dependency> dependencies = dependencies(sections.get(State.DEPENDENCIES), false);
141         List<Dependency> managedDependencies = dependencies(sections.get(State.MANAGEDDEPENDENCIES), true);
142         List<RemoteRepository> repositories = repositories(sections.get(State.REPOSITORIES));
143 
144         return new ArtifactDescription(relocation, dependencies, managedDependencies, repositories);
145     }
146 
147     private List<RemoteRepository> repositories(List<String> list) {
148         ArrayList<RemoteRepository> ret = new ArrayList<>();
149         if (list == null) {
150             return ret;
151         }
152         for (String coords : list) {
153             String[] split = coords.split(":", 3);
154             String id = split[0];
155             String type = split[1];
156             String url = split[2];
157 
158             ret.add(new RemoteRepository.Builder(id, type, url).build());
159         }
160         return ret;
161     }
162 
163     private List<Dependency> dependencies(List<String> list, boolean managed) {
164         List<Dependency> ret = new ArrayList<>();
165         if (list == null) {
166             return ret;
167         }
168 
169         Collection<Exclusion> exclusions = new ArrayList<>();
170 
171         Boolean optional = null;
172         Artifact artifact = null;
173         String scope = null;
174 
175         for (String coords : list) {
176             if (coords.startsWith("-")) {
177                 coords = coords.substring(1);
178                 String[] split = coords.split(":");
179                 exclusions.add(new Exclusion(split[0], split[1], "*", "*"));
180             } else {
181                 if (artifact != null) {
182                     // commit dependency
183                     Dependency dep = new Dependency(artifact, scope, optional, exclusions);
184                     ret.add(dep);
185 
186                     exclusions = new ArrayList<>();
187                 }
188 
189                 ArtifactDefinition def = new ArtifactDefinition(coords);
190 
191                 optional = managed ? def.getOptional() : Boolean.valueOf(Boolean.TRUE.equals(def.getOptional()));
192 
193                 scope = "".equals(def.getScope()) && !managed ? "compile" : def.getScope();
194 
195                 artifact = new DefaultArtifact(
196                         def.getGroupId(), def.getArtifactId(), "", def.getExtension(), def.getVersion());
197             }
198         }
199         if (artifact != null) {
200             // commit dependency
201             Dependency dep = new Dependency(artifact, scope, optional, exclusions);
202             ret.add(dep);
203         }
204 
205         return ret;
206     }
207 
208     private Artifact relocation(List<String> list) {
209         if (list == null || list.isEmpty()) {
210             return null;
211         }
212         String coords = list.get(0);
213         ArtifactDefinition def = new ArtifactDefinition(coords);
214         return new DefaultArtifact(def.getGroupId(), def.getArtifactId(), "", def.getExtension(), def.getVersion());
215     }
216 
217     private static boolean isEmpty(String line) {
218         return line == null || line.isEmpty();
219     }
220 
221     private static String cutComment(String line) {
222         int idx = line.indexOf('#');
223 
224         if (idx != -1) {
225             line = line.substring(0, idx);
226         }
227 
228         return line;
229     }
230 }