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