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