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   *   https://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.creadur.tentacles;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.net.URI;
24  import java.nio.file.Path;
25  import java.util.HashSet;
26  import java.util.LinkedHashMap;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.Set;
30  
31  
32  public class Archive {
33  
34      private final Layout layout;
35      private final FileSystem fileSystem;
36      private final URI uri;
37      private final File file;
38      private final Map<URI, URI> map;
39  
40      private final Set<License> licenses = new HashSet<>();
41      private final Set<Notice> notices = new HashSet<>();
42  
43      private final Set<License> declaredLicenses = new HashSet<>();
44      private final Set<Notice> declaredNotices = new HashSet<>();
45  
46      private final Set<License> otherLicenses = new HashSet<>();
47      private final Set<Notice> otherNotices = new HashSet<>();
48      private Map<URI, URI> others;
49  
50      public Archive(final File file, final FileSystem fileSystem,
51              final Layout layout) throws IOException {
52          this.fileSystem = fileSystem;
53          this.layout = layout;
54          this.uri =
55                  layout.getRepositoryDirectory().toURI()
56                          .relativize(file.toURI());
57          this.file = file;
58          this.map = map();
59      }
60  
61      public Set<License> getDeclaredLicenses() {
62          return this.declaredLicenses;
63      }
64  
65      public Set<Notice> getDeclaredNotices() {
66          return this.declaredNotices;
67      }
68  
69      public Set<License> getOtherLicenses() {
70          return this.otherLicenses;
71      }
72  
73      public Set<Notice> getOtherNotices() {
74          return this.otherNotices;
75      }
76  
77      public Set<License> getLicenses() {
78          return this.licenses;
79      }
80  
81      public Set<Notice> getNotices() {
82          return this.notices;
83      }
84  
85      public URI getUri() {
86          return this.uri;
87      }
88  
89      public File getFile() {
90          return this.file;
91      }
92  
93      public Map<URI, URI> getLegal() {
94          return this.map;
95      }
96  
97      public Map<URI, URI> getOtherLegal() throws IOException {
98          if (this.others == null) {
99              this.others = mapOther();
100         }
101         return this.others;
102     }
103 
104     private Map<URI, URI> mapOther() throws IOException {
105         final File jarContents = contentsDirectory();
106         final List<File> legal =
107                 this.fileSystem.legalDocumentsUndeclaredIn(jarContents);
108 
109         return buildMapFrom(jarContents, legal);
110     }
111 
112     private Map<URI, URI> buildMapFrom(final File jarContents,
113             final List<File> legal) {
114         final Map<URI, URI> map = new LinkedHashMap<>();
115         for (final File file : legal) {
116             final URI name = jarContents.toURI().relativize(file.toURI());
117             final URI link =
118                     this.layout.getLocalRootDirectory().toURI()
119                             .relativize(file.toURI());
120 
121             map.put(name, link);
122         }
123         return map;
124     }
125 
126     private Map<URI, URI> map() throws IOException {
127         final File jarContents = contentsDirectory();
128         final List<File> legal =
129                 this.fileSystem.legalDocumentsDeclaredIn(jarContents);
130 
131         return buildMapFrom(jarContents, legal);
132     }
133 
134     public File contentsDirectory() throws IOException {
135         final File archiveDocument = getFile();
136         String path =
137                 archiveDocument.getAbsolutePath().substring(
138                         this.layout.getLocalRootDirectory().getAbsolutePath()
139                                 .length() + 1);
140 
141         if (path.startsWith("repo/")) {
142             path = path.substring("repo/".length());
143         }
144         if (path.startsWith("content/")) {
145             path = path.substring("content/".length());
146         }
147 
148         final File contents =
149                 new File(this.layout.getContentRootDirectory(), path
150                         + ".contents");
151 
152         Path targetDir = this.layout.getContentRootDirectory().toPath().toAbsolutePath().normalize();
153         Path resolved = targetDir.resolve(path + ".contents").normalize();
154         if(!resolved.startsWith(targetDir)) {
155             throw new IOException("Invalid content directory: " + path + ".contents");
156         }
157 
158         this.fileSystem.mkdirs(contents);
159         return contents;
160     }
161 
162     public URI contentsURI() throws IOException {
163         return contentsDirectory().toURI();
164     }
165 }