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.apache.maven.index.creator;
20  
21  import javax.inject.Named;
22  import javax.inject.Singleton;
23  
24  import java.io.BufferedInputStream;
25  import java.io.File;
26  import java.io.InputStream;
27  import java.io.InputStreamReader;
28  import java.util.ArrayList;
29  import java.util.Arrays;
30  import java.util.Collection;
31  import java.util.zip.ZipEntry;
32  import java.util.zip.ZipFile;
33  
34  import org.apache.lucene.document.Document;
35  import org.apache.maven.index.ArtifactContext;
36  import org.apache.maven.index.ArtifactInfo;
37  import org.apache.maven.index.IndexerField;
38  import org.apache.maven.index.IndexerFieldVersion;
39  import org.apache.maven.index.MAVEN;
40  import org.codehaus.plexus.util.xml.Xpp3Dom;
41  import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
42  
43  /**
44   * A Maven Plugin index creator used to provide information about Maven Plugins. It will collect the plugin prefix and
45   * the goals the plugin provides. Also, the Lucene document and the returned ArtifactInfo will be correctly filled with
46   * these information.
47   *
48   * @author cstamas
49   */
50  @Singleton
51  @Named(MavenPluginArtifactInfoIndexCreator.ID)
52  public class MavenPluginArtifactInfoIndexCreator extends AbstractIndexCreator {
53      public static final String ID = "maven-plugin";
54  
55      private static final String MAVEN_PLUGIN_PACKAGING = "maven-plugin";
56  
57      public static final IndexerField FLD_PLUGIN_PREFIX = new IndexerField(
58              MAVEN.PLUGIN_PREFIX,
59              IndexerFieldVersion.V1,
60              "px",
61              "MavenPlugin prefix (as keyword, stored)",
62              IndexerField.KEYWORD_STORED);
63  
64      public static final IndexerField FLD_PLUGIN_GOALS = new IndexerField(
65              MAVEN.PLUGIN_GOALS,
66              IndexerFieldVersion.V1,
67              "gx",
68              "MavenPlugin goals (as keyword, stored)",
69              IndexerField.ANALYZED_STORED);
70  
71      public MavenPluginArtifactInfoIndexCreator() {
72          super(ID, Arrays.asList(MinimalArtifactInfoIndexCreator.ID));
73      }
74  
75      public void populateArtifactInfo(ArtifactContext ac) {
76          File artifact = ac.getArtifact();
77  
78          ArtifactInfo ai = ac.getArtifactInfo();
79  
80          // we need the file to perform these checks, and those may be only JARs
81          if (artifact != null
82                  && MAVEN_PLUGIN_PACKAGING.equals(ai.getPackaging())
83                  && artifact.getName().endsWith(".jar")) {
84              // TODO: recheck, is the following true? "Maven plugins and Maven Archetypes can be only JARs?"
85  
86              // 1st, check for maven plugin
87              checkMavenPlugin(ai, artifact);
88          }
89      }
90  
91      private void checkMavenPlugin(ArtifactInfo ai, File artifact) {
92          try (ZipFile zipFile = new ZipFile(artifact)) {
93              final String pluginDescriptorPath = "META-INF/maven/plugin.xml";
94              ZipEntry zipEntry = zipFile.getEntry(pluginDescriptorPath);
95              if (zipEntry != null) {
96                  try (InputStream is = new BufferedInputStream(zipFile.getInputStream(zipEntry))) {
97                      // here the reader is closed
98                      Xpp3Dom plexusConfig = Xpp3DomBuilder.build(new InputStreamReader(is));
99  
100                     ai.setPrefix(plexusConfig.getChild("goalPrefix").getValue());
101 
102                     ai.setGoals(new ArrayList<>());
103 
104                     Xpp3Dom[] mojoConfigs = plexusConfig.getChild("mojos").getChildren("mojo");
105 
106                     for (Xpp3Dom mojoConfig : mojoConfigs) {
107                         ai.getGoals().add(mojoConfig.getChild("goal").getValue());
108                     }
109                 }
110             }
111         } catch (Exception e) {
112             if (getLogger().isDebugEnabled()) {
113                 getLogger()
114                         .info("Failed to parse Maven artifact " + artifact.getAbsolutePath() + " due to exception:", e);
115             } else {
116                 getLogger()
117                         .info("Failed to parse Maven artifact " + artifact.getAbsolutePath() + " due to "
118                                 + e.getMessage());
119             }
120         }
121     }
122 
123     public void updateDocument(ArtifactInfo ai, Document doc) {
124         if (ai.getPrefix() != null) {
125             doc.add(FLD_PLUGIN_PREFIX.toField(ai.getPrefix()));
126         }
127 
128         if (ai.getGoals() != null) {
129             doc.add(FLD_PLUGIN_GOALS.toField(ArtifactInfo.lst2str(ai.getGoals())));
130         }
131     }
132 
133     public boolean updateArtifactInfo(Document doc, ArtifactInfo ai) {
134         boolean res = false;
135 
136         if ("maven-plugin".equals(ai.getPackaging())) {
137             ai.setPrefix(doc.get(ArtifactInfo.PLUGIN_PREFIX));
138 
139             String goals = doc.get(ArtifactInfo.PLUGIN_GOALS);
140 
141             if (goals != null) {
142                 ai.setGoals(ArtifactInfo.str2lst(goals));
143             }
144 
145             res = true;
146         }
147 
148         return res;
149     }
150 
151     @Override
152     public String toString() {
153         return ID;
154     }
155 
156     public Collection<IndexerField> getIndexerFields() {
157         return Arrays.asList(FLD_PLUGIN_GOALS, FLD_PLUGIN_PREFIX);
158     }
159 }