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 factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
118
119 DocumentBuilder builder = factory.newDocumentBuilder();
120 Document doc = builder.parse(config);
121 XPathFactory xPathfactory = XPathFactory.newInstance();
122 XPath xpath = xPathfactory.newXPath();
123 String url = (String) xpath.compile("/Repository/Workspace/PersistenceManager/param[@name='url']/@value")
124 .evaluate(doc, XPathConstants.STRING);
125 if (StringUtils.isNotBlank(url)) {
126 connectionString[0] = url;
127 } else {
128 connectionString[0] = (String) xpath.compile(
129 "/Repository/DataSources/DataSource/param[@name='url']/@value").evaluate(doc,
130 XPathConstants.STRING);
131 connectionString[1] = (String) xpath.compile(
132 "/Repository/DataSources/DataSource/param[@name='user']/@value").evaluate(doc,
133 XPathConstants.STRING);
134 connectionString[2] = (String) xpath.compile(
135 "/Repository/DataSources/DataSource/param[@name='password']/@value").evaluate(doc,
136 XPathConstants.STRING);
137 }
138 } catch (Exception e) {
139 log.debug("Failed to obtain DB connection info with {}", e.getMessage(), e);
140 }
141 return connectionString;
142 }
143
144 protected String getRepositoryName() {
145 String repoConfigPath = magnoliaProperties.getProperty("magnolia.repositories.config");
146 File config = new File(magnoliaProperties.getProperty("magnolia.app.rootdir") + "/" + repoConfigPath);
147 final String[] repoName = new String[1];
148 try {
149 SAXParserFactory.newInstance().newSAXParser().parse(config, new DefaultHandler() {
150 private boolean inRepo;
151
152 @Override
153 public void startElement(String uri, String localName, String qName, Attributes attributes)
154 throws SAXException {
155 super.startElement(uri, localName, qName, attributes);
156 if ("RepositoryMapping".equals(qName)) {
157 inRepo = true;
158 }
159 if (inRepo && "Map".equals(qName)) {
160 if ("config".equals(attributes.getValue("name"))) {
161 repoName[0] = attributes.getValue("repositoryName");
162 }
163 }
164 }
165
166 @Override
167 public void endElement(String uri, String localName, String qName) throws SAXException {
168 super.endElement(uri, localName, qName);
169 if ("RepositoryMapping".equals(localName)) {
170 inRepo = false;
171 }
172 }
173 });
174 return repoName[0];
175 } catch (Exception e) {
176 log.debug("Failed to obtain repository configuration info with {}", e.getMessage(), e);
177 }
178 return null;
179 }
180
181 protected String getRepositoryHome() {
182 return magnoliaProperties.getProperty("magnolia.repositories.home");
183 }
184
185 private Connection getConnection() throws SQLException, NamingException {
186 Connection connection = null;
187 String connectionString[] = getConnectionString();
188 String repoHome = getRepositoryHome();
189 String repoName = getRepositoryName();
190 connectionString[0] = StringUtils.replace(connectionString[0], "${wsp.home}", repoHome + "/" + repoName
191 + "/workspaces/default");
192 if (connectionString[0].startsWith("jdbc:")) {
193
194 connection = DriverManager.getConnection(connectionString[0], connectionString[1], connectionString[2]);
195 } else if (connectionString[0].startsWith("java:")) {
196
197 Context initialContext = new InitialContext();
198 DataSource datasource = (DataSource) initialContext.lookup(connectionString[0]);
199 if (datasource != null) {
200 connection = datasource.getConnection();
201 } else {
202 log.debug("Failed to lookup datasource.");
203 }
204 }
205 return connection;
206 }
207
208 private String getMySQLEngineInfo(Connection connection, String[] connectionString) {
209 PreparedStatement statement = null;
210 ResultSet resultSet = null;
211 try {
212 statement = connection.prepareStatement("SHOW TABLE STATUS FROM `"
213 + StringUtils.substringAfterLast(connectionString[0], "/") + "`;");
214 resultSet = statement.executeQuery();
215 if (resultSet.next()) {
216 String engine = resultSet.getString("Engine");
217 return " (" + engine + ")";
218 }
219 } catch (SQLException e) {
220
221 } finally {
222 try {
223 if (resultSet != null) {
224 resultSet.close();
225 }
226 if (statement != null) {
227 statement.close();
228 }
229 } catch (SQLException ignored) {
230 }
231 }
232 return null;
233 }
234
235 public String getDatabase() {
236 String dbInfo = null;
237 Connection connection = null;
238 try {
239 connection = getConnection();
240 if (connection != null) {
241 DatabaseMetaData meta = connection.getMetaData();
242 dbInfo = meta.getDatabaseProductName() + " " + meta.getDatabaseProductVersion();
243 if (dbInfo.toLowerCase().contains("mysql")) {
244 String engine = getMySQLEngineInfo(connection, getConnectionString());
245 if (engine != null) {
246 dbInfo += engine;
247 }
248 }
249 }
250 } catch (NamingException e) {
251 log.debug("Failed obtain DB connection through JNDI with {}", e.getMessage(), e);
252 } catch (SQLException e) {
253 log.debug("Failed to read DB and driver info from connection with {}", e.getMessage(), e);
254 } catch (IllegalArgumentException e) {
255 log.debug("Failed to understand DB connection URL with {}", e.getMessage(), e);
256 } finally {
257 if (connection != null) {
258 try {
259 connection.close();
260 } catch (SQLException e) {
261
262 }
263 }
264 }
265 return dbInfo;
266 }
267
268 public String getDatabaseDriver() {
269 String dbDriverInfo = null;
270 Connection connection = null;
271 try {
272 connection = getConnection();
273 if (connection != null) {
274 DatabaseMetaData meta = connection.getMetaData();
275 dbDriverInfo = meta.getDriverName() + " " + meta.getDriverVersion();
276 }
277 } catch (NamingException e) {
278 log.debug("Failed obtain DB connection through JNDI with {}", e.getMessage(), e);
279 } catch (SQLException e) {
280 log.debug("Failed to read DB and driver info from connection with {}", e.getMessage(), e);
281 } catch (IllegalArgumentException e) {
282 log.debug("Failed to understand DB connection URL with {}", e.getMessage(), e);
283 } finally {
284 if (connection != null) {
285 try {
286 connection.close();
287 } catch (SQLException e) {
288
289 }
290 }
291 }
292 return dbDriverInfo;
293 }
294
295 public String getDatabaseVersion() {
296 return null;
297 }
298
299 public String getJcrName() {
300 try {
301 Repository repo = JcrUtils.getRepository();
302 return repo.getDescriptor("jcr.repository.name");
303 } catch (RepositoryException e) {
304 log.debug("JCR repository information is not available", e);
305 }
306 return null;
307 }
308
309 public String getJcrVersion() {
310 try {
311 Repository repo = JcrUtils.getRepository();
312 return repo.getDescriptor("jcr.repository.version");
313 } catch (RepositoryException e) {
314 log.debug("JCR repository information is not available", e);
315 }
316 return null;
317 }
318
319 public String getMagnoliaVersion() {
320 return productDescriptorExtractor.get(ProductDescriptorExtractor.VERSION_NUMBER);
321 }
322
323 public boolean isAdmin() {
324 return serverConfiguration.isAdmin();
325 }
326
327 public String getOSName() {
328 return magnoliaProperties.getProperty("os.name");
329 }
330
331 public String getOSVersion() {
332 return magnoliaProperties.getProperty("os.version");
333 }
334
335 public String getOSArch() {
336 return magnoliaProperties.getProperty("os.arch");
337 }
338
339 public String getJavaVendor() {
340 return magnoliaProperties.getProperty("java.vendor");
341 }
342
343 public String getJavaVersion() {
344 return magnoliaProperties.getProperty("java.version");
345 }
346
347 public String getJavaRuntimeVersion() {
348 return magnoliaProperties.getProperty("java.runtime.version");
349 }
350
351 public String getApplicationServer() {
352 return contextProvider.get().getServletContext().getServerInfo();
353 }
354
355 public String getEditionName() {
356 return productDescriptorExtractor.get(ProductDescriptorExtractor.EDITION);
357 }
358 }