0d46ad098931efb58e839be32a646af26fb62458
[ccsdk/features.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP : ccsdk features
4  * ================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property.
6  * All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  *
21  */
22 package org.onap.ccsdk.features.sdnr.wt.dataprovider.http.yangschema;
23
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FilenameFilter;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.OutputStream;
30 import java.nio.file.Path;
31 import java.text.ParseException;
32 import java.util.ArrayList;
33 import java.util.Comparator;
34 import java.util.Date;
35 import java.util.List;
36
37 import javax.annotation.Nonnull;
38 import javax.annotation.Nullable;
39
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 public class YangFileProvider {
44
45     private static final Logger LOG = LoggerFactory.getLogger(YangFileProvider.class);
46
47     private static final FilenameFilter yangFilenameFilter = new FilenameFilter() {
48
49         @Override
50         public boolean accept(File dir, String name) {
51             return name.toLowerCase().endsWith(".yang");
52         }
53     };
54
55     private static final int BUFFER_SIZE = 1024;
56
57     private final Path mainSourcePath;
58     private final List<Path> additionalSources;
59
60     public YangFileProvider(String path) {
61         this.mainSourcePath = new File(path).toPath();
62         this.additionalSources = new ArrayList<>();
63     }
64
65     public boolean hasFileForModule(String module, String version) {
66         return this.mainSourcePath.resolve(YangFilename.createFilename(module, version)).toFile().exists();
67     }
68
69     public boolean hasFileForModule(String module) {
70         return this.findYangFiles(module).size() > 0;
71     }
72
73     private List<YangFilename> findYangFiles(String module) {
74         List<YangFilename> list = new ArrayList<>();
75         String[] files = this.mainSourcePath.toFile().list(yangFilenameFilter);
76         YangFilename yangfile;
77         for (String file : files) {
78             files = this.mainSourcePath.toFile().list(yangFilenameFilter);
79             for (String fn : files) {
80                 try {
81                     yangfile = new YangFilename(this.mainSourcePath.resolve(fn).toString());
82                     if (yangfile.getModule().equals(module)) {
83                         list.add(yangfile);
84                     }
85                 } catch (ParseException e) {
86                     LOG.warn("unable to handle yangfile {}: {}", file, e);
87                 }
88             }
89         }
90         for (Path addPath : this.additionalSources) {
91             files = addPath.toFile().list(yangFilenameFilter);
92             for (String file : files) {
93                 try {
94                     yangfile = new YangFilename(addPath.resolve(file).toString());
95                     if (yangfile.getModule().equals(module)) {
96                         list.add(yangfile);
97                     }
98                 } catch (ParseException e) {
99                     LOG.warn("unable to handle yangfile {}: {}", file, e);
100                 }
101             }
102         }
103         return list;
104     }
105
106     /**
107      * get yang file from source with specified version or least newer one if version is null then the latest one
108      * 
109      * @param module
110      * @param version
111      * @return
112      * @throws ParseException
113      */
114     private @Nullable YangFilename getYangFile(@Nonnull String module, @Nullable String version) throws ParseException {
115         YangFilename f = null;
116         List<YangFilename> list = this.findYangFiles(module);
117
118         list.sort(SortByDateAscComparator.getInstance());
119
120         // find specific version or nearest oldest
121         if (version != null) {
122             Date rev = YangFilename.parseRevision(version);
123             for (YangFilename item : list) {
124                 if (rev.equals(item.getRevision())) {
125                     f = item;
126                     break;
127                 }
128                 if (item.getRevision().after(rev)) {
129                     f = item;
130                     break;
131                 }
132             }
133         }
134         // get latest
135         else {
136             f = list.get(list.size() - 1);
137         }
138         return f;
139     }
140
141     /**
142      * write filestream directly to output stream easier for http handling
143      * 
144      * @param module
145      * @param version
146      * @param outputStream
147      * @return
148      * @throws IOException
149      * @throws ParseException
150      */
151     public int writeOutput(@Nonnull String module, @Nullable String version, @Nonnull OutputStream outputStream)
152             throws IOException, ParseException {
153         YangFilename fn = this.getYangFile(module, version);
154         if (fn == null) {
155             return 0;
156         }
157         byte[] buffer = new byte[BUFFER_SIZE];
158         int bytesRead = -1;
159         int sumlen = 0;
160         InputStream inputStream = null;
161         try {
162             inputStream = new FileInputStream(fn.getFilename());
163
164             while ((bytesRead = inputStream.read(buffer)) != -1) {
165                 outputStream.write(buffer, 0, bytesRead);
166                 sumlen += bytesRead;
167             }
168         } catch (IOException e) {
169             LOG.warn("problem sending {}: {}", fn.getFilename(), e);
170         } finally {
171             if (inputStream != null) {
172                 inputStream.close();
173             }
174         }
175         return sumlen;
176     }
177
178     private static class SortByDateAscComparator implements Comparator<YangFilename> {
179
180         private static SortByDateAscComparator instance;
181
182         @Override
183         public int compare(YangFilename o1, YangFilename o2) {
184             return o1.getRevision().compareTo(o2.getRevision());
185         }
186
187         public static Comparator<YangFilename> getInstance() {
188             if (instance == null) {
189                 instance = new SortByDateAscComparator();
190             }
191             return instance;
192         }
193
194     }
195
196     public YangFilename getFileForModule(String module, String rev) throws ParseException {
197         return this.getYangFile(module, rev);
198     }
199
200     public YangFilename getFileForModule(String module) throws ParseException {
201         return this.getFileForModule(module, null);
202     }
203
204     public boolean hasFileOrNewerForModule(String module, String version) throws ParseException {
205         return this.getYangFile(module, version) != null;
206     }
207
208 }