1
2
3
4
5
6
7
8
9
10
11 package psiprobe.controllers.sql;
12
13 import jakarta.servlet.http.HttpServletRequest;
14 import jakarta.servlet.http.HttpServletResponse;
15 import jakarta.servlet.http.HttpSession;
16
17 import java.sql.Connection;
18 import java.sql.PreparedStatement;
19 import java.sql.ResultSet;
20 import java.sql.ResultSetMetaData;
21 import java.sql.SQLException;
22 import java.util.ArrayList;
23 import java.util.LinkedHashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 import javax.naming.NamingException;
28 import javax.sql.DataSource;
29
30 import org.apache.catalina.Context;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.springframework.beans.factory.annotation.Value;
34 import org.springframework.stereotype.Controller;
35 import org.springframework.web.bind.ServletRequestUtils;
36 import org.springframework.web.bind.annotation.RequestMapping;
37 import org.springframework.web.servlet.ModelAndView;
38 import org.springframework.web.util.HtmlUtils;
39
40 import psiprobe.controllers.AbstractContextHandlerController;
41 import psiprobe.model.sql.DataSourceTestInfo;
42
43
44
45
46
47 @Controller
48 public class ExecuteSqlController extends AbstractContextHandlerController {
49
50
51 private static final Logger logger = LoggerFactory.getLogger(ExecuteSqlController.class);
52
53 @RequestMapping(path = "/sql/recordset.ajax")
54 @Override
55 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
56 throws Exception {
57 return super.handleRequest(request, response);
58 }
59
60 @Override
61 protected ModelAndView handleContext(String contextName, Context context,
62 HttpServletRequest request, HttpServletResponse response) throws Exception {
63
64 String resourceName = ServletRequestUtils.getStringParameter(request, "resource");
65 String sql = ServletRequestUtils.getStringParameter(request, "sql");
66
67 if (sql == null || sql.isEmpty() || sql.trim().isEmpty()) {
68 request.setAttribute("errorMessage",
69 getMessageSourceAccessor().getMessage("probe.src.dataSourceTest.sql.required"));
70
71 return new ModelAndView(getViewName());
72 }
73
74 int maxRows = ServletRequestUtils.getIntParameter(request, "maxRows", 0);
75 int rowsPerPage = ServletRequestUtils.getIntParameter(request, "rowsPerPage", 0);
76 int historySize = ServletRequestUtils.getIntParameter(request, "historySize", 0);
77
78
79
80 HttpSession sess = request.getSession(false);
81 DataSourceTestInfo sessData =
82 (DataSourceTestInfo) sess.getAttribute(DataSourceTestInfo.DS_TEST_SESS_ATTR);
83
84 synchronized (sess) {
85 if (sessData == null) {
86 sessData = new DataSourceTestInfo();
87 sess.setAttribute(DataSourceTestInfo.DS_TEST_SESS_ATTR, sessData);
88 }
89
90 sessData.setMaxRows(maxRows);
91 sessData.setRowsPerPage(rowsPerPage);
92 sessData.setHistorySize(historySize);
93 sessData.addQueryToHistory(sql);
94 }
95
96 DataSource dataSource = null;
97
98 try {
99 dataSource = getContainerWrapper().getResourceResolver().lookupDataSource(context,
100 resourceName, getContainerWrapper());
101 } catch (NamingException e) {
102 request.setAttribute("errorMessage", getMessageSourceAccessor().getMessage(
103 "probe.src.dataSourceTest.resource.lookup.failure", new Object[] {resourceName}));
104 logger.trace("", e);
105 }
106
107 if (dataSource == null) {
108 request.setAttribute("errorMessage", getMessageSourceAccessor().getMessage(
109 "probe.src.dataSourceTest.resource.lookup.failure", new Object[] {resourceName}));
110 } else {
111 List<Map<String, String>> results = null;
112 int rowsAffected = 0;
113
114 try {
115
116 try (Connection conn = dataSource.getConnection()) {
117 conn.setAutoCommit(true);
118
119 try (PreparedStatement stmt = conn.prepareStatement(sql)) {
120 boolean hasResultSet = stmt.execute();
121
122 if (!hasResultSet) {
123 rowsAffected = stmt.getUpdateCount();
124 } else {
125 results = new ArrayList<>();
126
127 try (ResultSet rs = stmt.getResultSet()) {
128 ResultSetMetaData metaData = rs.getMetaData();
129
130 while (rs.next() && (maxRows < 0 || results.size() < maxRows)) {
131 Map<String, String> record = new LinkedHashMap<>();
132
133 for (int i = 1; i <= metaData.getColumnCount(); i++) {
134 String value = rs.getString(i);
135
136 if (rs.wasNull()) {
137 value = getMessageSourceAccessor()
138 .getMessage("probe.src.dataSourceTest.sql.null");
139 } else {
140 value = HtmlUtils.htmlEscape(value);
141 }
142
143
144 StringBuilder key = new StringBuilder(metaData.getColumnLabel(i));
145 while (record.containsKey(key.toString())) {
146 key.append(" ");
147 }
148 record.put(HtmlUtils.htmlEscape(key.toString()), value);
149 }
150
151 results.add(record);
152 }
153 }
154
155 rowsAffected = results.size();
156 }
157 }
158 }
159
160
161
162
163 synchronized (sess) {
164 sessData.setResults(results);
165 }
166
167 ModelAndView mv = new ModelAndView(getViewName(), "results", results);
168 mv.addObject("rowsAffected", String.valueOf(rowsAffected));
169 mv.addObject("rowsPerPage", String.valueOf(rowsPerPage));
170
171 return mv;
172 } catch (SQLException e) {
173 String message = getMessageSourceAccessor()
174 .getMessage("probe.src.dataSourceTest.sql.failure", new Object[] {e.getMessage()});
175 logger.error(message, e);
176 request.setAttribute("errorMessage", message);
177 }
178 }
179
180 return new ModelAndView(getViewName());
181 }
182
183 @Override
184 protected boolean isContextOptional() {
185 return true;
186 }
187
188 @Value("ajax/sql/recordset")
189 @Override
190 public void setViewName(String viewName) {
191 super.setViewName(viewName);
192 }
193
194 }