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;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.nio.file.Files;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.zip.ZipEntry;
28  import java.util.zip.ZipException;
29  import java.util.zip.ZipFile;
30  
31  import org.apache.lucene.document.Document;
32  import org.apache.lucene.document.Field;
33  import org.apache.lucene.document.StoredField;
34  import org.apache.maven.index.artifact.Gav;
35  import org.apache.maven.index.context.IndexCreator;
36  import org.apache.maven.index.context.IndexingContext;
37  import org.apache.maven.model.Model;
38  import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
39  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
40  import org.slf4j.Logger;
41  import org.slf4j.LoggerFactory;
42  
43  /**
44   * An artifact context used to provide information about artifact during scanning. It is passed to the
45   * {@link IndexCreator}, which can populate {@link ArtifactInfo} for the given artifact.
46   *
47   * @see IndexCreator#populateArtifactInfo(ArtifactContext)
48   * @author Jason van Zyl
49   * @author Tamas Cservenak
50   */
51  public class ArtifactContext {
52  
53      private static final Logger LOGGER = LoggerFactory.getLogger(ArtifactContext.class);
54  
55      private final File pom;
56  
57      private final File artifact;
58  
59      private final File metadata;
60  
61      private final ArtifactInfo artifactInfo;
62  
63      private final Gav gav;
64  
65      private final List<Exception> errors = new ArrayList<>();
66  
67      public ArtifactContext(File pom, File artifact, File metadata, ArtifactInfo artifactInfo, Gav gav)
68              throws IllegalArgumentException {
69          if (artifactInfo == null) {
70              throw new IllegalArgumentException("Parameter artifactInfo must not be null.");
71          }
72  
73          this.pom = pom;
74          this.artifact = artifact;
75          this.metadata = metadata;
76          this.artifactInfo = artifactInfo;
77          this.gav = gav == null ? artifactInfo.calculateGav() : gav;
78      }
79  
80      public File getPom() {
81          return pom;
82      }
83  
84      public Model getPomModel() {
85          // First check for local pom file
86          File pom = getPom();
87          if (pom != null && pom.isFile()) {
88              try (InputStream inputStream = Files.newInputStream(pom.toPath())) {
89                  return new MavenXpp3Reader().read(inputStream, false);
90              } catch (IOException | XmlPullParserException e) {
91                  LOGGER.warn("skip error reading pom: " + pom, e);
92              }
93          }
94          // Otherwise, check for pom contained in maven generated artifact
95          else if (getArtifact() != null && getArtifact().isFile()) {
96              boolean isZip = false;
97              try (ZipFile zipFile = new ZipFile(artifact)) {
98                  isZip = true;
99                  final String embeddedPomPath =
100                         "META-INF/maven/" + getGav().getGroupId() + "/" + getGav().getArtifactId() + "/pom.xml";
101 
102                 ZipEntry zipEntry = zipFile.getEntry(embeddedPomPath);
103 
104                 if (zipEntry != null) {
105                     try (InputStream inputStream = zipFile.getInputStream(zipEntry)) {
106                         return new MavenXpp3Reader().read(inputStream, false);
107                     }
108                 }
109             } catch (IOException | XmlPullParserException e) {
110                 if (e instanceof ZipException && !isZip) {
111                     // ZipFile constructor threw ZipException which means this is no zip file -> ignore
112                 } else {
113                     LOGGER.warn("skip error reading pom within artifact:" + artifact, e);
114                 }
115             }
116         }
117 
118         return null;
119     }
120 
121     public File getArtifact() {
122         return artifact;
123     }
124 
125     public File getMetadata() {
126         return metadata;
127     }
128 
129     public ArtifactInfo getArtifactInfo() {
130         return artifactInfo;
131     }
132 
133     public Gav getGav() {
134         return gav;
135     }
136 
137     public List<Exception> getErrors() {
138         return errors;
139     }
140 
141     public void addError(Exception e) {
142         errors.add(e);
143     }
144 
145     /**
146      * Creates Lucene Document using {@link IndexCreator}s from the given {@link IndexingContext}.
147      */
148     public Document createDocument(IndexingContext context) {
149         Document doc = new Document();
150 
151         // unique key
152         doc.add(new Field(ArtifactInfo.UINFO, getArtifactInfo().getUinfo(), IndexerField.KEYWORD_STORED));
153 
154         doc.add(new StoredField(
155                 ArtifactInfo.LAST_MODIFIED, //
156                 Long.toString(System.currentTimeMillis())));
157 
158         for (IndexCreator indexCreator : context.getIndexCreators()) {
159             try {
160                 indexCreator.populateArtifactInfo(this);
161             } catch (IOException ex) {
162                 addError(ex);
163             }
164         }
165 
166         // need a second pass in case index creators updated document attributes
167         for (IndexCreator indexCreator : context.getIndexCreators()) {
168             indexCreator.updateDocument(getArtifactInfo(), doc);
169         }
170 
171         return doc;
172     }
173 }