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