1206842985e0362cf75f12c42388f8c4ca0230c8
[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;
23
24 import java.io.IOException;
25 import java.net.URL;
26 import java.util.HashMap;
27 import java.util.Map;
28 import java.util.Map.Entry;
29 import java.util.jar.Attributes;
30 import java.util.jar.Manifest;
31
32 import javax.servlet.ServletException;
33 import javax.servlet.ServletOutputStream;
34 import javax.servlet.http.HttpServlet;
35 import javax.servlet.http.HttpServletRequest;
36 import javax.servlet.http.HttpServletResponse;
37
38 import org.onap.ccsdk.features.sdnr.wt.common.Resources;
39 import org.onap.ccsdk.features.sdnr.wt.common.file.PomFile;
40 import org.onap.ccsdk.features.sdnr.wt.common.file.PomPropertiesFile;
41 import org.onap.ccsdk.features.sdnr.wt.dataprovider.data.ODLVersionLUT;
42 import org.onap.ccsdk.features.sdnr.wt.dataprovider.data.SystemInfo;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 public class AboutHttpServlet extends HttpServlet {
47
48     /**
49      * 
50      */
51     private static final long serialVersionUID = 1L;
52     private static final Logger LOG = LoggerFactory.getLogger(AboutHttpServlet.class);
53     private static final String UNKNOWN = "unknown";
54     private static final String METAINF_MAVEN = "/META-INF/maven/";
55     private static final String EXCEPTION_FORMAT_UNABLE_TO_READ_INNER_POMFILE = "unable to read inner pom file: {}";
56
57     private static final String URI_PRE = "/about";
58     private static final String RES_BASEPATH = "about/";
59
60     private static final String PLACEHOLDER_ONAP_RELEASENAME = "{release-name}";
61     private static final String PLACEHOLDER_ONAP_RELEASEVERSION = "{release-version}";
62     private static final String PLACEHOLDER_ODL_RELEASENAME = "{odl-version}";
63     private static final String PLACEHOLDER_BUILD_TIMESTAMP = "{build-time}";
64     private static final String PLACEHOLDER_ODLUX_REVISION = "{odlux-revision}";
65     private static final String PLACEHOLDER_PACKAGE_GITHASH = "{package-githash}";
66     private static final String PLACEHOLDER_PACAKGE_VERSION = "{package-version}";
67     private static final String PLACEHOLDER_CCSDK_VERSION = "{ccsdk-version}";
68     private static final String PLACEHOLDER_CLUSTER_SIZE = "{cluster-size}";
69     private static final String PLACEHOLDER_MDSAL_VERSION = "{mdsal-version}";
70     private static final String PLACEHOLDER_YANGTOOLS_VERSION = "{yangtools-version}";
71     private static final String PLACEHOLDER_KARAF_INFO = "{karaf-info}";
72     private static final String README_FILE = "README.md";
73
74     private final String groupId = "org.onap.ccsdk.features.sdnr.wt";
75     private final String artifactId = "sdnr-wt-data-provider-provider";
76
77     private final Map<String, String> data;
78     private final String readmeContent;
79
80     public AboutHttpServlet() {
81
82         this.data = new HashMap<>();
83         this.collectStaticData();
84         this.readmeContent = this.render(this.getResourceFileContent(README_FILE));
85     }
86
87     /**
88      * collect static versioning data
89      */
90     private void collectStaticData() {
91         PomPropertiesFile props = this.getPomProperties();
92         final String ccsdkVersion = this.getPomParentVersion();
93         this.data.put(PLACEHOLDER_ONAP_RELEASENAME, ODLVersionLUT.getONAPReleaseName(ccsdkVersion, UNKNOWN));
94         this.data.put(PLACEHOLDER_ODL_RELEASENAME, ODLVersionLUT.getOdlVersion(ccsdkVersion, UNKNOWN));
95         this.data.put(PLACEHOLDER_BUILD_TIMESTAMP, props != null ? props.getBuildDate().toString() : "");
96         this.data.put(PLACEHOLDER_ODLUX_REVISION, this.getPomProperty("odlux.buildno"));
97         this.data.put(PLACEHOLDER_PACAKGE_VERSION, this.getManifestValue("Bundle-Version"));
98         this.data.put(PLACEHOLDER_CCSDK_VERSION, ccsdkVersion);
99         this.data.put(PLACEHOLDER_ONAP_RELEASEVERSION, "1.8.1-SNAPSHOT");
100         this.data.put(PLACEHOLDER_MDSAL_VERSION, SystemInfo.getMdSalVersion(UNKNOWN));
101         this.data.put(PLACEHOLDER_YANGTOOLS_VERSION, SystemInfo.getYangToolsVersion(UNKNOWN));
102         this.data.put(PLACEHOLDER_PACKAGE_GITHASH, this.getGitHash(UNKNOWN));
103     }
104
105     @Override
106     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
107
108         String uri = req.getRequestURI().substring(URI_PRE.length());
109         LOG.debug("request for {}", uri);
110         if (uri.length() <= 0 || uri.equals("/")) {
111             // collect data
112             this.collectData();
113             // render readme
114             String content = this.render();
115             byte[] output = content != null ? content.getBytes() : new byte[0];
116             // output
117             resp.setStatus(HttpServletResponse.SC_OK);
118             resp.setContentLength(output.length);
119             resp.setContentType("text/plain");
120             ServletOutputStream os = null;
121             try {
122                 os = resp.getOutputStream();
123                 os.write(output);
124             } catch (IOException e) {
125                 LOG.warn("problem writing response for {}: {}", uri, e);
126             } finally {
127                 if (os != null) {
128                     try {
129                         os.close();
130                     } catch (IOException e) {
131                         LOG.warn("problem closing response stream: {}", e);
132                     }
133                 }
134             }
135
136         } else {
137             this.doGetFile(uri, resp);
138         }
139     }
140
141     /**
142      * load git.commit.id from jar /META-INF/git.properties
143      * 
144      * @param def
145      */
146     private String getGitHash(String def) {
147         String content = Resources.getFileContent(AboutHttpServlet.class, "/META-INF/git.properties");
148         if (content == null) {
149             return def;
150         }
151         String lines[] = content.split("\n");
152         for (String line : lines) {
153             if (line.startsWith("git.commit.id")) {
154                 def = line.substring("git.commit.id=".length());
155                 break;
156             }
157         }
158         return def;
159     }
160
161     private String getResourceFileContent(String filename) {
162         LOG.debug("try ti get content of {}", filename);
163         return Resources.getFileContent(AboutHttpServlet.class, RES_BASEPATH + filename);
164     }
165
166     /**
167      * collect dynamic data for about.md
168      */
169     private void collectData() {
170         LOG.info("collecting dynamic data");
171         try {
172             this.data.put(PLACEHOLDER_KARAF_INFO, SystemInfo.get());
173         } catch (Exception e) {
174             LOG.warn("problem collecting system data: {}", e);
175         }
176     }
177
178     /**
179      * get value for key out of /META-INF/MANIFEST.MF
180      * 
181      * @param key
182      * @return
183      */
184     private String getManifestValue(String key) {
185         URL url = Resources.getUrlForRessource(AboutHttpServlet.class, "/META-INF/MANIFEST.MF");
186         if (url == null) {
187             return null;
188         }
189         Manifest manifest;
190         try {
191             manifest = new Manifest(url.openStream());
192             Attributes attr = manifest.getMainAttributes();
193             return attr.getValue(key);
194         } catch (IOException e) {
195             LOG.warn("problem reading manifest: {}", e);
196         }
197         return null;
198
199     }
200
201     /**
202      * get object representation of /META-INF/maven/groupId/artifactId/pom.properties
203      * 
204      * @return
205      */
206     private PomPropertiesFile getPomProperties() {
207         URL url = Resources.getUrlForRessource(AboutHttpServlet.class,
208                 METAINF_MAVEN + groupId + "/" + artifactId + "/pom.properties");
209         PomPropertiesFile propfile;
210         if (url == null) {
211             return null;
212         }
213         try {
214             propfile = new PomPropertiesFile(url.openStream());
215             return propfile;
216         } catch (Exception e) {
217             LOG.warn(EXCEPTION_FORMAT_UNABLE_TO_READ_INNER_POMFILE, e);
218         }
219         return null;
220     }
221
222     /**
223      * get value for key out of /META-INF/maven/groupId/artifactId/pom.xml in properties section
224      * 
225      * @param key
226      * @return
227      */
228     private String getPomProperty(String key) {
229         LOG.info("try to get pom property for {}", key);
230         URL url = Resources.getUrlForRessource(AboutHttpServlet.class,
231                 METAINF_MAVEN + groupId + "/" + artifactId + "/pom.xml");
232         if (url == null) {
233             return null;
234         }
235         PomFile pomfile;
236         try {
237             pomfile = new PomFile(url.openStream());
238             return pomfile.getProperty(key);
239         } catch (Exception e) {
240             LOG.warn(EXCEPTION_FORMAT_UNABLE_TO_READ_INNER_POMFILE, e);
241         }
242         return null;
243     }
244
245     /**
246      * get parent pom version out of /META-INF/maven/groupId/artifactId/pom.xml
247      * 
248      * @return
249      */
250     private String getPomParentVersion() {
251         LOG.info("try to get pom parent version");
252         URL url = Resources.getUrlForRessource(AboutHttpServlet.class,
253                 METAINF_MAVEN + groupId + "/" + artifactId + "/pom.xml");
254         if (url == null) {
255             return null;
256         }
257         PomFile pomfile;
258         try {
259             pomfile = new PomFile(url.openStream());
260             return pomfile.getParentVersion();
261         } catch (Exception e) {
262             LOG.warn(EXCEPTION_FORMAT_UNABLE_TO_READ_INNER_POMFILE, e);
263         }
264         return null;
265     }
266
267     /**
268      * get file by uri from resources and write out to response stream
269      * 
270      * @param uri
271      * @param resp
272      */
273     private void doGetFile(String uri, HttpServletResponse resp) {
274         String content = this.getResourceFileContent(uri);
275         if (content == null) {
276             try {
277                 resp.sendError(HttpServletResponse.SC_NOT_FOUND);
278             } catch (IOException e) {
279                 LOG.debug("unable to send error response : {}", e);
280             }
281         } else {
282             byte[] data = content.getBytes();
283             resp.setStatus(HttpServletResponse.SC_OK);
284             resp.setContentType(this.getContentType(uri));
285             try {
286                 resp.getOutputStream().write(data);
287             } catch (IOException e) {
288                 LOG.debug("unable to send data : {}", e);
289             }
290         }
291
292     }
293
294     /**
295      * create http response contentType by filename
296      * 
297      * @param filename
298      * @return
299      */
300     private String getContentType(String filename) {
301         String ext = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
302         switch (ext) {
303             case "jpg":
304             case "jpeg":
305             case "svg":
306             case "png":
307             case "gif":
308             case "bmp":
309                 return "image/" + ext;
310             case "json":
311                 return "application/json";
312             case "html":
313             case "htm":
314                 return "text/html";
315             case "txt":
316             case "md":
317             default:
318                 return "text/plain";
319         }
320     }
321
322     /**
323      * render this.readmeContent with this.data
324      * 
325      * @return
326      */
327     private String render() {
328         return this.render(null);
329     }
330
331     /**
332      * render content with this.data
333      * 
334      * @param content
335      * @return
336      */
337     private String render(String content) {
338         if (content == null) {
339             content = this.readmeContent;
340         }
341         if (content == null) {
342             return null;
343         }
344         for (Entry<String, String> entry : this.data.entrySet()) {
345             if (entry.getValue() != null && content.contains(entry.getKey())) {
346                 content = content.replace(entry.getKey(), entry.getValue());
347             }
348         }
349
350         return content;
351     }
352
353     public void setClusterSize(String value) {
354         this.data.put(PLACEHOLDER_CLUSTER_SIZE, value);
355     }
356 }