8c33a29e70059efd66cf16c64f36902c80f12036
[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                         }
125                         catch(IOException e) {
126                                 LOG.warn("problem writing response for {}: {}",uri,e);
127                         }
128                         finally {
129                                 if(os!=null) {
130                                         try{
131                                                 os.close();
132                                         }
133                                         catch(IOException e) {
134                                                 LOG.warn("problem closing response stream: {}",e);
135                                         }
136                                 }
137                         }
138
139                 } else {
140                         this.doGetFile(uri, resp);
141                 }
142         }
143
144         /**
145          * load git.commit.id from jar /META-INF/git.properties
146          * 
147          * @param def
148          */
149         private String getGitHash(String def) {
150                 String content = Resources.getFileContent(AboutHttpServlet.class, "/META-INF/git.properties");
151                 if (content == null) {
152                         return def;
153                 }
154                 String lines[] = content.split("\n");
155                 for (String line : lines) {
156                         if (line.startsWith("git.commit.id")) {
157                                 def = line.substring("git.commit.id=".length());
158                                 break;
159                         }
160                 }
161                 return def;
162         }
163
164         private String getResourceFileContent(String filename) {
165                 LOG.debug("try ti get content of {}", filename);
166                 return Resources.getFileContent(AboutHttpServlet.class, RES_BASEPATH + filename);
167         }
168
169         /**
170          * collect dynamic data for about.md
171          */
172         private void collectData() {
173                 LOG.info("collecting dynamic data");
174                 try {
175                         this.data.put(PLACEHOLDER_KARAF_INFO, SystemInfo.get());
176                 } catch (Exception e) {
177                         LOG.warn("problem collecting system data: {}", e);
178                 }
179         }
180
181         /**
182          * get value for key out of /META-INF/MANIFEST.MF
183          * @param key
184          * @return
185          */
186         private String getManifestValue(String key) {
187                 URL url = Resources.getUrlForRessource(AboutHttpServlet.class, "/META-INF/MANIFEST.MF");
188                 if (url == null) {
189                         return null;
190                 }
191                 Manifest manifest;
192                 try {
193                         manifest = new Manifest(url.openStream());
194                         Attributes attr = manifest.getMainAttributes();
195                         return attr.getValue(key);
196                 } catch (IOException e) {
197                         LOG.warn("problem reading manifest: {}", e);
198                 }
199                 return null;
200
201         }
202         /**
203          * get object representation of /META-INF/maven/groupId/artifactId/pom.properties
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          * get value for key out of /META-INF/maven/groupId/artifactId/pom.xml in properties section
223          * @param key
224          * @return
225          */
226         private String getPomProperty(String key) {
227                 LOG.info("try to get pom property for {}", key);
228                 URL url = Resources.getUrlForRessource(AboutHttpServlet.class,
229                                 METAINF_MAVEN + groupId + "/" + artifactId + "/pom.xml");
230                 if (url == null) {
231                         return null;
232                 }
233                 PomFile pomfile;
234                 try {
235                         pomfile = new PomFile(url.openStream());
236                         return pomfile.getProperty(key);
237                 } catch (Exception e) {
238                         LOG.warn(EXCEPTION_FORMAT_UNABLE_TO_READ_INNER_POMFILE, e);
239                 }
240                 return null;
241         }
242         /**
243          * get parent pom version out of /META-INF/maven/groupId/artifactId/pom.xml 
244          * @return
245          */
246         private String getPomParentVersion() {
247                 LOG.info("try to get pom parent version");
248                 URL url = Resources.getUrlForRessource(AboutHttpServlet.class,
249                                 METAINF_MAVEN + groupId + "/" + artifactId + "/pom.xml");
250                 if (url == null) {
251                         return null;
252                 }
253                 PomFile pomfile;
254                 try {
255                         pomfile = new PomFile(url.openStream());
256                         return pomfile.getParentVersion();
257                 } catch (Exception e) {
258                         LOG.warn(EXCEPTION_FORMAT_UNABLE_TO_READ_INNER_POMFILE, e);
259                 }
260                 return null;
261         }
262
263         /**
264          * get file by uri from resources and write out to response stream 
265          * @param uri
266          * @param resp
267          */
268         private void doGetFile(String uri, HttpServletResponse resp) {
269                 String content = this.getResourceFileContent(uri);
270                 if (content == null) {
271                         try {
272                                 resp.sendError(HttpServletResponse.SC_NOT_FOUND);
273                         } catch (IOException e) {
274                                 LOG.debug("unable to send error response : {}", e);
275                         }
276                 } else {
277                         byte[] data = content.getBytes();
278                         resp.setStatus(HttpServletResponse.SC_OK);
279                         resp.setContentType(this.getContentType(uri));
280                         try {
281                                 resp.getOutputStream().write(data);
282                         } catch (IOException e) {
283                                 LOG.debug("unable to send data : {}", e);
284                         }
285                 }
286
287         }
288
289         /**
290          * create http response contentType by filename
291          * @param filename
292          * @return
293          */
294         private String getContentType(String filename) {
295                 String ext = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
296                 switch (ext) {
297                 case "jpg":
298                 case "jpeg":
299                 case "svg":
300                 case "png":
301                 case "gif":
302                 case "bmp":
303                         return "image/" + ext;
304                 case "json":
305                         return "application/json";
306                 case "html":
307                 case "htm":
308                         return "text/html";
309                 case "txt":
310                 case "md":
311                 default:
312                         return "text/plain";
313                 }
314         }
315
316         /**
317          * render this.readmeContent with this.data
318          * @return
319          */
320         private String render() {
321                 return this.render(null);
322         }
323
324         /**
325          * render content with this.data
326          * @param content
327          * @return
328          */
329         private String render(String content) {
330                 if (content == null) {
331                         content = this.readmeContent;
332                 }
333                 if (content == null) {
334                         return null;
335                 }
336                 for (Entry<String, String> entry : this.data.entrySet()) {
337                         if (entry.getValue() != null && content.contains(entry.getKey())) {
338                                 content = content.replace(entry.getKey(), entry.getValue());
339                         }
340                 }
341
342                 return content;
343         }
344
345         public void setClusterSize(String value) {
346                 this.data.put(PLACEHOLDER_CLUSTER_SIZE, value);
347         }
348 }