35e35156336b7d664fcf2c0d415f3a8daa61d342
[ccsdk/features.git] /
1 /*******************************************************************************
2  * ============LICENSE_START========================================================================
3  * ONAP : ccsdk feature sdnr wt
4  * =================================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6  * =================================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  * ============LICENSE_END==========================================================================
17  ******************************************************************************/
18 package org.onap.ccsdk.features.sdnr.wt.helpserver;
19
20 import java.io.BufferedReader;
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileReader;
24 import java.io.IOException;
25 import java.io.OutputStream;
26 import java.net.URISyntaxException;
27 import java.net.URLDecoder;
28 import java.nio.file.Path;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31 import javax.servlet.ServletException;
32 import javax.servlet.http.HttpServlet;
33 import javax.servlet.http.HttpServletRequest;
34 import javax.servlet.http.HttpServletResponse;
35 import org.onap.ccsdk.features.sdnr.wt.helpserver.data.HelpInfrastructureObject;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 public class HelpServlet extends HttpServlet implements AutoCloseable {
40
41     private static Logger LOG = LoggerFactory.getLogger(HelpServlet.class);
42     private static final long serialVersionUID = -4285072760648493461L;
43
44     private static final String BASEURI = "/help";
45
46     private static final boolean REDIRECT_LINKS = true;
47
48     private final Path basePath;
49
50     public HelpServlet() {
51         LOG.info("Starting HelpServlet instance {}", this.hashCode());
52         HelpInfrastructureObject.createFilesFromResources();
53         this.basePath = HelpInfrastructureObject.getHelpDirectoryBase();
54     }
55
56     @Override
57     public void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
58         resp.addHeader("Access-Control-Allow-Origin", "*");
59         resp.addHeader("Access-Control-Allow-Methods", "OPTIONS, HEAD, GET, POST, PUT, DELETE");
60         resp.addHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Content-Length");
61     }
62
63     @Override
64     public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
65         String query = req.getQueryString();
66         resp.addHeader("Access-Control-Allow-Origin", "*");
67         resp.addHeader("Access-Control-Allow-Methods", "OPTIONS, HEAD, GET, POST, PUT, DELETE");
68         resp.addHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Content-Length");
69         if (query != null && query.contains("meta")) {
70             /*
71              * LOG.debug("received post with uri="+req.getRequestURI()); String
72              * uri=req.getRequestURI().substring(BASEURI.length()); if(uri.startsWith("/"))
73              * uri=uri.substring(1);
74              */
75             File f = new File(HelpInfrastructureObject.KARAFHELPDIRECTORY, "meta.json");
76             if (f.exists()) {
77                 LOG.debug("found local meta file");
78                 try (BufferedReader rd = new BufferedReader(new FileReader(f));) {
79                     String line = rd.readLine();
80                     while (line != null) {
81                         resp.getOutputStream().println(line);
82                         line = rd.readLine();
83                     }
84                     rd.close();
85                 } catch (IOException e) {
86                     LOG.debug("Can not read meta file", e);
87                 }
88             } else {
89                 LOG.debug("start walking from path=" + basePath.toAbsolutePath().toString());
90                 HelpInfrastructureObject o = null;
91                 try {
92                     o = new HelpInfrastructureObject(this.basePath);
93                 } catch (URISyntaxException e) {
94                     LOG.debug("Can not relsolve URI. ", e);
95                 }
96                 resp.getOutputStream().println(o != null ? o.toString() : "");
97             }
98             resp.setHeader("Content-Type", "application/json");
99         } else {
100             LOG.debug("received get with uri=" + req.getRequestURI());
101             String uri = URLDecoder.decode(req.getRequestURI().substring(BASEURI.length()), "UTF-8");
102             if (uri.startsWith("/")) {
103                 uri = uri.substring(1);
104             }
105             Path p = basePath.resolve(uri);
106             File f = p.toFile();
107             if (f.isFile() && f.exists()) {
108                 LOG.debug("found file for request");
109                 if (this.isTextFile(f)) {
110                     resp.setHeader("Content-Type", "application/text");
111                     resp.setHeader("charset", "utf-8");
112                 } else if (this.isImageFile(f)) {
113                     resp.setHeader("Content-Type", "image/*");
114                 } else if (this.ispdf(f)) {
115                     resp.setHeader("Content-Type", "application/pdf");
116                 } else {
117                     LOG.debug("file is not allowed to deliver");
118                     resp.setStatus(404);
119                     return;
120                 }
121                 LOG.debug("delivering file");
122                 OutputStream out = resp.getOutputStream();
123                 String version = null;
124                 if (REDIRECT_LINKS) {
125                     version = getVersionFromRequestedUri(uri);
126                 }
127                 if (this.isTextFile(f) && REDIRECT_LINKS && version != null) {
128                     final String regex =
129                             "(!?\\[[^\\]]*?\\])\\(((?:(?!http|www\\.|\\#|\\.com|\\.net|\\.info|\\.org|\\.svg|\\.png|\\.jpg|\\.gif|\\.jpeg|\\.pdf).)*?)\\)";
130                     final Pattern pattern = Pattern.compile(regex);
131                     Matcher matcher;
132                     String line;
133                     try (BufferedReader br = new BufferedReader(new FileReader(f))) {
134                         line = br.readLine();
135                         while (line != null) {
136                             // check line for internal link
137                             matcher = pattern.matcher(line);
138                             if (matcher.find()) {
139                                 // extend link with specific version
140                                 line = line.replace(matcher.group(2),
141                                         "../" + matcher.group(2) + version + "/README.md");
142                             }
143                             out.write((line + "\n").getBytes());
144                             line = br.readLine();
145
146                         }
147                         out.flush();
148                         out.close();
149                         br.close();
150                     }
151
152                 } else {
153                     try (FileInputStream in = new FileInputStream(f)) {
154
155                         byte[] buffer = new byte[1024];
156                         int len;
157                         while ((len = in.read(buffer)) != -1) {
158                             out.write(buffer, 0, len);
159                         }
160                         in.close();
161                         out.flush();
162                         out.close();
163                     }
164                 }
165             } else {
166                 LOG.debug("found not file for request");
167                 resp.setStatus(404);
168             }
169         }
170     }
171
172     /**
173      * Extract version from URI string
174      * @param uri = "help/folder1/folder2/version/README.md"
175      * @return version as a string
176      */
177     private static String getVersionFromRequestedUri(String uri) {
178         if (uri == null) {
179             return null;
180         }
181         int lastidx = uri.lastIndexOf("/");
182         if (lastidx < 0) {
183             return null;
184         }
185         int slastidx = uri.lastIndexOf("/", lastidx - 1);
186         if (slastidx < 0) {
187             return null;
188         }
189         return uri.substring(slastidx + 1, lastidx);
190
191     }
192
193     private boolean ispdf(File f) {
194         return f != null ? this.ispdf(f.getName()) : false;
195     }
196
197     private boolean ispdf(String name) {
198         return name != null ? name.toLowerCase().endsWith("pdf") : false;
199     }
200
201     private boolean isImageFile(File f) {
202         return f != null ? this.isImageFile(f.getName()) : false;
203     }
204
205     private boolean isImageFile(String name) {
206
207         return name != null
208                 ? name.toLowerCase().endsWith("png") || name.toLowerCase().endsWith("jpg")
209                         || name.toLowerCase().endsWith("jpeg") || name.toLowerCase().endsWith("svg")
210                         || name.toLowerCase().endsWith("eps")
211                 : false;
212     }
213
214     private boolean isTextFile(File f) {
215         return f != null ? this.isTextFile(f.getName()) : false;
216
217     }
218
219     private boolean isTextFile(String name) {
220         return name != null
221                 ? name.toLowerCase().endsWith("md") || name.toLowerCase().endsWith("txt")
222                         || name.toLowerCase().endsWith("html") || name.toLowerCase().endsWith("htm")
223                         || name.toLowerCase().endsWith("js") || name.toLowerCase().endsWith("css")
224                 : false;
225     }
226
227     @Override
228     public void close() throws Exception {}
229 }