b6336240fcd99f276fd68f974662715de62f2dbe
[idea/community.git] / plugins / maven / maven2-server-impl / src / org / jetbrains / idea / maven / server / embedder / Maven2ModelConverter.java
1 // Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package org.jetbrains.idea.maven.server.embedder;
3
4 import com.intellij.util.ReflectionUtilRt;
5 import org.apache.maven.archetype.catalog.Archetype;
6 import org.apache.maven.artifact.Artifact;
7 import org.apache.maven.artifact.handler.ArtifactHandler;
8 import org.apache.maven.artifact.repository.ArtifactRepository;
9 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
10 import org.apache.maven.model.*;
11 import org.apache.maven.shared.dependency.tree.DependencyNode;
12 import org.codehaus.plexus.util.xml.Xpp3Dom;
13 import org.jdom.Element;
14 import org.jdom.IllegalNameException;
15 import org.jetbrains.annotations.NotNull;
16 import org.jetbrains.idea.maven.model.*;
17 import org.jetbrains.idea.maven.server.Maven2ServerGlobals;
18 import org.sonatype.nexus.index.ArtifactInfo;
19
20 import java.io.File;
21 import java.lang.reflect.Field;
22 import java.rmi.RemoteException;
23 import java.util.*;
24
25 public final class Maven2ModelConverter {
26   @NotNull
27   public static MavenModel convertModel(Model model, File localRepository) throws RemoteException {
28     Build build = model.getBuild();
29     return convertModel(model,
30                         asSourcesList(build.getSourceDirectory()),
31                         asSourcesList(build.getTestSourceDirectory()),
32                         Collections.<Artifact>emptyList(),
33                         Collections.<DependencyNode>emptyList(),
34                         Collections.<Artifact>emptyList(),
35                         localRepository);
36   }
37
38   private static List<String> asSourcesList(String directory) {
39     return directory == null ? Collections.<String>emptyList() : Collections.singletonList(directory);
40   }
41
42   @NotNull
43   public static MavenModel convertModel(Model model,
44                                         List<String> sources,
45                                         List<String> testSources,
46                                         Collection<? extends Artifact> dependencies,
47                                         Collection<? extends DependencyNode> dependencyTree,
48                                         Collection<? extends Artifact> extensions,
49                                         File localRepository) throws RemoteException {
50     MavenModel result = new MavenModel();
51     result.setMavenId(new MavenId(model.getGroupId(), model.getArtifactId(), model.getVersion()));
52
53     Parent parent = model.getParent();
54     if (parent != null) {
55       result.setParent(new MavenParent(new MavenId(parent.getGroupId(), parent.getArtifactId(), parent.getVersion()),
56                                        parent.getRelativePath()));
57     }
58     result.setPackaging(model.getPackaging());
59     result.setName(model.getName());
60     result.setProperties(model.getProperties() == null ? new Properties() : model.getProperties());
61     result.setPlugins(convertPlugins(model));
62
63     Map<Artifact, MavenArtifact> convertedArtifacts = new HashMap<Artifact, MavenArtifact>();
64     result.setExtensions(convertArtifacts(extensions, convertedArtifacts, localRepository));
65     result.setDependencies(convertArtifacts(dependencies, convertedArtifacts, localRepository));
66     result.setDependencyTree(convertDependencyNodes(null, dependencyTree, convertedArtifacts, localRepository));
67
68     result.setRemoteRepositories(convertRepositories(model.getRepositories()));
69     result.setProfiles(convertProfiles(model.getProfiles()));
70     result.setModules(model.getModules());
71
72     convertBuild(result.getBuild(), model.getBuild(), sources, testSources);
73     return result;
74   }
75
76   private static void convertBuild(MavenBuild result, Build build, List<String> sources, List<String> testSources) {
77     convertBuildBase(result, build);
78     result.setOutputDirectory(build.getOutputDirectory());
79     result.setTestOutputDirectory(build.getTestOutputDirectory());
80     result.setSources(sources);
81     result.setTestSources(testSources);
82   }
83
84   private static void convertBuildBase(MavenBuildBase result, BuildBase build) {
85     result.setFinalName(build.getFinalName());
86     result.setDefaultGoal(build.getDefaultGoal());
87     result.setDirectory(build.getDirectory());
88     result.setResources(convertResources(build.getResources()));
89     result.setTestResources(convertResources(build.getTestResources()));
90     result.setFilters(build.getFilters() == null ? Collections.<String>emptyList() : build.getFilters());
91   }
92
93   public static MavenId createMavenId(Artifact artifact) {
94     return new MavenId(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion());
95   }
96
97   private static List<MavenResource> convertResources(List<Resource> resources) {
98     if (resources == null) return new ArrayList<MavenResource>();
99
100     List<MavenResource> result = new ArrayList<MavenResource>(resources.size());
101     for (Resource each : resources) {
102       result.add(new MavenResource(each.getDirectory(),
103                                    each.isFiltering(),
104                                    each.getTargetPath(),
105                                    ensurePatterns(each.getIncludes()),
106                                    ensurePatterns(each.getExcludes())));
107     }
108     return result;
109   }
110
111   private static List<String> ensurePatterns(List<String> patterns) {
112     return patterns == null ? Collections.<String>emptyList() : patterns;
113   }
114
115   private static List<MavenRemoteRepository> convertRepositories(List<Repository> repositories) {
116     if (repositories == null) return new ArrayList<MavenRemoteRepository>();
117
118     List<MavenRemoteRepository> result = new ArrayList<MavenRemoteRepository>(repositories.size());
119     for (Repository each : repositories) {
120       result.add(new MavenRemoteRepository(each.getId(),
121                                            each.getName(),
122                                            each.getUrl(),
123                                            each.getLayout(),
124                                            convertPolicy(each.getReleases()),
125                                            convertPolicy(each.getSnapshots())));
126     }
127     return result;
128   }
129
130   public static List<MavenRemoteRepository> convertRemoteRepositories(List<? extends ArtifactRepository> repositories) {
131     if (repositories == null) return new ArrayList<MavenRemoteRepository>();
132
133     List<MavenRemoteRepository> result = new ArrayList<MavenRemoteRepository>(repositories.size());
134     for (ArtifactRepository each : repositories) {
135       result.add(new MavenRemoteRepository(each.getId(),
136                                            each.getId(),
137                                            each.getUrl(),
138                                            "default",
139                                            convertPolicy(each.getReleases()),
140                                            convertPolicy(each.getSnapshots())));
141     }
142     return result;
143   }
144
145   private static MavenRemoteRepository.Policy convertPolicy(ArtifactRepositoryPolicy policy) {
146     return policy != null
147            ? new MavenRemoteRepository.Policy(policy.isEnabled(), policy.getUpdatePolicy(), policy.getChecksumPolicy())
148            : null;
149   }
150
151   private static MavenRemoteRepository.Policy convertPolicy(RepositoryPolicy policy) {
152     return policy != null
153            ? new MavenRemoteRepository.Policy(policy.isEnabled(), policy.getUpdatePolicy(), policy.getChecksumPolicy())
154            : null;
155   }
156
157   public static List<MavenArtifact> convertArtifacts(Collection<? extends Artifact> artifacts,
158                                                      Map<Artifact, MavenArtifact> nativeToConvertedMap,
159                                                      File localRepository) {
160     if (artifacts == null) return new ArrayList<MavenArtifact>();
161
162     List<MavenArtifact> result = new ArrayList<MavenArtifact>(artifacts.size());
163     for (Artifact each : artifacts) {
164       result.add(convertArtifact(each, nativeToConvertedMap, localRepository));
165     }
166     return result;
167   }
168
169   public static List<MavenArtifactNode> convertDependencyNodes(MavenArtifactNode parent,
170                                                                Collection<? extends DependencyNode> nodes,
171                                                                Map<Artifact, MavenArtifact> nativeToConvertedMap,
172                                                                File localRepository) {
173     List<MavenArtifactNode> result = new ArrayList<MavenArtifactNode>(nodes.size());
174     for (DependencyNode each : nodes) {
175       Artifact a = each.getArtifact();
176       MavenArtifact ma = convertArtifact(a, nativeToConvertedMap, localRepository);
177
178       MavenArtifactState state = MavenArtifactState.ADDED;
179       switch (each.getState()) {
180         case DependencyNode.INCLUDED:
181           break;
182         case DependencyNode.OMITTED_FOR_CONFLICT:
183           state = MavenArtifactState.CONFLICT;
184           break;
185         case DependencyNode.OMITTED_FOR_DUPLICATE:
186           state = MavenArtifactState.DUPLICATE;
187           break;
188         case DependencyNode.OMITTED_FOR_CYCLE:
189           state = MavenArtifactState.CYCLE;
190           break;
191         default:
192           assert false : "unknown dependency node state: " + each.getState();
193       }
194       MavenArtifact relatedMA = each.getRelatedArtifact() == null ? null
195                                                                   : convertArtifact(each.getRelatedArtifact(), nativeToConvertedMap,
196                                                                                     localRepository);
197       MavenArtifactNode newNode = new MavenArtifactNode(parent, ma, state, relatedMA, each.getOriginalScope(),
198                                                         each.getPremanagedVersion(), each.getPremanagedScope());
199       newNode.setDependencies(convertDependencyNodes(newNode, each.getChildren(), nativeToConvertedMap, localRepository));
200       result.add(newNode);
201     }
202     return result;
203   }
204
205   private static MavenArtifact convertArtifact(Artifact artifact, Map<Artifact, MavenArtifact> nativeToConvertedMap, File localRepository) {
206     MavenArtifact result = nativeToConvertedMap.get(artifact);
207     if (result == null) {
208       result = convertArtifact(artifact, localRepository);
209       nativeToConvertedMap.put(artifact, result);
210     }
211     return result;
212   }
213
214   @NotNull
215   public static MavenArtifact convertArtifact(Artifact artifact, File localRepository) {
216     return new MavenArtifact(artifact.getGroupId(), artifact.getArtifactId(),
217                              artifact.getVersion(),
218                              artifact.getBaseVersion(),
219                              artifact.getType(),
220                              artifact.getClassifier(),
221
222                              artifact.getScope(),
223                              artifact.isOptional(),
224
225                              convertExtension(artifact),
226
227                              artifact.getFile(),
228                              localRepository,
229
230                              artifact.isResolved(),
231                              artifact instanceof CustomArtifact && ((CustomArtifact)artifact).isStub());
232   }
233
234   private static String convertExtension(Artifact artifact) {
235     ArtifactHandler handler = artifact.getArtifactHandler();
236     String result = null;
237     if (handler != null) result = handler.getExtension();
238     if (result == null) result = artifact.getType();
239     return result;
240   }
241
242   private static List<MavenPlugin> convertPlugins(Model mavenModel) throws RemoteException {
243     List<MavenPlugin> result = new ArrayList<MavenPlugin>();
244     Set<String> pluginKeys = new HashSet<String>();
245     Build build = mavenModel.getBuild();
246     doConvertPlugins(build, false, result, pluginKeys);
247     if (build != null) doConvertPlugins(build.getPluginManagement(), true, result, pluginKeys);
248     return result;
249   }
250
251   private static void doConvertPlugins(PluginContainer container,
252                                        boolean management,
253                                        List<MavenPlugin> result,
254                                        Set<String> pluginKeys) throws RemoteException {
255     if (container == null) return;
256
257     List<Plugin> plugins = container.getPlugins();
258     if (plugins == null) return;
259
260     for (Plugin each : plugins) {
261       String key = each.getGroupId() + ":" + each.getArtifactId();
262       result.add(convertPlugin(management, each));
263       pluginKeys.add(key);
264     }
265   }
266
267   private static MavenPlugin convertPlugin(boolean isDefault, Plugin plugin) throws RemoteException {
268     List<MavenPlugin.Execution> executions = new ArrayList<MavenPlugin.Execution>(plugin.getExecutions().size());
269     for (PluginExecution each : plugin.getExecutions()) {
270       executions.add(convertExecution(each));
271     }
272
273     List<MavenId> deps = new ArrayList<MavenId>(plugin.getDependencies().size());
274     for (Dependency each : plugin.getDependencies()) {
275       deps.add(new MavenId(each.getGroupId(), each.getArtifactId(), each.getVersion()));
276     }
277
278     return new MavenPlugin(plugin.getGroupId(),
279                            plugin.getArtifactId(),
280                            plugin.getVersion(),
281                            isDefault,
282                            plugin.isExtensions(),
283                            convertConfiguration(plugin.getConfiguration()),
284                            executions, deps);
285   }
286
287   public static MavenPlugin.Execution convertExecution(PluginExecution execution) throws RemoteException {
288     return new MavenPlugin.Execution(execution.getId(), execution.getPhase(), execution.getGoals(), convertConfiguration(execution.getConfiguration()));
289   }
290
291   private static Element convertConfiguration(Object config) throws RemoteException {
292     return config == null ? null : xppToElement((Xpp3Dom)config);
293   }
294
295   private static Element xppToElement(Xpp3Dom xpp) throws RemoteException {
296     Element result;
297     try {
298       result = new Element(xpp.getName());
299     }
300     catch (IllegalNameException e) {
301       Maven2ServerGlobals.getLogger().info(e);
302       return null;
303     }
304
305     Xpp3Dom[] children = xpp.getChildren();
306     if (children == null || children.length == 0) {
307       result.setText(xpp.getValue());
308     }
309     else {
310       for (Xpp3Dom each : children) {
311         Element child = xppToElement(each);
312         if (child != null) result.addContent(child);
313       }
314     }
315     return result;
316   }
317
318   public static List<MavenProfile> convertProfiles(Collection<? extends Profile> profiles) {
319     if (profiles == null) return Collections.emptyList();
320     List<MavenProfile> result = new ArrayList<MavenProfile>();
321     for (Profile each : profiles) {
322       String id = each.getId();
323       if (id == null) continue;
324       MavenProfile profile = new MavenProfile(id, each.getSource());
325       List<String> modules = each.getModules();
326       profile.setModules(modules == null ? Collections.<String>emptyList() : modules);
327       profile.setActivation(convertActivation(each.getActivation()));
328       if (each.getBuild() != null) convertBuildBase(profile.getBuild(), each.getBuild());
329       result.add(profile);
330     }
331     return result;
332   }
333
334   private static MavenProfileActivation convertActivation(Activation activation) {
335     if (activation == null) return null;
336
337     MavenProfileActivation result = new MavenProfileActivation();
338     result.setActiveByDefault(activation.isActiveByDefault());
339     result.setOs(convertOsActivation(activation.getOs()));
340     result.setJdk(activation.getJdk());
341     result.setFile(convertFileActivation(activation.getFile()));
342     result.setProperty(convertPropertyActivation(activation.getProperty()));
343     return result;
344   }
345
346   private static MavenProfileActivationOS convertOsActivation(ActivationOS os) {
347     return os == null ? null : new MavenProfileActivationOS(os.getName(), os.getFamily(), os.getArch(), os.getVersion());
348   }
349
350   private static MavenProfileActivationFile convertFileActivation(ActivationFile file) {
351     return file == null ? null : new MavenProfileActivationFile(file.getExists(), file.getMissing());
352   }
353
354   private static MavenProfileActivationProperty convertPropertyActivation(ActivationProperty property) {
355     return property == null ? null : new MavenProfileActivationProperty(property.getName(), property.getValue());
356   }
357
358   public static Map<String, String> convertToMap(Object object) {
359     try {
360       Map<String, String> result = new HashMap<String, String>();
361       doConvert(object, "", result);
362       return result;
363     }
364     catch (IllegalAccessException e) {
365       throw new RuntimeException(e);
366     }
367   }
368
369   private static boolean isNativeToString(String toStringResult, Object o) {
370     String className = o.getClass().getName();
371     return (toStringResult.startsWith(className) && toStringResult.startsWith("@", className.length()));
372   }
373
374   private static void doConvert(Object object, String prefix, Map<String, String> result) throws IllegalAccessException {
375     for (Field each : ReflectionUtilRt.collectFields(object.getClass())) {
376       Class<?> type = each.getType();
377       if (shouldSkip(type)) continue;
378
379       each.setAccessible(true);
380       Object value = each.get(object);
381
382       if (value != null) {
383         String name = prefix + each.getName();
384
385         String sValue = String.valueOf(value);
386         if (!isNativeToString(sValue, value)) {
387           result.put(name, sValue);
388         }
389
390         Package pack = type.getPackage();
391         if (pack != null && Model.class.getPackage().getName().equals(pack.getName())) {
392           doConvert(value, name + ".", result);
393         }
394       }
395     }
396   }
397
398   public static boolean shouldSkip(Class clazz) {
399     return clazz.isArray()
400            || Collection.class.isAssignableFrom(clazz)
401            || Map.class.isAssignableFrom(clazz)
402            || Xpp3Dom.class.isAssignableFrom(clazz);
403   }
404
405   public static MavenArchetype convertArchetype(Archetype archetype) {
406     return new MavenArchetype(archetype.getGroupId(),
407                               archetype.getArtifactId(),
408                               archetype.getVersion(),
409                               archetype.getRepository(),
410                               archetype.getDescription());
411   }
412
413   public static Model toNativeModel(MavenModel model) {
414     Model result = new Model();
415     result.setArtifactId(model.getMavenId().getArtifactId());
416     result.setGroupId(model.getMavenId().getGroupId());
417     result.setVersion(model.getMavenId().getVersion());
418     result.setPackaging(model.getPackaging());
419     result.setName(model.getName());
420
421     if (model.getParent() != null) {
422       Parent parent = new Parent();
423       parent.setArtifactId(model.getParent().getMavenId().getArtifactId());
424       parent.setGroupId(model.getParent().getMavenId().getGroupId());
425       parent.setVersion(model.getParent().getMavenId().getVersion());
426       parent.setRelativePath(model.getParent().getRelativePath());
427       result.setParent(parent);
428     }
429     toNativeModelBase(model, result);
430
431     result.setBuild(new Build());
432     MavenBuild modelBuild = model.getBuild();
433     toNativeBuildBase(modelBuild, result.getBuild());
434     result.getBuild().setOutputDirectory(modelBuild.getOutputDirectory());
435     result.getBuild().setTestOutputDirectory(modelBuild.getTestOutputDirectory());
436
437     if (modelBuild.getSources().size() > 1) throw new RuntimeException("too many source directories: " + modelBuild.getSources());
438     if (modelBuild.getTestSources().size() > 1) throw new RuntimeException("too many test directories: " + modelBuild.getTestSources());
439
440     if (modelBuild.getSources().size() == 1) {
441       result.getBuild().setSourceDirectory(modelBuild.getSources().get(0));
442     }
443     if (modelBuild.getTestSources().size() == 1) {
444       result.getBuild().setTestSourceDirectory(modelBuild.getTestSources().get(0));
445     }
446
447     result.setProfiles(toNativeProfiles(model.getProfiles()));
448
449     return result;
450   }
451
452   private static List<Profile> toNativeProfiles(List<MavenProfile> profiles) {
453     List<Profile> result = new ArrayList<Profile>(profiles.size());
454     for (MavenProfile each : profiles) {
455       Profile p = new Profile();
456       p.setId(each.getId());
457       p.setSource(each.getSource());
458       p.setBuild(new Build());
459       p.setActivation(toNativeActivation(each.getActivation()));
460       toNativeModelBase(each, p);
461       toNativeBuildBase(each.getBuild(), p.getBuild());
462       result.add(p);
463     }
464     return result;
465   }
466
467   private static Activation toNativeActivation(MavenProfileActivation activation) {
468     if (activation == null) return null;
469     Activation result = new Activation();
470     result.setActiveByDefault(activation.isActiveByDefault());
471     result.setJdk(activation.getJdk());
472     result.setOs(toNativeOsActivation(activation.getOs()));
473     result.setFile(toNativeFileActivation(activation.getFile()));
474     result.setProperty(toNativePropertyActivation(activation.getProperty()));
475     return result;
476   }
477
478   private static ActivationOS toNativeOsActivation(MavenProfileActivationOS os) {
479     if (os == null) return null;
480     ActivationOS result = new ActivationOS();
481     result.setArch(os.getArch());
482     result.setFamily(os.getFamily());
483     result.setName(os.getName());
484     result.setVersion(os.getVersion());
485     return result;
486   }
487
488   private static ActivationFile toNativeFileActivation(MavenProfileActivationFile file) {
489     if (file == null) return null;
490     ActivationFile result = new ActivationFile();
491     result.setExists(file.getExists());
492     result.setMissing(file.getMissing());
493     return result;
494   }
495
496   private static ActivationProperty toNativePropertyActivation(MavenProfileActivationProperty property) {
497     if (property == null) return null;
498     ActivationProperty result = new ActivationProperty();
499     result.setName(property.getName());
500     result.setValue(property.getValue());
501     return result;
502   }
503
504   private static void toNativeModelBase(MavenModelBase from, ModelBase to) {
505     to.setModules(from.getModules());
506     to.setProperties(from.getProperties());
507   }
508
509   private static void toNativeBuildBase(MavenBuildBase from, BuildBase to) {
510     to.setFinalName(from.getFinalName());
511     to.setDefaultGoal(from.getDefaultGoal());
512     to.setDirectory(from.getDirectory());
513     to.setFilters(from.getFilters());
514     to.setResources(toNativeResources(from.getResources()));
515     to.setTestResources(toNativeResources(from.getTestResources()));
516   }
517
518   private static List<Resource> toNativeResources(List<MavenResource> resources) {
519     List<Resource> result = new ArrayList<Resource>(resources.size());
520     for (MavenResource each : resources) {
521       Resource r = new Resource();
522       r.setDirectory(each.getDirectory());
523       r.setTargetPath(each.getTargetPath());
524       r.setFiltering(each.isFiltered());
525       r.setIncludes(each.getIncludes());
526       r.setExcludes(each.getExcludes());
527       result.add(r);
528     }
529     return result;
530   }
531
532   public static Repository toNativeRepository(MavenRemoteRepository r) {
533     Repository result = new Repository();
534     result.setId(r.getId());
535     result.setName(r.getName());
536     result.setUrl(r.getUrl());
537     result.setLayout(r.getLayout() == null ? "default" : r.getLayout());
538
539     if (r.getReleasesPolicy() != null) result.setReleases(toNativePolicy(r.getReleasesPolicy()));
540     if (r.getSnapshotsPolicy() != null) result.setSnapshots(toNativePolicy(r.getSnapshotsPolicy()));
541
542     return result;
543   }
544
545   private static RepositoryPolicy toNativePolicy(MavenRemoteRepository.Policy policy) {
546     RepositoryPolicy result = new RepositoryPolicy();
547     result.setEnabled(policy.isEnabled());
548     result.setUpdatePolicy(policy.getUpdatePolicy());
549     result.setChecksumPolicy(policy.getChecksumPolicy());
550     return result;
551   }
552
553   public static MavenArtifactInfo convertArtifactInfo(ArtifactInfo a) {
554     return new MavenArtifactInfo(a.groupId, a.artifactId, a.version, a.packaging, a.classifier, a.classNames, a.repository);
555   }
556 }
557