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  
20  package org.apache.rat.walker;
21  
22  import java.io.BufferedInputStream;
23  import java.io.ByteArrayInputStream;
24  import java.io.ByteArrayOutputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.util.ArrayList;
28  import java.util.Collection;
29  import java.util.Collections;
30  import java.util.List;
31  import java.util.SortedSet;
32  
33  import org.apache.commons.compress.archivers.ArchiveEntry;
34  import org.apache.commons.compress.archivers.ArchiveException;
35  import org.apache.commons.compress.archivers.ArchiveInputStream;
36  import org.apache.commons.compress.archivers.ArchiveStreamFactory;
37  import org.apache.commons.io.IOUtils;
38  import org.apache.rat.api.Document;
39  import org.apache.rat.api.RatException;
40  import org.apache.rat.document.ArchiveEntryName;
41  import org.apache.rat.document.DocumentName;
42  import org.apache.rat.document.DocumentNameMatcher;
43  import org.apache.rat.report.RatReport;
44  import org.apache.rat.utils.DefaultLog;
45  
46  import static java.lang.String.format;
47  
48  /**
49   * Walks various kinds of archives files.
50   */
51  public class ArchiveWalker extends Walker {
52  
53      /**
54       * Constructs a walker.
55       * @param document the document to process.
56       */
57      public ArchiveWalker(final Document document) {
58          super(document);
59      }
60  
61      /**
62       * Run a report over all files and directories in the archive
63       * ignoring any files/directories set to be ignored.
64       *
65       * @param report the defined RatReport to run on this GZIP walker.
66       *
67       */
68      public void run(final RatReport report) throws RatException {
69          for (Document document : getDocuments()) {
70              report.report(document);
71          }
72      }
73  
74      /**
75       * Creates an input stream from the directory being walked.
76       * @return A buffered input stream reading the archive data.
77       * @throws IOException on error.
78       */
79      private InputStream createInputStream() throws IOException {
80          return new BufferedInputStream(getDocument().inputStream());
81      }
82  
83      /**
84       * Retrieves the documents from the archive.
85       * @return A collection of documents that pass the file filter.
86       * @throws RatException on error.
87       */
88      public Collection<Document> getDocuments() throws RatException {
89          List<Document> result = new ArrayList<>();
90          try (ArchiveInputStream<? extends ArchiveEntry> input = new ArchiveStreamFactory().createArchiveInputStream(createInputStream())) {
91              ArchiveEntry entry;
92              while ((entry = input.getNextEntry()) != null) {
93                  if (!entry.isDirectory() && input.canReadEntryData(entry)) {
94                      final DocumentName innerName = DocumentName.builder().setName(entry.getName())
95                              .setBaseName(".").build();
96                      final DocumentNameMatcher documentNameMatcher = getDocument().getNameMatcher();
97                      if (documentNameMatcher.matches(innerName)) {
98                          ArchiveEntryName entryName = new ArchiveEntryName(getDocument().getName(), entry.getName());
99                          ByteArrayOutputStream baos = new ByteArrayOutputStream();
100                         IOUtils.copy(input, baos);
101                         result.add(new Document(entryName, documentNameMatcher) {
102                             @Override
103                             public InputStream inputStream() {
104                                 return new ByteArrayInputStream(baos.toByteArray());
105                             }
106 
107                             @Override
108                             public boolean isDirectory() {
109                                 return false;
110                             }
111 
112                             @Override
113                             public SortedSet<Document> listChildren() {
114                                 return Collections.emptySortedSet();
115                             }
116                         });
117                     }
118                 }
119             }
120         } catch (ArchiveException e) {
121             DefaultLog.getInstance().warn(format("Unable to process %s: %s", getDocument().getName(), e.getMessage()));
122         } catch (IOException e) {
123             throw RatException.makeRatException(e);
124         }
125         return result;
126     }
127 }