76ac17bb600661a819dca706d9408e2771f65a41
[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.InputStream;
26 import java.io.OutputStream;
27 import java.net.URISyntaxException;
28 import java.net.URL;
29 import java.net.URLDecoder;
30 import java.nio.file.Path;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33 import javax.servlet.ServletException;
34 import javax.servlet.http.HttpServlet;
35 import javax.servlet.http.HttpServletRequest;
36 import javax.servlet.http.HttpServletResponse;
37 import org.onap.ccsdk.features.sdnr.wt.helpserver.data.HelpInfrastructureObject;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 public class HelpServlet extends HttpServlet implements AutoCloseable {
42
43     private static Logger LOG = LoggerFactory.getLogger(HelpServlet.class);
44     private static final long serialVersionUID = -4285072760648493461L;
45
46     private static final boolean USE_FILESYSTEM = true;
47     private static final boolean USE_RESSOURCES = !USE_FILESYSTEM;
48     private static final String BASEURI = "/help";
49
50     private static final boolean REDIRECT_LINKS = true;
51
52     private final Path basePath;
53
54     public HelpServlet() {
55         LOG.info("Starting HelpServlet instance {}", this.hashCode());
56         HelpInfrastructureObject.createFilesFromResources();
57         this.basePath = HelpInfrastructureObject.getHelpDirectoryBase();
58     }
59
60     @Override
61     protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
62         resp.addHeader("Access-Control-Allow-Origin", "*");
63         resp.addHeader("Access-Control-Allow-Methods", "OPTIONS, HEAD, GET, POST, PUT, DELETE");
64         resp.addHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Content-Length");
65     }
66
67     /*
68      * (non-Javadoc)
69      *
70      * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
71      * javax.servlet.http.HttpServletResponse) Handle Get Request: if query=?meta=send json
72      * infrastructure for README.md else if file exist send file
73      */
74     @Override
75     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
76         String query = req.getQueryString();
77         resp.addHeader("Access-Control-Allow-Origin", "*");
78         resp.addHeader("Access-Control-Allow-Methods", "OPTIONS, HEAD, GET, POST, PUT, DELETE");
79         resp.addHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Content-Length");
80         if (query != null && query.contains("meta")) {
81             /*
82              * LOG.debug("received post with uri="+req.getRequestURI()); String
83              * uri=req.getRequestURI().substring(BASEURI.length()); if(uri.startsWith("/"))
84              * uri=uri.substring(1);
85              */
86             File f = new File(HelpInfrastructureObject.KARAFHELPDIRECTORY, "meta.json");
87             if (f.exists()) {
88                 LOG.debug("found local meta file");
89                 try (BufferedReader rd = new BufferedReader(new FileReader(f));) {
90                     String line = rd.readLine();
91                     while (line != null) {
92                         resp.getOutputStream().println(line);
93                         line = rd.readLine();
94                     }
95                     rd.close();
96                 } catch (IOException e) {
97                     LOG.debug("Can not read meta file", e);
98                 }
99             } else {
100                 LOG.debug("start walking from path=" + basePath.toAbsolutePath().toString());
101                 HelpInfrastructureObject o = null;
102                 if (USE_FILESYSTEM) {
103                     try {
104                         o = new HelpInfrastructureObject(this.basePath);
105                     } catch (URISyntaxException e) {
106                         LOG.debug("Can not relsolve URI. ", e);
107                     }
108                 } else if (USE_RESSOURCES) {
109                     // o=new HelpInfrastructureObject()
110                 }
111                 resp.getOutputStream().println(o != null ? o.toString() : "");
112             }
113             resp.setHeader("Content-Type", "application/json");
114        } else {
115             LOG.debug("received get with uri=" + req.getRequestURI());
116             String uri = URLDecoder.decode(req.getRequestURI().substring(BASEURI.length()), "UTF-8");
117             if (uri.startsWith("/")) {
118                 uri = uri.substring(1);
119             }
120             Path p = basePath.resolve(uri);
121             if (USE_FILESYSTEM) {
122                 File f = p.toFile();
123                 if (f.isFile() && f.exists()) {
124                     LOG.debug("found file for request");
125                     if (this.isTextFile(f)) {
126                         resp.setHeader("Content-Type", "application/text");
127                         resp.setHeader("charset", "utf-8");
128                     } else if (this.isImageFile(f)) {
129                         resp.setHeader("Content-Type", "image/*");
130                     } else if (this.ispdf(f)) {
131                         resp.setHeader("Content-Type", "application/pdf");
132                     } else {
133                         LOG.debug("file is not allowed to deliver");
134                         resp.setStatus(404);
135                         return;
136                     }
137                     LOG.debug("delivering file");
138                     OutputStream out = resp.getOutputStream();
139                     String version = null;
140                     if (REDIRECT_LINKS) {
141                         version = getVersionFromRequestedUri(uri);
142                     }
143                     if (this.isTextFile(f) && REDIRECT_LINKS && version != null) {
144                         final String regex =
145                                 "(!?\\[[^\\]]*?\\])\\(((?:(?!http|www\\.|\\#|\\.com|\\.net|\\.info|\\.org|\\.svg|\\.png|\\.jpg|\\.gif|\\.jpeg|\\.pdf).)*?)\\)";
146                         final Pattern pattern = Pattern.compile(regex);
147                         Matcher matcher;
148                         String line;
149                         try (BufferedReader br = new BufferedReader(new FileReader(f))) {
150                             line = br.readLine();
151                             while (line != null) {
152                                 // check line for internal link
153                                 matcher = pattern.matcher(line);
154                                 if (matcher.find()) {
155                                     // extend link with specific version
156                                     line = line.replace(matcher.group(2),
157                                             "../" + matcher.group(2) + version + "/README.md");
158                                 }
159                                 out.write((line + "\n").getBytes());
160                                 line = br.readLine();
161
162                             }
163                             out.flush();
164                             out.close();
165                             br.close();
166                         }
167
168                     } else {
169                         try (FileInputStream in = new FileInputStream(f)) {
170
171                             byte[] buffer = new byte[1024];
172                             int len;
173                             while ((len = in.read(buffer)) != -1) {
174                                 out.write(buffer, 0, len);
175                             }
176                             in.close();
177                             out.flush();
178                             out.close();
179                         }
180                     }
181                 } else {
182                     LOG.debug("found not file for request");
183                     resp.setStatus(404);
184                 }
185             } else if (USE_RESSOURCES) {
186                 URL resurl = this.getClass().getResource(p.toString());
187                 if (resurl != null)// resource file found
188                 {
189                     if (this.isTextFile(resurl)) {
190                         resp.setHeader("Content-Type", "application/text");
191                         resp.setHeader("charset", "utf-8");
192                     } else if (this.isImageFile(resurl)) {
193                         resp.setHeader("Content-Type", "image/*");
194                     } else if (this.ispdf(resurl)) {
195                         resp.setHeader("Content-Type", "application/pdf");
196                     } else {
197                         resp.setStatus(404);
198                         return;
199                     }
200                     try (InputStream in = this.getClass().getResourceAsStream(p.toString())) {
201                         OutputStream out = resp.getOutputStream();
202                         byte[] buffer = new byte[1024];
203                         int len;
204                         while ((len = in.read(buffer)) != -1) {
205                             out.write(buffer, 0, len);
206                         }
207                         in.close();
208                         out.flush();
209                         out.close();
210                     }
211
212                 } else // resource file not found
213                 {
214                     resp.setStatus(404);
215                 }
216             }
217         }
218     }
219
220     /*
221      *
222      * uri = "help/folder1/folder2/version/README.md"
223      */
224     private static String getVersionFromRequestedUri(String uri) {
225         if (uri == null) {
226             return null;
227         }
228         int lastidx = uri.lastIndexOf("/");
229         if (lastidx < 0) {
230             return null;
231         }
232         int slastidx = uri.lastIndexOf("/", lastidx - 1);
233         if (slastidx < 0) {
234             return null;
235         }
236         return uri.substring(slastidx + 1, lastidx);
237
238     }
239
240     private boolean isTextFile(URL url) {
241         return url != null ? this.isTextFile(url.toString()) : false;
242     }
243
244     private boolean ispdf(URL url) {
245         return url != null ? this.ispdf(url.toString()) : false;
246     }
247
248     private boolean isImageFile(URL url) {
249         return url != null ? this.isImageFile(url.toString()) : false;
250     }
251
252     private boolean ispdf(File f) {
253         return f != null ? this.ispdf(f.getName()) : false;
254     }
255
256     private boolean ispdf(String name) {
257         return name != null ? name.toLowerCase().endsWith("pdf") : false;
258     }
259
260     private boolean isImageFile(File f) {
261         return f != null ? this.isImageFile(f.getName()) : false;
262     }
263
264     private boolean isImageFile(String name) {
265
266         return name != null
267                 ? name.toLowerCase().endsWith("png") || name.toLowerCase().endsWith("jpg")
268                         || name.toLowerCase().endsWith("jpeg") || name.toLowerCase().endsWith("svg")
269                         || name.toLowerCase().endsWith("eps")
270                 : false;
271     }
272
273     private boolean isTextFile(File f) {
274         return f != null ? this.isTextFile(f.getName()) : false;
275
276     }
277
278     private boolean isTextFile(String name) {
279         return name != null
280                 ? name.toLowerCase().endsWith("md") || name.toLowerCase().endsWith("txt")
281                         || name.toLowerCase().endsWith("html") || name.toLowerCase().endsWith("htm")
282                         || name.toLowerCase().endsWith("js") || name.toLowerCase().endsWith("css")
283                 : false;
284     }
285
286     @Override
287     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
288
289     @Override
290     public void close() throws Exception {}
291 }