1
2
3
4
5
6
7
8
9
10
11 package psiprobe.controllers.deploy;
12
13 import jakarta.servlet.http.HttpServletRequest;
14 import jakarta.servlet.http.HttpServletResponse;
15
16 import java.io.File;
17 import java.io.IOException;
18 import java.nio.charset.StandardCharsets;
19 import java.nio.file.Files;
20 import java.nio.file.Path;
21 import java.util.List;
22
23 import org.apache.catalina.Context;
24 import org.apache.commons.io.FileUtils;
25 import org.apache.commons.io.FilenameUtils;
26 import org.apache.tomcat.util.http.fileupload.FileItem;
27 import org.apache.tomcat.util.http.fileupload.FileItemFactory;
28 import org.apache.tomcat.util.http.fileupload.FileUpload;
29 import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
30 import org.apache.tomcat.util.http.fileupload.servlet.ServletRequestContext;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.springframework.beans.factory.annotation.Value;
34 import org.springframework.security.core.Authentication;
35 import org.springframework.security.core.context.SecurityContextHolder;
36 import org.springframework.stereotype.Controller;
37 import org.springframework.web.bind.annotation.RequestMapping;
38 import org.springframework.web.servlet.ModelAndView;
39 import org.springframework.web.servlet.view.InternalResourceView;
40
41 import psiprobe.controllers.AbstractTomcatContainerController;
42 import psiprobe.controllers.jsp.DisplayJspController;
43 import psiprobe.model.jsp.Summary;
44
45
46
47
48 @Controller
49 public class UploadWarController extends AbstractTomcatContainerController {
50
51
52 private static final Logger logger = LoggerFactory.getLogger(UploadWarController.class);
53 private static final int MAXSECONDS_WAITFOR_CONTEXT = 10;
54
55 @RequestMapping(path = "/adm/war.htm")
56 @Override
57 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
58 throws Exception {
59 return super.handleRequest(request, response);
60 }
61
62 @Override
63 protected ModelAndView handleRequestInternal(HttpServletRequest request,
64 HttpServletResponse response) throws Exception {
65
66
67 if (!this.isMultipartContent(request)) {
68 return new ModelAndView(new InternalResourceView(getViewName()));
69 }
70
71 File tmpWar = null;
72 String contextName = null;
73 boolean update = false;
74 boolean compile = false;
75 boolean discard = false;
76
77
78 FileItemFactory factory =
79 new DiskFileItemFactory(1048000, Path.of(System.getProperty("java.io.tmpdir")).toFile());
80 FileUpload upload = new FileUpload();
81 upload.setFileItemFactory(factory);
82 upload.setSizeMax(-1);
83 upload.setHeaderEncoding(StandardCharsets.UTF_8.name());
84 try {
85 List<FileItem> fileItems = upload.parseRequest(new ServletRequestContext(request));
86 for (FileItem fi : fileItems) {
87 if (!fi.isFormField()) {
88 if (fi.getName() != null && fi.getName().length() > 0) {
89 tmpWar =
90 Path.of(System.getProperty("java.io.tmpdir"), FilenameUtils.getName(fi.getName()))
91 .toFile();
92 fi.write(tmpWar);
93 }
94 } else if ("context".equals(fi.getFieldName())) {
95 contextName = fi.getString();
96 } else if ("update".equals(fi.getFieldName()) && "yes".equals(fi.getString())) {
97 update = true;
98 } else if ("compile".equals(fi.getFieldName()) && "yes".equals(fi.getString())) {
99 compile = true;
100 } else if ("discard".equals(fi.getFieldName()) && "yes".equals(fi.getString())) {
101 discard = true;
102 }
103 }
104 } catch (Exception e) {
105 logger.error("Could not process file upload", e);
106 request.setAttribute("errorMessage", getMessageSourceAccessor()
107 .getMessage("probe.src.deploy.war.uploadfailure", new Object[] {e.getMessage()}));
108 if (tmpWar != null) {
109 Files.delete(tmpWar.toPath());
110 tmpWar = null;
111 }
112 }
113
114 String errMsg = null;
115
116 if (tmpWar == null) {
117 return new ModelAndView(new InternalResourceView(getViewName()));
118 }
119
120 try {
121 if (tmpWar.getName().endsWith(".war")) {
122
123 if (contextName == null || contextName.length() == 0) {
124 String warFileName = tmpWar.getName().replaceAll("\\.war$", "");
125 contextName = "/" + warFileName;
126 }
127
128 contextName = getContainerWrapper().getTomcatContainer().formatContextName(contextName);
129
130
131
132
133
134 String visibleContextName = contextName.isEmpty() ? "/" : contextName;
135 request.setAttribute("contextName", visibleContextName);
136
137 if (update && getContainerWrapper().getTomcatContainer().findContext(contextName) != null) {
138 logger.debug("updating {}: removing the old copy", contextName);
139 getContainerWrapper().getTomcatContainer().remove(contextName);
140 }
141
142 if (getContainerWrapper().getTomcatContainer().findContext(contextName) == null) {
143
144 String destWarFilename =
145 getContainerWrapper().getTomcatContainer().formatContextFilename(contextName);
146 File destWar = Path.of(getContainerWrapper().getTomcatContainer().getAppBase().getPath(),
147 destWarFilename + ".war").toFile();
148
149 FileUtils.moveFile(tmpWar, destWar);
150
151
152 getContainerWrapper().getTomcatContainer().installWar(contextName);
153
154 File destContext =
155 Path.of(getContainerWrapper().getTomcatContainer().getAppBase().getPath(),
156 destWarFilename).toFile();
157
158 FileUtils.waitFor(destContext, MAXSECONDS_WAITFOR_CONTEXT);
159
160 Context ctx = getContainerWrapper().getTomcatContainer().findContext(contextName);
161 if (ctx == null) {
162 errMsg = getMessageSourceAccessor().getMessage("probe.src.deploy.war.notinstalled",
163 new Object[] {visibleContextName});
164 } else {
165 request.setAttribute("success", Boolean.TRUE);
166
167 Authentication auth = SecurityContextHolder.getContext().getAuthentication();
168
169 String name = auth.getName();
170 logger.info(getMessageSourceAccessor().getMessage("probe.src.log.deploywar"), name,
171 contextName);
172 if (discard) {
173 getContainerWrapper().getTomcatContainer().discardWorkDir(ctx);
174 logger.info(getMessageSourceAccessor().getMessage("probe.src.log.discardwork"), name,
175 contextName);
176 }
177 if (compile) {
178 Summary summary = new Summary();
179 summary.setName(ctx.getName());
180 getContainerWrapper().getTomcatContainer().listContextJsps(ctx, summary, true);
181 request.getSession(false).setAttribute(DisplayJspController.SUMMARY_ATTRIBUTE,
182 summary);
183 request.setAttribute("compileSuccess", Boolean.TRUE);
184 }
185 }
186 } else {
187 errMsg = getMessageSourceAccessor().getMessage("probe.src.deploy.war.alreadyExists",
188 new Object[] {visibleContextName});
189 }
190 } else {
191 errMsg = getMessageSourceAccessor().getMessage("probe.src.deploy.war.notWar.failure");
192 }
193 } catch (IOException e) {
194 errMsg = getMessageSourceAccessor().getMessage("probe.src.deploy.war.failure",
195 new Object[] {e.getMessage()});
196 logger.error("Tomcat threw an exception when trying to deploy", e);
197 } finally {
198 if (errMsg != null) {
199 request.setAttribute("errorMessage", errMsg);
200 }
201
202 if (tmpWar.exists()) {
203 Files.delete(tmpWar.toPath());
204 }
205 }
206 return new ModelAndView(new InternalResourceView(getViewName()));
207 }
208
209 @Value("/adm/deploy.htm")
210 @Override
211 public void setViewName(String viewName) {
212 super.setViewName(viewName);
213 }
214
215 }