1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.about.app;
35
36 import info.magnolia.cms.beans.config.ServerConfiguration;
37 import info.magnolia.cms.pddescriptor.ProductDescriptorExtractor;
38 import info.magnolia.context.WebContext;
39 import info.magnolia.init.MagnoliaConfigurationProperties;
40
41 import java.io.File;
42 import java.sql.Connection;
43 import java.sql.DatabaseMetaData;
44 import java.sql.DriverManager;
45 import java.sql.PreparedStatement;
46 import java.sql.ResultSet;
47 import java.sql.SQLException;
48
49 import javax.inject.Inject;
50 import javax.inject.Provider;
51 import javax.jcr.Repository;
52 import javax.jcr.RepositoryException;
53 import javax.naming.Context;
54 import javax.naming.InitialContext;
55 import javax.naming.NamingException;
56 import javax.sql.DataSource;
57 import javax.xml.parsers.DocumentBuilder;
58 import javax.xml.parsers.DocumentBuilderFactory;
59 import javax.xml.parsers.SAXParserFactory;
60 import javax.xml.xpath.XPath;
61 import javax.xml.xpath.XPathConstants;
62 import javax.xml.xpath.XPathFactory;
63
64 import org.apache.commons.lang3.StringUtils;
65 import org.apache.jackrabbit.commons.JcrUtils;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
68 import org.w3c.dom.Document;
69 import org.xml.sax.Attributes;
70 import org.xml.sax.SAXException;
71 import org.xml.sax.helpers.DefaultHandler;
72
73
74
75
76 public class InstanceConfigurationProvider {
77
78 private static final Logger log = LoggerFactory.getLogger(InstanceConfigurationProvider.class);
79
80 private final Provider<WebContext> contextProvider;
81 private final ProductDescriptorExtractor productDescriptorExtractor;
82 private final MagnoliaConfigurationProperties magnoliaProperties;
83 private final ServerConfiguration serverConfiguration;
84
85 @Inject
86 public InstanceConfigurationProvider(final Provider<WebContext> contextProvider,
87 final ServerConfiguration serverConfiguration, final MagnoliaConfigurationProperties magnoliaProperties,
88 final ProductDescriptorExtractor productDescriptorExtractor) {
89 this.contextProvider = contextProvider;
90 this.productDescriptorExtractor = productDescriptorExtractor;
91 this.serverConfiguration = serverConfiguration;
92 this.magnoliaProperties = magnoliaProperties;
93 }
94
95 protected String[] getConnectionString() {
96 File config = null;
97
98
99
100
101 String configuredPath = magnoliaProperties.getProperty("magnolia.repositories.jackrabbit.config");
102 if (configuredPath != null) {
103 if (configuredPath.startsWith("WEB-INF")) {
104 config = new File(magnoliaProperties.getProperty("magnolia.app.rootdir") + "/" + configuredPath);
105 } else {
106 config = new File(configuredPath);
107 }
108 }
109
110
111
112
113
114 final String[] connectionString = new String[] { "", "", "" };
115 try {
116 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
117 DocumentBuilder builder = factory.newDocumentBuilder();
118 Document doc = builder.parse(config);
119 XPathFactory xPathfactory = XPathFactory.newInstance();
120 XPath xpath = xPathfactory.newXPath();
121 String url = (String) xpath.compile("/Repository/Workspace/PersistenceManager/param[@name='url']/@value")
122 .evaluate(doc, XPathConstants.STRING);
123 if (StringUtils.isNotBlank(url)) {
124 connectionString[0] = url;
125 } else {
126 connectionString[0] = (String) xpath.compile(
127 "/Repository/DataSources/DataSource/param[@name='url']/@value").evaluate(doc,
128 XPathConstants.STRING);
129 connectionString[1] = (String) xpath.compile(
130 "/Repository/DataSources/DataSource/param[@name='user']/@value").evaluate(doc,
131 XPathConstants.STRING);
132 connectionString[2] = (String) xpath.compile(
133 "/Repository/DataSources/DataSource/param[@name='password']/@value").evaluate(doc,
134 XPathConstants.STRING);
135 }
136 } catch (Exception e) {
137 log.debug("Failed to obtain DB connection info with {}", e.getMessage(), e);
138 }
139 return connectionString;
140 }
141
142 protected String getRepositoryName() {
143 String repoConfigPath = magnoliaProperties.getProperty("magnolia.repositories.config");
144 File config = new File(magnoliaProperties.getProperty("magnolia.app.rootdir") + "/" + repoConfigPath);
145 final String[] repoName = new String[1];
146 try {
147 SAXParserFactory.newInstance().newSAXParser().parse(config, new DefaultHandler() {
148 private boolean inRepo;
149
150 @Override
151 public void startElement(String uri, String localName, String qName, Attributes attributes)
152 throws SAXException {
153 super.startElement(uri, localName, qName, attributes);
154 if ("RepositoryMapping".equals(qName)) {
155 inRepo = true;
156 }
157 if (inRepo && "Map".equals(qName)) {
158 if ("config".equals(attributes.getValue("name"))) {
159 repoName[0] = attributes.getValue("repositoryName");
160 }
161 }
162 }
163
164 @Override
165 public void endElement(String uri, String localName, String qName) throws SAXException {
166 super.endElement(uri, localName, qName);
167 if ("RepositoryMapping".equals(localName)) {
168 inRepo = false;
169 }
170 }
171 });
172 return repoName[0];
173 } catch (Exception e) {
174 log.debug("Failed to obtain repository configuration info with {}", e.getMessage(), e);
175 }
176 return null;
177 }
178
179 protected String getRepositoryHome() {
180 return magnoliaProperties.getProperty("magnolia.repositories.home");
181 }
182
183 private Connection getConnection() throws SQLException, NamingException {
184 Connection connection = null;
185 String connectionString[] = getConnectionString();
186 String repoHome = getRepositoryHome();
187 String repoName = getRepositoryName();
188 connectionString[0] = StringUtils.replace(connectionString[0], "${wsp.home}", repoHome + "/" + repoName
189 + "/workspaces/default");
190 if (connectionString[0].startsWith("jdbc:")) {
191
192 connection = DriverManager.getConnection(connectionString[0], connectionString[1], connectionString[2]);
193 } else if (connectionString[0].startsWith("java:")) {
194
195 Context initialContext = new InitialContext();
196 DataSource datasource = (DataSource) initialContext.lookup(connectionString[0]);
197 if (datasource != null) {
198 connection = datasource.getConnection();
199 } else {
200 log.debug("Failed to lookup datasource.");
201 }
202 }
203 return connection;
204 }
205
206 private String getMySQLEngineInfo(Connection connection, String[] connectionString) {
207 PreparedStatement statement = null;
208 ResultSet resultSet = null;
209 try {
210 statement = connection.prepareStatement("SHOW TABLE STATUS FROM `"
211 + StringUtils.substringAfterLast(connectionString[0], "/") + "`;");
212 resultSet = statement.executeQuery();
213 if (resultSet.next()) {
214 String engine = resultSet.getString("Engine");
215 return " (" + engine + ")";
216 }
217 } catch (SQLException e) {
218
219 } finally {
220 try {
221 if (resultSet != null) {
222 resultSet.close();
223 }
224 if (statement != null) {
225 statement.close();
226 }
227 } catch (SQLException ignored) {
228 }
229 }
230 return null;
231 }
232
233 public String getDatabase() {
234 String dbInfo = null;
235 Connection connection = null;
236 try {
237 connection = getConnection();
238 if (connection != null) {
239 DatabaseMetaData meta = connection.getMetaData();
240 dbInfo = meta.getDatabaseProductName() + " " + meta.getDatabaseProductVersion();
241 if (dbInfo.toLowerCase().contains("mysql")) {
242 String engine = getMySQLEngineInfo(connection, getConnectionString());
243 if (engine != null) {
244 dbInfo += engine;
245 }
246 }
247 }
248 } catch (NamingException e) {
249 log.debug("Failed obtain DB connection through JNDI with {}", e.getMessage(), e);
250 } catch (SQLException e) {
251 log.debug("Failed to read DB and driver info from connection with {}", e.getMessage(), e);
252 } catch (IllegalArgumentException e) {
253 log.debug("Failed to understand DB connection URL with {}", e.getMessage(), e);
254 } finally {
255 if (connection != null) {
256 try {
257 connection.close();
258 } catch (SQLException e) {
259
260 }
261 }
262 }
263 return dbInfo;
264 }
265
266 public String getDatabaseDriver() {
267 String dbDriverInfo = null;
268 Connection connection = null;
269 try {
270 connection = getConnection();
271 if (connection != null) {
272 DatabaseMetaData meta = connection.getMetaData();
273 dbDriverInfo = meta.getDriverName() + " " + meta.getDriverVersion();
274 }
275 } catch (NamingException e) {
276 log.debug("Failed obtain DB connection through JNDI with {}", e.getMessage(), e);
277 } catch (SQLException e) {
278 log.debug("Failed to read DB and driver info from connection with {}", e.getMessage(), e);
279 } catch (IllegalArgumentException e) {
280 log.debug("Failed to understand DB connection URL with {}", e.getMessage(), e);
281 } finally {
282 if (connection != null) {
283 try {
284 connection.close();
285 } catch (SQLException e) {
286
287 }
288 }
289 }
290 return dbDriverInfo;
291 }
292
293 public String getDatabaseVersion() {
294 return null;
295 }
296
297 public String getJcrName() {
298 try {
299 Repository repo = JcrUtils.getRepository();
300 return repo.getDescriptor("jcr.repository.name");
301 } catch (RepositoryException e) {
302 log.debug("JCR repository information is not available", e);
303 }
304 return null;
305 }
306
307 public String getJcrVersion() {
308 try {
309 Repository repo = JcrUtils.getRepository();
310 return repo.getDescriptor("jcr.repository.version");
311 } catch (RepositoryException e) {
312 log.debug("JCR repository information is not available", e);
313 }
314 return null;
315 }
316
317 public String getMagnoliaVersion() {
318 return productDescriptorExtractor.get(ProductDescriptorExtractor.VERSION_NUMBER);
319 }
320
321 public boolean isAdmin() {
322 return serverConfiguration.isAdmin();
323 }
324
325 public String getOSName() {
326 return magnoliaProperties.getProperty("os.name");
327 }
328
329 public String getOSVersion() {
330 return magnoliaProperties.getProperty("os.version");
331 }
332
333 public String getOSArch() {
334 return magnoliaProperties.getProperty("os.arch");
335 }
336
337 public String getJavaVendor() {
338 return magnoliaProperties.getProperty("java.vendor");
339 }
340
341 public String getJavaVersion() {
342 return magnoliaProperties.getProperty("java.version");
343 }
344
345 public String getJavaRuntimeVersion() {
346 return magnoliaProperties.getProperty("java.runtime.version");
347 }
348
349 public String getApplicationServer() {
350 return contextProvider.get().getServletContext().getServerInfo();
351 }
352 }