c6758e240fe015e4fd292716191302244d3cbfcb
[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 import javax.annotation.Nonnull;
37 import javax.annotation.Nullable;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 public class YangFileProvider {
42
43     private static final Logger LOG = LoggerFactory.getLogger(YangFileProvider.class);
44
45     private static final FilenameFilter yangFilenameFilter = new FilenameFilter() {
46
47         @Override
48         public boolean accept(File dir, String name) {
49             return name.toLowerCase().endsWith(".yang");
50         }
51     };
52
53     private static final int BUFFER_SIZE = 1024;
54
55     private final Path mainSourcePath;
56     private final List<Path> additionalSources;
57
58     public YangFileProvider(String path) {
59         this.mainSourcePath = new File(path).toPath();
60         this.additionalSources = new ArrayList<>();
61     }
62
63     public boolean hasFileForModule(String module, String version) {
64         return this.mainSourcePath.resolve(YangFilename.createFilename(module, version)).toFile().exists();
65     }
66
67     public boolean hasFileForModule(String module) {
68         return this.findYangFiles(module).size() > 0;
69     }
70
71     private List<YangFilename> findYangFiles(String module) {
72         LOG.debug("try to find yang files for {}", module);
73         List<YangFilename> list = new ArrayList<>();
74         String[] files = this.mainSourcePath.toFile().list(yangFilenameFilter);
75         YangFilename yangfile;
76         for (String fn : files) {
77             try {
78                 yangfile = new YangFilename(this.mainSourcePath.resolve(fn).toString());
79                 if (yangfile.getModule().equals(module)) {
80                     list.add(yangfile);
81                 }
82             } catch (ParseException e) {
83                 LOG.warn("unable to handle yangfile {}: {}", fn, e);
84             }
85         }
86
87         for (Path addPath : this.additionalSources) {
88             files = addPath.toFile().list(yangFilenameFilter);
89             for (String file : files) {
90                 try {
91                     yangfile = new YangFilename(addPath.resolve(file).toString());
92                     if (yangfile.getModule().equals(module)) {
93                         list.add(yangfile);
94                     }
95                 } catch (ParseException e) {
96                     LOG.warn("unable to handle yangfile {}: {}", file, e);
97                 }
98             }
99         }
100         return list;
101     }
102
103     /**
104      * get yang file from source with specified version or least newer one if version is null then the latest one
105      *
106      * @param module
107      * @param version
108      * @return
109      * @throws ParseException
110      */
111     private @Nullable YangFilename getYangFile(@Nonnull String module, @Nullable String version) throws ParseException {
112         YangFilename f = null;
113         List<YangFilename> list = this.findYangFiles(module);
114
115         list.sort(SortByDateAscComparator.getInstance());
116
117         // find specific version or nearest oldest
118         if (version != null) {
119             Date rev = YangFilename.parseRevision(version);
120             for (YangFilename item : list) {
121                 if (rev.equals(item.getRevision())) {
122                     f = item;
123                     break;
124                 }
125                 if (item.getRevision().after(rev)) {
126                     f = item;
127                     break;
128                 }
129             }
130         }
131         // get latest
132         else {
133             f = list.get(list.size() - 1);
134         }
135         return f;
136     }
137
138     /**
139      * write filestream directly to output stream easier for http handling
140      *
141      * @param module
142      * @param version
143      * @param outputStream
144      * @return
145      * @throws IOException
146      * @throws ParseException
147      */
148     public int writeOutput(@Nonnull String module, @Nullable String version, @Nonnull OutputStream outputStream)
149             throws IOException, ParseException {
150         YangFilename fn = this.getYangFile(module, version);
151         if (fn == null) {
152             return 0;
153         }
154         byte[] buffer = new byte[BUFFER_SIZE];
155         int bytesRead = -1;
156         int sumlen = 0;
157         InputStream inputStream = null;
158         try {
159             inputStream = new FileInputStream(fn.getFilename());
160
161             while ((bytesRead = inputStream.read(buffer)) != -1) {
162                 outputStream.write(buffer, 0, bytesRead);
163                 sumlen += bytesRead;
164             }
165         } catch (IOException e) {
166             LOG.warn("problem sending {}: {}", fn.getFilename(), e);
167         } finally {
168             if (inputStream != null) {
169                 inputStream.close();
170             }
171         }
172         return sumlen;
173     }
174
175     private static class SortByDateAscComparator implements Comparator<YangFilename> {
176
177         private static SortByDateAscComparator instance;
178
179         @Override
180         public int compare(YangFilename o1, YangFilename o2) {
181             return o1.getRevision().compareTo(o2.getRevision());
182         }
183
184         public static Comparator<YangFilename> getInstance() {
185             if (instance == null) {
186                 instance = new SortByDateAscComparator();
187             }
188             return instance;
189         }
190
191     }
192
193     public YangFilename getFileForModule(String module, String rev) throws ParseException {
194         return this.getYangFile(module, rev);
195     }
196
197     public YangFilename getFileForModule(String module) throws ParseException {
198         return this.getFileForModule(module, null);
199     }
200
201     public boolean hasFileOrNewerForModule(String module, String version) throws ParseException {
202         return this.getYangFile(module, version) != null;
203     }
204
205 }