From 6078db0d5957db2e41d4619b077771815d336078 Mon Sep 17 00:00:00 2001 From: Sorin Date: Mon, 7 Aug 2023 14:48:30 +0300 Subject: [PATCH 01/72] Create the pom structure of the application #1 Created the pom structure of the project --- .gitignore | 43 ++++++++++++++++++ README.md | 12 ++++- SECURITY.md | 3 ++ application-admintools-api/pom.xml | 42 ++++++++++++++++++ application-admintools-default/pom.xml | 54 +++++++++++++++++++++++ application-admintools-ui/pom.xml | 60 +++++++++++++++++++++++++ pom.xml | 61 ++++++++++++++++++++++++++ 7 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 SECURITY.md create mode 100644 application-admintools-api/pom.xml create mode 100644 application-admintools-default/pom.xml create mode 100644 application-admintools-ui/pom.xml create mode 100644 pom.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b3e5c3ca --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# Build +target +target-eclipse + +# IDEA +*.iml +*.ipr +*.iws +.idea +atlassian-ide-plugin.xml + +# Eclipse +.classpath +.project +.settings +.checkstyle +.fbprefs +bin +# Automatically generated by WTP +/*/src/main/java/META-INF/ +/*/*/src/main/java/META-INF/ +/*/*/*/src/main/java/META-INF/ +/*/*/*/*/src/main/java/META-INF/ +/*/*/*/*/*/src/main/java/META-INF/ +/*/*/*/*/*/*/src/main/java/META-INF/ +/*/src/META-INF/ +/*/*/src/META-INF/ +/*/*/*/src/META-INF/ +/*/*/*/*/src/META-INF/ +/*/*/*/*/*/src/META-INF/ +/*/*/*/*/*/*/src/META-INF/ +#PyDev +.pydevproject + +# NetBeans +nbproject + +# Other +*.log.* +*.log +.sonar-ide.properties +.clover +*~ \ No newline at end of file diff --git a/README.md b/README.md index 7ae506a2..8adfa772 100644 --- a/README.md +++ b/README.md @@ -1 +1,11 @@ -# application-admintools \ No newline at end of file +# Admin Tools Application (Pro) + +Integration of Admin Tools Online in XWiki. View, edit and collaborate real-time on office attachments, via WOPI protocol. + +* Project Lead: [Sorin Chiuchiu](https://github.com/ChiuchiuSorin) +* Communication: [Mailing List](http://dev.xwiki.org/xwiki/bin/view/Community/MailingLists>), [IRC]( http://dev.xwiki.org/xwiki/bin/view/Community/IRC) +* [Development Practices](http://dev.xwiki.org) +* Minimal XWiki version supported: XWiki 11.10 +* License: LGPL 2.1+ +* Translations: N/A +* Sonar Dashboard: N/A diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..483c224d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,3 @@ +# Security Policy + +The security policy that applies to all the [XWiki Pro extensions](https://store.xwiki.com) is detailed on the following document: https://store.xwiki.com/xwiki/bin/view/Store/SecurityPolicy/ . diff --git a/application-admintools-api/pom.xml b/application-admintools-api/pom.xml new file mode 100644 index 00000000..4d3ee60e --- /dev/null +++ b/application-admintools-api/pom.xml @@ -0,0 +1,42 @@ + + + + + + application-admintools + com.xwiki.admintools + 1.0-SNAPSHOT + + 4.0.0 + + application-admintools-api + jar + Admin Tools(Pro) - API + Provides the Java APIs needed by the Admin tools Application. + + 11 + 11 + UTF-8 + + + \ No newline at end of file diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml new file mode 100644 index 00000000..760dc4f8 --- /dev/null +++ b/application-admintools-default/pom.xml @@ -0,0 +1,54 @@ + + + + + + application-admintools + com.xwiki.admintools + 1.0-SNAPSHOT + + 4.0.0 + + application-admintools-default + jar + Admin Tools Application (Pro) - Default + Admin Tools Application (Pro) - Default + + + 11 + 11 + UTF-8 + + + + com.xwiki.admintools + application-admintools-api + ${project.version} + + + org.xwiki.platform + xwiki-platform-oldcore + ${platform.version} + + + \ No newline at end of file diff --git a/application-admintools-ui/pom.xml b/application-admintools-ui/pom.xml new file mode 100644 index 00000000..a536fc81 --- /dev/null +++ b/application-admintools-ui/pom.xml @@ -0,0 +1,60 @@ + + + + + + + application-admintools + com.xwiki.admintools + 1.0-SNAPSHOT + + 4.0.0 + + application-admintools-ui + xar + Admin Tools Application (Pro) + Contains administration tools for managing a running XWiki instance + + + + Admin tools Application (Pro) + application + + true + 11 + 11 + UTF-8 + + + + com.xwiki.admintools + application-admintools-default + ${project.version} + + + com.xwiki.licensing + application-licensing-licensor-api + ${licensing.version} + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..934fb6ac --- /dev/null +++ b/pom.xml @@ -0,0 +1,61 @@ + + + + + + 4.0.0 + + com.xwiki.parent + xwikisas-parent-platform + 13.10-3 + + com.xwiki.admintools + application-admintools + pom + 1.0-SNAPSHOT + Admin Tools Application (Pro) Parent POM + Contains administration tools for managing a running XWiki instance + + + application-admintools-api + application-admintools-default + application-admintools-ui + + + GitHub + https://github.com/xwikisas/application-admintools/issues + + + scm:git:git://github.com/xwikisas/application-admintools.git + scm:git:git@github.com:xwikisas/application-admintools.git + https://github.com/xwikisas/application-admintools/tree/master + HEAD + + + 1.24.1 + 11 + 11 + UTF-8 + + + \ No newline at end of file From 6939275c4cb5b03bdc66eb26a55c0e78523ace8a Mon Sep 17 00:00:00 2001 From: Sorin Date: Wed, 9 Aug 2023 11:41:36 +0300 Subject: [PATCH 02/72] Create the pom structure of the application #1 --- README.md | 4 +- application-admintools-api/pom.xml | 29 ++++------- application-admintools-default/pom.xml | 69 +++++++++++++++----------- application-admintools-ui/pom.xml | 60 ++++++++++------------ pom.xml | 66 +++++++++++------------- 5 files changed, 107 insertions(+), 121 deletions(-) diff --git a/README.md b/README.md index 8adfa772..11e2911f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # Admin Tools Application (Pro) -Integration of Admin Tools Online in XWiki. View, edit and collaborate real-time on office attachments, via WOPI protocol. +Integration of administration tools for managing a running XWiki instance. * Project Lead: [Sorin Chiuchiu](https://github.com/ChiuchiuSorin) * Communication: [Mailing List](http://dev.xwiki.org/xwiki/bin/view/Community/MailingLists>), [IRC]( http://dev.xwiki.org/xwiki/bin/view/Community/IRC) * [Development Practices](http://dev.xwiki.org) -* Minimal XWiki version supported: XWiki 11.10 +* Minimal XWiki version supported: XWiki 13.10 * License: LGPL 2.1+ * Translations: N/A * Sonar Dashboard: N/A diff --git a/application-admintools-api/pom.xml b/application-admintools-api/pom.xml index 4d3ee60e..366b0db2 100644 --- a/application-admintools-api/pom.xml +++ b/application-admintools-api/pom.xml @@ -19,24 +19,17 @@ * 02110-1301 USA, or see the FSF site: http://www.fsf.org. --> - - - application-admintools - com.xwiki.admintools - 1.0-SNAPSHOT - - 4.0.0 + + + com.xwiki.admintools + application-admintools + 1.0.0-SNAPSHOT + + 4.0.0 - application-admintools-api - jar - Admin Tools(Pro) - API - Provides the Java APIs needed by the Admin tools Application. - - 11 - 11 - UTF-8 - + application-admintools-api + jar + Admin Tools (Pro) - API + Provides the Java APIs needed by the Admin tools Application. \ No newline at end of file diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index 760dc4f8..f5d01976 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -19,36 +19,45 @@ * 02110-1301 USA, or see the FSF site: http://www.fsf.org. --> - - - application-admintools - com.xwiki.admintools - 1.0-SNAPSHOT - - 4.0.0 + + + com.xwiki.admintools + application-admintools + 1.0.0-SNAPSHOT + + 4.0.0 - application-admintools-default - jar - Admin Tools Application (Pro) - Default - Admin Tools Application (Pro) - Default + application-admintools-default + jar + Admin Tools Application (Pro) - Default + Admin Tools Application (Pro) - Default + + + + com.xwiki.admintools + application-admintools-api + ${project.version} + + + org.xwiki.platform + xwiki-platform-oldcore + ${platform.version} + + + org.xwiki.commons + xwiki-commons-tool-test-component + ${commons.version} + test + + + org.xwiki.rendering + xwiki-rendering-test + ${rendering.version} + test + + + + true + - - 11 - 11 - UTF-8 - - - - com.xwiki.admintools - application-admintools-api - ${project.version} - - - org.xwiki.platform - xwiki-platform-oldcore - ${platform.version} - - \ No newline at end of file diff --git a/application-admintools-ui/pom.xml b/application-admintools-ui/pom.xml index a536fc81..2e116f8c 100644 --- a/application-admintools-ui/pom.xml +++ b/application-admintools-ui/pom.xml @@ -20,41 +20,31 @@ * 02110-1301 USA, or see the FSF site: http://www.fsf.org. --> - - - application-admintools - com.xwiki.admintools - 1.0-SNAPSHOT - - 4.0.0 + + + com.xwiki.admintools + application-admintools + 1.0.0-SNAPSHOT + + 4.0.0 - application-admintools-ui - xar - Admin Tools Application (Pro) - Contains administration tools for managing a running XWiki instance + application-admintools-ui + xar + Admin Tools Application (Pro) + Contains administration tools for managing a running XWiki instance - - - Admin tools Application (Pro) - application - - true - 11 - 11 - UTF-8 - - - - com.xwiki.admintools - application-admintools-default - ${project.version} - - - com.xwiki.licensing - application-licensing-licensor-api - ${licensing.version} - - + + + Admin tools Application (Pro) + application + + true + + + + com.xwiki.admintools + application-admintools-default + ${project.version} + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 934fb6ac..5e451e34 100644 --- a/pom.xml +++ b/pom.xml @@ -20,42 +20,36 @@ * 02110-1301 USA, or see the FSF site: http://www.fsf.org. --> - - 4.0.0 - - com.xwiki.parent - xwikisas-parent-platform - 13.10-3 - - com.xwiki.admintools - application-admintools - pom - 1.0-SNAPSHOT - Admin Tools Application (Pro) Parent POM - Contains administration tools for managing a running XWiki instance + + 4.0.0 + + com.xwiki.parent + xwikisas-parent-platform + 13.10-3 + + com.xwiki.admintools + application-admintools + pom + 1.0.0-SNAPSHOT + Admin Tools Application (Pro) Parent POM + The Admin Tools Pro application gives you full control and visibility over your XWiki instance. + Use it to manage your XWiki installation. Easily generate configuration reports. Perform sanity checks and show + logs history. - - application-admintools-api - application-admintools-default - application-admintools-ui - - - GitHub - https://github.com/xwikisas/application-admintools/issues - - - scm:git:git://github.com/xwikisas/application-admintools.git - scm:git:git@github.com:xwikisas/application-admintools.git - https://github.com/xwikisas/application-admintools/tree/master - HEAD - - - 1.24.1 - 11 - 11 - UTF-8 - + + application-admintools-api + application-admintools-default + application-admintools-ui + + + GitHub + https://github.com/xwikisas/application-admintools/issues + + + scm:git:git://github.com/xwikisas/application-admintools.git + scm:git:git@github.com:xwikisas/application-admintools.git + https://github.com/xwikisas/application-admintools/tree/master + HEAD + \ No newline at end of file From 04a62b81a9e919cecae71f703e997450a5e47570 Mon Sep 17 00:00:00 2001 From: Sorin Date: Fri, 11 Aug 2023 10:19:38 +0300 Subject: [PATCH 03/72] Create the pom structure of the application #1 --- application-admintools-api/pom.xml | 4 +--- application-admintools-default/pom.xml | 24 +----------------------- application-admintools-ui/pom.xml | 6 +++--- pom.xml | 13 ++++++------- 4 files changed, 11 insertions(+), 36 deletions(-) diff --git a/application-admintools-api/pom.xml b/application-admintools-api/pom.xml index 366b0db2..2c69b562 100644 --- a/application-admintools-api/pom.xml +++ b/application-admintools-api/pom.xml @@ -23,13 +23,11 @@ com.xwiki.admintools application-admintools - 1.0.0-SNAPSHOT + 1.0-SNAPSHOT 4.0.0 - application-admintools-api jar Admin Tools (Pro) - API Provides the Java APIs needed by the Admin tools Application. - \ No newline at end of file diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index f5d01976..5659992f 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -23,10 +23,9 @@ com.xwiki.admintools application-admintools - 1.0.0-SNAPSHOT + 1.0-SNAPSHOT 4.0.0 - application-admintools-default jar Admin Tools Application (Pro) - Default @@ -38,26 +37,5 @@ application-admintools-api ${project.version} - - org.xwiki.platform - xwiki-platform-oldcore - ${platform.version} - - - org.xwiki.commons - xwiki-commons-tool-test-component - ${commons.version} - test - - - org.xwiki.rendering - xwiki-rendering-test - ${rendering.version} - test - - - true - - \ No newline at end of file diff --git a/application-admintools-ui/pom.xml b/application-admintools-ui/pom.xml index 2e116f8c..dc3683f5 100644 --- a/application-admintools-ui/pom.xml +++ b/application-admintools-ui/pom.xml @@ -24,10 +24,9 @@ com.xwiki.admintools application-admintools - 1.0.0-SNAPSHOT + 1.0-SNAPSHOT 4.0.0 - application-admintools-ui xar Admin Tools Application (Pro) @@ -35,11 +34,12 @@ - Admin tools Application (Pro) + Admin Tools Application (Pro) application true + com.xwiki.admintools diff --git a/pom.xml b/pom.xml index 5e451e34..b9c3a732 100644 --- a/pom.xml +++ b/pom.xml @@ -30,17 +30,12 @@ com.xwiki.admintools application-admintools pom - 1.0.0-SNAPSHOT + 1.0-SNAPSHOT Admin Tools Application (Pro) Parent POM The Admin Tools Pro application gives you full control and visibility over your XWiki instance. Use it to manage your XWiki installation. Easily generate configuration reports. Perform sanity checks and show logs history. - - application-admintools-api - application-admintools-default - application-admintools-ui - GitHub https://github.com/xwikisas/application-admintools/issues @@ -51,5 +46,9 @@ https://github.com/xwikisas/application-admintools/tree/master HEAD - + + application-admintools-api + application-admintools-default + application-admintools-ui + \ No newline at end of file From 046cb6df62ddf4f7dd2074ff2df12fa9fa145981 Mon Sep 17 00:00:00 2001 From: Sorin Date: Fri, 11 Aug 2023 13:59:29 +0300 Subject: [PATCH 04/72] Display App server info #3 --- .gitignore | 3 + application-admintools-api/pom.xml | 8 + application-admintools-default/pom.xml | 17 ++ .../internal/ConfigurationManager.java | 57 +++++++ .../internal/util/ConfigurationInfoUtil.java | 158 ++++++++++++++++++ .../script/AdminToolsScriptService.java | 60 +++++++ .../main/resources/META-INF/components.txt | 3 + 7 files changed, 306 insertions(+) create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/ConfigurationManager.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfoUtil.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java create mode 100644 application-admintools-default/src/main/resources/META-INF/components.txt diff --git a/.gitignore b/.gitignore index b3e5c3ca..57115870 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ target target-eclipse +# VS Code +.vscode + # IDEA *.iml *.ipr diff --git a/application-admintools-api/pom.xml b/application-admintools-api/pom.xml index 2c69b562..f8492f9f 100644 --- a/application-admintools-api/pom.xml +++ b/application-admintools-api/pom.xml @@ -30,4 +30,12 @@ jar Admin Tools (Pro) - API Provides the Java APIs needed by the Admin tools Application. + + + org.xwiki.commons + xwiki-commons-component-api + ${commons.version} + compile + + \ No newline at end of file diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index 5659992f..71e94770 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -37,5 +37,22 @@ application-admintools-api ${project.version} + + org.xwiki.platform + xwiki-platform-oldcore + ${platform.version} + + + org.xwiki.commons + xwiki-commons-tool-test-component + ${commons.version} + test + + + org.xwiki.rendering + xwiki-rendering-test + ${rendering.version} + test + \ No newline at end of file diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/ConfigurationManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/ConfigurationManager.java new file mode 100644 index 00000000..56df3321 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/ConfigurationManager.java @@ -0,0 +1,57 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.internal.util.ConfigurationInfoUtil; + +/** + * Manage existing instances. + * + * @version $Id$ + * @since 1.0 + */ +@Component(roles = ConfigurationManager.class) +@Singleton +public class ConfigurationManager +{ + /** + * Contains useful functions for retrieving configuration data. + */ + @Inject + private final ConfigurationInfoUtil configurationInfoUtil = new ConfigurationInfoUtil(); + + /** + * Admin Tools script services. + * + * @return String + * @since 1.0 + */ + public Map generateResults() + { + return this.configurationInfoUtil.getSystemInfo(); + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfoUtil.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfoUtil.java new file mode 100644 index 00000000..effb610a --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfoUtil.java @@ -0,0 +1,158 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.util; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Singleton; +import org.xwiki.component.annotation.Component; + +/** + * Encapsulates functions used for retrieving configuration data. + * + * @version $Id$ + * @since 1.0 + */ +@Component(roles = ConfigurationInfoUtil.class) +@Singleton +public class ConfigurationInfoUtil +{ + /** + * Stores the path to the server. + */ + private final String serverSystemPath; + + /** + * Stores the possible paths for tomcat. + */ + private final String[] tomcatPossiblePaths; + + /** + * Stores the possible paths for the XWiki installation. + */ + private final String[] xwikiPossiblePaths; + + /** + * The class constructor. + */ + public ConfigurationInfoUtil() + { + String catalinaBase = System.getProperty("catalina.base"); + if (catalinaBase != null) { + serverSystemPath = catalinaBase; + } else { + serverSystemPath = System.getenv("CATALINA_HOME"); + } + + tomcatPossiblePaths = new String[] { + String.format("%s/conf/server.xml", serverSystemPath), + "/usr/local/tomcat/conf/server.xml", + "/opt/tomcat/conf/server.xml", + "/var/lib/tomcat8/conf/", + "/var/lib/tomcat9/conf/", + "/var/lib/tomcat/conf/" }; + + xwikiPossiblePaths = new String[] { + "/etc/xwiki/xwiki.cfg", + String.format("%s/webapps${request.contextPath}/WEB-INF/xwiki.cfg", serverSystemPath), + "/usr/local/xwiki/WEB-INF/xwiki.cfg", + "/opt/xwiki/WEB-INF/xwiki.cfg", + String.format("%s/webapps/ROOT/WEB-INF/xwiki.cfg", serverSystemPath), + String.format("%s/webapps/xwiki/WEB-INF/xwiki.cfg", serverSystemPath) }; + } + + /** + * Function used to retrieve the configuration info json. + * + * @return xwiki configuration info json. + * @since 1.0 + */ + public Map getSystemInfo() + { + Map systemInfo = new HashMap<>(); + + systemInfo.put("xwikiCfgPath", this.getXwikiCfgPath()); + systemInfo.put("tomcatConfPath", this.getTomcatConfPath()); + systemInfo.put("javaVersion", this.getJavaVersion()); + systemInfo.put("osInfo", this.getOSInfo()); + + return systemInfo; + } + + /** + * Function used to retrieve the configuration file path for the XWiki. + * + * @return the XWiki configuration file path. + * @since 1.0 + */ + private String getXwikiCfgPath() + { + for (String xwCfgPath : xwikiPossiblePaths) { + if ((new File(xwCfgPath)).exists()) { + return xwCfgPath; + } + } + return null; + } + + /** + * Function used to retrieve the configuration file path for Tomcat. + * + * @return path to Tomcat configuration file. + * @since 1.0 + */ + private String getTomcatConfPath() + { + for (String tomConfPath : tomcatPossiblePaths) { + if ((new File(tomConfPath)).exists()) { + return tomConfPath; + } + } + return null; + } + + /** + * Function used to retrieve the used version of Java. + * + * @return the used Java version. + * @since 1.0 + */ + private String getJavaVersion() + { + return System.getProperty("java.version"); + } + + /** + * Function used to retrieve info about the OS XWiki is running on. + * + * @return info about the OS. + * @since 1.0 + */ + private String getOSInfo() + { + String osName = System.getProperty("os.name"); + String osVersion = System.getProperty("os.version"); + String osArch = System.getProperty("os.arch"); + + return String.format("Operating System: %s %s (%s)", osName, osVersion, osArch); + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java new file mode 100644 index 00000000..dfc6efc3 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -0,0 +1,60 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.script; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; +import org.xwiki.script.service.ScriptService; + +import com.xwiki.admintools.internal.ConfigurationManager; + +/** + * Admin Tools script services. + * + * @version $Id$ + * @since 1.0 + */ +@Component +@Named("admintools") +@Singleton +public class AdminToolsScriptService implements ScriptService +{ + /** + * Manages the XWiki configuration info. + */ + @Inject + private ConfigurationManager configurationManager; + + /** + * Function used to retrieve the configuration info json. + * + * @return the configuration info json. + * @since 1.0 + */ + public Map getConfigurationDetails() + { + return this.configurationManager.generateResults(); + } +} diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt new file mode 100644 index 00000000..d1fe3d15 --- /dev/null +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -0,0 +1,3 @@ +com.xwiki.admintools.script.AdminToolsScriptService +com.xwiki.admintools.internal.ConfigurationManager +com.xwiki.admintools.internal.util.ConfigurationInfoUtil From 5b62df5550b5252cfc637ff2e9e69695130dc087 Mon Sep 17 00:00:00 2001 From: Sorin Date: Fri, 11 Aug 2023 17:51:40 +0300 Subject: [PATCH 05/72] Display App server info #3 --- ...ionManager.java => AdminToolsManager.java} | 15 +++-- ...onInfoUtil.java => ConfigurationInfo.java} | 62 ++++++++----------- .../script/AdminToolsScriptService.java | 7 +-- 3 files changed, 37 insertions(+), 47 deletions(-) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/{ConfigurationManager.java => AdminToolsManager.java} (76%) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/{ConfigurationInfoUtil.java => ConfigurationInfo.java} (68%) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/ConfigurationManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java similarity index 76% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/ConfigurationManager.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index 56df3321..ee955088 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/ConfigurationManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -26,32 +26,31 @@ import org.xwiki.component.annotation.Component; -import com.xwiki.admintools.internal.util.ConfigurationInfoUtil; +import com.xwiki.admintools.internal.util.ConfigurationInfo; /** - * Manage existing instances. + * Manage existing instances. or admin tools manager * * @version $Id$ * @since 1.0 */ -@Component(roles = ConfigurationManager.class) +@Component(roles = AdminToolsManager.class) @Singleton -public class ConfigurationManager +public class AdminToolsManager { /** * Contains useful functions for retrieving configuration data. */ @Inject - private final ConfigurationInfoUtil configurationInfoUtil = new ConfigurationInfoUtil(); + private ConfigurationInfo configurationInfo; /** * Admin Tools script services. * * @return String - * @since 1.0 */ - public Map generateResults() + public Map getConfigurationDetails() { - return this.configurationInfoUtil.getSystemInfo(); + return this.configurationInfo.generateConfigurationDetails(); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfoUtil.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java similarity index 68% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfoUtil.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java index effb610a..fb0bf509 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfoUtil.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java @@ -24,7 +24,10 @@ import java.util.Map; import javax.inject.Singleton; + import org.xwiki.component.annotation.Component; +import org.xwiki.component.phase.Initializable; +import org.xwiki.component.phase.InitializationException; /** * Encapsulates functions used for retrieving configuration data. @@ -32,61 +35,54 @@ * @version $Id$ * @since 1.0 */ -@Component(roles = ConfigurationInfoUtil.class) +@Component(roles = ConfigurationInfo.class) @Singleton -public class ConfigurationInfoUtil +public class ConfigurationInfo implements Initializable { /** * Stores the path to the server. */ - private final String serverSystemPath; + private String serverSystemPath; /** * Stores the possible paths for tomcat. */ - private final String[] tomcatPossiblePaths; + private String[] tomcatPossiblePaths; /** * Stores the possible paths for the XWiki installation. */ - private final String[] xwikiPossiblePaths; + private String[] xwikiPossiblePaths; /** - * The class constructor. + * The class initializer. */ - public ConfigurationInfoUtil() + public void initialize() throws InitializationException { String catalinaBase = System.getProperty("catalina.base"); if (catalinaBase != null) { - serverSystemPath = catalinaBase; + this.serverSystemPath = catalinaBase; } else { - serverSystemPath = System.getenv("CATALINA_HOME"); + this.serverSystemPath = System.getenv("CATALINA_HOME"); } - tomcatPossiblePaths = new String[] { - String.format("%s/conf/server.xml", serverSystemPath), - "/usr/local/tomcat/conf/server.xml", - "/opt/tomcat/conf/server.xml", - "/var/lib/tomcat8/conf/", - "/var/lib/tomcat9/conf/", - "/var/lib/tomcat/conf/" }; - - xwikiPossiblePaths = new String[] { - "/etc/xwiki/xwiki.cfg", - String.format("%s/webapps${request.contextPath}/WEB-INF/xwiki.cfg", serverSystemPath), - "/usr/local/xwiki/WEB-INF/xwiki.cfg", - "/opt/xwiki/WEB-INF/xwiki.cfg", - String.format("%s/webapps/ROOT/WEB-INF/xwiki.cfg", serverSystemPath), - String.format("%s/webapps/xwiki/WEB-INF/xwiki.cfg", serverSystemPath) }; + this.tomcatPossiblePaths = new String[] { String.format("%s/conf/server.xml", this.serverSystemPath), + "/usr/local/tomcat/conf/server.xml", "/opt/tomcat/conf/server.xml", "/var/lib/tomcat8/conf/", + "/var/lib/tomcat9/conf/", "/var/lib/tomcat/conf/" }; + + this.xwikiPossiblePaths = new String[] { "/etc/xwiki/xwiki.cfg", + String.format("%s/webapps${request.contextPath}/WEB-INF/xwiki.cfg", this.serverSystemPath), + "/usr/local/xwiki/WEB-INF/xwiki.cfg", "/opt/xwiki/WEB-INF/xwiki.cfg", + String.format("%s/webapps/ROOT/WEB-INF/xwiki.cfg", this.serverSystemPath), + String.format("%s/webapps/xwiki/WEB-INF/xwiki.cfg", this.serverSystemPath) }; } /** - * Function used to retrieve the configuration info json. + * Get the configuration info json. * * @return xwiki configuration info json. - * @since 1.0 */ - public Map getSystemInfo() + public Map generateConfigurationDetails() { Map systemInfo = new HashMap<>(); @@ -99,10 +95,9 @@ public Map getSystemInfo() } /** - * Function used to retrieve the configuration file path for the XWiki. + * Get the configuration file path for the XWiki. * * @return the XWiki configuration file path. - * @since 1.0 */ private String getXwikiCfgPath() { @@ -115,10 +110,9 @@ private String getXwikiCfgPath() } /** - * Function used to retrieve the configuration file path for Tomcat. + * Get the configuration file path for Tomcat. * * @return path to Tomcat configuration file. - * @since 1.0 */ private String getTomcatConfPath() { @@ -131,10 +125,9 @@ private String getTomcatConfPath() } /** - * Function used to retrieve the used version of Java. + * Get the used version of Java. * * @return the used Java version. - * @since 1.0 */ private String getJavaVersion() { @@ -142,10 +135,9 @@ private String getJavaVersion() } /** - * Function used to retrieve info about the OS XWiki is running on. + * Get info about the OS XWiki is running on. * * @return info about the OS. - * @since 1.0 */ private String getOSInfo() { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index dfc6efc3..c437bd4a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -28,7 +28,7 @@ import org.xwiki.component.annotation.Component; import org.xwiki.script.service.ScriptService; -import com.xwiki.admintools.internal.ConfigurationManager; +import com.xwiki.admintools.internal.AdminToolsManager; /** * Admin Tools script services. @@ -45,16 +45,15 @@ public class AdminToolsScriptService implements ScriptService * Manages the XWiki configuration info. */ @Inject - private ConfigurationManager configurationManager; + private AdminToolsManager adminToolsManager; /** * Function used to retrieve the configuration info json. * * @return the configuration info json. - * @since 1.0 */ public Map getConfigurationDetails() { - return this.configurationManager.generateResults(); + return this.adminToolsManager.getConfigurationDetails(); } } From 00ad0f6ad8f58b200bdeb892802dd57369ab9725 Mon Sep 17 00:00:00 2001 From: Sorin Date: Fri, 11 Aug 2023 17:52:22 +0300 Subject: [PATCH 06/72] Display App server info #3 --- .../src/main/resources/META-INF/components.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index d1fe3d15..27e5770f 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -1,3 +1,3 @@ com.xwiki.admintools.script.AdminToolsScriptService -com.xwiki.admintools.internal.ConfigurationManager -com.xwiki.admintools.internal.util.ConfigurationInfoUtil +com.xwiki.admintools.internal.AdminToolsManager +com.xwiki.admintools.internal.util.ConfigurationInfo From 5794faf7c22bf81db8f59378fca68df4b96367f3 Mon Sep 17 00:00:00 2001 From: Sorin Date: Fri, 11 Aug 2023 18:16:02 +0300 Subject: [PATCH 07/72] Display App server info #3 --- application-admintools-api/pom.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/application-admintools-api/pom.xml b/application-admintools-api/pom.xml index f8492f9f..2c69b562 100644 --- a/application-admintools-api/pom.xml +++ b/application-admintools-api/pom.xml @@ -30,12 +30,4 @@ jar Admin Tools (Pro) - API Provides the Java APIs needed by the Admin tools Application. - - - org.xwiki.commons - xwiki-commons-component-api - ${commons.version} - compile - - \ No newline at end of file From d3aab58bacb1a5437b786841d51086909a3c820e Mon Sep 17 00:00:00 2001 From: Sorin Date: Tue, 22 Aug 2023 10:03:48 +0300 Subject: [PATCH 08/72] Display App server info #3 --- .../internal/AdminToolsManager.java | 22 +++- .../internal/util/ConfigurationInfo.java | 52 ++++++--- .../internal/util/SecurityInfo.java | 105 ++++++++++++++++++ .../script/AdminToolsScriptService.java | 10 ++ .../main/resources/META-INF/components.txt | 1 + 5 files changed, 170 insertions(+), 20 deletions(-) create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index ee955088..6a664a40 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -19,6 +19,7 @@ */ package com.xwiki.admintools.internal; +import java.io.IOException; import java.util.Map; import javax.inject.Inject; @@ -27,6 +28,7 @@ import org.xwiki.component.annotation.Component; import com.xwiki.admintools.internal.util.ConfigurationInfo; +import com.xwiki.admintools.internal.util.SecurityInfo; /** * Manage existing instances. or admin tools manager @@ -45,12 +47,28 @@ public class AdminToolsManager private ConfigurationInfo configurationInfo; /** - * Admin Tools script services. + * Contains useful functions for retrieving security data. + */ + @Inject + private SecurityInfo securityInfo; + + /** + * Extract the configuration settings. * - * @return String + * @return a json containing the configuration info */ public Map getConfigurationDetails() { return this.configurationInfo.generateConfigurationDetails(); } + + /** + * Extract the security settings. + * + * @return a json containing the security info + */ + public Map getSecurityDetails() + { + return this.securityInfo.generateSecurityDetails(); + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java index fb0bf509..7c7d8092 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java @@ -23,12 +23,16 @@ import java.util.HashMap; import java.util.Map; +import javax.inject.Inject; +import javax.inject.Provider; import javax.inject.Singleton; import org.xwiki.component.annotation.Component; import org.xwiki.component.phase.Initializable; import org.xwiki.component.phase.InitializationException; +import com.xwiki.admintools.configuration.AdminToolsConfiguration; + /** * Encapsulates functions used for retrieving configuration data. * @@ -54,27 +58,15 @@ public class ConfigurationInfo implements Initializable */ private String[] xwikiPossiblePaths; + @Inject + private Provider configurationProvider; + /** * The class initializer. */ public void initialize() throws InitializationException { - String catalinaBase = System.getProperty("catalina.base"); - if (catalinaBase != null) { - this.serverSystemPath = catalinaBase; - } else { - this.serverSystemPath = System.getenv("CATALINA_HOME"); - } - - this.tomcatPossiblePaths = new String[] { String.format("%s/conf/server.xml", this.serverSystemPath), - "/usr/local/tomcat/conf/server.xml", "/opt/tomcat/conf/server.xml", "/var/lib/tomcat8/conf/", - "/var/lib/tomcat9/conf/", "/var/lib/tomcat/conf/" }; - - this.xwikiPossiblePaths = new String[] { "/etc/xwiki/xwiki.cfg", - String.format("%s/webapps${request.contextPath}/WEB-INF/xwiki.cfg", this.serverSystemPath), - "/usr/local/xwiki/WEB-INF/xwiki.cfg", "/opt/xwiki/WEB-INF/xwiki.cfg", - String.format("%s/webapps/ROOT/WEB-INF/xwiki.cfg", this.serverSystemPath), - String.format("%s/webapps/xwiki/WEB-INF/xwiki.cfg", this.serverSystemPath) }; + updatePaths(); } /** @@ -84,6 +76,7 @@ public void initialize() throws InitializationException */ public Map generateConfigurationDetails() { + updatePaths(); Map systemInfo = new HashMap<>(); systemInfo.put("xwikiCfgPath", this.getXwikiCfgPath()); @@ -94,10 +87,33 @@ public Map generateConfigurationDetails() return systemInfo; } + private void updatePaths() + { + String providedConfigServePath = configurationProvider.get().getServerPath(); + if (providedConfigServePath != null && !providedConfigServePath.equals("null")) { + this.serverSystemPath = providedConfigServePath; + } else { + String catalinaBase = System.getProperty("catalina.base"); + if (catalinaBase != null) { + this.serverSystemPath = catalinaBase; + } else { + this.serverSystemPath = System.getenv("CATALINA_HOME"); + } + } + + this.tomcatPossiblePaths = new String[] { String.format("%s/conf/server.xml", this.serverSystemPath), + "/usr/local/tomcat/conf/server.xml", "/opt/tomcat/conf/server.xml", "/var/lib/tomcat8/conf/", + "/var/lib/tomcat9/conf/", "/var/lib/tomcat/conf/" }; + + this.xwikiPossiblePaths = new String[] { "/etc/xwiki/xwiki.cfg", + String.format("%s/webapps${request.contextPath}/WEB-INF/xwiki.cfg", this.serverSystemPath), + "/usr/local/xwiki/WEB-INF/xwiki.cfg", "/opt/xwiki/WEB-INF/xwiki.cfg", + String.format("%s/webapps/ROOT/WEB-INF/xwiki.cfg", this.serverSystemPath), + String.format("%s/webapps/xwiki/WEB-INF/xwiki.cfg", this.serverSystemPath) }; + } + /** * Get the configuration file path for the XWiki. - * - * @return the XWiki configuration file path. */ private String getXwikiCfgPath() { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java new file mode 100644 index 00000000..9348340a --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java @@ -0,0 +1,105 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.util; + +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; +import org.xwiki.configuration.ConfigurationSource; + +import com.xpn.xwiki.XWiki; +import com.xpn.xwiki.XWikiContext; + +/** + * Encapsulates functions used for retrieving security data. + * + * @version $Id$ + * @since 1.0 + */ +@Component(roles = SecurityInfo.class) +@Singleton +public class SecurityInfo +{ + private final String[] searchedKeys = { "PWD", "LANG" }; + + /** + * Get the security details. + */ + @Inject + private Provider xWikiContextProvider; + + /** + * Get the security details. + */ + @Inject + @Named("xwikicfg") + private ConfigurationSource configurationSource; + + /** + * Generate the security details. + * + * @return the security details of the xwiki + */ + public Map generateSecurityDetails() + { + Map securityDetails = new HashMap<>(this.getXwikiSecurityInfo()); + + securityDetails.put("fileEncoding", getFileEncoding()); + securityDetails.put(searchedKeys[0], System.getenv(searchedKeys[0])); + securityDetails.put(searchedKeys[1], System.getenv(searchedKeys[1])); + return securityDetails; + } + + /** + * Get the encoding used for the files. + * + * @return the file encoding + */ + private String getFileEncoding() + { + return System.getProperty("file.encoding"); + } + + /** + * Get the security info of the current wiki. + * + * @return xwiki security info. + */ + private Map getXwikiSecurityInfo() + { + Map results = new HashMap<>(); + + XWikiContext wikiContext = xWikiContextProvider.get(); + XWiki wiki = wikiContext.getWiki(); + String wikiEncoding = wiki.getEncoding(); + String cfgEncoding = configurationSource.getProperty("xwiki.encoding", String.class); + + results.put("activeEncoding", wikiEncoding); + results.put("configurationEncoding", cfgEncoding); + + return results; + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index c437bd4a..f66db420 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -56,4 +56,14 @@ public Map getConfigurationDetails() { return this.adminToolsManager.getConfigurationDetails(); } + + /** + * Function used to retrieve the security info json. + * + * @return the configuration info json. + */ + public Map getSecDetails() + { + return this.adminToolsManager.getSecurityDetails(); + } } diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index 27e5770f..88005e02 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -1,3 +1,4 @@ com.xwiki.admintools.script.AdminToolsScriptService com.xwiki.admintools.internal.AdminToolsManager com.xwiki.admintools.internal.util.ConfigurationInfo +com.xwiki.admintools.internal.util.SecurityInfo From 63b0fb8750e53367e8a735ec57a82c752538693b Mon Sep 17 00:00:00 2001 From: Sorin Date: Thu, 24 Aug 2023 14:47:20 +0300 Subject: [PATCH 09/72] Display App server info #3 --- application-admintools-default/pom.xml | 5 +++++ .../internal/util/ConfigurationInfo.java | 8 ++++---- .../admintools/internal/util/SecurityInfo.java | 15 ++++++++------- .../script/AdminToolsScriptService.java | 2 +- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index 71e94770..9f2afa43 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -37,6 +37,11 @@ application-admintools-api ${project.version} + + org.xwiki.platform + xwiki-platform-activeinstalls2-api + ${platform.version} + org.xwiki.platform xwiki-platform-oldcore diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java index 7c7d8092..3adf2903 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java @@ -59,7 +59,7 @@ public class ConfigurationInfo implements Initializable private String[] xwikiPossiblePaths; @Inject - private Provider configurationProvider; + private Provider adminToolsConfig; /** * The class initializer. @@ -89,9 +89,9 @@ public Map generateConfigurationDetails() private void updatePaths() { - String providedConfigServePath = configurationProvider.get().getServerPath(); - if (providedConfigServePath != null && !providedConfigServePath.equals("null")) { - this.serverSystemPath = providedConfigServePath; + String providedConfigServerPath = adminToolsConfig.get().getServerPath(); + if (providedConfigServerPath != null) { + this.serverSystemPath = providedConfigServerPath; } else { String catalinaBase = System.getProperty("catalina.base"); if (catalinaBase != null) { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java index 9348340a..f85d8996 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java @@ -43,13 +43,11 @@ @Singleton public class SecurityInfo { - private final String[] searchedKeys = { "PWD", "LANG" }; - /** * Get the security details. */ @Inject - private Provider xWikiContextProvider; + private Provider xcontextProvider; /** * Get the security details. @@ -65,11 +63,14 @@ public class SecurityInfo */ public Map generateSecurityDetails() { - Map securityDetails = new HashMap<>(this.getXwikiSecurityInfo()); + Map securityDetails = this.getXwikiSecurityInfo(); + String workDirectory = "PWD"; + String language = "LANG"; securityDetails.put("fileEncoding", getFileEncoding()); - securityDetails.put(searchedKeys[0], System.getenv(searchedKeys[0])); - securityDetails.put(searchedKeys[1], System.getenv(searchedKeys[1])); + securityDetails.put(workDirectory, System.getenv(workDirectory)); + securityDetails.put(language, System.getenv(language)); + return securityDetails; } @@ -92,7 +93,7 @@ private Map getXwikiSecurityInfo() { Map results = new HashMap<>(); - XWikiContext wikiContext = xWikiContextProvider.get(); + XWikiContext wikiContext = xcontextProvider.get(); XWiki wiki = wikiContext.getWiki(); String wikiEncoding = wiki.getEncoding(); String cfgEncoding = configurationSource.getProperty("xwiki.encoding", String.class); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index f66db420..8f58680f 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -62,7 +62,7 @@ public Map getConfigurationDetails() * * @return the configuration info json. */ - public Map getSecDetails() + public Map getSecurityDetails() { return this.adminToolsManager.getSecurityDetails(); } From 853d8c593d88d77f2f6163574b2bf3cbb116c8ad Mon Sep 17 00:00:00 2001 From: Sorin Date: Fri, 25 Aug 2023 12:55:51 +0300 Subject: [PATCH 10/72] isplay App server info #3 - debug --- .../internal/AdminToolsManager.java | 64 +++++++++++++++---- .../admintools/internal/DataProvider.java | 46 +++++++++++++ .../internal/util/AbstractDataProvider.java | 60 +++++++++++++++++ .../internal/util/ConfigurationInfo.java | 24 +++++-- .../internal/util/SecurityInfo.java | 29 +++++---- .../script/AdminToolsScriptService.java | 33 ++++++++-- .../templates/configurationTemplate.vm | 23 +++++++ pom.xml | 2 +- 8 files changed, 245 insertions(+), 36 deletions(-) create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java create mode 100644 application-admintools-default/src/main/resources/templates/configurationTemplate.vm diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index 6a664a40..4a549e78 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -19,16 +19,16 @@ */ package com.xwiki.admintools.internal; -import java.io.IOException; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; import javax.inject.Singleton; import org.xwiki.component.annotation.Component; - -import com.xwiki.admintools.internal.util.ConfigurationInfo; -import com.xwiki.admintools.internal.util.SecurityInfo; +import org.xwiki.rendering.block.Block; /** * Manage existing instances. or admin tools manager @@ -44,22 +44,51 @@ public class AdminToolsManager * Contains useful functions for retrieving configuration data. */ @Inject - private ConfigurationInfo configurationInfo; + @Named("configuration") + private DataProvider configurationInfo; /** * Contains useful functions for retrieving security data. */ @Inject - private SecurityInfo securityInfo; + @Named("security") + private DataProvider securityInfo; + + @Inject + private Provider> dataProviderProvider; + +// /** +// * Extract the configuration settings. +// * +// * @return a json containing the configuration info +// */ +// public Map getConfigurationDetails() +// { +// return this.configurationInfo.provideData(); +// } +// +// /** +// * Extract the security settings. +// * +// * @return a json containing the security info +// */ +// public Map getSecurityDetails() +// { +// return this.securityInfo.provideData(); +// } /** - * Extract the configuration settings. + * Extract the security settings. * - * @return a json containing the configuration info + * @return a json containing the security info */ - public Map getConfigurationDetails() + public List generateData() { - return this.configurationInfo.generateConfigurationDetails(); + List generatedData = new ArrayList<>(); + for (DataProvider dataProvider : this.dataProviderProvider.get()) { + generatedData.add(dataProvider.provideData()); + } + return generatedData; } /** @@ -67,8 +96,17 @@ public Map getConfigurationDetails() * * @return a json containing the security info */ - public Map getSecurityDetails() + public List generateConfigData() { - return this.securityInfo.generateSecurityDetails(); + return configurationInfo.provideData().getChildren(); } + +// public Map generateData(String hint) +// { +// Map generatedData = new HashMap<>(); +// for (DataProvider dataProvider : this.dataProviderProvider.get()) { +// generatedData.putAll(dataProvider.provideData()); +// } +// return generatedData; +// } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java new file mode 100644 index 00000000..957a1ff4 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java @@ -0,0 +1,46 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal; + +import org.xwiki.component.annotation.Role; +import org.xwiki.component.phase.InitializationException; +import org.xwiki.rendering.block.Block; + +/** + * Allows data gathering. + * + * @version $Id$ + * @since 1.0 + */ +@Role +public interface DataProvider +{ + /** + * Extract the security settings. + * + * @return a json containing the security info + */ + Block provideData(); + + /** + * Extract the security settings. + */ + void initialize() throws InitializationException; +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java new file mode 100644 index 00000000..9f4fc12a --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java @@ -0,0 +1,60 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.util; + +import javax.inject.Inject; +import javax.inject.Provider; + +import org.slf4j.Logger; +import org.xwiki.component.phase.InitializationException; +import org.xwiki.model.reference.LocalDocumentReference; +import org.xwiki.template.TemplateManager; + +import com.xpn.xwiki.XWikiContext; +import com.xwiki.admintools.internal.DataProvider; + +/** + * To be extended by {@link DataProvider} implementations to simplify the code. + * + * @version $Id$ + * @since 1.0 + */ +public abstract class AbstractDataProvider implements DataProvider +{ + protected static final LocalDocumentReference ADMINTOOLS_DOC = new LocalDocumentReference("AdminTools", "WebHome"); + + @Inject + protected TemplateManager templateManager; + + /** + * Get the security details. + */ + @Inject + protected Provider xcontextProvider; + + @Inject + protected Logger logger; + + @Override + public void initialize() throws InitializationException + { + // Overwrite to initialize a component + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java index 3adf2903..7215e8d1 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java @@ -24,13 +24,17 @@ import java.util.Map; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.xwiki.component.annotation.Component; -import org.xwiki.component.phase.Initializable; import org.xwiki.component.phase.InitializationException; +import org.xwiki.rendering.block.Block; +import org.xwiki.template.Template; +import com.xpn.xwiki.XWikiContext; import com.xwiki.admintools.configuration.AdminToolsConfiguration; /** @@ -39,9 +43,10 @@ * @version $Id$ * @since 1.0 */ -@Component(roles = ConfigurationInfo.class) +@Component +@Named("configuration") @Singleton -public class ConfigurationInfo implements Initializable +public class ConfigurationInfo extends AbstractDataProvider { /** * Stores the path to the server. @@ -74,17 +79,26 @@ public void initialize() throws InitializationException * * @return xwiki configuration info json. */ - public Map generateConfigurationDetails() + public Block provideData() { updatePaths(); Map systemInfo = new HashMap<>(); + XWikiContext xcontext = xcontextProvider.get(); systemInfo.put("xwikiCfgPath", this.getXwikiCfgPath()); systemInfo.put("tomcatConfPath", this.getTomcatConfPath()); systemInfo.put("javaVersion", this.getJavaVersion()); systemInfo.put("osInfo", this.getOSInfo()); - return systemInfo; + Template customTemplate = this.templateManager.getTemplate("configurationTemplate.vm"); + try { + // Set a document in the context to act as the current document when the template is rendered. + + return this.templateManager.execute(customTemplate); + } catch (Exception e) { + logger.warn("Failed to render custom template. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); + } + return null; } private void updatePaths() diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java index f85d8996..4cbde3b1 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java @@ -24,11 +24,13 @@ import javax.inject.Inject; import javax.inject.Named; -import javax.inject.Provider; import javax.inject.Singleton; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.xwiki.component.annotation.Component; import org.xwiki.configuration.ConfigurationSource; +import org.xwiki.rendering.block.Block; +import org.xwiki.template.Template; import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiContext; @@ -39,16 +41,11 @@ * @version $Id$ * @since 1.0 */ -@Component(roles = SecurityInfo.class) +@Component +@Named("security") @Singleton -public class SecurityInfo +public class SecurityInfo extends AbstractDataProvider { - /** - * Get the security details. - */ - @Inject - private Provider xcontextProvider; - /** * Get the security details. */ @@ -61,7 +58,7 @@ public class SecurityInfo * * @return the security details of the xwiki */ - public Map generateSecurityDetails() + public Block provideData() { Map securityDetails = this.getXwikiSecurityInfo(); String workDirectory = "PWD"; @@ -70,8 +67,18 @@ public Map generateSecurityDetails() securityDetails.put("fileEncoding", getFileEncoding()); securityDetails.put(workDirectory, System.getenv(workDirectory)); securityDetails.put(language, System.getenv(language)); + XWikiContext xcontext = xcontextProvider.get(); + + Template customTemplate = this.templateManager.getTemplate("configurationTemplate.vm"); + try { + // Set a document in the context to act as the current document when the template is rendered. + xcontext.setDoc(xcontext.getWiki().getDocument(ADMINTOOLS_DOC, xcontext)); - return securityDetails; + return this.templateManager.execute(customTemplate); + } catch (Exception e) { + logger.warn("Failed to render custom template. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); + } + return null; } /** diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index 8f58680f..87d4a898 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -19,13 +19,14 @@ */ package com.xwiki.admintools.script; -import java.util.Map; +import java.util.List; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import org.xwiki.component.annotation.Component; +import org.xwiki.rendering.block.Block; import org.xwiki.script.service.ScriptService; import com.xwiki.admintools.internal.AdminToolsManager; @@ -47,14 +48,34 @@ public class AdminToolsScriptService implements ScriptService @Inject private AdminToolsManager adminToolsManager; +// /** +// * Function used to retrieve the configuration info json. +// * +// * @return the configuration info json. +// */ +// public Map getConfigurationDetails() +// { +// return this.adminToolsManager.getConfigurationDetails(); +// } +// +// /** +// * Function used to retrieve the security info json. +// * +// * @return the configuration info json. +// */ +// public Map getSecurityDetails() +// { +// return this.adminToolsManager.getSecurityDetails(); +// } + /** - * Function used to retrieve the configuration info json. + * Function used to retrieve the security info json. * * @return the configuration info json. */ - public Map getConfigurationDetails() + public List getAllData() { - return this.adminToolsManager.getConfigurationDetails(); + return this.adminToolsManager.generateData(); } /** @@ -62,8 +83,8 @@ public Map getConfigurationDetails() * * @return the configuration info json. */ - public Map getSecurityDetails() + public List getConfigData() { - return this.adminToolsManager.getSecurityDetails(); + return this.adminToolsManager.generateConfigData(); } } diff --git a/application-admintools-default/src/main/resources/templates/configurationTemplate.vm b/application-admintools-default/src/main/resources/templates/configurationTemplate.vm new file mode 100644 index 00000000..f6b7c26f --- /dev/null +++ b/application-admintools-default/src/main/resources/templates/configurationTemplate.vm @@ -0,0 +1,23 @@ +## --------------------------------------------------------------------------- +## See the NOTICE file distributed with this work for additional +## information regarding copyright ownership. +## +## This is free software; you can redistribute it and/or modify it +## under the terms of the GNU Lesser General Public License as +## published by the Free Software Foundation; either version 2.1 of +## the License, or (at your option) any later version. +## +## This software is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this software; if not, write to the Free +## Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +## 02110-1301 USA, or see the FSF site: http://www.fsf.org. +## --------------------------------------------------------------------------- + +
+

test config class

+
\ No newline at end of file diff --git a/pom.xml b/pom.xml index b9c3a732..4ddbf031 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ com.xwiki.parent xwikisas-parent-platform - 13.10-3 + 14.10 com.xwiki.admintools application-admintools From 2d3de9e5ead5f142a81e8e62a0a0ed65abdd9561 Mon Sep 17 00:00:00 2001 From: Sorin Date: Fri, 25 Aug 2023 17:24:27 +0300 Subject: [PATCH 11/72] Display App server info #3 - Created an interface and abstract class DataProvider for better generalization and future extension of the components that provide data. - Created templates for data gathering components. --- .../internal/AdminToolsManager.java | 75 ++++++------------- .../admintools/internal/DataProvider.java | 16 ++-- .../internal/util/AbstractDataProvider.java | 50 ++++++++++++- ...fo.java => ConfigurationDataProvider.java} | 45 ++++++----- ...ityInfo.java => SecurityDataProvider.java} | 31 ++++---- .../script/AdminToolsScriptService.java | 38 ++-------- .../main/resources/META-INF/components.txt | 4 +- .../{ => data}/configurationTemplate.vm | 7 +- .../templates/data/securityTemplate.vm | 27 +++++++ 9 files changed, 165 insertions(+), 128 deletions(-) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/{ConfigurationInfo.java => ConfigurationDataProvider.java} (86%) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/{SecurityInfo.java => SecurityDataProvider.java} (76%) rename application-admintools-default/src/main/resources/templates/{ => data}/configurationTemplate.vm (96%) create mode 100644 application-admintools-default/src/main/resources/templates/data/securityTemplate.vm diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index 4a549e78..9d3d1e3a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -19,7 +19,6 @@ */ package com.xwiki.admintools.internal; -import java.util.ArrayList; import java.util.List; import javax.inject.Inject; @@ -28,7 +27,6 @@ import javax.inject.Singleton; import org.xwiki.component.annotation.Component; -import org.xwiki.rendering.block.Block; /** * Manage existing instances. or admin tools manager @@ -41,72 +39,43 @@ public class AdminToolsManager { /** - * Contains useful functions for retrieving configuration data. + * A list of all the data providers for Admin Tools. */ - @Inject - @Named("configuration") - private DataProvider configurationInfo; - - /** - * Contains useful functions for retrieving security data. - */ - @Inject - @Named("security") - private DataProvider securityInfo; - @Inject private Provider> dataProviderProvider; -// /** -// * Extract the configuration settings. -// * -// * @return a json containing the configuration info -// */ -// public Map getConfigurationDetails() -// { -// return this.configurationInfo.provideData(); -// } -// -// /** -// * Extract the security settings. -// * -// * @return a json containing the security info -// */ -// public Map getSecurityDetails() -// { -// return this.securityInfo.provideData(); -// } - /** - * Extract the security settings. + * Merges all the templates. * - * @return a json containing the security info + * @return a string containing all templates. */ - public List generateData() + public String generateData() { - List generatedData = new ArrayList<>(); + StringBuilder strBuilder = new StringBuilder(); + for (DataProvider dataProvider : this.dataProviderProvider.get()) { - generatedData.add(dataProvider.provideData()); + strBuilder.append(dataProvider.provideData()); + strBuilder.append("\n"); } - return generatedData; + return strBuilder.toString(); } /** - * Extract the security settings. + * Extract a specific template. * - * @return a json containing the security info + * @param hint represents the data provider identifier. + * @return a String representing a template */ - public List generateConfigData() + public String generateData(String hint) { - return configurationInfo.provideData().getChildren(); - } + StringBuilder strBuilder = new StringBuilder(); -// public Map generateData(String hint) -// { -// Map generatedData = new HashMap<>(); -// for (DataProvider dataProvider : this.dataProviderProvider.get()) { -// generatedData.putAll(dataProvider.provideData()); -// } -// return generatedData; -// } + for (DataProvider dataProvider : this.dataProviderProvider.get()) { + if (dataProvider.getIdentifier().equals(hint)) { + strBuilder.append(dataProvider.provideData()); + return strBuilder.toString(); + } + } + return null; + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java index 957a1ff4..ba221dc8 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java @@ -21,7 +21,6 @@ import org.xwiki.component.annotation.Role; import org.xwiki.component.phase.InitializationException; -import org.xwiki.rendering.block.Block; /** * Allows data gathering. @@ -33,14 +32,21 @@ public interface DataProvider { /** - * Extract the security settings. + * Provides the template of a specific type. * - * @return a json containing the security info + * @return a data provider template */ - Block provideData(); + String provideData(); /** - * Extract the security settings. + * If needed, it is used to initialize a template */ void initialize() throws InitializationException; + + /** + * Extract the hint of a component. + * + * @return component hint + */ + String getIdentifier(); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java index 9f4fc12a..beb5ceae 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java @@ -19,12 +19,19 @@ */ package com.xwiki.admintools.internal.util; +import java.io.StringWriter; +import java.io.Writer; +import java.util.Map; + import javax.inject.Inject; import javax.inject.Provider; +import javax.script.ScriptContext; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.xwiki.component.phase.InitializationException; -import org.xwiki.model.reference.LocalDocumentReference; +import org.xwiki.script.ScriptContextManager; +import org.xwiki.template.Template; import org.xwiki.template.TemplateManager; import com.xpn.xwiki.XWikiContext; @@ -38,8 +45,6 @@ */ public abstract class AbstractDataProvider implements DataProvider { - protected static final LocalDocumentReference ADMINTOOLS_DOC = new LocalDocumentReference("AdminTools", "WebHome"); - @Inject protected TemplateManager templateManager; @@ -52,9 +57,48 @@ public abstract class AbstractDataProvider implements DataProvider @Inject protected Logger logger; + @Inject + private ScriptContextManager scriptContextManager; + + /** + * Used if needed by the extending classes to initialize the resources. + * + * @throws InitializationException + */ @Override public void initialize() throws InitializationException { // Overwrite to initialize a component } + + /** + * Generates the template of a data provider. + * + * @param data contains the data to be shown in the template. + * @param template path to the template. + * @param hint data provider identifier. + * @return String containing the generated template. + */ + protected String templateGenerator(Map data, String template, String hint) + { + Writer writer = new StringWriter(); + Template customTemplate = this.templateManager.getTemplate(template); + try { + // Set a document in the context to act as the current document when the template is rendered. + this.bindData(hint, data); + this.templateManager.render(customTemplate, writer); + return writer.toString(); + } catch (Exception e) { + logger.warn("Failed to render custom template. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); + } + return null; + } + + + private void bindData(String key, Map data) + { + ScriptContext scriptContext = scriptContextManager.getScriptContext(); + + scriptContext.setAttribute(key, data, ScriptContext.ENGINE_SCOPE); + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationDataProvider.java similarity index 86% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationDataProvider.java index 7215e8d1..3858e206 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationInfo.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationDataProvider.java @@ -28,13 +28,9 @@ import javax.inject.Provider; import javax.inject.Singleton; -import org.apache.commons.lang3.exception.ExceptionUtils; import org.xwiki.component.annotation.Component; import org.xwiki.component.phase.InitializationException; -import org.xwiki.rendering.block.Block; -import org.xwiki.template.Template; -import com.xpn.xwiki.XWikiContext; import com.xwiki.admintools.configuration.AdminToolsConfiguration; /** @@ -44,10 +40,15 @@ * @since 1.0 */ @Component -@Named("configuration") +@Named(ConfigurationDataProvider.HINT) @Singleton -public class ConfigurationInfo extends AbstractDataProvider +public class ConfigurationDataProvider extends AbstractDataProvider { + /** + * Stores the possible paths for the XWiki installation. + */ + public static final String HINT = "configuration"; + /** * Stores the path to the server. */ @@ -63,6 +64,9 @@ public class ConfigurationInfo extends AbstractDataProvider */ private String[] xwikiPossiblePaths; + /** + * Stores the possible paths for the XWiki installation. + */ @Inject private Provider adminToolsConfig; @@ -79,28 +83,33 @@ public void initialize() throws InitializationException * * @return xwiki configuration info json. */ - public Block provideData() + @Override + public String getIdentifier() + { + return HINT; + } + + /** + * Get the configuration info json. + * + * @return xwiki configuration info json. + */ + public String provideData() { updatePaths(); Map systemInfo = new HashMap<>(); - XWikiContext xcontext = xcontextProvider.get(); systemInfo.put("xwikiCfgPath", this.getXwikiCfgPath()); systemInfo.put("tomcatConfPath", this.getTomcatConfPath()); systemInfo.put("javaVersion", this.getJavaVersion()); systemInfo.put("osInfo", this.getOSInfo()); - Template customTemplate = this.templateManager.getTemplate("configurationTemplate.vm"); - try { - // Set a document in the context to act as the current document when the template is rendered. - - return this.templateManager.execute(customTemplate); - } catch (Exception e) { - logger.warn("Failed to render custom template. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); - } - return null; + return templateGenerator(systemInfo, "data/configurationTemplate.vm", HINT); } - + /** + * Get the configuration info json. + * + */ private void updatePaths() { String providedConfigServerPath = adminToolsConfig.get().getServerPath(); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityDataProvider.java similarity index 76% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityDataProvider.java index 4cbde3b1..9cdf22b7 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityInfo.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityDataProvider.java @@ -26,11 +26,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.commons.lang3.exception.ExceptionUtils; import org.xwiki.component.annotation.Component; import org.xwiki.configuration.ConfigurationSource; -import org.xwiki.rendering.block.Block; -import org.xwiki.template.Template; import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiContext; @@ -42,10 +39,16 @@ * @since 1.0 */ @Component -@Named("security") +@Named(SecurityDataProvider.HINT) @Singleton -public class SecurityInfo extends AbstractDataProvider +public class SecurityDataProvider extends AbstractDataProvider { + /** + * Get the configuration info json. + * + */ + public static final String HINT = "security"; + /** * Get the security details. */ @@ -58,7 +61,7 @@ public class SecurityInfo extends AbstractDataProvider * * @return the security details of the xwiki */ - public Block provideData() + public String provideData() { Map securityDetails = this.getXwikiSecurityInfo(); String workDirectory = "PWD"; @@ -67,18 +70,14 @@ public Block provideData() securityDetails.put("fileEncoding", getFileEncoding()); securityDetails.put(workDirectory, System.getenv(workDirectory)); securityDetails.put(language, System.getenv(language)); - XWikiContext xcontext = xcontextProvider.get(); - Template customTemplate = this.templateManager.getTemplate("configurationTemplate.vm"); - try { - // Set a document in the context to act as the current document when the template is rendered. - xcontext.setDoc(xcontext.getWiki().getDocument(ADMINTOOLS_DOC, xcontext)); + return templateGenerator(securityDetails, "data/securityTemplate.vm", HINT); + } - return this.templateManager.execute(customTemplate); - } catch (Exception e) { - logger.warn("Failed to render custom template. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); - } - return null; + @Override + public String getIdentifier() + { + return HINT; } /** diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index 87d4a898..607e5560 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -19,14 +19,11 @@ */ package com.xwiki.admintools.script; -import java.util.List; - import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import org.xwiki.component.annotation.Component; -import org.xwiki.rendering.block.Block; import org.xwiki.script.service.ScriptService; import com.xwiki.admintools.internal.AdminToolsManager; @@ -48,43 +45,24 @@ public class AdminToolsScriptService implements ScriptService @Inject private AdminToolsManager adminToolsManager; -// /** -// * Function used to retrieve the configuration info json. -// * -// * @return the configuration info json. -// */ -// public Map getConfigurationDetails() -// { -// return this.adminToolsManager.getConfigurationDetails(); -// } -// -// /** -// * Function used to retrieve the security info json. -// * -// * @return the configuration info json. -// */ -// public Map getSecurityDetails() -// { -// return this.adminToolsManager.getSecurityDetails(); -// } - /** - * Function used to retrieve the security info json. + * Function used to retrieve all the templates of Admin Tools. * - * @return the configuration info json. + * @return all templates. */ - public List getAllData() + public String getAllData() { return this.adminToolsManager.generateData(); } /** - * Function used to retrieve the security info json. + * Get sa specific data provider. * - * @return the configuration info json. + * @param hint represents the data provider + * @return the template of a specific data provider */ - public List getConfigData() + public String getSpecificData(String hint) { - return this.adminToolsManager.generateConfigData(); + return this.adminToolsManager.generateData(hint); } } diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index 68e791b3..ac996d5e 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -1,6 +1,6 @@ com.xwiki.admintools.script.AdminToolsScriptService com.xwiki.admintools.internal.AdminToolsManager -com.xwiki.admintools.internal.util.ConfigurationInfo -com.xwiki.admintools.internal.util.SecurityInfo +com.xwiki.admintools.internal.util.ConfigurationDataProvider +com.xwiki.admintools.internal.util.SecurityDataProvider com.xwiki.admintools.internal.configuration.AdminToolsConfigurationSource com.xwiki.admintools.internal.configuration.DefaultAdminToolsConfiguration diff --git a/application-admintools-default/src/main/resources/templates/configurationTemplate.vm b/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm similarity index 96% rename from application-admintools-default/src/main/resources/templates/configurationTemplate.vm rename to application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm index f6b7c26f..379603b0 100644 --- a/application-admintools-default/src/main/resources/templates/configurationTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm @@ -18,6 +18,11 @@ ## 02110-1301 USA, or see the FSF site: http://www.fsf.org. ## --------------------------------------------------------------------------- +{{html}}

test config class

-
\ No newline at end of file + +{{/html}} + + +$configuration diff --git a/application-admintools-default/src/main/resources/templates/data/securityTemplate.vm b/application-admintools-default/src/main/resources/templates/data/securityTemplate.vm new file mode 100644 index 00000000..8cc6a9d3 --- /dev/null +++ b/application-admintools-default/src/main/resources/templates/data/securityTemplate.vm @@ -0,0 +1,27 @@ +## --------------------------------------------------------------------------- +## See the NOTICE file distributed with this work for additional +## information regarding copyright ownership. +## +## This is free software; you can redistribute it and/or modify it +## under the terms of the GNU Lesser General Public License as +## published by the Free Software Foundation; either version 2.1 of +## the License, or (at your option) any later version. +## +## This software is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this software; if not, write to the Free +## Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +## 02110-1301 USA, or see the FSF site: http://www.fsf.org. +## --------------------------------------------------------------------------- + +{{html}} +
+

test security class

+
+{{/html}} + +$security From 93451010cbaf1e695ac19f98e6db7e47fdfc38b5 Mon Sep 17 00:00:00 2001 From: Sorin Date: Mon, 28 Aug 2023 12:00:57 +0300 Subject: [PATCH 12/72] Display App server info #3 Rewrited some of the comments and corrected some typos. --- .../admintools/internal/AdminToolsManager.java | 1 - .../xwiki/admintools/internal/DataProvider.java | 4 +++- .../internal/util/AbstractDataProvider.java | 15 ++++++--------- .../util/ConfigurationDataProvider.java | 17 +++++++---------- .../internal/util/SecurityDataProvider.java | 7 +++---- .../script/AdminToolsScriptService.java | 2 +- 6 files changed, 20 insertions(+), 26 deletions(-) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index 9d3d1e3a..db1d4a15 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -22,7 +22,6 @@ import java.util.List; import javax.inject.Inject; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java index ba221dc8..617e3b5b 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java @@ -39,7 +39,9 @@ public interface DataProvider String provideData(); /** - * If needed, it is used to initialize a template + * If needed, it is used to initialize a template. + * + * @throws InitializationException */ void initialize() throws InitializationException; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java index beb5ceae..eeadc6f9 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java @@ -48,9 +48,6 @@ public abstract class AbstractDataProvider implements DataProvider @Inject protected TemplateManager templateManager; - /** - * Get the security details. - */ @Inject protected Provider xcontextProvider; @@ -60,11 +57,6 @@ public abstract class AbstractDataProvider implements DataProvider @Inject private ScriptContextManager scriptContextManager; - /** - * Used if needed by the extending classes to initialize the resources. - * - * @throws InitializationException - */ @Override public void initialize() throws InitializationException { @@ -94,7 +86,12 @@ protected String templateGenerator(Map data, String template, St return null; } - + /** + * Binds the data provided by the DataProvider to the template. + * + * @param key + * @param data + */ private void bindData(String key, Map data) { ScriptContext scriptContext = scriptContextManager.getScriptContext(); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationDataProvider.java index 3858e206..c333f8d9 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationDataProvider.java @@ -45,7 +45,7 @@ public class ConfigurationDataProvider extends AbstractDataProvider { /** - * Stores the possible paths for the XWiki installation. + * The hint for the component. */ public static final String HINT = "configuration"; @@ -65,24 +65,21 @@ public class ConfigurationDataProvider extends AbstractDataProvider private String[] xwikiPossiblePaths; /** - * Stores the possible paths for the XWiki installation. + * Provides the XWiki configuration data. */ @Inject private Provider adminToolsConfig; /** - * The class initializer. + * Initialize the component. + * + * @throws InitializationException */ public void initialize() throws InitializationException { updatePaths(); } - /** - * Get the configuration info json. - * - * @return xwiki configuration info json. - */ @Override public String getIdentifier() { @@ -106,9 +103,9 @@ public String provideData() return templateGenerator(systemInfo, "data/configurationTemplate.vm", HINT); } + /** - * Get the configuration info json. - * + * Function used to update the possible paths to the xwiki and tomcat installations. */ private void updatePaths() { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityDataProvider.java index 9cdf22b7..47c82621 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityDataProvider.java @@ -44,13 +44,12 @@ public class SecurityDataProvider extends AbstractDataProvider { /** - * Get the configuration info json. - * + * The hint for the component. */ - public static final String HINT = "security"; + public static final String HINT = "security"; /** - * Get the security details. + * XWiki configuration file source. */ @Inject @Named("xwikicfg") diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index 607e5560..ff25d2b0 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -56,7 +56,7 @@ public String getAllData() } /** - * Get sa specific data provider. + * Get a specific data provider template. * * @param hint represents the data provider * @return the template of a specific data provider From e9bc0f4e08758188cf9e27601831d08f1e69e50d Mon Sep 17 00:00:00 2001 From: Sorin Date: Wed, 30 Aug 2023 12:23:21 +0300 Subject: [PATCH 13/72] Display App server info #3 Code refactoring --- .../com/xwiki/admintools}/DataProvider.java | 10 +---- application-admintools-default/pom.xml | 5 --- .../internal/AdminToolsManager.java | 2 + .../{util => data}/AbstractDataProvider.java | 7 ++-- .../ConfigurationDataProvider.java | 17 ++++++++- .../{util => data}/SecurityDataProvider.java | 38 +++++++++++-------- .../script/AdminToolsScriptService.java | 4 +- .../main/resources/META-INF/components.txt | 4 +- pom.xml | 2 +- 9 files changed, 50 insertions(+), 39 deletions(-) rename {application-admintools-default/src/main/java/com/xwiki/admintools/internal => application-admintools-api/src/main/java/com/xwiki/admintools}/DataProvider.java (82%) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/{util => data}/AbstractDataProvider.java (95%) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/{util => data}/ConfigurationDataProvider.java (92%) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/{util => data}/SecurityDataProvider.java (81%) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java similarity index 82% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java rename to application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java index 617e3b5b..32f2b11c 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/DataProvider.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java @@ -17,10 +17,9 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal; +package com.xwiki.admintools; import org.xwiki.component.annotation.Role; -import org.xwiki.component.phase.InitializationException; /** * Allows data gathering. @@ -38,13 +37,6 @@ public interface DataProvider */ String provideData(); - /** - * If needed, it is used to initialize a template. - * - * @throws InitializationException - */ - void initialize() throws InitializationException; - /** * Extract the hint of a component. * diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index 4e11f4c2..75a5cc0e 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -37,11 +37,6 @@ application-admintools-api ${project.version}
- - org.xwiki.platform - xwiki-platform-activeinstalls2-api - ${platform.version} - org.xwiki.platform xwiki-platform-oldcore diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index db1d4a15..f4e6c45d 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -27,6 +27,8 @@ import org.xwiki.component.annotation.Component; +import com.xwiki.admintools.DataProvider; + /** * Manage existing instances. or admin tools manager * diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java similarity index 95% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java index eeadc6f9..54f1cffd 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/AbstractDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.util; +package com.xwiki.admintools.internal.data; import java.io.StringWriter; import java.io.Writer; @@ -29,13 +29,14 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; +import org.xwiki.component.phase.Initializable; import org.xwiki.component.phase.InitializationException; import org.xwiki.script.ScriptContextManager; import org.xwiki.template.Template; import org.xwiki.template.TemplateManager; import com.xpn.xwiki.XWikiContext; -import com.xwiki.admintools.internal.DataProvider; +import com.xwiki.admintools.DataProvider; /** * To be extended by {@link DataProvider} implementations to simplify the code. @@ -43,7 +44,7 @@ * @version $Id$ * @since 1.0 */ -public abstract class AbstractDataProvider implements DataProvider +public abstract class AbstractDataProvider implements DataProvider, Initializable { @Inject protected TemplateManager templateManager; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java similarity index 92% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationDataProvider.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index c333f8d9..58e3eff5 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.util; +package com.xwiki.admintools.internal.data; import java.io.File; import java.util.HashMap; @@ -54,6 +54,11 @@ public class ConfigurationDataProvider extends AbstractDataProvider */ private String serverSystemPath; + /** + * Saves the server type. + */ + private String serverType; + /** * Stores the possible paths for tomcat. */ @@ -75,6 +80,7 @@ public class ConfigurationDataProvider extends AbstractDataProvider * * @throws InitializationException */ + @Override public void initialize() throws InitializationException { updatePaths(); @@ -104,6 +110,15 @@ public String provideData() return templateGenerator(systemInfo, "data/configurationTemplate.vm", HINT); } + public Map getServerIdentifiers() + { + Map serverIdentifiers = new HashMap<>(); + serverIdentifiers.put("serverPath", serverSystemPath); + serverIdentifiers.put("serverType", serverType); + + return serverIdentifiers; + } + /** * Function used to update the possible paths to the xwiki and tomcat installations. */ diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java similarity index 81% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityDataProvider.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java index 47c82621..21878149 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/SecurityDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.util; +package com.xwiki.admintools.internal.data; import java.util.HashMap; import java.util.Map; @@ -48,6 +48,10 @@ public class SecurityDataProvider extends AbstractDataProvider */ public static final String HINT = "security"; + private static final String workDirectory = "PWD"; + + private static final String language = "LANG"; + /** * XWiki configuration file source. */ @@ -63,12 +67,8 @@ public class SecurityDataProvider extends AbstractDataProvider public String provideData() { Map securityDetails = this.getXwikiSecurityInfo(); - String workDirectory = "PWD"; - String language = "LANG"; - securityDetails.put("fileEncoding", getFileEncoding()); - securityDetails.put(workDirectory, System.getenv(workDirectory)); - securityDetails.put(language, System.getenv(language)); + securityDetails.putAll(getEnvironmentInfo()); return templateGenerator(securityDetails, "data/securityTemplate.vm", HINT); } @@ -79,16 +79,6 @@ public String getIdentifier() return HINT; } - /** - * Get the encoding used for the files. - * - * @return the file encoding - */ - private String getFileEncoding() - { - return System.getProperty("file.encoding"); - } - /** * Get the security info of the current wiki. * @@ -105,6 +95,22 @@ private Map getXwikiSecurityInfo() results.put("activeEncoding", wikiEncoding); results.put("configurationEncoding", cfgEncoding); + results.put("fileEncoding", System.getProperty("file.encoding")); + + return results; + } + + /** + * Get the security info regarding the environment. + * + * @return environment security info. + */ + private Map getEnvironmentInfo() + { + Map results = new HashMap<>(); + + results.put(workDirectory, System.getenv(workDirectory)); + results.put(language, System.getenv(language)); return results; } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index ff25d2b0..2b004677 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -46,11 +46,11 @@ public class AdminToolsScriptService implements ScriptService private AdminToolsManager adminToolsManager; /** - * Function used to retrieve all the templates of Admin Tools. + * Function used to retrieve all the configuration info templates of Admin Tools. * * @return all templates. */ - public String getAllData() + public String getAllConfigurationTemplates() { return this.adminToolsManager.generateData(); } diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index ac996d5e..42d9da64 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -1,6 +1,6 @@ com.xwiki.admintools.script.AdminToolsScriptService com.xwiki.admintools.internal.AdminToolsManager -com.xwiki.admintools.internal.util.ConfigurationDataProvider -com.xwiki.admintools.internal.util.SecurityDataProvider +com.xwiki.admintools.internal.data.ConfigurationDataProvider +com.xwiki.admintools.internal.data.SecurityDataProvider com.xwiki.admintools.internal.configuration.AdminToolsConfigurationSource com.xwiki.admintools.internal.configuration.DefaultAdminToolsConfiguration diff --git a/pom.xml b/pom.xml index 4ddbf031..b9c3a732 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ com.xwiki.parent xwikisas-parent-platform - 14.10 + 13.10-3 com.xwiki.admintools application-admintools From 7439f99f9fd4af5ea7ea421d33748f206f2745c1 Mon Sep 17 00:00:00 2001 From: Sorin Date: Thu, 31 Aug 2023 14:29:24 +0300 Subject: [PATCH 14/72] Download important files #8 - DRAFT --- application-admintools-api/pom.xml | 10 ++ .../com/xwiki/admintools/FilesDownloader.java | 51 ++++++ .../admintools/rest/AdminToolsRestApi.java | 64 ++++++++ .../internal/downloads/DownloadsManager.java | 150 ++++++++++++++++++ .../downloads/TomcatFilesDownloader.java | 62 ++++++++ .../internal/rest/DefaultRestApi.java | 88 ++++++++++ .../main/resources/META-INF/components.txt | 2 + 7 files changed, 427 insertions(+) create mode 100644 application-admintools-api/src/main/java/com/xwiki/admintools/FilesDownloader.java create mode 100644 application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsRestApi.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatFilesDownloader.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultRestApi.java diff --git a/application-admintools-api/pom.xml b/application-admintools-api/pom.xml index c89369b0..23c47374 100644 --- a/application-admintools-api/pom.xml +++ b/application-admintools-api/pom.xml @@ -36,5 +36,15 @@ xwiki-commons-component-api ${commons.version} + + org.xwiki.contrib + xwiki-restserver-example + 4.1-SNAPSHOT + + + org.xwiki.platform + xwiki-platform-rest-server + ${platform.version} + \ No newline at end of file diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/FilesDownloader.java b/application-admintools-api/src/main/java/com/xwiki/admintools/FilesDownloader.java new file mode 100644 index 00000000..1d4efd80 --- /dev/null +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/FilesDownloader.java @@ -0,0 +1,51 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools; + +import java.util.Map; + +import org.xwiki.component.annotation.Role; + +/** + * Allows data gathering. CREATE AN ABSTRACT CLASS CONTAINING THE SAME FEATURES (adminToolsCfgProvider, templateManager, + * logger)? + * + * @version $Id$ + * @since 1.0 + */ +@Role +public interface FilesDownloader +{ + /** + * TBC. + * + * @param filter + * @param path + * @return TBC + */ + Object getLogs(Map filter, String path); + + /** + * Extract the hint of a component. + * + * @return component hint + */ + String getIdentifier(); +} diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsRestApi.java b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsRestApi.java new file mode 100644 index 00000000..f33cc7d8 --- /dev/null +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsRestApi.java @@ -0,0 +1,64 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.rest; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; + +import org.xwiki.rest.XWikiRestComponent; +import org.xwiki.rest.XWikiRestException; + +/** + * Provides the APIs needed by the collabora server in order to access a file and it's content, but also to save it. + * + * @version $Id$ + * @since 1.0 + */ +@Path("/admintools/download") +public interface AdminToolsRestApi extends XWikiRestComponent +{ + /** + * TBC. + * @param type + * @param token + * @return TBC + * @throws XWikiRestException + */ + @GET + @Path("/configs/{fileType}") + Response getConfigs(@PathParam("fileType") String type, @QueryParam("access_token") String token) + throws XWikiRestException; + + /** + * TBC. + * + * @param type + * @param token + * @return TBC + * @throws XWikiRestException + */ + @GET + @Path("/logs") + Response getLogs(@PathParam("fileType") String type, @QueryParam("access_token") String token) + throws XWikiRestException; +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java new file mode 100644 index 00000000..963b9864 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java @@ -0,0 +1,150 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.downloads; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.phase.Initializable; +import org.xwiki.component.phase.InitializationException; + +import com.xwiki.admintools.FilesDownloader; +import com.xwiki.admintools.internal.data.identifiers.CurrentServer; + +/** + * Encapsulates functions used for downloading configuration files. + * + * @version $Id$ + * @since 1.0 + */ +@Component(roles = DownloadsManager.class) +@Singleton +public class DownloadsManager implements Initializable +{ + /** + * TBC. + */ + @Inject + private CurrentServer currentServer; + + /** + * A list of all the data providers for Admin Tools. + */ + @Inject + private Provider> filesDownloader; + + private String serverPath; + + private String serverType; + + /** + * TBC. + * + * @throws InitializationException + */ + @Override + public void initialize() throws InitializationException + { + Map identifiers = currentServer.getServerIdentifiers(); + serverPath = identifiers.get("serverPath"); + serverType = identifiers.get("serverType"); + } + + /** + * TBC. + * + * @param fileType TBC. + * @return TBC. + * @throws IOException + */ + public byte[] downloadXWikiFile(String fileType) throws IOException + { + return prepareFile(fileType); + } + + /** + * TBC. + * + * @param filters TBC + * @return TBC + */ + public Object downloadLogs(Map filters) + { + return callLogsDownloader(serverType + "Logs", filters); + } + + /** + * As all servers have the same path to the xwiki properties and configuration files, it is not needed to call this + * function in a server specific class. + * + * @param type + * @return + * @throws IOException + */ + private byte[] prepareFile(String type) throws IOException + { + String filePath = serverPath; + if (Objects.equals(type, "properties")) { + filePath += "/webapps/xwiki/WEB-INF/xwiki.properties"; + } else { + filePath += "/webapps/xwiki/WEB-INF/xwiki.cfg"; + } + File inputFile = new File(filePath); + + BufferedReader reader = new BufferedReader(new FileReader(inputFile)); + StringBuilder stringBuilder = new StringBuilder(); + + String currentLine; + List wordsList = new ArrayList<>( + Arrays.asList("xwiki.authentication.validationKey", "xwiki.authentication.encryptionKey", + "xwiki.superadminpassword", "extension.repositories.privatemavenid.auth", "mail.sender.password")); + while ((currentLine = reader.readLine()) != null) { + String trimmedLine = currentLine.trim(); + if (wordsList.stream().anyMatch(trimmedLine::contains)) { + continue; + } + stringBuilder.append(currentLine).append(System.getProperty("line.separator")); + } + reader.close(); + return stringBuilder.toString().getBytes(); + } + + private Object callLogsDownloader(String hint, Map filter) + { + for (FilesDownloader specificFilesDownloader : this.filesDownloader.get()) { + if (specificFilesDownloader.getIdentifier().equals(hint)) { + return specificFilesDownloader.getLogs(filter, serverPath); + } + } + return null; + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatFilesDownloader.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatFilesDownloader.java new file mode 100644 index 00000000..74e53a4b --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatFilesDownloader.java @@ -0,0 +1,62 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.downloads; + +import java.util.Map; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.FilesDownloader; + +/** + * Encapsulates functions used for downloading configuration files. + * + * @version $Id$ + * @since 1.0 + */ +@Component(roles = TomcatFilesDownloader.class) +@Named(TomcatFilesDownloader.HINT) +@Singleton +public class TomcatFilesDownloader implements FilesDownloader +{ + /** + * The hint for the component. + */ + public static final String HINT = "tomcatLogs"; + + /** + * @param filter + * @return + */ + @Override + public Object getLogs(Map filter, String path) + { + return null; + } + + @Override + public String getIdentifier() + { + return HINT; + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultRestApi.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultRestApi.java new file mode 100644 index 00000000..5c997b5b --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultRestApi.java @@ -0,0 +1,88 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.rest; + +import javax.inject.Inject; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.xwiki.rest.XWikiRestException; + +import com.xwiki.admintools.internal.downloads.DownloadsManager; +import com.xwiki.admintools.rest.AdminToolsRestApi; + +/** + * TBC. + * + * @version $Id$ + * @since 1.0 + */ +public class DefaultRestApi implements AdminToolsRestApi +{ + @Inject + private Logger logger; + + @Inject + private DownloadsManager downloadsManager; + + @Override + @Produces(MediaType.APPLICATION_OCTET_STREAM) + public Response getConfigs(String type, String token) throws XWikiRestException + { +// if (token == null || !fileTokenManager.hasAccess(token)) { +// logger.warn("Failed to get file [{}] due to invalid token or restricted rights.", fileId); +// throw new WebApplicationException(Response.Status.UNAUTHORIZED); +// } + try { + byte[] xWikiFile = downloadsManager.downloadXWikiFile(type); + String contentDisposition = "Content-Disposition"; + if (type.equals("properties")) { + return Response.ok(xWikiFile, MediaType.APPLICATION_OCTET_STREAM) + .header(contentDisposition, "attachment; filename = xwiki.properties").build(); + } else if (type.equals("configuration")) { + return Response.ok(xWikiFile, MediaType.APPLICATION_OCTET_STREAM) + .header(contentDisposition, "attachment; filename = xwiki.cfg").build(); + } else { + return Response.status(401).build(); + } + } catch (Exception e) { + logger.warn("Failed to get file [{}]. Root cause: [{}]", type, ExceptionUtils.getRootCauseMessage(e)); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } + + /** + * TBC. + * + * @param type + * @param token + * @return TBC + * @throws XWikiRestException + */ + @Override + public Response getLogs(String type, String token) throws XWikiRestException + { + return null; + } +} diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index 42d9da64..109fe32c 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -2,5 +2,7 @@ com.xwiki.admintools.script.AdminToolsScriptService com.xwiki.admintools.internal.AdminToolsManager com.xwiki.admintools.internal.data.ConfigurationDataProvider com.xwiki.admintools.internal.data.SecurityDataProvider +com.xwiki.admintools.internal.downloads.TomcatFilesDownloader +com.xwiki.admintools.internal.downloads.DownloadsManager com.xwiki.admintools.internal.configuration.AdminToolsConfigurationSource com.xwiki.admintools.internal.configuration.DefaultAdminToolsConfiguration From fa919650f078c3beebc874ced44269fe18ddb306 Mon Sep 17 00:00:00 2001 From: Sorin Date: Thu, 31 Aug 2023 15:38:15 +0300 Subject: [PATCH 15/72] Display App server info #3 --- .../xwiki/admintools/ServerIdentifier.java | 75 ++++++++++ .../DefaultAdminToolsConfiguration.java | 5 + .../internal/data/AbstractDataProvider.java | 4 +- .../data/ConfigurationDataProvider.java | 117 ++------------- .../internal/data/SecurityDataProvider.java | 17 ++- .../identifiers/AbstractServerIdentifier.java | 87 ++++++++++++ .../data/identifiers/CurrentServer.java | 134 ++++++++++++++++++ .../data/identifiers/TomcatIdentifier.java | 121 ++++++++++++++++ .../script/AdminToolsScriptService.java | 4 +- .../main/resources/META-INF/components.txt | 2 + 10 files changed, 445 insertions(+), 121 deletions(-) create mode 100644 application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java new file mode 100644 index 00000000..4c6f642c --- /dev/null +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java @@ -0,0 +1,75 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools; + +import java.util.Map; + +import org.xwiki.component.annotation.Role; + +/** + * TBC. + * + * @version $Id$ + * @since 1.0 + */ +@Role +public interface ServerIdentifier +{ + /** + * TBC. + * @param providedConfigServerPath TBC + * @return TBC + */ + boolean isUsed(String providedConfigServerPath); + + /** + * Extract the hint of a component. + * + * @return component hint + */ + String getIdentifier(); + + /** + * TBC. + * + * @return TBC + */ + String getServerCfgPath(); + + /** + * TBC. + * + * @return TBC + */ + String getXwikiCfgPath(); + + /** + * TBC. + * + * @param providedConfigServerPath TBC + */ + void updatePaths(String providedConfigServerPath); + + /** + * TBC. + * @return TBC + */ + Map getServerIdentifiers(); +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java index 2122e6a3..5a07487a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java @@ -35,9 +35,14 @@ * @since 1.0 */ @Component +@Named(DefaultAdminToolsConfiguration.HINT) @Singleton public class DefaultAdminToolsConfiguration implements AdminToolsConfiguration { + /** + * Component identifier. + */ + public static final String HINT = "defaultConfiguration"; private static final String SERVER_LOCATION = "serverLocation"; @Inject diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java index 54f1cffd..6ae43c92 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java @@ -72,12 +72,12 @@ public void initialize() throws InitializationException * @param hint data provider identifier. * @return String containing the generated template. */ - protected String templateGenerator(Map data, String template, String hint) + protected String getRenderedTemplate(String template, Map data, String hint) { Writer writer = new StringWriter(); Template customTemplate = this.templateManager.getTemplate(template); try { - // Set a document in the context to act as the current document when the template is rendered. + // Binds the data provided to the template. this.bindData(hint, data); this.templateManager.render(customTemplate, writer); return writer.toString(); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index 58e3eff5..cf42ca2c 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -19,19 +19,16 @@ */ package com.xwiki.admintools.internal.data; -import java.io.File; import java.util.HashMap; import java.util.Map; import javax.inject.Inject; import javax.inject.Named; -import javax.inject.Provider; import javax.inject.Singleton; import org.xwiki.component.annotation.Component; -import org.xwiki.component.phase.InitializationException; -import com.xwiki.admintools.configuration.AdminToolsConfiguration; +import com.xwiki.admintools.internal.data.identifiers.CurrentServer; /** * Encapsulates functions used for retrieving configuration data. @@ -50,41 +47,10 @@ public class ConfigurationDataProvider extends AbstractDataProvider public static final String HINT = "configuration"; /** - * Stores the path to the server. - */ - private String serverSystemPath; - - /** - * Saves the server type. - */ - private String serverType; - - /** - * Stores the possible paths for tomcat. - */ - private String[] tomcatPossiblePaths; - - /** - * Stores the possible paths for the XWiki installation. - */ - private String[] xwikiPossiblePaths; - - /** - * Provides the XWiki configuration data. + * Collection of functions used to retrieve info about the current server paths and type. */ @Inject - private Provider adminToolsConfig; - - /** - * Initialize the component. - * - * @throws InitializationException - */ - @Override - public void initialize() throws InitializationException - { - updatePaths(); - } + private CurrentServer usedServer; @Override public String getIdentifier() @@ -93,86 +59,21 @@ public String getIdentifier() } /** - * Get the configuration info json. + * Get the configuration info template. * * @return xwiki configuration info json. */ + @Override public String provideData() { - updatePaths(); + usedServer.updatePaths(); Map systemInfo = new HashMap<>(); - - systemInfo.put("xwikiCfgPath", this.getXwikiCfgPath()); - systemInfo.put("tomcatConfPath", this.getTomcatConfPath()); + systemInfo.put("xwikiCfgPath", usedServer.getXwikiCfgPath()); + systemInfo.put("tomcatConfPath", this.usedServer.getServerCfgPath()); systemInfo.put("javaVersion", this.getJavaVersion()); systemInfo.put("osInfo", this.getOSInfo()); - return templateGenerator(systemInfo, "data/configurationTemplate.vm", HINT); - } - - public Map getServerIdentifiers() - { - Map serverIdentifiers = new HashMap<>(); - serverIdentifiers.put("serverPath", serverSystemPath); - serverIdentifiers.put("serverType", serverType); - - return serverIdentifiers; - } - - /** - * Function used to update the possible paths to the xwiki and tomcat installations. - */ - private void updatePaths() - { - String providedConfigServerPath = adminToolsConfig.get().getServerPath(); - if (providedConfigServerPath != null) { - this.serverSystemPath = providedConfigServerPath; - } else { - String catalinaBase = System.getProperty("catalina.base"); - if (catalinaBase != null) { - this.serverSystemPath = catalinaBase; - } else { - this.serverSystemPath = System.getenv("CATALINA_HOME"); - } - } - - this.tomcatPossiblePaths = new String[] { String.format("%s/conf/server.xml", this.serverSystemPath), - "/usr/local/tomcat/conf/server.xml", "/opt/tomcat/conf/server.xml", "/var/lib/tomcat8/conf/", - "/var/lib/tomcat9/conf/", "/var/lib/tomcat/conf/" }; - - this.xwikiPossiblePaths = new String[] { "/etc/xwiki/xwiki.cfg", - String.format("%s/webapps${request.contextPath}/WEB-INF/xwiki.cfg", this.serverSystemPath), - "/usr/local/xwiki/WEB-INF/xwiki.cfg", "/opt/xwiki/WEB-INF/xwiki.cfg", - String.format("%s/webapps/ROOT/WEB-INF/xwiki.cfg", this.serverSystemPath), - String.format("%s/webapps/xwiki/WEB-INF/xwiki.cfg", this.serverSystemPath) }; - } - - /** - * Get the configuration file path for the XWiki. - */ - private String getXwikiCfgPath() - { - for (String xwCfgPath : xwikiPossiblePaths) { - if ((new File(xwCfgPath)).exists()) { - return xwCfgPath; - } - } - return null; - } - - /** - * Get the configuration file path for Tomcat. - * - * @return path to Tomcat configuration file. - */ - private String getTomcatConfPath() - { - for (String tomConfPath : tomcatPossiblePaths) { - if ((new File(tomConfPath)).exists()) { - return tomConfPath; - } - } - return null; + return getRenderedTemplate("data/configurationTemplate.vm", systemInfo, HINT); } /** diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java index 21878149..f9c6cabb 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java @@ -48,9 +48,9 @@ public class SecurityDataProvider extends AbstractDataProvider */ public static final String HINT = "security"; - private static final String workDirectory = "PWD"; + private static final String WORK_DIRECTORY = "PWD"; - private static final String language = "LANG"; + private static final String LANGUAGE = "LANG"; /** * XWiki configuration file source. @@ -64,13 +64,14 @@ public class SecurityDataProvider extends AbstractDataProvider * * @return the security details of the xwiki */ + @Override public String provideData() { Map securityDetails = this.getXwikiSecurityInfo(); securityDetails.putAll(getEnvironmentInfo()); - return templateGenerator(securityDetails, "data/securityTemplate.vm", HINT); + return getRenderedTemplate("data/securityTemplate.vm", securityDetails, HINT); } @Override @@ -90,11 +91,9 @@ private Map getXwikiSecurityInfo() XWikiContext wikiContext = xcontextProvider.get(); XWiki wiki = wikiContext.getWiki(); - String wikiEncoding = wiki.getEncoding(); - String cfgEncoding = configurationSource.getProperty("xwiki.encoding", String.class); - results.put("activeEncoding", wikiEncoding); - results.put("configurationEncoding", cfgEncoding); + results.put("activeEncoding", wiki.getEncoding()); + results.put("configurationEncoding", configurationSource.getProperty("xwiki.encoding", String.class)); results.put("fileEncoding", System.getProperty("file.encoding")); return results; @@ -109,8 +108,8 @@ private Map getEnvironmentInfo() { Map results = new HashMap<>(); - results.put(workDirectory, System.getenv(workDirectory)); - results.put(language, System.getenv(language)); + results.put(WORK_DIRECTORY, System.getenv(WORK_DIRECTORY)); + results.put(LANGUAGE, System.getenv(LANGUAGE)); return results; } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java new file mode 100644 index 00000000..e644db2f --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java @@ -0,0 +1,87 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.data.identifiers; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import com.xwiki.admintools.ServerIdentifier; + +/** + * Implements methods to ease the usage of the server identifiers. + * + * @version $Id$ + * @since 1.0 + */ +public abstract class AbstractServerIdentifier implements ServerIdentifier +{ + protected String[] serverCfgPossiblePaths; + + protected String[] xwikiCfgPossiblePaths; + + /** + * The path to the server. + */ + protected String serverPath; + + @Override + public Map getServerIdentifiers() + { + Map serverIdentifiers = new HashMap<>(); + serverIdentifiers.put("serverPath", serverPath); + serverIdentifiers.put("serverType", getIdentifier()); + + return serverIdentifiers; + } + + /** + * Get the configuration file path for Tomcat. + * + * @return path to Tomcat configuration file. + */ + @Override + public String getServerCfgPath() + { + for (String serverCfgPath : serverCfgPossiblePaths) { + if ((new File(serverCfgPath)).exists()) { + return serverCfgPath; + } + } + return null; + } + + /** + * Get the configuration file path for the XWiki. + * + * @return path to the XWiki configuration file. + */ + @Override + public String getXwikiCfgPath() + { + for (String xwikiCfgPath : xwikiCfgPossiblePaths) { + if ((new File(xwikiCfgPath)).exists()) { + return xwikiCfgPath; + } + } + return null; + } +} + diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java new file mode 100644 index 00000000..9f875430 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java @@ -0,0 +1,134 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.data.identifiers; + +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; +import org.xwiki.component.phase.Initializable; +import org.xwiki.component.phase.InitializationException; + +import com.xwiki.admintools.ServerIdentifier; +import com.xwiki.admintools.configuration.AdminToolsConfiguration; +import com.xwiki.admintools.internal.configuration.DefaultAdminToolsConfiguration; + +/** + * Manages the server identifiers and offers endpoints to retrieve info about their paths. + * + * @version $Id$ + * @since 1.0 + */ +@Component(roles = CurrentServer.class) +@Singleton +public class CurrentServer implements Initializable +{ + @Inject + private Provider> supportedServers; + + private ServerIdentifier usedServer; + + @Inject + @Named(DefaultAdminToolsConfiguration.HINT) + private AdminToolsConfiguration adminToolsConfig; + + /** + * Method called by the Component Manager when the component is created for the first time (i.e. when it's looked up + * for the first time or if the component is specified as being loaded on startup). If the component instantiation + * strategy is singleton then this method is called only once during the lifecycle of the Component Manager. + * Otherwise the component is created at each lookup and thus this method is called at each lookup too. + * + * @throws InitializationException if an error happens during a component's initialization + */ + @Override + public void initialize() throws InitializationException + { + String providedConfigServerPath = adminToolsConfig.getServerPath(); + findServer(providedConfigServerPath); + } + + /** + * Retrieves the XWiki configuration file path for the installation. + * + * @return a String representing the path to the XWiki configuration file. + */ + public String getXwikiCfgPath() + { + return usedServer.getXwikiCfgPath(); + } + + /** + * Retrieves the server configuration file path for the installation. + * + * @return a String representing the path to the server configuration file. + */ + public String getServerCfgPath() + { + return usedServer.getServerCfgPath(); + } + + /** + * Verifies if a server type was found and updates the paths. + */ + public void updatePaths() + { + String providedConfigServerPath = adminToolsConfig.getServerPath(); + if (usedServer == null) { + findServer(providedConfigServerPath); + usedServer.updatePaths(providedConfigServerPath); + } else { + usedServer.updatePaths(providedConfigServerPath); + } + } + + /** + * Retrieves the server type. + * + * @return a string representing the server HINT. + */ + public String getServerType() + { + return usedServer.getIdentifier(); + } + + /** + * Calls the used server function to retrieve the server identifiers. + * + * @return a Map with the info used to identify the server. + */ + public Map getServerIdentifiers() + { + return usedServer.getServerIdentifiers(); + } + + private void findServer(String providedConfigServerPath) + { + for (ServerIdentifier serverIdentifier : this.supportedServers.get()) { + if (serverIdentifier.isUsed(providedConfigServerPath)) { + usedServer = serverIdentifier; + } + } + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java new file mode 100644 index 00000000..1e5cdf6a --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java @@ -0,0 +1,121 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.data.identifiers; + +import java.io.File; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; + +/** + * Encapsulates functions used for identifying a Tomcat server and retrieving it's info. + * + * @version $Id$ + * @since 1.0 + */ +@Component +@Named(TomcatIdentifier.HINT) +@Singleton +public class TomcatIdentifier extends AbstractServerIdentifier +{ + /** + * Component identifier. + */ + public static final String HINT = "tomcat"; + + /** + * Verify if this server is the one that stores the XWiki instance. + * + * @return true if this server is used, false otherwise + */ + @Override + public boolean isUsed(String providedConfigServerPath) + { + if (tomcatIsUsed(providedConfigServerPath)) { + updatePaths(providedConfigServerPath); + return true; + } else { + return false; + } + } + + /** + * Extract the hint of a component. + * + * @return component hint + */ + @Override + public String getIdentifier() + { + return HINT; + } + + /** + * Update the possible paths to the configuration files. + * + * @param providedConfigServerPath the server path provided in the XWiki configuration page. + */ + @Override + public void updatePaths(String providedConfigServerPath) + { + if (tomcatIsUsed(providedConfigServerPath)) { + this.serverCfgPossiblePaths = new String[] { String.format("%s/conf/server.xml", this.serverPath), + "/usr/local/tomcat/conf/server.xml", "/opt/tomcat/conf/server.xml", "/var/lib/tomcat8/conf/", + "/var/lib/tomcat9/conf/", "/var/lib/tomcat/conf/" }; + + this.xwikiCfgPossiblePaths = new String[] { "/etc/xwiki/xwiki.cfg", + String.format("%s/webapps${request.contextPath}/WEB-INF/xwiki.cfg", this.serverPath), + "/usr/local/xwiki/WEB-INF/xwiki.cfg", "/opt/xwiki/WEB-INF/xwiki.cfg", + String.format("%s/webapps/ROOT/WEB-INF/xwiki.cfg", this.serverPath), + String.format("%s/webapps/xwiki/WEB-INF/xwiki.cfg", this.serverPath) }; + } + } + + /** + * Function used to verify if a Tomcat server is used. + * + * @param providedConfigServerPath the server path provided in the XWiki configuration page. + * @return true if Tomcat is the used server, false otherwise + */ + private boolean tomcatIsUsed(String providedConfigServerPath) + { + if (providedConfigServerPath != null) { + File file = new File(providedConfigServerPath + "conf/catalina.properties"); + if (file.exists()) { + this.serverPath = providedConfigServerPath; + return true; + } + } + String catalinaBase = System.getProperty("catalina.base"); + String catalinaHome = System.getenv("CATALINA_HOME"); + + if (catalinaBase != null) { + this.serverPath = catalinaBase; + } else if (catalinaHome != null) { + this.serverPath = catalinaHome; + } else { + this.serverPath = null; + return false; + } + return true; + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index 2b004677..8d324e42 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -50,7 +50,7 @@ public class AdminToolsScriptService implements ScriptService * * @return all templates. */ - public String getAllConfigurationTemplates() + public String getConfigurationData() { return this.adminToolsManager.generateData(); } @@ -61,7 +61,7 @@ public String getAllConfigurationTemplates() * @param hint represents the data provider * @return the template of a specific data provider */ - public String getSpecificData(String hint) + public String getConfigurationData(String hint) { return this.adminToolsManager.generateData(hint); } diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index 42d9da64..9f01ca2c 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -2,5 +2,7 @@ com.xwiki.admintools.script.AdminToolsScriptService com.xwiki.admintools.internal.AdminToolsManager com.xwiki.admintools.internal.data.ConfigurationDataProvider com.xwiki.admintools.internal.data.SecurityDataProvider +com.xwiki.admintools.internal.data.identifiers.CurrentServer +com.xwiki.admintools.internal.data.identifiers.TomcatIdentifier com.xwiki.admintools.internal.configuration.AdminToolsConfigurationSource com.xwiki.admintools.internal.configuration.DefaultAdminToolsConfiguration From 57cebb5a16268d3044084028b1a46030a5bfe90a Mon Sep 17 00:00:00 2001 From: Sorin Date: Tue, 5 Sep 2023 09:26:18 +0300 Subject: [PATCH 16/72] Display App server info #3 --- .../com/xwiki/admintools/DataProvider.java | 2 +- .../xwiki/admintools/ServerIdentifier.java | 25 ++++++++++--------- .../internal/AdminToolsManager.java | 8 +++--- .../internal/data/AbstractDataProvider.java | 1 - .../data/ConfigurationDataProvider.java | 12 ++------- .../internal/data/SecurityDataProvider.java | 5 +++- .../identifiers/AbstractServerIdentifier.java | 4 +-- .../data/identifiers/CurrentServer.java | 6 +++++ .../data/identifiers/TomcatIdentifier.java | 16 +++--------- 9 files changed, 36 insertions(+), 43 deletions(-) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java index 32f2b11c..0e518cf0 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java @@ -22,7 +22,7 @@ import org.xwiki.component.annotation.Role; /** - * Allows data gathering. + * Gathers specific parts of data and provides the template for it. * * @version $Id$ * @since 1.0 diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java index 4c6f642c..b0aafdd5 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java @@ -24,7 +24,8 @@ import org.xwiki.component.annotation.Role; /** - * TBC. + * Endpoints for identifying the used server and the paths to the configuration files of the server and XWiki + * installation. * * @version $Id$ * @since 1.0 @@ -33,9 +34,9 @@ public interface ServerIdentifier { /** - * TBC. - * @param providedConfigServerPath TBC - * @return TBC + * Check if this server type is used. + * @param providedConfigServerPath path to the server provided by XWiki configuration. + * @return true if the server is used, false otherwise. */ boolean isUsed(String providedConfigServerPath); @@ -47,29 +48,29 @@ public interface ServerIdentifier String getIdentifier(); /** - * TBC. + * Access the path to the server configuration file. * - * @return TBC + * @return String representing the path to the server configuration file. */ String getServerCfgPath(); /** - * TBC. + * Access the path to the XWiki configuration file. * - * @return TBC + * @return String representing the path to the XWiki configuration file. */ String getXwikiCfgPath(); /** - * TBC. + * Update the possible paths to the configuration files. * - * @param providedConfigServerPath TBC + * @param providedConfigServerPath the server path provided in the XWiki configuration page. */ void updatePaths(String providedConfigServerPath); /** - * TBC. - * @return TBC + * Access the server path and type. + * @return Map containing server path and type. */ Map getServerIdentifiers(); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index f4e6c45d..74ecaee9 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -30,7 +30,7 @@ import com.xwiki.admintools.DataProvider; /** - * Manage existing instances. or admin tools manager + * Manages the data providers. * * @version $Id$ * @since 1.0 @@ -46,9 +46,9 @@ public class AdminToolsManager private Provider> dataProviderProvider; /** - * Merges all the templates. + * Merges all templates generated by the data providers. * - * @return a string containing all templates. + * @return a string containing all templates builds. */ public String generateData() { @@ -62,7 +62,7 @@ public String generateData() } /** - * Extract a specific template. + * Extract a specific data provider template. * * @param hint represents the data provider identifier. * @return a String representing a template diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java index 6ae43c92..6d84c608 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java @@ -96,7 +96,6 @@ protected String getRenderedTemplate(String template, Map data, private void bindData(String key, Map data) { ScriptContext scriptContext = scriptContextManager.getScriptContext(); - scriptContext.setAttribute(key, data, ScriptContext.ENGINE_SCOPE); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index cf42ca2c..295a84f8 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -46,9 +46,6 @@ public class ConfigurationDataProvider extends AbstractDataProvider */ public static final String HINT = "configuration"; - /** - * Collection of functions used to retrieve info about the current server paths and type. - */ @Inject private CurrentServer usedServer; @@ -58,11 +55,6 @@ public String getIdentifier() return HINT; } - /** - * Get the configuration info template. - * - * @return xwiki configuration info json. - */ @Override public String provideData() { @@ -77,7 +69,7 @@ public String provideData() } /** - * Get the used version of Java. + * Get the version of Java used on the server. * * @return the used Java version. */ @@ -87,7 +79,7 @@ private String getJavaVersion() } /** - * Get info about the OS XWiki is running on. + * Get info about the OS that XWiki is running on. * * @return info about the OS. */ diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java index f9c6cabb..15923af2 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java @@ -28,6 +28,8 @@ import org.xwiki.component.annotation.Component; import org.xwiki.configuration.ConfigurationSource; +import org.xwiki.model.reference.DocumentReference; +import org.xwiki.model.reference.WikiReference; import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiContext; @@ -91,7 +93,8 @@ private Map getXwikiSecurityInfo() XWikiContext wikiContext = xcontextProvider.get(); XWiki wiki = wikiContext.getWiki(); - + DocumentReference a = wikiContext.getUserReference(); + WikiReference b = wikiContext.getWikiReference(); results.put("activeEncoding", wiki.getEncoding()); results.put("configurationEncoding", configurationSource.getProperty("xwiki.encoding", String.class)); results.put("fileEncoding", System.getProperty("file.encoding")); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java index e644db2f..7d8de45e 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java @@ -53,7 +53,7 @@ public Map getServerIdentifiers() } /** - * Get the configuration file path for Tomcat. + * Get the server configuration file path. * * @return path to Tomcat configuration file. */ @@ -69,7 +69,7 @@ public String getServerCfgPath() } /** - * Get the configuration file path for the XWiki. + * Get the configuration file path for the XWiki installation. * * @return path to the XWiki configuration file. */ diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java index 9f875430..09bdaa55 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java @@ -123,11 +123,17 @@ public Map getServerIdentifiers() return usedServer.getServerIdentifiers(); } + /** + * Go through all supported servers and return the one that is used. + * + * @param providedConfigServerPath server path provided by XWiki configurations. + */ private void findServer(String providedConfigServerPath) { for (ServerIdentifier serverIdentifier : this.supportedServers.get()) { if (serverIdentifier.isUsed(providedConfigServerPath)) { usedServer = serverIdentifier; + break; } } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java index 1e5cdf6a..9223c213 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java @@ -58,22 +58,12 @@ public boolean isUsed(String providedConfigServerPath) } } - /** - * Extract the hint of a component. - * - * @return component hint - */ @Override public String getIdentifier() { return HINT; } - /** - * Update the possible paths to the configuration files. - * - * @param providedConfigServerPath the server path provided in the XWiki configuration page. - */ @Override public void updatePaths(String providedConfigServerPath) { @@ -91,10 +81,12 @@ public void updatePaths(String providedConfigServerPath) } /** - * Function used to verify if a Tomcat server is used. + * Function used to verify if a Tomcat server is used. If a server path is provided in the XWiki + * configurations, it verifies if the path corresponds to a Tomcat server. Otherwise, it searches the Catalina + * location in system properties and system environment. * * @param providedConfigServerPath the server path provided in the XWiki configuration page. - * @return true if Tomcat is the used server, false otherwise + * @return true if Tomcat is the used server, false otherwise. */ private boolean tomcatIsUsed(String providedConfigServerPath) { From a1096b34a23f7a4602acbc83e26d6e641d8fa276 Mon Sep 17 00:00:00 2001 From: Sorin Date: Tue, 5 Sep 2023 09:52:08 +0300 Subject: [PATCH 17/72] Download important files #8 --- .../com/xwiki/admintools/DataProvider.java | 2 +- ...lesDownloader.java => LogsDownloader.java} | 14 +++-- .../xwiki/admintools/ServerIdentifier.java | 27 +++++----- ...sRestApi.java => AdminToolsResources.java} | 23 ++++---- .../internal/AdminToolsManager.java | 8 +-- .../data/ConfigurationDataProvider.java | 12 +---- .../identifiers/AbstractServerIdentifier.java | 4 +- .../data/identifiers/CurrentServer.java | 6 +++ .../data/identifiers/TomcatIdentifier.java | 16 ++---- .../downloads/AbstractLogsDownloader.java | 50 ++++++++++++----- .../internal/downloads/DownloadsManager.java | 54 +++++++++++-------- .../downloads/TomcatLogsDownloader.java | 11 +--- ...aultRestApi.java => DefaultResources.java} | 36 ++++++------- .../main/resources/META-INF/components.txt | 2 +- 14 files changed, 139 insertions(+), 126 deletions(-) rename application-admintools-api/src/main/java/com/xwiki/admintools/{FilesDownloader.java => LogsDownloader.java} (73%) rename application-admintools-api/src/main/java/com/xwiki/admintools/rest/{AdminToolsRestApi.java => AdminToolsResources.java} (67%) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/{DefaultRestApi.java => DefaultResources.java} (83%) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java index 32f2b11c..0e518cf0 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java @@ -22,7 +22,7 @@ import org.xwiki.component.annotation.Role; /** - * Allows data gathering. + * Gathers specific parts of data and provides the template for it. * * @version $Id$ * @since 1.0 diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/FilesDownloader.java b/application-admintools-api/src/main/java/com/xwiki/admintools/LogsDownloader.java similarity index 73% rename from application-admintools-api/src/main/java/com/xwiki/admintools/FilesDownloader.java rename to application-admintools-api/src/main/java/com/xwiki/admintools/LogsDownloader.java index 6bd55974..534d55e0 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/FilesDownloader.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/LogsDownloader.java @@ -20,26 +20,24 @@ package com.xwiki.admintools; import java.util.Map; -import java.util.zip.ZipEntry; import org.xwiki.component.annotation.Role; /** - * Allows data gathering. CREATE AN ABSTRACT CLASS CONTAINING THE SAME FEATURES (adminToolsCfgProvider, templateManager, - * logger)? + * Interface to be extended by specific server types. Function are used when the logs download REST API is accessed. * * @version $Id$ * @since 1.0 */ @Role -public interface FilesDownloader +public interface LogsDownloader { /** - * TBC. + * Generates the logs archive from a specified path that are to be downloaded after applying the filters. * - * @param filter - * @param path - * @return TBC + * @param filter Map representing the filters that can be applied to the search. + * @param path path to where the logs are stored. + * @return byte array representing the logs archive. */ byte[] generateLogsArchive(Map filter, String path); diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java index 4c6f642c..39f39446 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java @@ -24,7 +24,8 @@ import org.xwiki.component.annotation.Role; /** - * TBC. + * Endpoints for identifying the used server and the paths to the configuration files of the server and XWiki + * installation. * * @version $Id$ * @since 1.0 @@ -33,9 +34,10 @@ public interface ServerIdentifier { /** - * TBC. - * @param providedConfigServerPath TBC - * @return TBC + * Check if this server type is used. + * + * @param providedConfigServerPath path to the server provided by XWiki configuration. + * @return true if the server is used, false otherwise. */ boolean isUsed(String providedConfigServerPath); @@ -47,29 +49,30 @@ public interface ServerIdentifier String getIdentifier(); /** - * TBC. + * Access the path to the server configuration file. * - * @return TBC + * @return String representing the path to the server configuration file. */ String getServerCfgPath(); /** - * TBC. + * Access the path to the XWiki configuration file. * - * @return TBC + * @return String representing the path to the XWiki configuration file. */ String getXwikiCfgPath(); /** - * TBC. + * Update the possible paths to the configuration files. * - * @param providedConfigServerPath TBC + * @param providedConfigServerPath the server path provided in the XWiki configuration page. */ void updatePaths(String providedConfigServerPath); /** - * TBC. - * @return TBC + * Access the server path and type. + * + * @return Map containing server path and type. */ Map getServerIdentifiers(); } diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsRestApi.java b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResources.java similarity index 67% rename from application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsRestApi.java rename to application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResources.java index ee390263..3b952360 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsRestApi.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResources.java @@ -19,7 +19,6 @@ */ package com.xwiki.admintools.rest; -import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -30,34 +29,34 @@ import org.xwiki.rest.XWikiRestException; /** - * Provides the APIs needed by the collabora server in order to access a file and it's content, but also to save it. + * Provides the APIs needed by the Admin Tools server in order to download configuration files and a logs archive. * * @version $Id$ * @since 1.0 */ @Path("/admintools/download") -public interface AdminToolsRestApi extends XWikiRestComponent +public interface AdminToolsResources extends XWikiRestComponent { /** - * TBC. + * REST endpoint for accessing the XWiki configuration or properties download. * - * @param type - * @return TBC + * @param type specifies the XWiki searched file. + * @return Response with a configured header for file download. * @throws XWikiRestException */ @GET @Path("/configs/{fileType}") - Response getConfigs(@PathParam("fileType") String type) - throws XWikiRestException; + Response getConfigs(@PathParam("fileType") String type) throws XWikiRestException; /** - * TBC. + * REST endpoint for accessing the logs archive download. * - * @return TBC + * @param from filter date, starting from. + * @param to filter date, until. + * @return Response with a configured header for zip download. * @throws XWikiRestException */ @GET @Path("/logs") - Response getLogs(@QueryParam("from") String from, @QueryParam("to") String to) - throws XWikiRestException; + Response getLogs(@QueryParam("from") String from, @QueryParam("to") String to) throws XWikiRestException; } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index f4e6c45d..74ecaee9 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -30,7 +30,7 @@ import com.xwiki.admintools.DataProvider; /** - * Manage existing instances. or admin tools manager + * Manages the data providers. * * @version $Id$ * @since 1.0 @@ -46,9 +46,9 @@ public class AdminToolsManager private Provider> dataProviderProvider; /** - * Merges all the templates. + * Merges all templates generated by the data providers. * - * @return a string containing all templates. + * @return a string containing all templates builds. */ public String generateData() { @@ -62,7 +62,7 @@ public String generateData() } /** - * Extract a specific template. + * Extract a specific data provider template. * * @param hint represents the data provider identifier. * @return a String representing a template diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index cf42ca2c..295a84f8 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -46,9 +46,6 @@ public class ConfigurationDataProvider extends AbstractDataProvider */ public static final String HINT = "configuration"; - /** - * Collection of functions used to retrieve info about the current server paths and type. - */ @Inject private CurrentServer usedServer; @@ -58,11 +55,6 @@ public String getIdentifier() return HINT; } - /** - * Get the configuration info template. - * - * @return xwiki configuration info json. - */ @Override public String provideData() { @@ -77,7 +69,7 @@ public String provideData() } /** - * Get the used version of Java. + * Get the version of Java used on the server. * * @return the used Java version. */ @@ -87,7 +79,7 @@ private String getJavaVersion() } /** - * Get info about the OS XWiki is running on. + * Get info about the OS that XWiki is running on. * * @return info about the OS. */ diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java index e644db2f..7d8de45e 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java @@ -53,7 +53,7 @@ public Map getServerIdentifiers() } /** - * Get the configuration file path for Tomcat. + * Get the server configuration file path. * * @return path to Tomcat configuration file. */ @@ -69,7 +69,7 @@ public String getServerCfgPath() } /** - * Get the configuration file path for the XWiki. + * Get the configuration file path for the XWiki installation. * * @return path to the XWiki configuration file. */ diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java index 9f875430..09bdaa55 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java @@ -123,11 +123,17 @@ public Map getServerIdentifiers() return usedServer.getServerIdentifiers(); } + /** + * Go through all supported servers and return the one that is used. + * + * @param providedConfigServerPath server path provided by XWiki configurations. + */ private void findServer(String providedConfigServerPath) { for (ServerIdentifier serverIdentifier : this.supportedServers.get()) { if (serverIdentifier.isUsed(providedConfigServerPath)) { usedServer = serverIdentifier; + break; } } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java index 1e5cdf6a..9223c213 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java @@ -58,22 +58,12 @@ public boolean isUsed(String providedConfigServerPath) } } - /** - * Extract the hint of a component. - * - * @return component hint - */ @Override public String getIdentifier() { return HINT; } - /** - * Update the possible paths to the configuration files. - * - * @param providedConfigServerPath the server path provided in the XWiki configuration page. - */ @Override public void updatePaths(String providedConfigServerPath) { @@ -91,10 +81,12 @@ public void updatePaths(String providedConfigServerPath) } /** - * Function used to verify if a Tomcat server is used. + * Function used to verify if a Tomcat server is used. If a server path is provided in the XWiki + * configurations, it verifies if the path corresponds to a Tomcat server. Otherwise, it searches the Catalina + * location in system properties and system environment. * * @param providedConfigServerPath the server path provided in the XWiki configuration page. - * @return true if Tomcat is the used server, false otherwise + * @return true if Tomcat is the used server, false otherwise. */ private boolean tomcatIsUsed(String providedConfigServerPath) { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractLogsDownloader.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractLogsDownloader.java index 63246c48..762f4fb0 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractLogsDownloader.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractLogsDownloader.java @@ -35,23 +35,38 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; -import com.xwiki.admintools.FilesDownloader; +import com.xwiki.admintools.LogsDownloader; -public abstract class AbstractLogsDownloader implements FilesDownloader +/** + * Abstract implementation of {@link LogsDownloader}. Adds common functions to all server types. + * + * @version $Id$ + * @since 1.0 + */ +public abstract class AbstractLogsDownloader implements LogsDownloader { @Inject private Logger logger; + /** + * Identifies the logs location and applies the filters to the specified server pattern. + * + * @param filters Map that can contain the start and end date of the search. It can also be empty. + * @param listOfFiles File list of all the log files. + * @param pattern server specific pattern used to identify the log date from the log name. + * @return byte array representing the logs archive. + */ protected byte[] generateArchive(Map filters, File[] listOfFiles, Pattern pattern) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[2048]; - try(ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) { - + try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) { + // Go through all the files in the list. for (File file : listOfFiles != null ? listOfFiles : new File[0]) { + // Check if the selected file is of file type and check filters. if (file.isFile() && checkFilters(filters, pattern, file)) { - + // Create a new zip entry and add the content. ZipEntry zipEntry = new ZipEntry(file.getName()); zipOutputStream.putNextEntry(zipEntry); try (FileInputStream fileInputStream = new FileInputStream(file)) { @@ -76,22 +91,31 @@ protected byte[] generateArchive(Map filters, File[] listOfFiles } } + /** + * Check that the file date is in the filter range. Returns true if no filter is provided. + * + * @param filters Map that can contain the start and end date of the search. It can also be empty. + * @param pattern server specific pattern used to identify the log date from the log name. + * @param file current file that is to be checked. + * @return true if the file is between the provided dates or there is no filter, false otherwise + */ private boolean checkFilters(Map filters, Pattern pattern, File file) { - Matcher matcher = pattern.matcher(file.getName()); if (matcher.find()) { + String fromDateFilterKey = "from"; + String toDateFilterKey = "to"; String fileDateString = matcher.group(); LocalDate fileDate = LocalDate.parse(fileDateString); - if (filters.get("from") != null && filters.get("to") != null) { - LocalDate fromDate = LocalDate.parse(filters.get("from")); - LocalDate toDate = LocalDate.parse(filters.get("to")); + if (filters.get(fromDateFilterKey) != null && filters.get(toDateFilterKey) != null) { + LocalDate fromDate = LocalDate.parse(filters.get(fromDateFilterKey)); + LocalDate toDate = LocalDate.parse(filters.get(toDateFilterKey)); return fileDate.isAfter(fromDate) && fileDate.isBefore(toDate); - } else if (filters.get("from") != null) { - LocalDate fromDate = LocalDate.parse(filters.get("from")); + } else if (filters.get(fromDateFilterKey) != null) { + LocalDate fromDate = LocalDate.parse(filters.get(fromDateFilterKey)); return fileDate.isAfter(fromDate); - } else if (filters.get("to") != null) { - LocalDate toDate = LocalDate.parse(filters.get("to")); + } else if (filters.get(toDateFilterKey) != null) { + LocalDate toDate = LocalDate.parse(filters.get(toDateFilterKey)); return fileDate.isBefore(toDate); } else { return true; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java index 9be58d6d..eb0ad76e 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java @@ -43,11 +43,11 @@ import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiContext; -import com.xwiki.admintools.FilesDownloader; +import com.xwiki.admintools.LogsDownloader; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; /** - * Encapsulates functions used for downloading configuration files. + * Encapsulates functions used for downloading important server files. * * @version $Id$ * @since 1.0 @@ -59,9 +59,6 @@ public class DownloadsManager implements Initializable @Inject protected Provider xcontextProvider; - /** - * TBC. - */ @Inject private CurrentServer currentServer; @@ -69,17 +66,17 @@ public class DownloadsManager implements Initializable private ContextualAuthorizationManager authorizationManager; /** - * A list of all the data providers for Admin Tools. + * A list of all supported server file downloaders. */ @Inject - private Provider> filesDownloader; + private Provider> filesDownloader; private String serverPath; private String serverType; /** - * TBC. + * Initializes variables with the server type and the path to the server. * * @throws InitializationException */ @@ -92,10 +89,10 @@ public void initialize() throws InitializationException } /** - * TBC. + * Initiates the download process for the xwiki files. It removes the sensitive content from the file. * - * @param fileType TBC. - * @return TBC. + * @param fileType properties of configuration file. + * @return filtered file content as a byte array * @throws IOException */ public byte[] downloadXWikiFile(String fileType) throws IOException @@ -104,7 +101,9 @@ public byte[] downloadXWikiFile(String fileType) throws IOException } /** - * @return + * Checks the admin rights of the calling user. + * + * @return true if the user is admin, false otherwise */ public boolean isAdmin() { @@ -118,10 +117,11 @@ public boolean isAdmin() } /** - * TBC. + * Initiates the download process for the server logs. Taking into consideration the used server, it identifies the + * right downloader. It returns null if none is corresponding. * - * @param filters TBC - * @return TBC + * @param filters Map that can contain the start and end date of the search. It can also be empty. + * @return byte array representing the logs archive. */ public byte[] downloadLogs(Map filters) { @@ -129,11 +129,12 @@ public byte[] downloadLogs(Map filters) } /** - * As all servers have the same path to the xwiki properties and configuration files, it is not needed to call this - * function in a server specific class. + * Identifies the searched file and filters the sensitive info from it. The searched As all servers types have the + * same path to the xwiki properties configuration files, it is not needed to call this function in a server + * specific class. * - * @param type - * @return + * @param type identifies the searched file. + * @return byte array representing the filtered file content. * @throws IOException */ private byte[] prepareFile(String type) throws IOException @@ -153,6 +154,8 @@ private byte[] prepareFile(String type) throws IOException List wordsList = new ArrayList<>( Arrays.asList("xwiki.authentication.validationKey", "xwiki.authentication.encryptionKey", "xwiki.superadminpassword", "extension.repositories.privatemavenid.auth", "mail.sender.password")); + + // Read line by line and do not add it if it contains sensitive info. while ((currentLine = reader.readLine()) != null) { String trimmedLine = currentLine.trim(); if (wordsList.stream().anyMatch(trimmedLine::contains)) { @@ -164,11 +167,18 @@ private byte[] prepareFile(String type) throws IOException return stringBuilder.toString().getBytes(); } + /** + * Calls the logs generator for the used server. + * + * @param hint represents the used server hint. + * @param filter Map representing the filters that can be applied to the search. + * @return byte array representing the logs archive. + */ private byte[] callLogsDownloader(String hint, Map filter) { - for (FilesDownloader specificFilesDownloader : this.filesDownloader.get()) { - if (specificFilesDownloader.getIdentifier().equals(hint)) { - return specificFilesDownloader.generateLogsArchive(filter, serverPath); + for (LogsDownloader specificLogsDownloader : this.filesDownloader.get()) { + if (specificLogsDownloader.getIdentifier().equals(hint)) { + return specificLogsDownloader.generateLogsArchive(filter, serverPath); } } return null; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatLogsDownloader.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatLogsDownloader.java index 2836cacc..b597e9c3 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatLogsDownloader.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatLogsDownloader.java @@ -23,16 +23,13 @@ import java.util.Map; import java.util.regex.Pattern; -import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import org.apache.commons.lang3.exception.ExceptionUtils; import org.xwiki.component.annotation.Component; -import org.xwiki.logging.Logger; /** - * Encapsulates functions used for downloading configuration files. + * Encapsulates functions used for downloading log files. * * @version $Id$ * @since 1.0 @@ -47,12 +44,6 @@ public class TomcatLogsDownloader extends AbstractLogsDownloader */ public static final String HINT = "tomcatLogs"; - - - /** - * @param filter - * @return - */ @Override public byte[] generateLogsArchive(Map filter, String serverPath) { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultRestApi.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java similarity index 83% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultRestApi.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java index 1eb01d79..2a1ae0db 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultRestApi.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java @@ -28,7 +28,6 @@ import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; -import javax.servlet.http.HttpServletRequest; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -38,44 +37,49 @@ import org.xwiki.component.annotation.Component; import org.xwiki.rest.XWikiRestException; import org.xwiki.rest.internal.resources.pages.ModifiablePageResource; -import org.xwiki.security.authorization.AuthorizationManager; -import com.xpn.xwiki.XWikiContext; import com.xwiki.admintools.internal.downloads.DownloadsManager; -import com.xwiki.admintools.rest.AdminToolsRestApi; +import com.xwiki.admintools.rest.AdminToolsResources; /** - * TBC. + * Default implementation of {@link AdminToolsResources}. * * @version $Id$ * @since 1.0 */ @Component -@Named("com.xwiki.admintools.internal.rest.DefaultRestApi") +@Named("com.xwiki.admintools.internal.rest.DefaultResources") @Singleton -public class DefaultRestApi extends ModifiablePageResource implements AdminToolsRestApi +public class DefaultResources extends ModifiablePageResource implements AdminToolsResources { private final String contentDisposition = "Content-Disposition"; @Inject private Logger logger; + /** + * Handles downloads requests. + */ @Inject - private DownloadsManager downloadsManager; + private Provider downloadsManagerProvider; @Override public Response getConfigs(String type) throws XWikiRestException { // boolean a = request.isUserInRole("admin"); - if (downloadsManager.isAdmin()) { + // Check to see if the request was made by a user with admin rights. + if (downloadsManagerProvider.get().isAdmin()) { logger.warn("Failed to get file xwiki.[{}] due to restricted rights.", type); throw new WebApplicationException(Response.Status.UNAUTHORIZED); } try { - byte[] xWikiFile = downloadsManager.downloadXWikiFile(type); - InputStream inputStream = new ByteArrayInputStream(xWikiFile); + byte[] xWikiFileContent = downloadsManagerProvider.get().downloadXWikiFile(type); + InputStream inputStream = new ByteArrayInputStream(xWikiFileContent); + Response.ResponseBuilder response = Response.ok(inputStream); response.type(MediaType.TEXT_PLAIN_TYPE); + + // Set the appropriate response headers to indicate a file download. if (type.equals("properties")) { response.header(contentDisposition, "attachment; filename=xwiki.properties"); return response.build(); @@ -91,12 +95,6 @@ public Response getConfigs(String type) throws XWikiRestException } } - /** - * TBC. - * - * @return TBC - * @throws XWikiRestException - */ @Override public Response getLogs(String from, String to) throws XWikiRestException { @@ -104,9 +102,9 @@ public Response getLogs(String from, String to) throws XWikiRestException Map filters = new HashMap<>(); filters.put("from", from); filters.put("to", to); - byte[] logsArchive = downloadsManager.downloadLogs(filters); + byte[] logsArchive = downloadsManagerProvider.get().downloadLogs(filters); if (logsArchive != null) { - // Set the appropriate response headers to indicate a file download. + // Set the appropriate response headers to indicate a zip file download. Response.ResponseBuilder response = Response.ok(logsArchive); response.header("Content-Type", "application/zip"); response.header(contentDisposition, "attachment; filename=logs_archive.zip"); diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index 452153ee..271be404 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -8,4 +8,4 @@ com.xwiki.admintools.internal.data.identifiers.CurrentServer com.xwiki.admintools.internal.data.identifiers.TomcatIdentifier com.xwiki.admintools.internal.configuration.AdminToolsConfigurationSource com.xwiki.admintools.internal.configuration.DefaultAdminToolsConfiguration -com.xwiki.admintools.internal.rest.DefaultRestApi +com.xwiki.admintools.internal.rest.DefaultResources From a2a79ba6ff5871a48ad69ab0c52a7ded9623ed7d Mon Sep 17 00:00:00 2001 From: Sorin Date: Tue, 5 Sep 2023 15:02:49 +0300 Subject: [PATCH 18/72] Download important files #8 --- .../internal/downloads/DownloadsManager.java | 14 +++++--------- .../internal/rest/DefaultResources.java | 15 ++++++++------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java index eb0ad76e..0199f09f 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java @@ -38,10 +38,9 @@ import org.xwiki.component.phase.InitializationException; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.WikiReference; -import org.xwiki.security.authorization.ContextualAuthorizationManager; +import org.xwiki.security.authorization.AuthorizationManager; import org.xwiki.security.authorization.Right; -import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiContext; import com.xwiki.admintools.LogsDownloader; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; @@ -63,7 +62,7 @@ public class DownloadsManager implements Initializable private CurrentServer currentServer; @Inject - private ContextualAuthorizationManager authorizationManager; + private AuthorizationManager authorizationManager; /** * A list of all supported server file downloaders. @@ -108,12 +107,9 @@ public byte[] downloadXWikiFile(String fileType) throws IOException public boolean isAdmin() { XWikiContext wikiContext = xcontextProvider.get(); - XWiki wiki = wikiContext.getWiki(); - DocumentReference a = wikiContext.getUserReference(); - WikiReference b = wikiContext.getWikiReference(); - boolean c = this.authorizationManager.hasAccess(Right.ADMIN); - String d = ""; - return c; + DocumentReference user = wikiContext.getUserReference(); + WikiReference wikiReference = wikiContext.getWikiReference(); + return this.authorizationManager.hasAccess(Right.ADMIN, user, wikiReference); } /** diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java index 2a1ae0db..f2ebfeb6 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java @@ -26,7 +26,6 @@ import javax.inject.Inject; import javax.inject.Named; -import javax.inject.Provider; import javax.inject.Singleton; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; @@ -61,21 +60,19 @@ public class DefaultResources extends ModifiablePageResource implements AdminToo * Handles downloads requests. */ @Inject - private Provider downloadsManagerProvider; + private DownloadsManager downloadsManager; @Override public Response getConfigs(String type) throws XWikiRestException { -// boolean a = request.isUserInRole("admin"); // Check to see if the request was made by a user with admin rights. - if (downloadsManagerProvider.get().isAdmin()) { + if (!downloadsManager.isAdmin()) { logger.warn("Failed to get file xwiki.[{}] due to restricted rights.", type); throw new WebApplicationException(Response.Status.UNAUTHORIZED); } try { - byte[] xWikiFileContent = downloadsManagerProvider.get().downloadXWikiFile(type); + byte[] xWikiFileContent = downloadsManager.downloadXWikiFile(type); InputStream inputStream = new ByteArrayInputStream(xWikiFileContent); - Response.ResponseBuilder response = Response.ok(inputStream); response.type(MediaType.TEXT_PLAIN_TYPE); @@ -98,11 +95,15 @@ public Response getConfigs(String type) throws XWikiRestException @Override public Response getLogs(String from, String to) throws XWikiRestException { + if (!downloadsManager.isAdmin()) { + logger.warn("Failed to get server logs due to restricted rights."); + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } try { Map filters = new HashMap<>(); filters.put("from", from); filters.put("to", to); - byte[] logsArchive = downloadsManagerProvider.get().downloadLogs(filters); + byte[] logsArchive = downloadsManager.downloadLogs(filters); if (logsArchive != null) { // Set the appropriate response headers to indicate a zip file download. Response.ResponseBuilder response = Response.ok(logsArchive); From 1d56ff407b519cd899fb2c458f8549e10b9f53b1 Mon Sep 17 00:00:00 2001 From: Sorin Date: Wed, 6 Sep 2023 17:28:09 +0300 Subject: [PATCH 19/72] Download important files #8 - Removed the download logs endpoint - Added an endpoint for downloading a multiple files archive - Added function for data providers to return info json - Added script function to retrieve the context path --- .../com/xwiki/admintools/DataProvider.java | 9 ++ .../admintools/rest/AdminToolsResources.java | 25 +++-- .../internal/AdminToolsManager.java | 18 ++++ .../data/ConfigurationDataProvider.java | 13 ++- .../internal/data/SecurityDataProvider.java | 24 ++--- .../downloads/AbstractLogsDownloader.java | 7 +- .../internal/downloads/DownloadsManager.java | 101 +++++++++++++++++- .../internal/rest/DefaultResources.java | 66 +++++++----- .../script/AdminToolsScriptService.java | 10 ++ 9 files changed, 219 insertions(+), 54 deletions(-) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java index 0e518cf0..99ca1faf 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java @@ -19,6 +19,8 @@ */ package com.xwiki.admintools; +import java.util.Map; + import org.xwiki.component.annotation.Role; /** @@ -37,6 +39,13 @@ public interface DataProvider */ String provideData(); + /** + * Provides the info structured in a json. + * + * @return Map containing the generated info. + */ + Map generateJson(); + /** * Extract the hint of a component. * diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResources.java b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResources.java index 3b952360..2cbb4631 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResources.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResources.java @@ -20,6 +20,7 @@ package com.xwiki.admintools.rest; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; @@ -48,15 +49,27 @@ public interface AdminToolsResources extends XWikiRestComponent @Path("/configs/{fileType}") Response getConfigs(@PathParam("fileType") String type) throws XWikiRestException; +// /** +// * REST endpoint for accessing the logs archive download. +// * +// * @param from filter date, starting from. +// * @param to filter date, until. +// * @return Response with a configured header for zip download. +// * @throws XWikiRestException +// */ +// @GET +// @Path("/logs") +// Response getLogs(@QueryParam("from") String from, @QueryParam("to") String to) throws XWikiRestException; + /** - * REST endpoint for accessing the logs archive download. + * Rest endpoint to download all selected files. * - * @param from filter date, starting from. - * @param to filter date, until. + * @param from filter date, starting from given value. + * @param to filter date, until given value. * @return Response with a configured header for zip download. * @throws XWikiRestException */ - @GET - @Path("/logs") - Response getLogs(@QueryParam("from") String from, @QueryParam("to") String to) throws XWikiRestException; + @POST + @Path("/all") + Response getFiles(@QueryParam("from") String from, @QueryParam("to") String to) throws XWikiRestException; } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index 74ecaee9..358b5195 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -27,6 +27,8 @@ import org.xwiki.component.annotation.Component; +import com.xpn.xwiki.XWikiContext; +import com.xpn.xwiki.web.XWikiRequest; import com.xwiki.admintools.DataProvider; /** @@ -45,6 +47,9 @@ public class AdminToolsManager @Inject private Provider> dataProviderProvider; + @Inject + private Provider xcontextProvider; + /** * Merges all templates generated by the data providers. * @@ -79,4 +84,17 @@ public String generateData(String hint) } return null; } + + /** + * Get the context path for the current XWiki request. + * + * @return a String representing the xwiki context path. + */ + public String getContextPath() + { + XWikiContext xWikiContext = this.xcontextProvider.get(); + XWikiRequest xWikiRequest = xWikiContext.getRequest(); + + return xWikiRequest.getContextPath(); + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index 295a84f8..aee8510f 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -57,6 +57,17 @@ public String getIdentifier() @Override public String provideData() + { + return getRenderedTemplate("data/configurationTemplate.vm", generateJson(), HINT); + } + + /** + * Provides the info structured in a json. + * + * @return Map containing the generated info. + */ + @Override + public Map generateJson() { usedServer.updatePaths(); Map systemInfo = new HashMap<>(); @@ -65,7 +76,7 @@ public String provideData() systemInfo.put("javaVersion", this.getJavaVersion()); systemInfo.put("osInfo", this.getOSInfo()); - return getRenderedTemplate("data/configurationTemplate.vm", systemInfo, HINT); + return systemInfo; } /** diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java index 15923af2..66f0e5e0 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java @@ -69,25 +69,18 @@ public class SecurityDataProvider extends AbstractDataProvider @Override public String provideData() { - Map securityDetails = this.getXwikiSecurityInfo(); - - securityDetails.putAll(getEnvironmentInfo()); + Map securityDetails = this.generateJson(); return getRenderedTemplate("data/securityTemplate.vm", securityDetails, HINT); } - @Override - public String getIdentifier() - { - return HINT; - } - /** - * Get the security info of the current wiki. + * Provides the info structured in a json. * - * @return xwiki security info. + * @return Map containing the generated info. */ - private Map getXwikiSecurityInfo() + @Override + public Map generateJson() { Map results = new HashMap<>(); @@ -98,10 +91,17 @@ private Map getXwikiSecurityInfo() results.put("activeEncoding", wiki.getEncoding()); results.put("configurationEncoding", configurationSource.getProperty("xwiki.encoding", String.class)); results.put("fileEncoding", System.getProperty("file.encoding")); + results.putAll(getEnvironmentInfo()); return results; } + @Override + public String getIdentifier() + { + return HINT; + } + /** * Get the security info regarding the environment. * diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractLogsDownloader.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractLogsDownloader.java index 762f4fb0..ab827d26 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractLogsDownloader.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractLogsDownloader.java @@ -107,16 +107,17 @@ private boolean checkFilters(Map filters, Pattern pattern, File String toDateFilterKey = "to"; String fileDateString = matcher.group(); LocalDate fileDate = LocalDate.parse(fileDateString); + if (filters.get(fromDateFilterKey) != null && filters.get(toDateFilterKey) != null) { LocalDate fromDate = LocalDate.parse(filters.get(fromDateFilterKey)); LocalDate toDate = LocalDate.parse(filters.get(toDateFilterKey)); - return fileDate.isAfter(fromDate) && fileDate.isBefore(toDate); + return fileDate.isAfter(fromDate.minusDays(1)) && fileDate.isBefore(toDate.plusDays(1)); } else if (filters.get(fromDateFilterKey) != null) { LocalDate fromDate = LocalDate.parse(filters.get(fromDateFilterKey)); - return fileDate.isAfter(fromDate); + return fileDate.isAfter(fromDate.minusDays(1)); } else if (filters.get(toDateFilterKey) != null) { LocalDate toDate = LocalDate.parse(filters.get(toDateFilterKey)); - return fileDate.isBefore(toDate); + return fileDate.isBefore(toDate.plusDays(1)); } else { return true; } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java index 0199f09f..bdf53565 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java @@ -20,19 +20,26 @@ package com.xwiki.admintools.internal.downloads; import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; import org.xwiki.component.annotation.Component; import org.xwiki.component.phase.Initializable; import org.xwiki.component.phase.InitializationException; @@ -42,7 +49,10 @@ import org.xwiki.security.authorization.Right; import com.xpn.xwiki.XWikiContext; +import com.xpn.xwiki.web.XWikiRequest; +import com.xwiki.admintools.DataProvider; import com.xwiki.admintools.LogsDownloader; +import com.xwiki.admintools.internal.data.ConfigurationDataProvider; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; /** @@ -55,8 +65,12 @@ @Singleton public class DownloadsManager implements Initializable { + private final String config = "config"; + + private final String properties = "properties"; + @Inject - protected Provider xcontextProvider; + private Provider xcontextProvider; @Inject private CurrentServer currentServer; @@ -70,10 +84,17 @@ public class DownloadsManager implements Initializable @Inject private Provider> filesDownloader; + @Inject + @Named(ConfigurationDataProvider.HINT) + private DataProvider configurationDataProvider; + private String serverPath; private String serverType; + @Inject + private Logger logger; + /** * Initializes variables with the server type and the path to the server. * @@ -94,7 +115,7 @@ public void initialize() throws InitializationException * @return filtered file content as a byte array * @throws IOException */ - public byte[] downloadXWikiFile(String fileType) throws IOException + public byte[] getXWikiFile(String fileType) throws IOException { return prepareFile(fileType); } @@ -112,6 +133,76 @@ public boolean isAdmin() return this.authorizationManager.hasAccess(Right.ADMIN, user, wikiReference); } + /** + * Retrieve the selected files from the request and create an archive containing them. + * + * @return byte array representing the files archive. + */ + public byte[] downloadMultipleFiles() + { + XWikiContext wikiContext = xcontextProvider.get(); + XWikiRequest xWikiRequest = wikiContext.getRequest(); + Map files = xWikiRequest.getParameterMap(); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) { + createArchiveEntries(files, zipOutputStream); + zipOutputStream.flush(); + byteArrayOutputStream.flush(); + zipOutputStream.close(); + byteArrayOutputStream.close(); + return byteArrayOutputStream.toByteArray(); + } catch (Exception e) { + logger.warn("Failed to download logs. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); + return null; + } + } + + private void createArchiveEntries(Map files, ZipOutputStream zipOutputStream) throws IOException + { + ZipEntry zipEntry; + byte[] buffer; + for (String fileType : files.get("files")) { + switch (fileType) { + case "cfg_file": + zipEntry = new ZipEntry("xwiki.cfg"); + zipOutputStream.putNextEntry(zipEntry); + buffer = prepareFile(config); + zipOutputStream.write(buffer, 0, buffer.length); + zipOutputStream.closeEntry(); + break; + case "properties_file": + zipEntry = new ZipEntry("xwiki.properties"); + zipOutputStream.putNextEntry(zipEntry); + buffer = prepareFile(properties); + zipOutputStream.write(buffer, 0, buffer.length); + zipOutputStream.closeEntry(); + break; + case "logs": + zipEntry = new ZipEntry("logs.zip"); + zipOutputStream.putNextEntry(zipEntry); + Map filters = new HashMap<>(); + String from = "from"; + String to = "to"; + filters.put(from, !Objects.equals(files.get(from)[0], "") ? files.get(from)[0] : null); + filters.put(to, !Objects.equals(files.get(to)[0], "") ? files.get(to)[0] : null); + buffer = getLogs(filters); + zipOutputStream.write(buffer, 0, buffer.length); + zipOutputStream.closeEntry(); + break; + case "configuration_info": + zipEntry = new ZipEntry("configuration_json.txt"); + zipOutputStream.putNextEntry(zipEntry); + buffer = configurationDataProvider.generateJson().toString().getBytes(); + zipOutputStream.write(buffer, 0, buffer.length); + zipOutputStream.closeEntry(); + break; + default: + break; + } + } + } + /** * Initiates the download process for the server logs. Taking into consideration the used server, it identifies the * right downloader. It returns null if none is corresponding. @@ -119,7 +210,7 @@ public boolean isAdmin() * @param filters Map that can contain the start and end date of the search. It can also be empty. * @return byte array representing the logs archive. */ - public byte[] downloadLogs(Map filters) + private byte[] getLogs(Map filters) { return callLogsDownloader(serverType + "Logs", filters); } @@ -136,9 +227,9 @@ public byte[] downloadLogs(Map filters) private byte[] prepareFile(String type) throws IOException { String filePath = serverPath; - if (Objects.equals(type, "properties")) { + if (Objects.equals(type, properties)) { filePath += "/webapps/xwiki/WEB-INF/xwiki.properties"; - } else { + } else if (Objects.equals(type, config)) { filePath += "/webapps/xwiki/WEB-INF/xwiki.cfg"; } File inputFile = new File(filePath); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java index f2ebfeb6..d59104bf 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java @@ -21,8 +21,7 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; +import java.util.Arrays; import javax.inject.Inject; import javax.inject.Named; @@ -71,44 +70,57 @@ public Response getConfigs(String type) throws XWikiRestException throw new WebApplicationException(Response.Status.UNAUTHORIZED); } try { - byte[] xWikiFileContent = downloadsManager.downloadXWikiFile(type); - InputStream inputStream = new ByteArrayInputStream(xWikiFileContent); - Response.ResponseBuilder response = Response.ok(inputStream); - response.type(MediaType.TEXT_PLAIN_TYPE); - - // Set the appropriate response headers to indicate a file download. - if (type.equals("properties")) { - response.header(contentDisposition, "attachment; filename=xwiki.properties"); - return response.build(); - } else if (type.equals("config")) { - response.header(contentDisposition, "attachment; filename=xwiki.cfg"); - return response.build(); - } else { + byte[] xWikiFileContent = downloadsManager.getXWikiFile(type); + if (xWikiFileContent.length == 0) { return Response.status(404).build(); } + InputStream inputStream = new ByteArrayInputStream(xWikiFileContent); + return Response.ok(inputStream). + type(MediaType.TEXT_PLAIN_TYPE).build(); + // Set the appropriate response headers to indicate a file download. } catch (Exception e) { logger.warn("Failed to get file [{}]. Root cause: [{}]", type, ExceptionUtils.getRootCauseMessage(e)); throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } } +// @Override +// public Response getLogs(String from, String to) throws XWikiRestException +// { +// if (!downloadsManager.isAdmin()) { +// logger.warn("Failed to get server logs due to restricted rights."); +// throw new WebApplicationException(Response.Status.UNAUTHORIZED); +// } +// try { +// Map filters = new HashMap<>(); +// filters.put("from", from); +// filters.put("to", to); +// byte[] logsArchive = downloadsManager.getLogs(filters); +// if (!(logsArchive == null) && !(Arrays.toString(logsArchive).length() == 0)) { +// // Set the appropriate response headers to indicate a zip file download. +// Response.ResponseBuilder response = Response.ok(logsArchive); +// response.header("Content-Type", "application/zip"); +// return response.build(); +// } else { +// // Handle the case when no logs are found or an error occurs. +// return Response.status(Response.Status.NOT_FOUND).entity("No logs found.").build(); +// } +// } catch (Exception e) { +// logger.warn("Failed to get logs. Root cause: [{}]", ExceptionUtils.getRootCauseMessage(e)); +// throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); +// } +// } + @Override - public Response getLogs(String from, String to) throws XWikiRestException + public Response getFiles(String from, String to) throws XWikiRestException { - if (!downloadsManager.isAdmin()) { - logger.warn("Failed to get server logs due to restricted rights."); - throw new WebApplicationException(Response.Status.UNAUTHORIZED); - } try { - Map filters = new HashMap<>(); - filters.put("from", from); - filters.put("to", to); - byte[] logsArchive = downloadsManager.downloadLogs(filters); - if (logsArchive != null) { + byte[] filesArchive = downloadsManager.downloadMultipleFiles(); + if (!(filesArchive == null) && !(Arrays.toString(filesArchive).length() == 0)) { // Set the appropriate response headers to indicate a zip file download. - Response.ResponseBuilder response = Response.ok(logsArchive); + Response.ResponseBuilder response = Response.ok(filesArchive); response.header("Content-Type", "application/zip"); - response.header(contentDisposition, "attachment; filename=logs_archive.zip"); + response.header(contentDisposition, "attachment; filename=files_archive.zip"); return response.build(); } else { // Handle the case when no logs are found or an error occurs. diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index 8d324e42..c3cd94c8 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -65,4 +65,14 @@ public String getConfigurationData(String hint) { return this.adminToolsManager.generateData(hint); } + + /** + * Get the context path for the current XWiki installation. + * + * @return a String representing the xwiki context path. + */ + public String getContextPath() + { + return this.adminToolsManager.getContextPath(); + } } From f2e164a6c370c0a71bbe13bc47104dab179c420f Mon Sep 17 00:00:00 2001 From: Sorin Date: Fri, 8 Sep 2023 16:49:34 +0300 Subject: [PATCH 20/72] Display App server info #3 --- .../com/xwiki/admintools/DataProvider.java | 6 +- .../xwiki/admintools/ServerIdentifier.java | 25 +++---- .../AdminToolsConfiguration.java | 2 +- application-admintools-default/pom.xml | 12 ---- .../internal/AdminToolsManager.java | 11 ++- .../DefaultAdminToolsConfiguration.java | 5 -- .../internal/data/AbstractDataProvider.java | 18 ++--- .../data/ConfigurationDataProvider.java | 70 +++++++++++++++---- .../internal/data/SecurityDataProvider.java | 22 ++---- .../identifiers/AbstractServerIdentifier.java | 10 +-- .../data/identifiers/CurrentServer.java | 35 +++------- .../data/identifiers/TomcatIdentifier.java | 37 ++++------ .../script/AdminToolsScriptService.java | 11 ++- .../templates/data/configurationTemplate.vm | 19 +++-- 14 files changed, 140 insertions(+), 143 deletions(-) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java index 0e518cf0..5877c5af 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java @@ -31,16 +31,16 @@ public interface DataProvider { /** - * Provides the template of a specific type. + * Provides the template rendering the data provider information. * - * @return a data provider template + * @return {@link String} representing the data provider template. */ String provideData(); /** * Extract the hint of a component. * - * @return component hint + * @return {@link String} representing the component hint */ String getIdentifier(); } diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java index b0aafdd5..15ca403d 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java @@ -24,8 +24,7 @@ import org.xwiki.component.annotation.Role; /** - * Endpoints for identifying the used server and the paths to the configuration files of the server and XWiki - * installation. + * Identify the used server and the paths to the configuration files of the server and XWiki installation. * * @version $Id$ * @since 1.0 @@ -34,43 +33,45 @@ public interface ServerIdentifier { /** - * Check if this server type is used. - * @param providedConfigServerPath path to the server provided by XWiki configuration. - * @return true if the server is used, false otherwise. + * Check if the server is used. + * + * @param providedConfigServerPath {@link String} path to the server provided by XWiki configuration. + * @return {@link Boolean} true if the server is used, false otherwise. */ boolean isUsed(String providedConfigServerPath); /** * Extract the hint of a component. * - * @return component hint + * @return {@link String} component hint. */ String getIdentifier(); /** * Access the path to the server configuration file. * - * @return String representing the path to the server configuration file. + * @return {@link String} representing the path to the server configuration file. */ String getServerCfgPath(); /** - * Access the path to the XWiki configuration file. + * Access the path to the XWiki configuration folder. * - * @return String representing the path to the XWiki configuration file. + * @return {@link String} representing the path to the XWiki configuration folder. */ - String getXwikiCfgPath(); + String getXwikiCfgFolderPath(); /** * Update the possible paths to the configuration files. * - * @param providedConfigServerPath the server path provided in the XWiki configuration page. + * @param providedConfigServerPath {@link String} the server path provided in the XWiki configuration page. */ void updatePaths(String providedConfigServerPath); /** * Access the server path and type. - * @return Map containing server path and type. + * + * @return {@link Map} containing server path and type. */ Map getServerIdentifiers(); } diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/configuration/AdminToolsConfiguration.java b/application-admintools-api/src/main/java/com/xwiki/admintools/configuration/AdminToolsConfiguration.java index 363f2098..96222c25 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/configuration/AdminToolsConfiguration.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/configuration/AdminToolsConfiguration.java @@ -35,7 +35,7 @@ public interface AdminToolsConfiguration /** * Get the server installation path. * - * @return the server installation path. + * @return {@link String} representing the server installation path. */ String getServerPath(); } diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index 75a5cc0e..42223e82 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -42,18 +42,6 @@ xwiki-platform-oldcore ${platform.version} - - org.xwiki.commons - xwiki-commons-tool-test-component - ${commons.version} - test - - - org.xwiki.rendering - xwiki-rendering-test - ${rendering.version} - test - org.xwiki.platform xwiki-platform-configuration-default diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index 74ecaee9..4d5a95dc 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -48,7 +48,7 @@ public class AdminToolsManager /** * Merges all templates generated by the data providers. * - * @return a string containing all templates builds. + * @return a {@link String} containing all templates builds. */ public String generateData() { @@ -64,17 +64,14 @@ public String generateData() /** * Extract a specific data provider template. * - * @param hint represents the data provider identifier. - * @return a String representing a template + * @param hint {@link String} represents the data provider identifier. + * @return a {@link String} representing a template */ public String generateData(String hint) { - StringBuilder strBuilder = new StringBuilder(); - for (DataProvider dataProvider : this.dataProviderProvider.get()) { if (dataProvider.getIdentifier().equals(hint)) { - strBuilder.append(dataProvider.provideData()); - return strBuilder.toString(); + return dataProvider.provideData(); } } return null; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java index 5a07487a..2122e6a3 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java @@ -35,14 +35,9 @@ * @since 1.0 */ @Component -@Named(DefaultAdminToolsConfiguration.HINT) @Singleton public class DefaultAdminToolsConfiguration implements AdminToolsConfiguration { - /** - * Component identifier. - */ - public static final String HINT = "defaultConfiguration"; private static final String SERVER_LOCATION = "serverLocation"; @Inject diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java index 6d84c608..c6ef568b 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java @@ -39,7 +39,7 @@ import com.xwiki.admintools.DataProvider; /** - * To be extended by {@link DataProvider} implementations to simplify the code. + * {@link DataProvider} implementations to simplify the code. * * @version $Id$ * @since 1.0 @@ -67,10 +67,10 @@ public void initialize() throws InitializationException /** * Generates the template of a data provider. * - * @param data contains the data to be shown in the template. - * @param template path to the template. - * @param hint data provider identifier. - * @return String containing the generated template. + * @param data {@link Map} contains the data to be shown in the template. + * @param template {@link String} path to the template. + * @param hint {@link String} data provider identifier. + * @return {@link String} containing the generated template. */ protected String getRenderedTemplate(String template, Map data, String hint) { @@ -90,12 +90,12 @@ protected String getRenderedTemplate(String template, Map data, /** * Binds the data provided by the DataProvider to the template. * - * @param key - * @param data + * @param hint {@link String} component hint used as an identification key inside the template. + * @param data {@link Map} component data to be rendered. */ - private void bindData(String key, Map data) + private void bindData(String hint, Map data) { ScriptContext scriptContext = scriptContextManager.getScriptContext(); - scriptContext.setAttribute(key, data, ScriptContext.ENGINE_SCOPE); + scriptContext.setAttribute(hint, data, ScriptContext.ENGINE_SCOPE); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index 295a84f8..97d0a62e 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -19,19 +19,23 @@ */ package com.xwiki.admintools.internal.data; +import java.io.File; +import java.io.FileNotFoundException; import java.util.HashMap; import java.util.Map; +import java.util.Scanner; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.xwiki.component.annotation.Component; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; /** - * Encapsulates functions used for retrieving configuration data. + * Extension of {@link AbstractDataProvider} for retrieving configuration data. * * @version $Id$ * @since 1.0 @@ -47,7 +51,7 @@ public class ConfigurationDataProvider extends AbstractDataProvider public static final String HINT = "configuration"; @Inject - private CurrentServer usedServer; + private CurrentServer currentServer; @Override public String getIdentifier() @@ -58,12 +62,13 @@ public String getIdentifier() @Override public String provideData() { - usedServer.updatePaths(); + currentServer.findPaths(); Map systemInfo = new HashMap<>(); - systemInfo.put("xwikiCfgPath", usedServer.getXwikiCfgPath()); - systemInfo.put("tomcatConfPath", this.usedServer.getServerCfgPath()); + systemInfo.put("xwikiCfgPath", currentServer.retrieveXwikiCfgPath()); + systemInfo.put("tomcatConfPath", this.currentServer.retrieveServerCfgPath()); systemInfo.put("javaVersion", this.getJavaVersion()); - systemInfo.put("osInfo", this.getOSInfo()); + systemInfo.putAll(this.getOSInfo()); + systemInfo.put("database", this.identifyDB()); return getRenderedTemplate("data/configurationTemplate.vm", systemInfo, HINT); } @@ -71,7 +76,7 @@ public String provideData() /** * Get the version of Java used on the server. * - * @return the used Java version. + * @return {@link String} Java version. */ private String getJavaVersion() { @@ -81,14 +86,53 @@ private String getJavaVersion() /** * Get info about the OS that XWiki is running on. * - * @return info about the OS. + * @return {@link Map} info about the OS. */ - private String getOSInfo() + private Map getOSInfo() { - String osName = System.getProperty("os.name"); - String osVersion = System.getProperty("os.version"); - String osArch = System.getProperty("os.arch"); + Map result = new HashMap<>(); + result.put("osName", System.getProperty("os.name")); + result.put("osVersion", System.getProperty("os.version")); + result.put("osArch", System.getProperty("os.arch")); - return String.format("Operating System: %s %s (%s)", osName, osVersion, osArch); + return result; + } + + /** + * Identify the used database for XWiki by verifying the configration files. + * + * @return {@link String} name of the used database as a String. + */ + private String identifyDB() + { + String databaseCfgPath = currentServer.retrieveXwikiCfgPath() + "hibernate.cfg.xml"; + File file = new File(databaseCfgPath); + + try (Scanner scanner = new Scanner(file)) { + String usedDB = null; + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.contains("jdbc:")) { + if (line.contains("mysql")) { + usedDB = "MySQL"; + } else if (line.contains("hsqldb")) { + usedDB = "HSQLDB"; + } else if (line.contains("mariadb")) { + usedDB = "MariaDB"; + } else if (line.contains("postgresql")) { + usedDB = "PostgreSQL"; + } else if (line.contains("oracle")) { + usedDB = "Oracle"; + } + break; + } + } + scanner.close(); + return usedDB; + } catch (FileNotFoundException e) { + logger.warn("Failed to open database configuration file. Root cause is: [{}]", + ExceptionUtils.getRootCauseMessage(e)); + return null; + } } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java index 15923af2..3495e1ae 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java @@ -28,14 +28,12 @@ import org.xwiki.component.annotation.Component; import org.xwiki.configuration.ConfigurationSource; -import org.xwiki.model.reference.DocumentReference; -import org.xwiki.model.reference.WikiReference; -import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiContext; /** - * Encapsulates functions used for retrieving security data. + * Extension of {@link AbstractDataProvider} for retrieving security data, like XWiki encoding, file encoding, system + * info. * * @version $Id$ * @since 1.0 @@ -61,17 +59,13 @@ public class SecurityDataProvider extends AbstractDataProvider @Named("xwikicfg") private ConfigurationSource configurationSource; - /** - * Generate the security details. - * - * @return the security details of the xwiki - */ @Override public String provideData() { Map securityDetails = this.getXwikiSecurityInfo(); securityDetails.putAll(getEnvironmentInfo()); + securityDetails.put("fileEncoding", System.getProperty("file.encoding")); return getRenderedTemplate("data/securityTemplate.vm", securityDetails, HINT); } @@ -85,19 +79,15 @@ public String getIdentifier() /** * Get the security info of the current wiki. * - * @return xwiki security info. + * @return {@link Map} with XWiki security info regarding used and active encodings. */ private Map getXwikiSecurityInfo() { Map results = new HashMap<>(); XWikiContext wikiContext = xcontextProvider.get(); - XWiki wiki = wikiContext.getWiki(); - DocumentReference a = wikiContext.getUserReference(); - WikiReference b = wikiContext.getWikiReference(); - results.put("activeEncoding", wiki.getEncoding()); + results.put("activeEncoding", wikiContext.getWiki().getEncoding()); results.put("configurationEncoding", configurationSource.getProperty("xwiki.encoding", String.class)); - results.put("fileEncoding", System.getProperty("file.encoding")); return results; } @@ -105,7 +95,7 @@ private Map getXwikiSecurityInfo() /** * Get the security info regarding the environment. * - * @return environment security info. + * @return {@link Map} with environment info regarding working directory and system language. */ private Map getEnvironmentInfo() { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java index 7d8de45e..8061f3ce 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java @@ -26,7 +26,7 @@ import com.xwiki.admintools.ServerIdentifier; /** - * Implements methods to ease the usage of the server identifiers. + * Common methods for {@link ServerIdentifier} classes. * * @version $Id$ * @since 1.0 @@ -55,7 +55,7 @@ public Map getServerIdentifiers() /** * Get the server configuration file path. * - * @return path to Tomcat configuration file. + * @return {@link String} path to Tomcat configuration file. */ @Override public String getServerCfgPath() @@ -71,13 +71,13 @@ public String getServerCfgPath() /** * Get the configuration file path for the XWiki installation. * - * @return path to the XWiki configuration file. + * @return {@link String} path to the XWiki configuration file. */ @Override - public String getXwikiCfgPath() + public String getXwikiCfgFolderPath() { for (String xwikiCfgPath : xwikiCfgPossiblePaths) { - if ((new File(xwikiCfgPath)).exists()) { + if ((new File(xwikiCfgPath + "xwiki.cfg")).exists()) { return xwikiCfgPath; } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java index 09bdaa55..0fe2fb56 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java @@ -33,7 +33,6 @@ import com.xwiki.admintools.ServerIdentifier; import com.xwiki.admintools.configuration.AdminToolsConfiguration; -import com.xwiki.admintools.internal.configuration.DefaultAdminToolsConfiguration; /** * Manages the server identifiers and offers endpoints to retrieve info about their paths. @@ -51,7 +50,7 @@ public class CurrentServer implements Initializable private ServerIdentifier usedServer; @Inject - @Named(DefaultAdminToolsConfiguration.HINT) + @Named("default") private AdminToolsConfiguration adminToolsConfig; /** @@ -72,19 +71,19 @@ public void initialize() throws InitializationException /** * Retrieves the XWiki configuration file path for the installation. * - * @return a String representing the path to the XWiki configuration file. + * @return a {@link String} representing the path to the XWiki configuration file. */ - public String getXwikiCfgPath() + public String retrieveXwikiCfgPath() { - return usedServer.getXwikiCfgPath(); + return usedServer.getXwikiCfgFolderPath(); } /** * Retrieves the server configuration file path for the installation. * - * @return a String representing the path to the server configuration file. + * @return a {@link String} representing the path to the server configuration file. */ - public String getServerCfgPath() + public String retrieveServerCfgPath() { return usedServer.getServerCfgPath(); } @@ -92,31 +91,18 @@ public String getServerCfgPath() /** * Verifies if a server type was found and updates the paths. */ - public void updatePaths() + public void findPaths() { - String providedConfigServerPath = adminToolsConfig.getServerPath(); if (usedServer == null) { + String providedConfigServerPath = adminToolsConfig.getServerPath(); findServer(providedConfigServerPath); - usedServer.updatePaths(providedConfigServerPath); - } else { - usedServer.updatePaths(providedConfigServerPath); } } - /** - * Retrieves the server type. - * - * @return a string representing the server HINT. - */ - public String getServerType() - { - return usedServer.getIdentifier(); - } - /** * Calls the used server function to retrieve the server identifiers. * - * @return a Map with the info used to identify the server. + * @return a {@link Map} with the info used to identify the server. */ public Map getServerIdentifiers() { @@ -126,13 +112,14 @@ public Map getServerIdentifiers() /** * Go through all supported servers and return the one that is used. * - * @param providedConfigServerPath server path provided by XWiki configurations. + * @param providedConfigServerPath {@link String} server path provided by XWiki configurations. */ private void findServer(String providedConfigServerPath) { for (ServerIdentifier serverIdentifier : this.supportedServers.get()) { if (serverIdentifier.isUsed(providedConfigServerPath)) { usedServer = serverIdentifier; + usedServer.updatePaths(providedConfigServerPath); break; } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java index 9223c213..f7137fb2 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java @@ -26,8 +26,10 @@ import org.xwiki.component.annotation.Component; +import com.xwiki.admintools.ServerIdentifier; + /** - * Encapsulates functions used for identifying a Tomcat server and retrieving it's info. + * {@link ServerIdentifier} implementation used for identifying a Tomcat server and retrieving it's info. * * @version $Id$ * @since 1.0 @@ -42,20 +44,10 @@ public class TomcatIdentifier extends AbstractServerIdentifier */ public static final String HINT = "tomcat"; - /** - * Verify if this server is the one that stores the XWiki instance. - * - * @return true if this server is used, false otherwise - */ @Override public boolean isUsed(String providedConfigServerPath) { - if (tomcatIsUsed(providedConfigServerPath)) { - updatePaths(providedConfigServerPath); - return true; - } else { - return false; - } + return tomcatIsUsed(providedConfigServerPath); } @Override @@ -70,23 +62,22 @@ public void updatePaths(String providedConfigServerPath) if (tomcatIsUsed(providedConfigServerPath)) { this.serverCfgPossiblePaths = new String[] { String.format("%s/conf/server.xml", this.serverPath), "/usr/local/tomcat/conf/server.xml", "/opt/tomcat/conf/server.xml", "/var/lib/tomcat8/conf/", - "/var/lib/tomcat9/conf/", "/var/lib/tomcat/conf/" }; + "/var/lib/tomcat9/conf/server.xml", "/var/lib/tomcat/conf/server.xml" }; - this.xwikiCfgPossiblePaths = new String[] { "/etc/xwiki/xwiki.cfg", - String.format("%s/webapps${request.contextPath}/WEB-INF/xwiki.cfg", this.serverPath), - "/usr/local/xwiki/WEB-INF/xwiki.cfg", "/opt/xwiki/WEB-INF/xwiki.cfg", - String.format("%s/webapps/ROOT/WEB-INF/xwiki.cfg", this.serverPath), - String.format("%s/webapps/xwiki/WEB-INF/xwiki.cfg", this.serverPath) }; + this.xwikiCfgPossiblePaths = new String[] { "/etc/xwiki/", + "/usr/local/xwiki/WEB-INF/", "/opt/xwiki/WEB-INF/", + String.format("%s/webapps/ROOT/WEB-INF/", this.serverPath), + String.format("%s/webapps/xwiki/WEB-INF/", this.serverPath) }; } } /** - * Function used to verify if a Tomcat server is used. If a server path is provided in the XWiki - * configurations, it verifies if the path corresponds to a Tomcat server. Otherwise, it searches the Catalina - * location in system properties and system environment. + * Function used to verify if a Tomcat server is used. If a server path is provided in the XWiki configurations, it + * verifies if the path corresponds to a Tomcat server. Otherwise, it searches the Catalina location in system + * properties and system environment. * - * @param providedConfigServerPath the server path provided in the XWiki configuration page. - * @return true if Tomcat is the used server, false otherwise. + * @param providedConfigServerPath {@link String} server path provided in the XWiki configuration page. + * @return {@link Boolean} true if Tomcat is the used server, false otherwise. */ private boolean tomcatIsUsed(String providedConfigServerPath) { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index 8d324e42..44016baf 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -39,16 +39,13 @@ @Singleton public class AdminToolsScriptService implements ScriptService { - /** - * Manages the XWiki configuration info. - */ @Inject private AdminToolsManager adminToolsManager; /** - * Function used to retrieve all the configuration info templates of Admin Tools. + * Retrieve all the configuration info templates of Admin Tools. * - * @return all templates. + * @return {@link String} representing all templates. */ public String getConfigurationData() { @@ -58,8 +55,8 @@ public String getConfigurationData() /** * Get a specific data provider template. * - * @param hint represents the data provider - * @return the template of a specific data provider + * @param hint {@link String} representing the data provider + * @return {@link String} representing the template of a specific data provider */ public String getConfigurationData(String hint) { diff --git a/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm b/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm index 379603b0..1bd85202 100644 --- a/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm @@ -18,11 +18,18 @@ ## 02110-1301 USA, or see the FSF site: http://www.fsf.org. ## --------------------------------------------------------------------------- -{{html}} -
-

test config class

-
-{{/html}} +(% border="0" %) +|(% style="background-color:#fafafa; border-color:#ffffff; width:400px" %)((( +== 🌐**Backend ** == +((( +Get info about your backend -$configuration +---- +* XWiki installation version: $xwiki.version +** [[Show latest logs]] +* OS info: +** OS name: $configuration["osName"] +** OS version: $configuration["osVersion"] +** OS Architecture: $configuration["osArch"] +* Used database: $configuration["database"] From 6f5aff4ce8fbdf9cdf675c83e75631f403c454dc Mon Sep 17 00:00:00 2001 From: Sorin Date: Fri, 8 Sep 2023 18:01:34 +0300 Subject: [PATCH 21/72] Download important files #8 --- .../admintools/FilesResourceProvider.java | 74 +++++++++++ .../com/xwiki/admintools/LogsDownloader.java | 50 -------- .../admintools/rest/AdminToolsResources.java | 43 +++---- .../data/ConfigurationDataProvider.java | 69 ++++++++--- .../internal/data/SecurityDataProvider.java | 33 ++--- .../identifiers/AbstractServerIdentifier.java | 13 +- .../data/identifiers/CurrentServer.java | 10 -- .../data/identifiers/TomcatIdentifier.java | 9 +- ...ava => AbstractFilesResourceProvider.java} | 102 ++++++++++++++-- .../internal/downloads/DownloadsManager.java | 115 +++++++----------- ....java => TomcatFilesResourceProvider.java} | 11 +- .../internal/rest/DefaultResources.java | 59 ++++----- .../main/resources/META-INF/components.txt | 2 +- 13 files changed, 343 insertions(+), 247 deletions(-) create mode 100644 application-admintools-api/src/main/java/com/xwiki/admintools/FilesResourceProvider.java delete mode 100644 application-admintools-api/src/main/java/com/xwiki/admintools/LogsDownloader.java rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/{AbstractLogsDownloader.java => AbstractFilesResourceProvider.java} (51%) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/{TomcatLogsDownloader.java => TomcatFilesResourceProvider.java} (83%) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/FilesResourceProvider.java b/application-admintools-api/src/main/java/com/xwiki/admintools/FilesResourceProvider.java new file mode 100644 index 00000000..ff6c504e --- /dev/null +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/FilesResourceProvider.java @@ -0,0 +1,74 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools; + +import java.io.IOException; +import java.util.Map; + +import org.xwiki.component.annotation.Role; + +/** + * Provides functions for logs retrieval. + * + * @version $Id$ + * @since 1.0 + */ +@Role +public interface FilesResourceProvider +{ + /** + * Generates the logs archive from a specified path that are to be downloaded after applying the filters. + * + * @param filter {@link Map} representing the filters that can be applied to the search. + * @param path {@link String} path to where the logs are stored. + * @return {@link Byte} array representing the logs archive. + */ + byte[] generateLogsArchive(Map filter, String path); + + /** + * Extract the hint of a component. + * + * @return {@link String} component hint. + */ + String getIdentifier(); + + /** + * Retreive the last "noLines" logs from the server. + * + * @param serverPath {@link String} path to the server log file. + * @param noLines {@link Long} number of lines of log to be retrieved. + * @return {@link Byte} array representing the last "noLines" logs from the server. + * @throws IOException + */ + byte[] retrieveLastLogs(String serverPath, long noLines) throws IOException; + + /** + * Identifies the searched file and filters the sensitive info from it. The searched As all servers types have the + * same path to the xwiki properties configuration files, it is not needed to call this function in a server + * specific class. + * + * @param type {@link String} identifies the searched file. + * @param xwikiCfgFolderPath {@link String} path to the xwiki configuration folder. + * @return {@link Byte} array representing the filtered file content. + * @throws IOException + */ + byte[] getConfigurationFileContent(String type, String xwikiCfgFolderPath) throws IOException; + +} diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/LogsDownloader.java b/application-admintools-api/src/main/java/com/xwiki/admintools/LogsDownloader.java deleted file mode 100644 index 534d55e0..00000000 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/LogsDownloader.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools; - -import java.util.Map; - -import org.xwiki.component.annotation.Role; - -/** - * Interface to be extended by specific server types. Function are used when the logs download REST API is accessed. - * - * @version $Id$ - * @since 1.0 - */ -@Role -public interface LogsDownloader -{ - /** - * Generates the logs archive from a specified path that are to be downloaded after applying the filters. - * - * @param filter Map representing the filters that can be applied to the search. - * @param path path to where the logs are stored. - * @return byte array representing the logs archive. - */ - byte[] generateLogsArchive(Map filter, String path); - - /** - * Extract the hint of a component. - * - * @return component hint - */ - String getIdentifier(); -} diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResources.java b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResources.java index 2cbb4631..f9f4cb63 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResources.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResources.java @@ -23,53 +23,48 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; import org.xwiki.rest.XWikiRestComponent; import org.xwiki.rest.XWikiRestException; /** - * Provides the APIs needed by the Admin Tools server in order to download configuration files and a logs archive. + * Provides the APIs needed by the Admin Tools server in order to download configuration files and logs archive. * * @version $Id$ * @since 1.0 */ -@Path("/admintools/download") +@Path("/admintools") public interface AdminToolsResources extends XWikiRestComponent { /** - * REST endpoint for accessing the XWiki configuration or properties download. + * REST endpoint for accessing the XWiki configuration or properties files. * - * @param type specifies the XWiki searched file. - * @return Response with a configured header for file download. + * @param type {link String} specifies the XWiki searched file. + * @return {@link Response} with the content of the file, or specific error code. * @throws XWikiRestException */ @GET - @Path("/configs/{fileType}") + @Path("/show/configs/{fileType}") Response getConfigs(@PathParam("fileType") String type) throws XWikiRestException; -// /** -// * REST endpoint for accessing the logs archive download. -// * -// * @param from filter date, starting from. -// * @param to filter date, until. -// * @return Response with a configured header for zip download. -// * @throws XWikiRestException -// */ -// @GET -// @Path("/logs") -// Response getLogs(@QueryParam("from") String from, @QueryParam("to") String to) throws XWikiRestException; + /** + * Rest endpoint to download multiple files. + * + * @return {@link Response} with a configured header for zip download, or specific error code. + * @throws XWikiRestException + */ + @POST + @Path("/download/all") + Response getFiles() throws XWikiRestException; /** - * Rest endpoint to download all selected files. + * Rest endpoint to retrieve last logs from server. * - * @param from filter date, starting from given value. - * @param to filter date, until given value. - * @return Response with a configured header for zip download. + * @return {@link Response} with the content of the last logs, or specific error code. * @throws XWikiRestException */ @POST - @Path("/all") - Response getFiles(@QueryParam("from") String from, @QueryParam("to") String to) throws XWikiRestException; + @Path("/show/logs") + Response retrieveLastLogs() throws XWikiRestException; } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index aee8510f..d4cb13af 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -19,13 +19,17 @@ */ package com.xwiki.admintools.internal.data; +import java.io.File; +import java.io.FileNotFoundException; import java.util.HashMap; import java.util.Map; +import java.util.Scanner; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.xwiki.component.annotation.Component; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; @@ -47,7 +51,7 @@ public class ConfigurationDataProvider extends AbstractDataProvider public static final String HINT = "configuration"; @Inject - private CurrentServer usedServer; + private CurrentServer currentServer; @Override public String getIdentifier() @@ -61,20 +65,16 @@ public String provideData() return getRenderedTemplate("data/configurationTemplate.vm", generateJson(), HINT); } - /** - * Provides the info structured in a json. - * - * @return Map containing the generated info. - */ @Override public Map generateJson() { - usedServer.updatePaths(); + currentServer.updatePaths(); Map systemInfo = new HashMap<>(); - systemInfo.put("xwikiCfgPath", usedServer.getXwikiCfgPath()); - systemInfo.put("tomcatConfPath", this.usedServer.getServerCfgPath()); + systemInfo.put("xwikiCfgPath", currentServer.getXwikiCfgPath()); + systemInfo.put("tomcatConfPath", this.currentServer.getServerCfgPath()); systemInfo.put("javaVersion", this.getJavaVersion()); - systemInfo.put("osInfo", this.getOSInfo()); + systemInfo.putAll(this.getOSInfo()); + systemInfo.put("database", this.identifyDB()); return systemInfo; } @@ -94,12 +94,51 @@ private String getJavaVersion() * * @return info about the OS. */ - private String getOSInfo() + private Map getOSInfo() + { + Map result = new HashMap<>(); + result.put("osName", System.getProperty("os.name")); + result.put("osVersion", System.getProperty("os.version")); + result.put("osArch", System.getProperty("os.arch")); + + return result; + } + + /** + * Identify the used database for XWiki by verifying the configration files. + * + * @return the name of the used database as a String. + */ + private String identifyDB() { - String osName = System.getProperty("os.name"); - String osVersion = System.getProperty("os.version"); - String osArch = System.getProperty("os.arch"); + String databaseCfgPath = currentServer.getXwikiCfgPath() + "hibernate.cfg.xml"; + File file = new File(databaseCfgPath); - return String.format("Operating System: %s %s (%s)", osName, osVersion, osArch); + try (Scanner scanner = new Scanner(file)) { + String usedDB = null; + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.contains("jdbc:")) { + if (line.contains("mysql")) { + usedDB = "MySQL"; + } else if (line.contains("hsqldb")) { + usedDB = "HSQLDB"; + } else if (line.contains("mariadb")) { + usedDB = "MariaDB"; + } else if (line.contains("postgresql")) { + usedDB = "PostgreSQL"; + } else if (line.contains("oracle")) { + usedDB = "Oracle"; + } + break; + } + } + scanner.close(); + return usedDB; + } catch (FileNotFoundException e) { + logger.warn("Failed to open database configuration file. Root cause is: [{}]", + ExceptionUtils.getRootCauseMessage(e)); + return null; + } } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java index 66f0e5e0..884eb285 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java @@ -28,10 +28,7 @@ import org.xwiki.component.annotation.Component; import org.xwiki.configuration.ConfigurationSource; -import org.xwiki.model.reference.DocumentReference; -import org.xwiki.model.reference.WikiReference; -import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiContext; /** @@ -69,9 +66,7 @@ public class SecurityDataProvider extends AbstractDataProvider @Override public String provideData() { - Map securityDetails = this.generateJson(); - - return getRenderedTemplate("data/securityTemplate.vm", securityDetails, HINT); + return getRenderedTemplate("data/securityTemplate.vm", this.generateJson(), HINT); } /** @@ -82,16 +77,10 @@ public String provideData() @Override public Map generateJson() { - Map results = new HashMap<>(); + Map results = this.getXwikiSecurityInfo(); - XWikiContext wikiContext = xcontextProvider.get(); - XWiki wiki = wikiContext.getWiki(); - DocumentReference a = wikiContext.getUserReference(); - WikiReference b = wikiContext.getWikiReference(); - results.put("activeEncoding", wiki.getEncoding()); - results.put("configurationEncoding", configurationSource.getProperty("xwiki.encoding", String.class)); - results.put("fileEncoding", System.getProperty("file.encoding")); results.putAll(getEnvironmentInfo()); + results.put("fileEncoding", System.getProperty("file.encoding")); return results; } @@ -102,6 +91,22 @@ public String getIdentifier() return HINT; } + /** + * Get the security info of the current wiki. + * + * @return {@link Map} with XWiki security info regarding used and active encodings. + */ + private Map getXwikiSecurityInfo() + { + Map results = new HashMap<>(); + + XWikiContext wikiContext = xcontextProvider.get(); + results.put("activeEncoding", wikiContext.getWiki().getEncoding()); + results.put("configurationEncoding", configurationSource.getProperty("xwiki.encoding", String.class)); + + return results; + } + /** * Get the security info regarding the environment. * diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java index 7d8de45e..34c346c9 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java @@ -52,11 +52,6 @@ public Map getServerIdentifiers() return serverIdentifiers; } - /** - * Get the server configuration file path. - * - * @return path to Tomcat configuration file. - */ @Override public String getServerCfgPath() { @@ -68,20 +63,14 @@ public String getServerCfgPath() return null; } - /** - * Get the configuration file path for the XWiki installation. - * - * @return path to the XWiki configuration file. - */ @Override public String getXwikiCfgPath() { for (String xwikiCfgPath : xwikiCfgPossiblePaths) { - if ((new File(xwikiCfgPath)).exists()) { + if ((new File(xwikiCfgPath + "xwiki.cfg")).exists()) { return xwikiCfgPath; } } return null; } } - diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java index 09bdaa55..84a7c96b 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java @@ -103,16 +103,6 @@ public void updatePaths() } } - /** - * Retrieves the server type. - * - * @return a string representing the server HINT. - */ - public String getServerType() - { - return usedServer.getIdentifier(); - } - /** * Calls the used server function to retrieve the server identifiers. * diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java index 9223c213..4ecd8828 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java @@ -72,11 +72,10 @@ public void updatePaths(String providedConfigServerPath) "/usr/local/tomcat/conf/server.xml", "/opt/tomcat/conf/server.xml", "/var/lib/tomcat8/conf/", "/var/lib/tomcat9/conf/", "/var/lib/tomcat/conf/" }; - this.xwikiCfgPossiblePaths = new String[] { "/etc/xwiki/xwiki.cfg", - String.format("%s/webapps${request.contextPath}/WEB-INF/xwiki.cfg", this.serverPath), - "/usr/local/xwiki/WEB-INF/xwiki.cfg", "/opt/xwiki/WEB-INF/xwiki.cfg", - String.format("%s/webapps/ROOT/WEB-INF/xwiki.cfg", this.serverPath), - String.format("%s/webapps/xwiki/WEB-INF/xwiki.cfg", this.serverPath) }; + this.xwikiCfgPossiblePaths = new String[] { "/etc/xwiki/", + "/usr/local/xwiki/WEB-INF/", "/opt/xwiki/WEB-INF/", + String.format("%s/webapps/ROOT/WEB-INF/", this.serverPath), + String.format("%s/webapps/xwiki/WEB-INF/", this.serverPath) }; } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractLogsDownloader.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractFilesResourceProvider.java similarity index 51% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractLogsDownloader.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractFilesResourceProvider.java index ab827d26..54c56f6d 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractLogsDownloader.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractFilesResourceProvider.java @@ -20,11 +20,21 @@ package com.xwiki.admintools.internal.downloads; import java.io.BufferedInputStream; +import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.RandomAccessFile; import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.ZipEntry; @@ -35,26 +45,57 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; -import com.xwiki.admintools.LogsDownloader; +import com.xwiki.admintools.FilesResourceProvider; /** - * Abstract implementation of {@link LogsDownloader}. Adds common functions to all server types. + * Abstract implementation of {@link FilesResourceProvider}. Adds common functions for all server types. * * @version $Id$ * @since 1.0 */ -public abstract class AbstractLogsDownloader implements LogsDownloader +public abstract class AbstractFilesResourceProvider implements FilesResourceProvider { @Inject private Logger logger; + @Override + public byte[] getConfigurationFileContent(String type, String xwikiCfgFolderPath) throws IOException + { + String filePath = ""; + if (Objects.equals(type, "properties")) { + filePath = xwikiCfgFolderPath + "xwiki.properties"; + } else if (Objects.equals(type, "config")) { + filePath = xwikiCfgFolderPath + "xwiki.cfg"; + } + File inputFile = new File(filePath); + + BufferedReader reader = new BufferedReader(new FileReader(inputFile)); + StringBuilder stringBuilder = new StringBuilder(); + + String currentLine; + List wordsList = new ArrayList<>( + Arrays.asList("xwiki.authentication.validationKey", "xwiki.authentication.encryptionKey", + "xwiki.superadminpassword", "extension.repositories.privatemavenid.auth", "mail.sender.password")); + + // Read line by line and do not add it if it contains sensitive info. + while ((currentLine = reader.readLine()) != null) { + String trimmedLine = currentLine.trim(); + if (wordsList.stream().anyMatch(trimmedLine::contains)) { + continue; + } + stringBuilder.append(currentLine).append(System.getProperty("line.separator")); + } + reader.close(); + return stringBuilder.toString().getBytes(); + } + /** * Identifies the logs location and applies the filters to the specified server pattern. * - * @param filters Map that can contain the start and end date of the search. It can also be empty. - * @param listOfFiles File list of all the log files. - * @param pattern server specific pattern used to identify the log date from the log name. - * @return byte array representing the logs archive. + * @param filters {@link Map} that can contain the start and end date of the search. It can also be empty. + * @param listOfFiles {@link File} list of all the log files. + * @param pattern server specific {@link Pattern} used to identify the log date from the log name. + * @return {@link Byte} array representing the logs archive. */ protected byte[] generateArchive(Map filters, File[] listOfFiles, Pattern pattern) { @@ -91,13 +132,52 @@ protected byte[] generateArchive(Map filters, File[] listOfFiles } } + /** + * Get server's last "noLines" logs. It is limited to 50000 lines. + * + * @param filePath {@link String} path to the log file. + * @param noLines {@link Long} number of lines to be retrieved. + * @return {@link Byte} array representing the last "noLine" logs. + * @throws IOException + */ + protected byte[] defaultRetrieveLastLogs(String filePath, long noLines) throws IOException + { + File file = new File(filePath); + if (!file.exists() || !file.isFile()) { + throw new FileNotFoundException("File not found: " + filePath); + } + try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) { + long fileLength = randomAccessFile.length(); + List logLines = new ArrayList<>(); + + // Calculate the approximate position to start reading from based on line length + long startPosition = fileLength - 1; + for (long i = 0; i < noLines && startPosition > 0 && i < 50000; startPosition--) { + randomAccessFile.seek(startPosition - 1); + int currentByte = randomAccessFile.read(); + if (currentByte == '\n' || currentByte == '\r') { + // Found a newline character, add the line to the list + logLines.add(randomAccessFile.readLine()); + i++; + } + } + // Reverse the list to get the lines in the correct order + Collections.reverse(logLines); + // Join the lines with newline characters + return String.join("\n", logLines).getBytes(); + } catch (IOException e) { + logger.warn("Failed to retrieve logs. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); + return null; + } + } + /** * Check that the file date is in the filter range. Returns true if no filter is provided. * - * @param filters Map that can contain the start and end date of the search. It can also be empty. - * @param pattern server specific pattern used to identify the log date from the log name. - * @param file current file that is to be checked. - * @return true if the file is between the provided dates or there is no filter, false otherwise + * @param filters {@link Map} that can contain the start and end date of the search. It can also be empty. + * @param pattern server specific {@link Pattern} used to identify the log date from the log name. + * @param file current {@link File} that is to be checked. + * @return {@link Boolean} true if the file is between the provided dates or there is no filter, false otherwise */ private boolean checkFilters(Map filters, Pattern pattern, File file) { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java index bdf53565..5535b55b 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java @@ -19,13 +19,8 @@ */ package com.xwiki.admintools.internal.downloads; -import java.io.BufferedReader; import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileReader; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -51,7 +46,7 @@ import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.web.XWikiRequest; import com.xwiki.admintools.DataProvider; -import com.xwiki.admintools.LogsDownloader; +import com.xwiki.admintools.FilesResourceProvider; import com.xwiki.admintools.internal.data.ConfigurationDataProvider; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; @@ -65,10 +60,6 @@ @Singleton public class DownloadsManager implements Initializable { - private final String config = "config"; - - private final String properties = "properties"; - @Inject private Provider xcontextProvider; @@ -82,7 +73,9 @@ public class DownloadsManager implements Initializable * A list of all supported server file downloaders. */ @Inject - private Provider> filesDownloader; + private Provider> filesResourceProviderProvider; + + private FilesResourceProvider usedFilesResourceProvider; @Inject @Named(ConfigurationDataProvider.HINT) @@ -90,8 +83,6 @@ public class DownloadsManager implements Initializable private String serverPath; - private String serverType; - @Inject private Logger logger; @@ -105,25 +96,26 @@ public void initialize() throws InitializationException { Map identifiers = currentServer.getServerIdentifiers(); serverPath = identifiers.get("serverPath"); - serverType = identifiers.get("serverType"); + String usedServerLogsHint = identifiers.get("serverType") + "Logs"; + findUsedServer(usedServerLogsHint); } /** * Initiates the download process for the xwiki files. It removes the sensitive content from the file. * - * @param fileType properties of configuration file. - * @return filtered file content as a byte array + * @param fileType {@link String} representing the file type. + * @return filtered file content as a {@link Byte} array * @throws IOException */ public byte[] getXWikiFile(String fileType) throws IOException { - return prepareFile(fileType); + return usedFilesResourceProvider.getConfigurationFileContent(fileType, currentServer.getXwikiCfgPath()); } /** * Checks the admin rights of the calling user. * - * @return true if the user is admin, false otherwise + * @return {@link Boolean} true if the user is admin, false otherwise */ public boolean isAdmin() { @@ -136,7 +128,7 @@ public boolean isAdmin() /** * Retrieve the selected files from the request and create an archive containing them. * - * @return byte array representing the files archive. + * @return {@link Byte} array representing the files archive. */ public byte[] downloadMultipleFiles() { @@ -158,6 +150,27 @@ public byte[] downloadMultipleFiles() } } + /** + * Select the right server downloader and call the logs retrieval function. + * + * @return {@link Byte} array representing the last "n" logs. + * @throws IOException + */ + public byte[] callLogsRetriever() throws IOException + { + XWikiContext wikiContext = xcontextProvider.get(); + XWikiRequest xWikiRequest = wikiContext.getRequest(); + long noLines = Long.parseLong(xWikiRequest.getParameter("noLines")); + return usedFilesResourceProvider.retrieveLastLogs(serverPath, noLines); + } + + /** + * Verify which files are selected, prepare the zip entry and add it to the zip stream. + * + * @param files {@link Map} representing the files that are to be processed. + * @param zipOutputStream {@link ZipOutputStream} where the zip entries are stored. + * @throws IOException + */ private void createArchiveEntries(Map files, ZipOutputStream zipOutputStream) throws IOException { ZipEntry zipEntry; @@ -167,14 +180,16 @@ private void createArchiveEntries(Map files, ZipOutputStream z case "cfg_file": zipEntry = new ZipEntry("xwiki.cfg"); zipOutputStream.putNextEntry(zipEntry); - buffer = prepareFile(config); + buffer = usedFilesResourceProvider.getConfigurationFileContent("config", + currentServer.getXwikiCfgPath()); zipOutputStream.write(buffer, 0, buffer.length); zipOutputStream.closeEntry(); break; case "properties_file": zipEntry = new ZipEntry("xwiki.properties"); zipOutputStream.putNextEntry(zipEntry); - buffer = prepareFile(properties); + buffer = usedFilesResourceProvider.getConfigurationFileContent("properties", + currentServer.getXwikiCfgPath()); zipOutputStream.write(buffer, 0, buffer.length); zipOutputStream.closeEntry(); break; @@ -207,67 +222,25 @@ private void createArchiveEntries(Map files, ZipOutputStream z * Initiates the download process for the server logs. Taking into consideration the used server, it identifies the * right downloader. It returns null if none is corresponding. * - * @param filters Map that can contain the start and end date of the search. It can also be empty. - * @return byte array representing the logs archive. + * @param filters {@link Map} that can contain the start and end date of the search. It can also be empty. + * @return {@link Byte} array representing the logs archive. */ private byte[] getLogs(Map filters) { - return callLogsDownloader(serverType + "Logs", filters); - } - - /** - * Identifies the searched file and filters the sensitive info from it. The searched As all servers types have the - * same path to the xwiki properties configuration files, it is not needed to call this function in a server - * specific class. - * - * @param type identifies the searched file. - * @return byte array representing the filtered file content. - * @throws IOException - */ - private byte[] prepareFile(String type) throws IOException - { - String filePath = serverPath; - if (Objects.equals(type, properties)) { - filePath += "/webapps/xwiki/WEB-INF/xwiki.properties"; - } else if (Objects.equals(type, config)) { - filePath += "/webapps/xwiki/WEB-INF/xwiki.cfg"; - } - File inputFile = new File(filePath); - - BufferedReader reader = new BufferedReader(new FileReader(inputFile)); - StringBuilder stringBuilder = new StringBuilder(); - - String currentLine; - List wordsList = new ArrayList<>( - Arrays.asList("xwiki.authentication.validationKey", "xwiki.authentication.encryptionKey", - "xwiki.superadminpassword", "extension.repositories.privatemavenid.auth", "mail.sender.password")); - - // Read line by line and do not add it if it contains sensitive info. - while ((currentLine = reader.readLine()) != null) { - String trimmedLine = currentLine.trim(); - if (wordsList.stream().anyMatch(trimmedLine::contains)) { - continue; - } - stringBuilder.append(currentLine).append(System.getProperty("line.separator")); - } - reader.close(); - return stringBuilder.toString().getBytes(); + return usedFilesResourceProvider.generateLogsArchive(filters, serverPath); } /** * Calls the logs generator for the used server. * - * @param hint represents the used server hint. - * @param filter Map representing the filters that can be applied to the search. - * @return byte array representing the logs archive. + * @param hint {@link String} represents the used server hint. */ - private byte[] callLogsDownloader(String hint, Map filter) + private void findUsedServer(String hint) { - for (LogsDownloader specificLogsDownloader : this.filesDownloader.get()) { - if (specificLogsDownloader.getIdentifier().equals(hint)) { - return specificLogsDownloader.generateLogsArchive(filter, serverPath); + for (FilesResourceProvider specificFilesResourceProvider : this.filesResourceProviderProvider.get()) { + if (specificFilesResourceProvider.getIdentifier().equals(hint)) { + usedFilesResourceProvider = specificFilesResourceProvider; } } - return null; } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatLogsDownloader.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatFilesResourceProvider.java similarity index 83% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatLogsDownloader.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatFilesResourceProvider.java index b597e9c3..e1cb7c1a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatLogsDownloader.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatFilesResourceProvider.java @@ -20,6 +20,7 @@ package com.xwiki.admintools.internal.downloads; import java.io.File; +import java.io.IOException; import java.util.Map; import java.util.regex.Pattern; @@ -35,9 +36,9 @@ * @since 1.0 */ @Component -@Named(TomcatLogsDownloader.HINT) +@Named(TomcatFilesResourceProvider.HINT) @Singleton -public class TomcatLogsDownloader extends AbstractLogsDownloader +public class TomcatFilesResourceProvider extends AbstractFilesResourceProvider { /** * The hint for the component. @@ -59,4 +60,10 @@ public String getIdentifier() { return HINT; } + + @Override + public byte[] retrieveLastLogs(String serverPath, long noLines) throws IOException + { + return defaultRetrieveLastLogs(serverPath + "/logs/catalina.out", noLines); + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java index d59104bf..7a373ccf 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java @@ -75,45 +75,20 @@ public Response getConfigs(String type) throws XWikiRestException return Response.status(404).build(); } InputStream inputStream = new ByteArrayInputStream(xWikiFileContent); - return Response.ok(inputStream). - type(MediaType.TEXT_PLAIN_TYPE).build(); - // Set the appropriate response headers to indicate a file download. + return Response.ok(inputStream).type(MediaType.TEXT_PLAIN_TYPE).build(); } catch (Exception e) { logger.warn("Failed to get file [{}]. Root cause: [{}]", type, ExceptionUtils.getRootCauseMessage(e)); throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } } -// @Override -// public Response getLogs(String from, String to) throws XWikiRestException -// { -// if (!downloadsManager.isAdmin()) { -// logger.warn("Failed to get server logs due to restricted rights."); -// throw new WebApplicationException(Response.Status.UNAUTHORIZED); -// } -// try { -// Map filters = new HashMap<>(); -// filters.put("from", from); -// filters.put("to", to); -// byte[] logsArchive = downloadsManager.getLogs(filters); -// if (!(logsArchive == null) && !(Arrays.toString(logsArchive).length() == 0)) { -// // Set the appropriate response headers to indicate a zip file download. -// Response.ResponseBuilder response = Response.ok(logsArchive); -// response.header("Content-Type", "application/zip"); -// return response.build(); -// } else { -// // Handle the case when no logs are found or an error occurs. -// return Response.status(Response.Status.NOT_FOUND).entity("No logs found.").build(); -// } -// } catch (Exception e) { -// logger.warn("Failed to get logs. Root cause: [{}]", ExceptionUtils.getRootCauseMessage(e)); -// throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); -// } -// } - @Override - public Response getFiles(String from, String to) throws XWikiRestException + public Response getFiles() throws XWikiRestException { + if (!downloadsManager.isAdmin()) { + logger.warn("Failed to get files due to restricted rights."); + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } try { byte[] filesArchive = downloadsManager.downloadMultipleFiles(); if (!(filesArchive == null) && !(Arrays.toString(filesArchive).length() == 0)) { @@ -124,8 +99,28 @@ public Response getFiles(String from, String to) throws XWikiRestException return response.build(); } else { // Handle the case when no logs are found or an error occurs. - return Response.status(Response.Status.NOT_FOUND).entity("No logs found.").build(); + return Response.status(Response.Status.NOT_FOUND).entity("No files found.").build(); } + } catch (Exception e) { + logger.warn("Failed to download files. Root cause: [{}]", ExceptionUtils.getRootCauseMessage(e)); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } + + @Override + public Response retrieveLastLogs() throws XWikiRestException + { + if (!downloadsManager.isAdmin()) { + logger.warn("Failed to get the logs due to restricted rights."); + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + try { + byte[] xWikiFileContent = downloadsManager.callLogsRetriever(); + if (xWikiFileContent.length == 0) { + return Response.status(404).build(); + } + InputStream inputStream = new ByteArrayInputStream(xWikiFileContent); + return Response.ok(inputStream).type(MediaType.TEXT_PLAIN_TYPE).build(); } catch (Exception e) { logger.warn("Failed to get logs. Root cause: [{}]", ExceptionUtils.getRootCauseMessage(e)); throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index 271be404..453332b3 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -2,7 +2,7 @@ com.xwiki.admintools.script.AdminToolsScriptService com.xwiki.admintools.internal.AdminToolsManager com.xwiki.admintools.internal.data.ConfigurationDataProvider com.xwiki.admintools.internal.data.SecurityDataProvider -com.xwiki.admintools.internal.downloads.TomcatLogsDownloader +com.xwiki.admintools.internal.downloads.TomcatFilesResourceProvider com.xwiki.admintools.internal.downloads.DownloadsManager com.xwiki.admintools.internal.data.identifiers.CurrentServer com.xwiki.admintools.internal.data.identifiers.TomcatIdentifier From 8cc8c1d4bee48c79dd94e4f74acb1f4b29f91351 Mon Sep 17 00:00:00 2001 From: Sorin Date: Tue, 12 Sep 2023 18:21:29 +0300 Subject: [PATCH 22/72] Download important files #8 - DRAFT --- .../com/xwiki/admintools/DataProvider.java | 2 +- .../admintools/FilesResourceProvider.java | 74 ---------- .../xwiki/admintools/ResourceProvider.java | 44 ++++++ .../xwiki/admintools/ServerIdentifier.java | 29 +++- .../internal/AdminToolsManager.java | 5 +- .../data/ConfigurationDataProvider.java | 6 +- .../identifiers/AbstractServerIdentifier.java | 10 +- .../data/identifiers/CurrentServer.java | 29 +--- .../data/identifiers/TomcatIdentifier.java | 74 +++++----- .../AbstractResourceProvider.java} | 72 +++++---- .../DownloadManager.java} | 83 +++-------- .../download/FileResourceProvider.java | 96 ++++++++++++ .../LogsDownloadResourceProvider.java | 137 ++++++++++++++++++ .../download/LogsViewerResourceProvider.java | 94 ++++++++++++ .../TomcatFilesResourceProvider.java | 69 --------- .../internal/rest/DefaultResources.java | 18 +-- .../script/AdminToolsScriptService.java | 4 +- .../main/resources/META-INF/components.txt | 6 +- .../templates/data/configurationTemplate.vm | 31 +++- 19 files changed, 546 insertions(+), 337 deletions(-) delete mode 100644 application-admintools-api/src/main/java/com/xwiki/admintools/FilesResourceProvider.java create mode 100644 application-admintools-api/src/main/java/com/xwiki/admintools/ResourceProvider.java rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/{downloads/AbstractFilesResourceProvider.java => download/AbstractResourceProvider.java} (80%) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/{downloads/DownloadsManager.java => download/DownloadManager.java} (70%) create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/FileResourceProvider.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/LogsDownloadResourceProvider.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/LogsViewerResourceProvider.java delete mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatFilesResourceProvider.java diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java index c6bd131e..e523ba3d 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java @@ -42,7 +42,7 @@ public interface DataProvider /** * Provides the info structured in a json. * - * @return Map containing the generated info. + * @return {@link Map} containing the generated info. */ Map generateJson(); diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/FilesResourceProvider.java b/application-admintools-api/src/main/java/com/xwiki/admintools/FilesResourceProvider.java deleted file mode 100644 index ff6c504e..00000000 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/FilesResourceProvider.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools; - -import java.io.IOException; -import java.util.Map; - -import org.xwiki.component.annotation.Role; - -/** - * Provides functions for logs retrieval. - * - * @version $Id$ - * @since 1.0 - */ -@Role -public interface FilesResourceProvider -{ - /** - * Generates the logs archive from a specified path that are to be downloaded after applying the filters. - * - * @param filter {@link Map} representing the filters that can be applied to the search. - * @param path {@link String} path to where the logs are stored. - * @return {@link Byte} array representing the logs archive. - */ - byte[] generateLogsArchive(Map filter, String path); - - /** - * Extract the hint of a component. - * - * @return {@link String} component hint. - */ - String getIdentifier(); - - /** - * Retreive the last "noLines" logs from the server. - * - * @param serverPath {@link String} path to the server log file. - * @param noLines {@link Long} number of lines of log to be retrieved. - * @return {@link Byte} array representing the last "noLines" logs from the server. - * @throws IOException - */ - byte[] retrieveLastLogs(String serverPath, long noLines) throws IOException; - - /** - * Identifies the searched file and filters the sensitive info from it. The searched As all servers types have the - * same path to the xwiki properties configuration files, it is not needed to call this function in a server - * specific class. - * - * @param type {@link String} identifies the searched file. - * @param xwikiCfgFolderPath {@link String} path to the xwiki configuration folder. - * @return {@link Byte} array representing the filtered file content. - * @throws IOException - */ - byte[] getConfigurationFileContent(String type, String xwikiCfgFolderPath) throws IOException; - -} diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/ResourceProvider.java b/application-admintools-api/src/main/java/com/xwiki/admintools/ResourceProvider.java new file mode 100644 index 00000000..ac5eb0b8 --- /dev/null +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/ResourceProvider.java @@ -0,0 +1,44 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools; + +import java.io.IOException; + +import org.xwiki.component.annotation.Role; + +/** + * Provides functions for logs retrieval. + * + * @param + * @version $Id$ + * @since 1.0 + */ +@Role +public interface ResourceProvider +{ + /** + * Get the requested data from the server. + * + * @param input {@link T} data received from user input. + * @return {@link Byte} array representing the transfer data. + * @throws IOException + */ + byte[] getByteData(T input) throws IOException; +} diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java index 15ca403d..02999869 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java @@ -19,7 +19,7 @@ */ package com.xwiki.admintools; -import java.util.Map; +import java.util.regex.Pattern; import org.xwiki.component.annotation.Role; @@ -69,9 +69,30 @@ public interface ServerIdentifier void updatePaths(String providedConfigServerPath); /** - * Access the server path and type. + * Get path to server. * - * @return {@link Map} containing server path and type. + * @return {@link String} with server path. */ - Map getServerIdentifiers(); + String getServerPath(); + + /** + * Get path to server logs folder. + * + * @return {@link String} with server logs folder path. + */ + String getLogsFolderPath(); + + /** + * Get path to server last updated main log file. + * + * @return {@link String} path to server log file. + */ + String getLogFilePath(); + + /** + * Get server pattern for identifying log files date. + * + * @return {@link Pattern} representing the date format in server log files names. + */ + Pattern getLogsPattern(); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index 4c061bc2..810b8ab2 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -20,6 +20,7 @@ package com.xwiki.admintools.internal; import java.util.List; +import java.util.Map; import javax.inject.Inject; import javax.inject.Provider; @@ -72,11 +73,11 @@ public String generateData() * @param hint {@link String} represents the data provider identifier. * @return a {@link String} representing a template */ - public String generateData(String hint) + public Map generateData(String hint) { for (DataProvider dataProvider : this.dataProviderProvider.get()) { if (dataProvider.getIdentifier().equals(hint)) { - return dataProvider.provideData(); + return dataProvider.generateJson(); } } return null; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index f51d9f11..b2fa2c2c 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -70,8 +70,8 @@ public Map generateJson() { currentServer.findPaths(); Map systemInfo = new HashMap<>(); - systemInfo.put("xwikiCfgPath", currentServer.retrieveXwikiCfgPath()); - systemInfo.put("tomcatConfPath", this.currentServer.retrieveServerCfgPath()); + systemInfo.put("xwikiCfgPath", currentServer.getUsedServer().getXwikiCfgFolderPath()); + systemInfo.put("tomcatConfPath", this.currentServer.getUsedServer().getServerCfgPath()); systemInfo.put("javaVersion", this.getJavaVersion()); systemInfo.putAll(this.getOSInfo()); systemInfo.put("database", this.identifyDB()); @@ -111,7 +111,7 @@ private Map getOSInfo() */ private String identifyDB() { - String databaseCfgPath = currentServer.retrieveXwikiCfgPath() + "hibernate.cfg.xml"; + String databaseCfgPath = currentServer.getUsedServer().getXwikiCfgFolderPath() + "hibernate.cfg.xml"; File file = new File(databaseCfgPath); try (Scanner scanner = new Scanner(file)) { String usedDB = null; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java index 16d3f447..6a2e6b48 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java @@ -20,8 +20,6 @@ package com.xwiki.admintools.internal.data.identifiers; import java.io.File; -import java.util.HashMap; -import java.util.Map; import com.xwiki.admintools.ServerIdentifier; @@ -43,13 +41,9 @@ public abstract class AbstractServerIdentifier implements ServerIdentifier protected String serverPath; @Override - public Map getServerIdentifiers() + public String getServerPath() { - Map serverIdentifiers = new HashMap<>(); - serverIdentifiers.put("serverPath", serverPath); - serverIdentifiers.put("serverType", getIdentifier()); - - return serverIdentifiers; + return serverPath; } /** diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java index 0fe2fb56..d2335568 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java @@ -20,7 +20,6 @@ package com.xwiki.admintools.internal.data.identifiers; import java.util.List; -import java.util.Map; import javax.inject.Inject; import javax.inject.Named; @@ -69,23 +68,13 @@ public void initialize() throws InitializationException } /** - * Retrieves the XWiki configuration file path for the installation. + * Get the used server identifier. * - * @return a {@link String} representing the path to the XWiki configuration file. + * @return {@link ServerIdentifier} */ - public String retrieveXwikiCfgPath() + public ServerIdentifier getUsedServer() { - return usedServer.getXwikiCfgFolderPath(); - } - - /** - * Retrieves the server configuration file path for the installation. - * - * @return a {@link String} representing the path to the server configuration file. - */ - public String retrieveServerCfgPath() - { - return usedServer.getServerCfgPath(); + return usedServer; } /** @@ -99,16 +88,6 @@ public void findPaths() } } - /** - * Calls the used server function to retrieve the server identifiers. - * - * @return a {@link Map} with the info used to identify the server. - */ - public Map getServerIdentifiers() - { - return usedServer.getServerIdentifiers(); - } - /** * Go through all supported servers and return the one that is used. * diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java index f7137fb2..5cb9fb3c 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java @@ -20,6 +20,7 @@ package com.xwiki.admintools.internal.data.identifiers; import java.io.File; +import java.util.regex.Pattern; import javax.inject.Named; import javax.inject.Singleton; @@ -42,44 +43,10 @@ public class TomcatIdentifier extends AbstractServerIdentifier /** * Component identifier. */ - public static final String HINT = "tomcat"; + public static final String HINT = "Tomcat"; @Override public boolean isUsed(String providedConfigServerPath) - { - return tomcatIsUsed(providedConfigServerPath); - } - - @Override - public String getIdentifier() - { - return HINT; - } - - @Override - public void updatePaths(String providedConfigServerPath) - { - if (tomcatIsUsed(providedConfigServerPath)) { - this.serverCfgPossiblePaths = new String[] { String.format("%s/conf/server.xml", this.serverPath), - "/usr/local/tomcat/conf/server.xml", "/opt/tomcat/conf/server.xml", "/var/lib/tomcat8/conf/", - "/var/lib/tomcat9/conf/server.xml", "/var/lib/tomcat/conf/server.xml" }; - - this.xwikiCfgPossiblePaths = new String[] { "/etc/xwiki/", - "/usr/local/xwiki/WEB-INF/", "/opt/xwiki/WEB-INF/", - String.format("%s/webapps/ROOT/WEB-INF/", this.serverPath), - String.format("%s/webapps/xwiki/WEB-INF/", this.serverPath) }; - } - } - - /** - * Function used to verify if a Tomcat server is used. If a server path is provided in the XWiki configurations, it - * verifies if the path corresponds to a Tomcat server. Otherwise, it searches the Catalina location in system - * properties and system environment. - * - * @param providedConfigServerPath {@link String} server path provided in the XWiki configuration page. - * @return {@link Boolean} true if Tomcat is the used server, false otherwise. - */ - private boolean tomcatIsUsed(String providedConfigServerPath) { if (providedConfigServerPath != null) { File file = new File(providedConfigServerPath + "conf/catalina.properties"); @@ -101,4 +68,41 @@ private boolean tomcatIsUsed(String providedConfigServerPath) } return true; } + + @Override + public String getIdentifier() + { + return HINT; + } + + @Override + public void updatePaths(String providedConfigServerPath) + { + this.serverCfgPossiblePaths = + new String[] { String.format("%s/conf/server.xml", this.serverPath), "/usr/local/tomcat/conf/server.xml", + "/opt/tomcat/conf/server.xml", "/var/lib/tomcat8/conf/", "/var/lib/tomcat9/conf/server.xml", + "/var/lib/tomcat/conf/server.xml" }; + + this.xwikiCfgPossiblePaths = new String[] { "/etc/xwiki/", "/usr/local/xwiki/WEB-INF/", "/opt/xwiki/WEB-INF/", + String.format("%s/webapps/ROOT/WEB-INF/", this.serverPath), + String.format("%s/webapps/xwiki/WEB-INF/", this.serverPath) }; + } + + @Override + public String getLogsFolderPath() + { + return this.serverPath + "/logs"; + } + + @Override + public String getLogFilePath() + { + return this.serverPath + "/logs/catalina.out"; + } + + @Override + public Pattern getLogsPattern() + { + return Pattern.compile("\\d{4}-\\d{2}-\\d{2}"); + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractFilesResourceProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/AbstractResourceProvider.java similarity index 80% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractFilesResourceProvider.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/AbstractResourceProvider.java index 54c56f6d..f8b6595c 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/AbstractFilesResourceProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/AbstractResourceProvider.java @@ -17,24 +17,20 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.downloads; +package com.xwiki.admintools.internal.download; import java.io.BufferedInputStream; -import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; import java.io.RandomAccessFile; import java.time.LocalDate; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.ZipEntry; @@ -45,49 +41,49 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; -import com.xwiki.admintools.FilesResourceProvider; +import com.xwiki.admintools.ResourceProvider; /** - * Abstract implementation of {@link FilesResourceProvider}. Adds common functions for all server types. + * Abstract implementation of {@link ResourceProvider}. Adds common functions for all server types. * * @version $Id$ * @since 1.0 */ -public abstract class AbstractFilesResourceProvider implements FilesResourceProvider +public abstract class AbstractResourceProvider implements ResourceProvider { @Inject private Logger logger; - @Override - public byte[] getConfigurationFileContent(String type, String xwikiCfgFolderPath) throws IOException - { - String filePath = ""; - if (Objects.equals(type, "properties")) { - filePath = xwikiCfgFolderPath + "xwiki.properties"; - } else if (Objects.equals(type, "config")) { - filePath = xwikiCfgFolderPath + "xwiki.cfg"; - } - File inputFile = new File(filePath); - - BufferedReader reader = new BufferedReader(new FileReader(inputFile)); - StringBuilder stringBuilder = new StringBuilder(); - - String currentLine; - List wordsList = new ArrayList<>( - Arrays.asList("xwiki.authentication.validationKey", "xwiki.authentication.encryptionKey", - "xwiki.superadminpassword", "extension.repositories.privatemavenid.auth", "mail.sender.password")); - - // Read line by line and do not add it if it contains sensitive info. - while ((currentLine = reader.readLine()) != null) { - String trimmedLine = currentLine.trim(); - if (wordsList.stream().anyMatch(trimmedLine::contains)) { - continue; - } - stringBuilder.append(currentLine).append(System.getProperty("line.separator")); - } - reader.close(); - return stringBuilder.toString().getBytes(); - } +// @Override +// public byte[] getConfigurationFileContent(String type, String xwikiCfgFolderPath) throws IOException +// { +// String filePath = ""; +// if (Objects.equals(type, "properties")) { +// filePath = xwikiCfgFolderPath + "xwiki.properties"; +// } else if (Objects.equals(type, "config")) { +// filePath = xwikiCfgFolderPath + "xwiki.cfg"; +// } +// File inputFile = new File(filePath); +// +// BufferedReader reader = new BufferedReader(new FileReader(inputFile)); +// StringBuilder stringBuilder = new StringBuilder(); +// +// String currentLine; +// List wordsList = new ArrayList<>( +// Arrays.asList("xwiki.authentication.validationKey", "xwiki.authentication.encryptionKey", +// "xwiki.superadminpassword", "extension.repositories.privatemavenid.auth", "mail.sender.password")); +// +// // Read line by line and do not add it if it contains sensitive info. +// while ((currentLine = reader.readLine()) != null) { +// String trimmedLine = currentLine.trim(); +// if (wordsList.stream().anyMatch(trimmedLine::contains)) { +// continue; +// } +// stringBuilder.append(currentLine).append(System.getProperty("line.separator")); +// } +// reader.close(); +// return stringBuilder.toString().getBytes(); +// } /** * Identifies the logs location and applies the filters to the specified server pattern. diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/DownloadManager.java similarity index 70% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/DownloadManager.java index 9f0201a6..f60e89ce 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/DownloadsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/DownloadManager.java @@ -17,12 +17,11 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.downloads; +package com.xwiki.admintools.internal.download; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.zip.ZipEntry; @@ -36,8 +35,6 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.xwiki.component.annotation.Component; -import org.xwiki.component.phase.Initializable; -import org.xwiki.component.phase.InitializationException; import org.xwiki.model.reference.DocumentReference; import org.xwiki.model.reference.WikiReference; import org.xwiki.security.authorization.AuthorizationManager; @@ -46,9 +43,8 @@ import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.web.XWikiRequest; import com.xwiki.admintools.DataProvider; -import com.xwiki.admintools.FilesResourceProvider; +import com.xwiki.admintools.ResourceProvider; import com.xwiki.admintools.internal.data.ConfigurationDataProvider; -import com.xwiki.admintools.internal.data.identifiers.CurrentServer; /** * Encapsulates functions used for downloading important server files. @@ -56,50 +52,35 @@ * @version $Id$ * @since 1.0 */ -@Component(roles = DownloadsManager.class) +@Component(roles = DownloadManager.class) @Singleton -public class DownloadsManager implements Initializable +public class DownloadManager { @Inject private Provider xcontextProvider; @Inject - private CurrentServer currentServer; + @Named(LogsDownloadResourceProvider.HINT) + private ResourceProvider> logsDownloadResourceProvider; @Inject - private AuthorizationManager authorizationManager; + @Named(LogsViewerResourceProvider.HINT) + private ResourceProvider logsViewerResourceProvider; - /** - * A list of all supported server file downloaders. - */ @Inject - private Provider> filesResourceProviderProvider; + @Named(FileResourceProvider.HINT) + private ResourceProvider filesResourceProvider; - private FilesResourceProvider usedFilesResourceProvider; + @Inject + private AuthorizationManager authorizationManager; @Inject @Named(ConfigurationDataProvider.HINT) private DataProvider configurationDataProvider; - private String serverPath; - @Inject private Logger logger; - /** - * Initializes variables with the server type and the path to the server. - * - * @throws InitializationException - */ - @Override - public void initialize() throws InitializationException - { - Map identifiers = currentServer.getServerIdentifiers(); - serverPath = identifiers.get("serverPath"); - String usedServerLogsHint = identifiers.get("serverType") + "Logs"; - findUsedServer(usedServerLogsHint); - } - /** * Initiates the download process for the xwiki files. It removes the sensitive content from the file. * @@ -109,7 +90,7 @@ public void initialize() throws InitializationException */ public byte[] getXWikiFile(String fileType) throws IOException { - return usedFilesResourceProvider.getConfigurationFileContent(fileType, currentServer.retrieveXwikiCfgPath()); + return filesResourceProvider.getByteData(fileType); } /** @@ -160,8 +141,8 @@ public byte[] callLogsRetriever() throws IOException { XWikiContext wikiContext = xcontextProvider.get(); XWikiRequest xWikiRequest = wikiContext.getRequest(); - long noLines = Long.parseLong(xWikiRequest.getParameter("noLines")); - return usedFilesResourceProvider.retrieveLastLogs(serverPath, noLines); + Long noLines = Long.parseLong(xWikiRequest.getParameter("noLines")); + return logsViewerResourceProvider.getByteData(noLines); } /** @@ -180,16 +161,14 @@ private void createArchiveEntries(Map files, ZipOutputStream z case "cfg_file": zipEntry = new ZipEntry("xwiki.cfg"); zipOutputStream.putNextEntry(zipEntry); - buffer = usedFilesResourceProvider.getConfigurationFileContent("config", - currentServer.retrieveXwikiCfgPath()); + buffer = filesResourceProvider.getByteData("config"); zipOutputStream.write(buffer, 0, buffer.length); zipOutputStream.closeEntry(); break; case "properties_file": zipEntry = new ZipEntry("xwiki.properties"); zipOutputStream.putNextEntry(zipEntry); - buffer = usedFilesResourceProvider.getConfigurationFileContent("properties", - currentServer.retrieveXwikiCfgPath()); + buffer = filesResourceProvider.getByteData("properties"); zipOutputStream.write(buffer, 0, buffer.length); zipOutputStream.closeEntry(); break; @@ -201,7 +180,7 @@ private void createArchiveEntries(Map files, ZipOutputStream z String to = "to"; filters.put(from, !Objects.equals(files.get(from)[0], "") ? files.get(from)[0] : null); filters.put(to, !Objects.equals(files.get(to)[0], "") ? files.get(to)[0] : null); - buffer = getLogs(filters); + buffer = logsDownloadResourceProvider.getByteData(filters); zipOutputStream.write(buffer, 0, buffer.length); zipOutputStream.closeEntry(); break; @@ -217,30 +196,4 @@ private void createArchiveEntries(Map files, ZipOutputStream z } } } - - /** - * Initiates the download process for the server logs. Taking into consideration the used server, it identifies the - * right downloader. It returns null if none is corresponding. - * - * @param filters {@link Map} that can contain the start and end date of the search. It can also be empty. - * @return {@link Byte} array representing the logs archive. - */ - private byte[] getLogs(Map filters) - { - return usedFilesResourceProvider.generateLogsArchive(filters, serverPath); - } - - /** - * Calls the logs generator for the used server. - * - * @param hint {@link String} represents the used server hint. - */ - private void findUsedServer(String hint) - { - for (FilesResourceProvider specificFilesResourceProvider : this.filesResourceProviderProvider.get()) { - if (specificFilesResourceProvider.getIdentifier().equals(hint)) { - usedFilesResourceProvider = specificFilesResourceProvider; - } - } - } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/FileResourceProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/FileResourceProvider.java new file mode 100644 index 00000000..1815c9a4 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/FileResourceProvider.java @@ -0,0 +1,96 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.download; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.ResourceProvider; +import com.xwiki.admintools.internal.data.identifiers.CurrentServer; + +/** + * Encapsulates functions used for downloading XWiki files. + * + * @version $Id$ + * @since 1.0 + */ +@Component +@Named(FileResourceProvider.HINT) +@Singleton +public class FileResourceProvider implements ResourceProvider +{ + /** + * Component identifier. + */ + public static final String HINT = "fileResourceProvider"; + + @Inject + private CurrentServer currentServer; + + @Inject + private Logger logger; + + @Override + public byte[] getByteData(String input) throws IOException + { + String filePath = currentServer.getUsedServer().getXwikiCfgFolderPath(); + if (Objects.equals(input, "properties")) { + filePath += "xwiki.properties"; + } else if (Objects.equals(input, "config")) { + filePath += "xwiki.cfg"; + } + File inputFile = new File(filePath); + try (BufferedReader reader = new BufferedReader(new FileReader(inputFile))) { + StringBuilder stringBuilder = new StringBuilder(); + String currentLine; + List wordsList = new ArrayList<>( + Arrays.asList("xwiki.authentication.validationKey", "xwiki.authentication.encryptionKey", + "xwiki.superadminpassword", "extension.repositories.privatemavenid.auth", "mail.sender.password")); + + // Read line by line and do not add it if it contains sensitive info. + while ((currentLine = reader.readLine()) != null) { + String trimmedLine = currentLine.trim(); + if (wordsList.stream().anyMatch(trimmedLine::contains)) { + continue; + } + stringBuilder.append(currentLine).append(System.getProperty("line.separator")); + } + reader.close(); + return stringBuilder.toString().getBytes(); + } catch (Exception e) { + logger.warn("Failed to download logs. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); + return null; + } + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/LogsDownloadResourceProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/LogsDownloadResourceProvider.java new file mode 100644 index 00000000..a0bfa324 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/LogsDownloadResourceProvider.java @@ -0,0 +1,137 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.download; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.time.LocalDate; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.ResourceProvider; +import com.xwiki.admintools.internal.data.identifiers.CurrentServer; + +/** + * Encapsulates functions used for downloading log files. + * + * @version $Id$ + * @since 1.0 + */ +@Component +@Named(LogsDownloadResourceProvider.HINT) +@Singleton +public class LogsDownloadResourceProvider implements ResourceProvider> +{ + /** + * Component identifier. + */ + public static final String HINT = "logsDownloadResourceProvider"; + + @Inject + private Logger logger; + + @Inject + private CurrentServer currentServer; + + @Override + public byte[] getByteData(Map input) + { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[2048]; + + try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) { + File logsFolder = new File(currentServer.getUsedServer().getLogsFolderPath()); + File[] listOfFiles = logsFolder.listFiles(); + // Go through all the files in the list. + for (File file : listOfFiles != null ? listOfFiles : new File[0]) { + // Check if the selected file is of file type and check filters. + if (file.isFile() && checkFilters(input, currentServer.getUsedServer().getLogsPattern(), file)) { + // Create a new zip entry and add the content. + ZipEntry zipEntry = new ZipEntry("logs/" + file.getName()); + zipOutputStream.putNextEntry(zipEntry); + try (FileInputStream fileInputStream = new FileInputStream(file)) { + BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); + int bytesRead; + while ((bytesRead = bufferedInputStream.read(buffer)) != -1) { + zipOutputStream.write(buffer, 0, bytesRead); + } + bufferedInputStream.close(); + } + zipOutputStream.closeEntry(); + } + } + zipOutputStream.flush(); + byteArrayOutputStream.flush(); + zipOutputStream.close(); + byteArrayOutputStream.close(); + return byteArrayOutputStream.toByteArray(); + } catch (Exception e) { + logger.warn("Failed to download logs. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); + return null; + } + } + + /** + * Check that the file date is in the filter range. Returns true if no filter is provided. + * + * @param filters {@link Map} that can contain the start and end date of the search. It can also be empty. + * @param pattern server specific {@link Pattern} used to identify the log date from the log name. + * @param file current {@link File} that is to be checked. + * @return {@link Boolean} true if the file is between the provided dates or there is no filter, false otherwise + */ + private boolean checkFilters(Map filters, Pattern pattern, File file) + { + Matcher matcher = pattern.matcher(file.getName()); + if (matcher.find()) { + String fromDateFilterKey = "from"; + String toDateFilterKey = "to"; + String fileDateString = matcher.group(); + LocalDate fileDate = LocalDate.parse(fileDateString); + + if (filters.get(fromDateFilterKey) != null && filters.get(toDateFilterKey) != null) { + LocalDate fromDate = LocalDate.parse(filters.get(fromDateFilterKey)); + LocalDate toDate = LocalDate.parse(filters.get(toDateFilterKey)); + return fileDate.isAfter(fromDate.minusDays(1)) && fileDate.isBefore(toDate.plusDays(1)); + } else if (filters.get(fromDateFilterKey) != null) { + LocalDate fromDate = LocalDate.parse(filters.get(fromDateFilterKey)); + return fileDate.isAfter(fromDate.minusDays(1)); + } else if (filters.get(toDateFilterKey) != null) { + LocalDate toDate = LocalDate.parse(filters.get(toDateFilterKey)); + return fileDate.isBefore(toDate.plusDays(1)); + } else { + return true; + } + } + return false; + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/LogsViewerResourceProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/LogsViewerResourceProvider.java new file mode 100644 index 00000000..ea00f5d2 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/LogsViewerResourceProvider.java @@ -0,0 +1,94 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.download; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.ResourceProvider; +import com.xwiki.admintools.internal.data.identifiers.CurrentServer; + +/** + * Encapsulates functions used for viewing last log lines. + * + * @version $Id$ + * @since 1.0 + */ +@Component +@Named(LogsViewerResourceProvider.HINT) +@Singleton +public class LogsViewerResourceProvider implements ResourceProvider +{ + /** + * Component identifier. + */ + public static final String HINT = "logsViewerResourceProvider"; + + @Inject + private Logger logger; + + @Inject + private CurrentServer currentServer; + + @Override + public byte[] getByteData(Long input) throws IOException + { + File file = new File(currentServer.getUsedServer().getLogFilePath()); + if (!file.exists() || !file.isFile()) { + throw new FileNotFoundException("File not found: " + currentServer.getUsedServer().getLogFilePath()); + } + try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) { + long fileLength = randomAccessFile.length(); + List logLines = new ArrayList<>(); + + // Calculate the approximate position to start reading from based on line length + long startPosition = fileLength - 1; + for (long i = 0; i < input && startPosition > 0 && i < 50000; startPosition--) { + randomAccessFile.seek(startPosition - 1); + int currentByte = randomAccessFile.read(); + if (currentByte == '\n' || currentByte == '\r') { + // Found a newline character, add the line to the list + logLines.add(randomAccessFile.readLine()); + i++; + } + } + // Reverse the list to get the lines in the correct order + Collections.reverse(logLines); + // Join the lines with newline characters + return String.join("\n", logLines).getBytes(); + } catch (IOException e) { + logger.warn("Failed to retrieve logs. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); + return null; + } + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatFilesResourceProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatFilesResourceProvider.java deleted file mode 100644 index e1cb7c1a..00000000 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/downloads/TomcatFilesResourceProvider.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools.internal.downloads; - -import java.io.File; -import java.io.IOException; -import java.util.Map; -import java.util.regex.Pattern; - -import javax.inject.Named; -import javax.inject.Singleton; - -import org.xwiki.component.annotation.Component; - -/** - * Encapsulates functions used for downloading log files. - * - * @version $Id$ - * @since 1.0 - */ -@Component -@Named(TomcatFilesResourceProvider.HINT) -@Singleton -public class TomcatFilesResourceProvider extends AbstractFilesResourceProvider -{ - /** - * The hint for the component. - */ - public static final String HINT = "tomcatLogs"; - - @Override - public byte[] generateLogsArchive(Map filter, String serverPath) - { - File logsFolder = new File(serverPath + "/logs"); - File[] listOfFiles = logsFolder.listFiles(); - Pattern pattern = Pattern.compile("\\d{4}-\\d{2}-\\d{2}"); - - return this.generateArchive(filter, listOfFiles, pattern); - } - - @Override - public String getIdentifier() - { - return HINT; - } - - @Override - public byte[] retrieveLastLogs(String serverPath, long noLines) throws IOException - { - return defaultRetrieveLastLogs(serverPath + "/logs/catalina.out", noLines); - } -} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java index 7a373ccf..d054dfb1 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultResources.java @@ -36,7 +36,7 @@ import org.xwiki.rest.XWikiRestException; import org.xwiki.rest.internal.resources.pages.ModifiablePageResource; -import com.xwiki.admintools.internal.downloads.DownloadsManager; +import com.xwiki.admintools.internal.download.DownloadManager; import com.xwiki.admintools.rest.AdminToolsResources; /** @@ -56,21 +56,21 @@ public class DefaultResources extends ModifiablePageResource implements AdminToo private Logger logger; /** - * Handles downloads requests. + * Handles download requests. */ @Inject - private DownloadsManager downloadsManager; + private DownloadManager downloadManager; @Override public Response getConfigs(String type) throws XWikiRestException { // Check to see if the request was made by a user with admin rights. - if (!downloadsManager.isAdmin()) { + if (!downloadManager.isAdmin()) { logger.warn("Failed to get file xwiki.[{}] due to restricted rights.", type); throw new WebApplicationException(Response.Status.UNAUTHORIZED); } try { - byte[] xWikiFileContent = downloadsManager.getXWikiFile(type); + byte[] xWikiFileContent = downloadManager.getXWikiFile(type); if (xWikiFileContent.length == 0) { return Response.status(404).build(); } @@ -85,12 +85,12 @@ public Response getConfigs(String type) throws XWikiRestException @Override public Response getFiles() throws XWikiRestException { - if (!downloadsManager.isAdmin()) { + if (!downloadManager.isAdmin()) { logger.warn("Failed to get files due to restricted rights."); throw new WebApplicationException(Response.Status.UNAUTHORIZED); } try { - byte[] filesArchive = downloadsManager.downloadMultipleFiles(); + byte[] filesArchive = downloadManager.downloadMultipleFiles(); if (!(filesArchive == null) && !(Arrays.toString(filesArchive).length() == 0)) { // Set the appropriate response headers to indicate a zip file download. Response.ResponseBuilder response = Response.ok(filesArchive); @@ -110,12 +110,12 @@ public Response getFiles() throws XWikiRestException @Override public Response retrieveLastLogs() throws XWikiRestException { - if (!downloadsManager.isAdmin()) { + if (!downloadManager.isAdmin()) { logger.warn("Failed to get the logs due to restricted rights."); throw new WebApplicationException(Response.Status.UNAUTHORIZED); } try { - byte[] xWikiFileContent = downloadsManager.callLogsRetriever(); + byte[] xWikiFileContent = downloadManager.callLogsRetriever(); if (xWikiFileContent.length == 0) { return Response.status(404).build(); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index a7565860..f7a7e7df 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -19,6 +19,8 @@ */ package com.xwiki.admintools.script; +import java.util.Map; + import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; @@ -58,7 +60,7 @@ public String getConfigurationData() * @param hint {@link String} representing the data provider * @return {@link String} representing the template of a specific data provider */ - public String getConfigurationData(String hint) + public Map getConfigurationData(String hint) { return this.adminToolsManager.generateData(hint); } diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index 453332b3..4c7cdaf1 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -2,8 +2,10 @@ com.xwiki.admintools.script.AdminToolsScriptService com.xwiki.admintools.internal.AdminToolsManager com.xwiki.admintools.internal.data.ConfigurationDataProvider com.xwiki.admintools.internal.data.SecurityDataProvider -com.xwiki.admintools.internal.downloads.TomcatFilesResourceProvider -com.xwiki.admintools.internal.downloads.DownloadsManager +com.xwiki.admintools.internal.download.FileResourceProvider +com.xwiki.admintools.internal.download.LogsDownloadResourceProvider +com.xwiki.admintools.internal.download.LogsViewerResourceProvider +com.xwiki.admintools.internal.download.DownloadManager com.xwiki.admintools.internal.data.identifiers.CurrentServer com.xwiki.admintools.internal.data.identifiers.TomcatIdentifier com.xwiki.admintools.internal.configuration.AdminToolsConfigurationSource diff --git a/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm b/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm index 1bd85202..8e5ee223 100644 --- a/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm @@ -27,9 +27,38 @@ Get info about your backend ---- * XWiki installation version: $xwiki.version -** [[Show latest logs]] +** {{html}}Show last logs{{/html}} * OS info: ** OS name: $configuration["osName"] ** OS version: $configuration["osVersion"] ** OS Architecture: $configuration["osArch"] * Used database: $configuration["database"] +* Java version: $configuration["javaVersion"] + +{{html}} + +{{/html}} +))) +))) From 0e4c97fca557ac979c1f94838d82cac5e01638dd Mon Sep 17 00:00:00 2001 From: Sorin Date: Wed, 13 Sep 2023 13:57:07 +0300 Subject: [PATCH 23/72] Display App server info #3 --- .../com/xwiki/admintools/DataProvider.java | 6 +- .../xwiki/admintools/ServerIdentifier.java | 18 +- .../internal/AdminToolsManager.java | 2 +- .../data/ConfigurationDataProvider.java | 31 ++- .../identifiers/AbstractServerIdentifier.java | 23 --- .../data/identifiers/CurrentServer.java | 47 ++--- .../data/identifiers/TomcatIdentifier.java | 55 ++--- .../script/AdminToolsScriptService.java | 5 +- .../templates/data/configurationTemplate.vm | 18 +- .../AdminTools/Code/Translations.xml | 1 + .../src/main/resources/AdminTools/WebHome.xml | 195 +++++++++++++++++- 11 files changed, 283 insertions(+), 118 deletions(-) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java index 5877c5af..b0583034 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java @@ -22,7 +22,7 @@ import org.xwiki.component.annotation.Role; /** - * Gathers specific parts of data and provides the template for it. + * Gathers specific data and returns it in a specific format, using a template. * * @version $Id$ * @since 1.0 @@ -31,9 +31,9 @@ public interface DataProvider { /** - * Provides the template rendering the data provider information. + * Provides the data provider information in a format given by the associated template. * - * @return {@link String} representing the data provider template. + * @return {@link String} representing the information formatted by the associated template. */ String provideData(); diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java index 15ca403d..929d2913 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java @@ -19,12 +19,11 @@ */ package com.xwiki.admintools; -import java.util.Map; - import org.xwiki.component.annotation.Role; /** - * Identify the used server and the paths to the configuration files of the server and XWiki installation. + * Exposes methods for accessing server specific information, like configurations, logs or other XWiki and server + * files. * * @version $Id$ * @since 1.0 @@ -33,9 +32,11 @@ public interface ServerIdentifier { /** - * Check if the server is used. + * Verify if a specific server is used. If a server path is provided in the XWiki configurations, it verifies if the + * path corresponds to a server. Otherwise, it searches the server location in system properties and system + * environment. * - * @param providedConfigServerPath {@link String} path to the server provided by XWiki configuration. + * @param providedConfigServerPath {@link String} server path provided in the XWiki configuration page. * @return {@link Boolean} true if the server is used, false otherwise. */ boolean isUsed(String providedConfigServerPath); @@ -67,11 +68,4 @@ public interface ServerIdentifier * @param providedConfigServerPath {@link String} the server path provided in the XWiki configuration page. */ void updatePaths(String providedConfigServerPath); - - /** - * Access the server path and type. - * - * @return {@link Map} containing server path and type. - */ - Map getServerIdentifiers(); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index 4d5a95dc..100c217f 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -46,7 +46,7 @@ public class AdminToolsManager private Provider> dataProviderProvider; /** - * Merges all templates generated by the data providers. + * Get data generated in a specific format, using a template, by each provider and merge it. * * @return a {@link String} containing all templates builds. */ diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index 97d0a62e..08e1b391 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -50,6 +50,10 @@ public class ConfigurationDataProvider extends AbstractDataProvider */ public static final String HINT = "configuration"; + private final String serverFound = "serverFound"; + + private final String template = "data/configurationTemplate.vm"; + @Inject private CurrentServer currentServer; @@ -62,15 +66,26 @@ public String getIdentifier() @Override public String provideData() { - currentServer.findPaths(); Map systemInfo = new HashMap<>(); - systemInfo.put("xwikiCfgPath", currentServer.retrieveXwikiCfgPath()); - systemInfo.put("tomcatConfPath", this.currentServer.retrieveServerCfgPath()); - systemInfo.put("javaVersion", this.getJavaVersion()); - systemInfo.putAll(this.getOSInfo()); - systemInfo.put("database", this.identifyDB()); - return getRenderedTemplate("data/configurationTemplate.vm", systemInfo, HINT); + currentServer.findPaths(); + try { + systemInfo.put("xwikiCfgPath", currentServer.getCurrentServer().getXwikiCfgFolderPath()); + systemInfo.put("tomcatConfPath", this.currentServer.getCurrentServer().getServerCfgPath()); + systemInfo.put("javaVersion", this.getJavaVersion()); + systemInfo.putAll(this.getOSInfo()); + systemInfo.put("database", this.identifyDB()); + systemInfo.put("usedServer", this.currentServer.getCurrentServer().getIdentifier()); + systemInfo.put(serverFound, "found"); + return getRenderedTemplate(template, systemInfo, HINT); + } catch (Exception e) { + logger.warn("Failed to generate the configuration details. Error info : [{}]", + ExceptionUtils.getRootCauseMessage(e)); + systemInfo.put(serverFound, null); + systemInfo.put("supportedServers", currentServer.getSupportedServers().toString()); + + return getRenderedTemplate(template, systemInfo, HINT); + } } /** @@ -105,7 +120,7 @@ private Map getOSInfo() */ private String identifyDB() { - String databaseCfgPath = currentServer.retrieveXwikiCfgPath() + "hibernate.cfg.xml"; + String databaseCfgPath = currentServer.getCurrentServer().getXwikiCfgFolderPath() + "hibernate.cfg.xml"; File file = new File(databaseCfgPath); try (Scanner scanner = new Scanner(file)) { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java index 8061f3ce..89ed9ce5 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java @@ -20,8 +20,6 @@ package com.xwiki.admintools.internal.data.identifiers; import java.io.File; -import java.util.HashMap; -import java.util.Map; import com.xwiki.admintools.ServerIdentifier; @@ -42,21 +40,6 @@ public abstract class AbstractServerIdentifier implements ServerIdentifier */ protected String serverPath; - @Override - public Map getServerIdentifiers() - { - Map serverIdentifiers = new HashMap<>(); - serverIdentifiers.put("serverPath", serverPath); - serverIdentifiers.put("serverType", getIdentifier()); - - return serverIdentifiers; - } - - /** - * Get the server configuration file path. - * - * @return {@link String} path to Tomcat configuration file. - */ @Override public String getServerCfgPath() { @@ -68,11 +51,6 @@ public String getServerCfgPath() return null; } - /** - * Get the configuration file path for the XWiki installation. - * - * @return {@link String} path to the XWiki configuration file. - */ @Override public String getXwikiCfgFolderPath() { @@ -84,4 +62,3 @@ public String getXwikiCfgFolderPath() return null; } } - diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java index 0fe2fb56..9ad14006 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java @@ -19,8 +19,8 @@ */ package com.xwiki.admintools.internal.data.identifiers; +import java.util.ArrayList; import java.util.List; -import java.util.Map; import javax.inject.Inject; import javax.inject.Named; @@ -47,7 +47,7 @@ public class CurrentServer implements Initializable @Inject private Provider> supportedServers; - private ServerIdentifier usedServer; + private ServerIdentifier currentServerIdentifier; @Inject @Named("default") @@ -65,27 +65,17 @@ public class CurrentServer implements Initializable public void initialize() throws InitializationException { String providedConfigServerPath = adminToolsConfig.getServerPath(); - findServer(providedConfigServerPath); + updateCurrentServer(providedConfigServerPath); } /** - * Retrieves the XWiki configuration file path for the installation. + * Get the used server identifier. * - * @return a {@link String} representing the path to the XWiki configuration file. + * @return {@link ServerIdentifier} */ - public String retrieveXwikiCfgPath() + public ServerIdentifier getCurrentServer() { - return usedServer.getXwikiCfgFolderPath(); - } - - /** - * Retrieves the server configuration file path for the installation. - * - * @return a {@link String} representing the path to the server configuration file. - */ - public String retrieveServerCfgPath() - { - return usedServer.getServerCfgPath(); + return currentServerIdentifier; } /** @@ -93,20 +83,25 @@ public String retrieveServerCfgPath() */ public void findPaths() { - if (usedServer == null) { + currentServerIdentifier = null; + if (currentServerIdentifier == null) { String providedConfigServerPath = adminToolsConfig.getServerPath(); - findServer(providedConfigServerPath); + updateCurrentServer(providedConfigServerPath); } } /** - * Calls the used server function to retrieve the server identifiers. + * Returns a list of the supported servers. * - * @return a {@link Map} with the info used to identify the server. + * @return {@link List} with the supported servers. */ - public Map getServerIdentifiers() + public List getSupportedServers() { - return usedServer.getServerIdentifiers(); + List supportedServerList = new ArrayList<>(); + for (ServerIdentifier serverIdentifier : this.supportedServers.get()) { + supportedServerList.add(serverIdentifier.getIdentifier()); + } + return supportedServerList; } /** @@ -114,12 +109,12 @@ public Map getServerIdentifiers() * * @param providedConfigServerPath {@link String} server path provided by XWiki configurations. */ - private void findServer(String providedConfigServerPath) + private void updateCurrentServer(String providedConfigServerPath) { for (ServerIdentifier serverIdentifier : this.supportedServers.get()) { if (serverIdentifier.isUsed(providedConfigServerPath)) { - usedServer = serverIdentifier; - usedServer.updatePaths(providedConfigServerPath); + currentServerIdentifier = serverIdentifier; + currentServerIdentifier.updatePaths(providedConfigServerPath); break; } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java index f7137fb2..d20724a9 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java @@ -42,44 +42,10 @@ public class TomcatIdentifier extends AbstractServerIdentifier /** * Component identifier. */ - public static final String HINT = "tomcat"; + public static final String HINT = "Tomcat"; @Override public boolean isUsed(String providedConfigServerPath) - { - return tomcatIsUsed(providedConfigServerPath); - } - - @Override - public String getIdentifier() - { - return HINT; - } - - @Override - public void updatePaths(String providedConfigServerPath) - { - if (tomcatIsUsed(providedConfigServerPath)) { - this.serverCfgPossiblePaths = new String[] { String.format("%s/conf/server.xml", this.serverPath), - "/usr/local/tomcat/conf/server.xml", "/opt/tomcat/conf/server.xml", "/var/lib/tomcat8/conf/", - "/var/lib/tomcat9/conf/server.xml", "/var/lib/tomcat/conf/server.xml" }; - - this.xwikiCfgPossiblePaths = new String[] { "/etc/xwiki/", - "/usr/local/xwiki/WEB-INF/", "/opt/xwiki/WEB-INF/", - String.format("%s/webapps/ROOT/WEB-INF/", this.serverPath), - String.format("%s/webapps/xwiki/WEB-INF/", this.serverPath) }; - } - } - - /** - * Function used to verify if a Tomcat server is used. If a server path is provided in the XWiki configurations, it - * verifies if the path corresponds to a Tomcat server. Otherwise, it searches the Catalina location in system - * properties and system environment. - * - * @param providedConfigServerPath {@link String} server path provided in the XWiki configuration page. - * @return {@link Boolean} true if Tomcat is the used server, false otherwise. - */ - private boolean tomcatIsUsed(String providedConfigServerPath) { if (providedConfigServerPath != null) { File file = new File(providedConfigServerPath + "conf/catalina.properties"); @@ -101,4 +67,23 @@ private boolean tomcatIsUsed(String providedConfigServerPath) } return true; } + + @Override + public String getIdentifier() + { + return HINT; + } + + @Override + public void updatePaths(String providedConfigServerPath) + { + this.serverCfgPossiblePaths = + new String[] { String.format("%s/conf/server.xml", this.serverPath), "/usr/local/tomcat/conf/server.xml", + "/opt/tomcat/conf/server.xml", "/var/lib/tomcat8/conf/server.xml", "/var/lib/tomcat9/conf/server.xml", + "/var/lib/tomcat/conf/server.xml" }; + + this.xwikiCfgPossiblePaths = new String[] { "/etc/xwiki/", "/usr/local/xwiki/WEB-INF/", "/opt/xwiki/WEB-INF/", + String.format("%s/webapps/ROOT/WEB-INF/", this.serverPath), + String.format("%s/webapps/xwiki/WEB-INF/", this.serverPath) }; + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index 44016baf..b4ec9d23 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -43,7 +43,8 @@ public class AdminToolsScriptService implements ScriptService private AdminToolsManager adminToolsManager; /** - * Retrieve all the configuration info templates of Admin Tools. + * Retrieve all the configuration info information in a format given by the associated templates generated by the + * data providers. * * @return {@link String} representing all templates. */ @@ -53,7 +54,7 @@ public String getConfigurationData() } /** - * Get a specific data provider template. + * Get a specific data provider information in a format given by the associated template. * * @param hint {@link String} representing the data provider * @return {@link String} representing the template of a specific data provider diff --git a/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm b/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm index 1bd85202..a2026a18 100644 --- a/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/data/configurationTemplate.vm @@ -17,19 +17,27 @@ ## Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ## 02110-1301 USA, or see the FSF site: http://www.fsf.org. ## --------------------------------------------------------------------------- +#if($configuration["serverFound"] != $null) +|(% id="admin-tools-dash-content" %)((( -(% border="0" %) -|(% style="background-color:#fafafa; border-color:#ffffff; width:400px" %)((( -== 🌐**Backend ** == - -((( Get info about your backend ---- * XWiki installation version: $xwiki.version ** [[Show latest logs]] +* Used server: $configuration["usedServer"] * OS info: ** OS name: $configuration["osName"] ** OS version: $configuration["osVersion"] ** OS Architecture: $configuration["osArch"] * Used database: $configuration["database"] +))) +#else +#set($warningMessage = "Currently supported servers: " + $configuration.get('supportedServers')) + +{{html}} +#warning("Server path was not found. Please manually add the path to the server on the Admin Tools configuration page.") +#warning($warningMessage) +{{/html}} +#end + diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml index 791328b1..df907d28 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml @@ -39,6 +39,7 @@ admin.admintools.description=Configure Admin Tools Application AdminTools.Code.ConfigurationClass_serverLocation.hint=Path to the server location AdminTools.Code.ConfigurationClass_serverLocation=Server location +AdminTools.dashboard.section.title.backend=🌐**Backend ** AdminTools.Code.Translations diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index ca9a6d0a..e0b34f65 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -1,5 +1,4 @@ - + + AdminTools.Code + Macros + + + 0 + xwiki:XWiki.Admin + AdminTools.WebHome + xwiki:XWiki.Admin + xwiki:XWiki.Admin + 1.1 + Macros + + false + xwiki/2.1 + true + {{velocity output="false"}} +#macro (viewLastNLinesMoldal $id) + #set ($modalId = $id + "ViewLastNLinesModal") + #set ($formId = $id + "LastNLogLinesForm") + #set ($inputId = $id + "NoLines") + {{html clean='false'}} + <div class="modal fade" id="$modalId" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog modal-sm" role="document"> + <div class="modal-content"> + <div class="logs-modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">&times;</span></button> + <h1 class="modal-title" id="viewLastNLinesModalLabel"> + $escapetool.xml($services.localization.render('adminTools.dashboard.logs.modal.title')) + </h1> + </div> + <div class="modal-body"> + <form class="xform" id="$formId" action="$request.getContextPath()/rest/admintools/files/logs"> + <dl> + <dt> + <label for="noLines">$escapetool.xml($services.localization.render('adminTools.dashboard.logs.modal.nLines.label')) </label> + <span class="xHint">max 50000</span> + </dt> + <dd><input type="number" id="$inputId" name="noLines" placeholder="1000"></dd> + </dl> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-primary"> + $escapetool.xml($services.localization.render('adminTools.dashboard.logs.modal.submit'))</button> + <button type="button" class="btn btn-default" data-dismiss="modal"> + $escapetool.xml($services.localization.render('cancel'))</button> + </div> + </div> + </div> + </div> + </div> + {{/html}} +#end + +#macro (downloadFiles $id) + #set ($modalId = $id + "DownloadFilesModal") + #set ($formId = $id + "DownloadForm") + + {{html clean='false'}} + <div class="modal fade" id="$modalId" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">&times;</span></button> + <h1 class="modal-title downloadFilesModalTitle"> + $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.title')) + </h1> + </div> + <div class="modal-body"> + <form id="$formId" action="$request.getContextPath()/rest/admintools/files"> + <div class="download-modal-content"> + <dl> + <dt><label><input type="checkbox" name="files" value="xwikiConfig" checked> + $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.xwikiConfig.title')) + </label> + </dt> + <dt><label><input type="checkbox" name="files" value="xwikiProperties" checked> + $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.xwikiProperties.title')) + </label> + </dt> + <dt><label><input type="checkbox" name="files" value="dataProviderResource" checked> + $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.provided'))</label> + </dt> + <dt><label><input type="checkbox" name="files" value="logsDataResource" checked> Logs</label></dt> + <dt> + <div class="dateFields"> + <label for="from">$escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.date.from')) + </label> <input type="date" id="from" name="from"> + <label for="to">$escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.date.to')) + </label> <input type="date" id="to" name="to"> + </div> + </dt> + </dl> + </div> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-primary"> + $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.button'))</button> + <button type="button" class="btn btn-default" data-dismiss="modal"> + $escapetool.xml($services.localization.render('cancel'))</button> + </div> + </div> + </div> + </div> + {{/html}} +#end +{{/velocity}} + \ No newline at end of file diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml index 714c71af..45c04f2c 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml @@ -51,44 +51,44 @@ adminTools.dashboard.download.modal.title=Select Files adminTools.dashboard.download.modal.xwikiConfig.title=xwiki.cfg adminTools.dashboard.download.modal.xwikiProperties.title=xwiki.properties adminTools.dashboard.download.modal.logs.title=logs -adminTools.dashboard.logs.modal.submit=View logs +adminTools.dashboard.logs.modal.submit=View adminTools.dashboard.logs.modal.nLines.label=Number of extracted lines -adminTools.dashboard.logs.modal.title=Show latest n lines of log -adminTools.dashboard.showLogs=View +adminTools.dashboard.logs.modal.title=Show last n lines of log +adminTools.dashboard.showLogs=View last n lines of log... ## Dashboard sections ## Config adminTools.dashboard.section.backend.configuration.error=Server path was not found. Please manually add the path to the server on the Admin Tools configuration page. adminTools.dashboard.section.backend.description=Get info about your backend -adminTools.dashboard.section.backend.java=Detected java version: -adminTools.dashboard.section.backend.os.architecture=OS architecture: -adminTools.dashboard.section.backend.os.legend=OS info: -adminTools.dashboard.section.backend.os.name=OS name: -adminTools.dashboard.section.backend.os.version=OS version: -adminTools.dashboard.section.backend.supportedDB.error=Database not found. Currently supported databases: -adminTools.dashboard.section.backend.supportedServers.error=Currently supported servers: +adminTools.dashboard.section.backend.java=Detected java version +adminTools.dashboard.section.backend.os.architecture=OS architecture +adminTools.dashboard.section.backend.os.legend=OS info +adminTools.dashboard.section.backend.os.name=OS name +adminTools.dashboard.section.backend.os.version=OS version +adminTools.dashboard.section.backend.supportedDB.error=Database not found. Currently supported databases +adminTools.dashboard.section.backend.supportedServers.error=Currently supported servers adminTools.dashboard.section.backend.title=Backend -adminTools.dashboard.section.backend.usedDB=Used database: -adminTools.dashboard.section.backend.usedServer=Used server: -adminTools.dashboard.section.backend.xwiki.version=XWiki installation version: +adminTools.dashboard.section.backend.usedDB=Used database +adminTools.dashboard.section.backend.usedServer=Used server +adminTools.dashboard.section.backend.xwiki.version=XWiki installation version ## Files adminTools.dashboard.section.download.description=Get the files you need. View them directly in the browser or download them as an archive. adminTools.dashboard.section.download.modal.open=Export files needed for getting support adminTools.dashboard.section.download.title=Files adminTools.dashboard.section.download.view.configuration=XWiki configuration file -adminTools.dashboard.section.download.view.description=View files content: +adminTools.dashboard.section.download.view.description=View files content adminTools.dashboard.section.download.view.properties=XWiki properties file adminTools.dashboard.section.download.warning=Before downloading and sending the files, please make sure you introduced the lines that may contain sensitive info in Admin Tools configuration page! ## Security -adminTools.dashboard.section.security.activeEncoding=Active encoding: -adminTools.dashboard.section.security.configurationEncoding=Configuration encoding: +adminTools.dashboard.section.security.activeEncoding=Active encoding +adminTools.dashboard.section.security.configurationEncoding=Configuration encoding adminTools.dashboard.section.security.description=See an overview of your security information. adminTools.dashboard.section.security.error=Error while gathering security information. -adminTools.dashboard.section.security.fileEncoding=File encoding: -adminTools.dashboard.section.security.lang=Used language: -adminTools.dashboard.section.security.pwd=Working directory: +adminTools.dashboard.section.security.fileEncoding=File encoding +adminTools.dashboard.section.security.lang=Used language +adminTools.dashboard.section.security.pwd=Working directory adminTools.dashboard.section.security.title=Security diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index 821e7e94..34e751c0 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -34,92 +34,10 @@ false xwiki/2.1 false - {{dashboard/}} + {{include reference="AdminTools.Code.Macros"/}} -{{velocity}} -{{html clean='false'}} -<div class="modal fade" id="downloadFilesModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> - <div class="modal-dialog" role="document"> - <div class="modal-content"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal" aria-label="Close"> - <span aria-hidden="true">&times;</span></button> - <h1 class="modal-title" id="downloadFilesModalLabel"> - $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.title')) - </h1> - </div> - <div class="modal-body"> - <form id="downloadForm" action="$request.getContextPath()/rest/admintools/files" method="POST"> - <div class="download-modal-content"> - <dl> - <dt><label><input type="checkbox" name="files" value="xwikiConfig" checked> - $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.xwikiConfig.title')) - </label> - </dt> - <dt><label><input type="checkbox" name="files" value="xwikiProperties" checked> - $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.xwikiProperties.title')) - </label> - </dt> - <dt><label><input type="checkbox" name="files" value="dataProviderResource" checked> - $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.provided'))</label> - </dt> - <dt><label><input type="checkbox" name="files" value="logsDataResource" checked> Logs</label></dt> - <dt> - <div id="dateFields"> - <label>$escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.date.from')) - </label> <input type="date" id="from" name="from"> - <label>$escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.date.to')) - </label> <input type="date" id="to" name="to"> - </div> - </dt> - </dl> - </div> - <div class="download-button"> - <input class="btn btn-primary btn-lg" type="submit" - value="$escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.button'))"> - </div> - </form> - </div> - <div class="modal-footer"> - <button type="button" class="btn btn-default" data-dismiss="modal"> - $escapetool.xml($services.localization.render('cancel'))</button> - </div> - </div> - </div> -</div> - -<div class="modal fade" id="viewLastNLinesModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> - <div class="modal-dialog" role="document"> - <div class="modal-content"> - <div class="logs-modal-content"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal" aria-label="Close"> - <span aria-hidden="true">&times;</span></button> - <h1 class="modal-title" id="viewLastNLinesModalLabel"> - $escapetool.xml($services.localization.render('adminTools.dashboard.logs.modal.title')) - </h1> - </div> - <div class="modal-body"> - <form id="downloadForm" action="$request.getContextPath()/rest/admintools/files/logs" - method="POST" target="_blank"> - <dl> - <dt><label>$escapetool.xml($services.localization.render('adminTools.dashboard.logs.modal.nLines.label')) </label></dt> - <dd><input type="number" id="noLines" name="noLines" placeholder="100"></dd> - </dl> - <input class="btn btn-primary btn-lg" type="submit" - value="$escapetool.xml($services.localization.render('adminTools.dashboard.logs.modal.submit'))"> - </form> - </div> - <div class="modal-footer"> - <button type="button" class="btn btn-default" data-dismiss="modal"> - $escapetool.xml($services.localization.render('cancel'))</button> - </div> - </div> - </div> - </div> -</div> -{{/html}} -{{/velocity}} +{{dashboard/}} + AdminTools.WebHome 0 @@ -312,6 +230,167 @@ $services.admintools.getConfigurationData('configuration') + + AdminTools.WebHome + 0 + XWiki.JavaScriptExtension + db26a9ff-8a2e-4a46-83c2-697aa46eef7a + + XWiki.JavaScriptExtension + + + + + + + + + 0 + long + 0 + select + forbidden + 0 + 0 + cache + 5 + Caching policy + 0 + + |, + 1 + 0 + long|short|default|forbid + com.xpn.xwiki.objects.classes.StaticListClass + + + PureText + 0 + PureText + code + 2 + Code + 0 + 20 + 50 + 0 + com.xpn.xwiki.objects.classes.TextAreaClass + + + 0 + name + 1 + Name + 30 + 0 + com.xpn.xwiki.objects.classes.StringClass + + + 0 + select + yesno + parse + 4 + Parse content + 0 + com.xpn.xwiki.objects.classes.BooleanClass + + + 0 + 0 + select + forbidden + 0 + 0 + use + 3 + Use this extension + 0 + + |, + 1 + 0 + currentPage|onDemand|always + com.xpn.xwiki.objects.classes.StaticListClass + + + + default + + + require(['jquery'], function($) { + $(document).on('click', '#filesDownloadFilesModal .btn-primary', function(event) { + event.preventDefault() + var downloadForm = $(document.getElementById("filesDownloadForm")); + var form = downloadForm.serialize() + var link = document.createElement('a'); + link.href = downloadForm.attr('action'); + link.href += "?" + form; + link.click(); + }); + + $(document).on('click', '#filesViewLastNLinesModal .btn-primary', function(event) { + event.preventDefault() + var downloadForm = $(document.getElementById("filesLastNLogLinesForm")); + var noLines = $("#filesNoLines").val(); + if(noLines == ""){ + noLines = "1000"; + } + var link = document.createElement('a'); + link.href = downloadForm.attr('action'); + debugger; + link.href += "/" + noLines; + link.target="_blank"; + link.click(); + }); + + $(document).on('click', '#configurationViewLastNLinesModal .btn-primary', function(event) { + event.preventDefault() + var downloadForm = $(document.getElementById("configurationLastNLogLinesForm")); + var noLines = $("#configurationNoLines").val(); + if(noLines == ""){ + noLines = "1000"; + } + var link = document.createElement('a'); + link.href = downloadForm.attr('action'); + debugger; + link.href += "/" + noLines; + link.target="_blank"; + link.click(); + }); + + $(document).ready(function() { + var logsCheckbox = $('input[name="files"][value="logsDataResource"]'); + var dateFields = $('.dateFields'); + + if (!logsCheckbox.is(':checked')) { + dateFields.hide(); + } else { + dateFields.show(); + } + + logsCheckbox.change(function() { + if (this.checked) { + dateFields.show(); + } else { + dateFields.hide(); + } + }); +}); +}); + + + + + AdminToolsJavaScript + + + 0 + + + currentPage + + AdminTools.WebHome 0 @@ -435,12 +514,16 @@ $services.admintools.getConfigurationData('configuration') text-align: center; } -#downloadFilesModalLabel{ +.downloadFilesModalTitle{ text-align: center; } .download-modal-content{ padding-left: 5rem; +} + +.dateFields { + margin: 2rem 4rem; } From 34d2f03bd662325f9f619b6daabefbff01a0bf76 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Tue, 17 Oct 2023 13:34:44 +0300 Subject: [PATCH 45/72] Add support for downloading important files #8 * Edited REST endpoints * Merged files/logs/{nolines} endpoint with files/{fileType} * Refactored tests * Refactored JS functions * Refactored modals * Minor modifications in templates * minor modifications in CSS --- application-admintools-api/pom.xml | 5 -- .../admintools/rest/AdminToolsResource.java | 12 --- application-admintools-default/pom.xml | 2 +- .../data/identifiers/TomcatIdentifier.java | 24 +++--- .../download/resources/LogsDataResource.java | 10 ++- .../rest/DefaultAdminToolsResource.java | 41 ++++------ .../templates/configurationTemplate.vm | 2 +- .../templates/filesSectionTemplate.vm | 5 +- .../resources/templates/securityTemplate.vm | 2 - .../identifiers/TomcatIdentifierTest.java | 8 -- .../download/DownloadManagerTest.java | 9 ++- .../DataProvidersDataResourceTest.java | 30 +++----- .../resources/LogsDataResourceTest.java | 6 +- .../rest/DefaultAdminToolsResourceTest.java | 61 ++++----------- .../main/resources/AdminTools/Code/Macros.xml | 69 +++++++++++------ .../AdminTools/Code/Translations.xml | 4 +- .../src/main/resources/AdminTools/WebHome.xml | 76 +++++-------------- 17 files changed, 139 insertions(+), 227 deletions(-) diff --git a/application-admintools-api/pom.xml b/application-admintools-api/pom.xml index 23c47374..fba7f3f6 100644 --- a/application-admintools-api/pom.xml +++ b/application-admintools-api/pom.xml @@ -36,11 +36,6 @@ xwiki-commons-component-api ${commons.version} - - org.xwiki.contrib - xwiki-restserver-example - 4.1-SNAPSHOT - org.xwiki.platform xwiki-platform-rest-server diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java index a70616b4..d7020c36 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java @@ -19,7 +19,6 @@ */ package com.xwiki.admintools.rest; -import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -57,15 +56,4 @@ public interface AdminToolsResource extends XWikiRestComponent @GET @Path("/files") Response getFiles() throws XWikiRestException; - - /** - * Get last n lines of server logs. - * - * @param noLines number of lines to be retrieved from the log file. - * @return a file containing the last n lines of server logs. - * @throws XWikiRestException if an error occurred while retrieving the logs file . - */ - @GET - @Path("/files/logs/{noLines}") - Response getLastLogs(@PathParam("noLines") @DefaultValue("1000") String noLines) throws XWikiRestException; } diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index 2c0d7374..c2ebc849 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -63,6 +63,6 @@ - 0.81 + 0.77 \ No newline at end of file diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java index 1c88de4d..fcb89b2a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java @@ -55,9 +55,9 @@ public boolean isUsed() } else { String catalinaBase = System.getProperty("catalina.base"); String catalinaHome = System.getenv("CATALINA_HOME"); - if (catalinaBase != null) { + if (catalinaBase != null && !catalinaBase.isEmpty()) { return checkAndSetServerPath(catalinaBase); - } else if (catalinaHome != null) { + } else if (catalinaHome != null && !catalinaHome.isEmpty()) { return checkAndSetServerPath(catalinaHome); } } @@ -83,16 +83,6 @@ public void updatePossiblePaths() String.format("%s/webapps/xwiki/WEB-INF/", this.serverPath) }; } - private boolean checkAndSetServerPath(String path) - { - File file = new File(path + "/conf/catalina.properties"); - if (file.exists()) { - this.serverPath = path; - return true; - } - return false; - } - @Override public String getLogsFolderPath() { @@ -110,4 +100,14 @@ public Pattern getLogsPattern() { return Pattern.compile("\\d{4}-\\d{2}-\\d{2}"); } + + private boolean checkAndSetServerPath(String path) + { + File file = new File(path + "/conf/catalina.properties"); + if (file.exists()) { + this.serverPath = path; + return true; + } + return false; + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/LogsDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/LogsDataResource.java index e8dfaccf..797b0ee2 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/LogsDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/LogsDataResource.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -171,15 +172,16 @@ private boolean checkFilters(File file, Map filters) if (matcher.find()) { String fileDateString = matcher.group(); LocalDate fileDate = LocalDate.parse(fileDateString); + DateTimeFormatter filtersFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); if (filters.get(FROM_DATE_FILTER_KEY) != null && filters.get(TO_DATE_FILTER_KEY) != null) { - LocalDate fromDate = LocalDate.parse(filters.get(FROM_DATE_FILTER_KEY)); - LocalDate toDate = LocalDate.parse(filters.get(TO_DATE_FILTER_KEY)); + LocalDate fromDate = LocalDate.parse(filters.get(FROM_DATE_FILTER_KEY), filtersFormatter); + LocalDate toDate = LocalDate.parse(filters.get(TO_DATE_FILTER_KEY), filtersFormatter); return fileDate.isAfter(fromDate.minusDays(1)) && fileDate.isBefore(toDate.plusDays(1)); } else if (filters.get(FROM_DATE_FILTER_KEY) != null) { - LocalDate fromDate = LocalDate.parse(filters.get(FROM_DATE_FILTER_KEY)); + LocalDate fromDate = LocalDate.parse(filters.get(FROM_DATE_FILTER_KEY), filtersFormatter); return fileDate.isAfter(fromDate.minusDays(1)); } else if (filters.get(TO_DATE_FILTER_KEY) != null) { - LocalDate toDate = LocalDate.parse(filters.get(TO_DATE_FILTER_KEY)); + LocalDate toDate = LocalDate.parse(filters.get(TO_DATE_FILTER_KEY), filtersFormatter); return fileDate.isBefore(toDate.plusDays(1)); } else { return true; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java index 25cf7e41..c3ab6b0f 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java @@ -78,11 +78,22 @@ public Response getFile(String hint) throw new WebApplicationException(Response.Status.UNAUTHORIZED); } try { - byte[] xWikiFileContent = downloadManager.getFile(hint, null); - InputStream inputStream = new ByteArrayInputStream(xWikiFileContent); + byte[] fileContent; + if (hint.equals(LogsDataResource.HINT)) { + XWikiContext wikiContext = xcontextProvider.get(); + XWikiRequest xWikiRequest = wikiContext.getRequest(); + String noLines = xWikiRequest.getParameter("noLines"); + if (noLines == null || noLines.equals("")) { + noLines = "1000"; + } + fileContent = downloadManager.getFile(hint, noLines); + } else { + fileContent = downloadManager.getFile(hint, null); + } + InputStream inputStream = new ByteArrayInputStream(fileContent); return Response.ok(inputStream).type(MediaType.TEXT_PLAIN_TYPE).build(); } catch (IOException e) { - logger.warn("Could not find file from DataResource[{}]. Root cause: [{}]", hint, + logger.warn("Could not find file from DataResource [{}]. Root cause: [{}]", hint, ExceptionUtils.getRootCauseMessage(e)); return Response.status(Response.Status.NOT_FOUND).build(); } catch (Exception e) { @@ -113,30 +124,6 @@ public Response getFiles() } } - @Override - public Response getLastLogs(String input) - { - if (!isAdmin()) { - logger.warn("Failed to get the logs due to restricted rights."); - throw new WebApplicationException(Response.Status.UNAUTHORIZED); - } - try { - String noLines = input; - if (noLines == null || noLines.equals("")) { - noLines = "1000"; - } - byte[] xWikiFileContent = downloadManager.getFile(LogsDataResource.HINT, noLines); - InputStream inputStream = new ByteArrayInputStream(xWikiFileContent); - return Response.ok(inputStream).type(MediaType.TEXT_PLAIN_TYPE).build(); - } catch (IOException e) { - logger.warn("Could not retrieve logs from server. Root cause: [{}]", ExceptionUtils.getRootCauseMessage(e)); - return Response.status(Response.Status.NOT_FOUND).build(); - } catch (Exception e) { - logger.warn("Failed to get logs. Root cause: [{}]", ExceptionUtils.getRootCauseMessage(e)); - throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); - } - } - private boolean isAdmin() { XWikiContext wikiContext = xcontextProvider.get(); diff --git a/application-admintools-default/src/main/resources/templates/configurationTemplate.vm b/application-admintools-default/src/main/resources/templates/configurationTemplate.vm index 1ed56a35..906625d4 100644 --- a/application-admintools-default/src/main/resources/templates/configurationTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/configurationTemplate.vm @@ -17,6 +17,7 @@ ## Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ## 02110-1301 USA, or see the FSF site: http://www.fsf.org. ## --------------------------------------------------------------------------- +#includeMacros("AdminTools.Code.Macros") #viewLastNLinesMoldal("configuration") {{html clean='false'}} #if ($configuration['serverFound'] == 'true') @@ -74,7 +75,6 @@ #set($warningMessage = $warningMessage + $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.supportedServers.error')) + ':' + $stringtool.join($services.admintools.getSupportedServers(), ', ')) - #warning($warningMessage) #end {{/html}} \ No newline at end of file diff --git a/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm b/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm index af5ea634..46ca9667 100644 --- a/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm @@ -17,9 +17,10 @@ ## Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ## 02110-1301 USA, or see the FSF site: http://www.fsf.org. ## --------------------------------------------------------------------------- +#includeMacros("AdminTools.Code.Macros") #set($adminToolsFilesPath = "$request.getContextPath()/rest/admintools/files") #viewLastNLinesMoldal("files") -#downloadFiles("files") +#downloadArchiveModal("files") {{html clean='false'}} #if ($found == 'true')
@@ -30,7 +31,7 @@
  • - $escapetool.xml($services.localization.render('adminTools.dashboard.section.download.modal.open')) + $escapetool.xml($services.localization.render('adminTools.dashboard.section.download.label'))
  • $escapetool.xml($services.localization.render('adminTools.dashboard.section.download.view.description')) diff --git a/application-admintools-default/src/main/resources/templates/securityTemplate.vm b/application-admintools-default/src/main/resources/templates/securityTemplate.vm index 18cc16bf..fa334e4e 100644 --- a/application-admintools-default/src/main/resources/templates/securityTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/securityTemplate.vm @@ -45,10 +45,8 @@
- #else #set($warningMessage = $escapetool.xml($services.localization.render('adminTools.dashboard.section.security.error'))) #warning($warningMessage) #end - {{/html}} \ No newline at end of file diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifierTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifierTest.java index 05465422..f14994ae 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifierTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifierTest.java @@ -101,14 +101,6 @@ void isUsedValidSystemPathMissingCatalinaProperties() configDirectory.delete(); } - // Test with neither providedConfigServerPath nor catalina.base/CATALINA_HOME set. - @Test - void isUsedPathNotFound() - { - when(adminToolsConfig.getServerPath()).thenReturn(null); - assertFalse(tomcatIdentifier.isUsed()); - } - @Test void getIdentifier() { diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/DownloadManagerTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/DownloadManagerTest.java index 6e2a19c0..e4c3a74a 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/DownloadManagerTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/DownloadManagerTest.java @@ -160,8 +160,11 @@ void downloadMultipleFiles() throws Exception } @Test - void downloadMultipleFilesNoArchiverFound() throws Exception + void downloadMultipleFilesNoArchiverFound() { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(downloadManager, "logger", this.logger); + String[] files = { "data_resource_identifier_invalid", LogsDataResource.HINT }; Map request = new HashMap<>(); request.put("files", files); @@ -174,10 +177,12 @@ void downloadMultipleFilesNoArchiverFound() throws Exception }); assertEquals("Error while generating the file archive.", exception.getMessage()); + verify(logger).warn("Error while generating the file archive. Root cause is: [{}]", + "NullPointerException: "); } @Test - void downloadMultipleFilesInvalidRequest() throws Exception + void downloadMultipleFilesInvalidRequest() { when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(downloadManager, "logger", this.logger); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/DataProvidersDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/DataProvidersDataResourceTest.java index 46f6e80d..9f7fc31e 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/DataProvidersDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/DataProvidersDataResourceTest.java @@ -27,6 +27,7 @@ import javax.inject.Provider; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.slf4j.Logger; @@ -69,6 +70,15 @@ public class DataProvidersDataResourceTest @MockComponent private DataProvider dataProvider; + @BeforeEach + void setUp() + { + List dataProviderList = new ArrayList<>(); + dataProviderList.add(dataProvider); + when(dataProviders.get()).thenReturn(dataProviderList); + when(dataProvider.getIdentifier()).thenReturn("data_provider_identifier"); + } + @Test void getIdentifier() { @@ -78,11 +88,6 @@ void getIdentifier() @Test void getByteDataSuccess() throws Exception { - List dataProviderList = new ArrayList<>(); - dataProviderList.add(dataProvider); - when(dataProviders.get()).thenReturn(dataProviderList); - when(dataProvider.getIdentifier()).thenReturn("data_provider_identifier"); - Map providerJson = new HashMap<>(); providerJson.put("success", "true"); when(dataProvider.getDataAsJSON()).thenReturn(providerJson); @@ -98,11 +103,6 @@ void getByteDataThrowError() throws Exception when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(dataProviderResource, "logger", this.logger); - List dataProviderList = new ArrayList<>(); - dataProviderList.add(dataProvider); - when(dataProviders.get()).thenReturn(dataProviderList); - when(dataProvider.getIdentifier()).thenReturn("data_provider_identifier"); - when(dataProvider.getDataAsJSON()).thenThrow(new Exception("TEST - PROVIDER ERROR AT GET DATA AS JASON!")); Exception exception = assertThrows(Exception.class, () -> { this.dataProviderResource.getByteData(null); @@ -115,11 +115,6 @@ void getByteDataThrowError() throws Exception @Test void addZipEntry() throws Exception { - List dataProviderList = new ArrayList<>(); - dataProviderList.add(dataProvider); - when(dataProviders.get()).thenReturn(dataProviderList); - when(dataProvider.getIdentifier()).thenReturn("data_provider_identifier"); - Map providerJson = new HashMap<>(); providerJson.put("success", "true"); when(dataProvider.getDataAsJSON()).thenReturn(providerJson); @@ -139,11 +134,6 @@ void addZipEntryGetByteDataError() throws Exception when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(dataProviderResource, "logger", this.logger); - List dataProviderList = new ArrayList<>(); - dataProviderList.add(dataProvider); - when(dataProviders.get()).thenReturn(dataProviderList); - when(dataProvider.getIdentifier()).thenReturn("data_provider_identifier"); - when(dataProvider.getDataAsJSON()).thenThrow(new Exception("ERROR AT GET DATA AS JASON.")); dataProviderResource.addZipEntry(zipOutputStream, null); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/LogsDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/LogsDataResourceTest.java index 4c36dc30..3556e852 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/LogsDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/LogsDataResourceTest.java @@ -208,8 +208,8 @@ void addZipEntrySuccessWithFilters() throws IOException when(serverIdentifier.getLogsPattern()).thenReturn(Pattern.compile("\\d{4}-\\d{2}-\\d{2}")); Map filters = new HashMap<>(); - filters.put("from", "2023-10-06"); - filters.put("to", "2023-10-07"); + filters.put("from", "06-10-2023"); + filters.put("to", "07-10-2023"); readLines(400); logsDataResource.addZipEntry(zipOutputStream, filters); byte[] buff = new byte[2048]; @@ -229,7 +229,7 @@ void addZipEntryFilesOutOfFiltersRange() throws IOException when(serverIdentifier.getLogsPattern()).thenReturn(Pattern.compile("\\d{4}-\\d{2}-\\d{2}")); Map filters = new HashMap<>(); - filters.put("from", "2023-10-10"); + filters.put("from", "10-10-2023"); filters.put("to", null); logsDataResource.addZipEntry(zipOutputStream, filters); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java index aec14923..cfce9601 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java @@ -24,6 +24,7 @@ import java.util.Map; import javax.inject.Provider; +import javax.ws.rs.WebApplicationException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -119,7 +120,7 @@ void getFileNotFound() throws Exception when(downloadManager.getFile("resource_hint", null)).thenThrow(new IOException("FILE NOT FOUND")); assertEquals(404, defaultAdminToolsResource.getFile("resource_hint").getStatus()); - verify(logger).warn("Could not find file from DataResource[{}]. Root cause: [{}]", "resource_hint", + verify(logger).warn("Could not find file from DataResource [{}]. Root cause: [{}]", "resource_hint", "IOException: FILE NOT FOUND"); } @@ -129,10 +130,10 @@ void getFileDownloadManagerError() when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(defaultAdminToolsResource, "logger", this.logger); - Exception exception = assertThrows(Exception.class, () -> { + WebApplicationException exception = assertThrows(WebApplicationException.class, () -> { this.defaultAdminToolsResource.getFile("resource_hint"); }); - assertEquals("HTTP 500 Internal Server Error", exception.getMessage()); + assertEquals(500, exception.getResponse().getStatus()); verify(logger).warn("Failed to get data from DataResource [{}]. Root cause: [{}]", "resource_hint", "NullPointerException: "); } @@ -144,10 +145,10 @@ void getFileNotAdmin() ReflectionUtils.setFieldValue(defaultAdminToolsResource, "logger", this.logger); when(authorizationManager.hasAccess(Right.ADMIN, user, wikiReference)).thenReturn(false); - Exception exception = assertThrows(Exception.class, () -> { + WebApplicationException exception = assertThrows(WebApplicationException.class, () -> { this.defaultAdminToolsResource.getFile("resource_hint"); }); - assertEquals("HTTP 401 Unauthorized", exception.getMessage()); + assertEquals(401, exception.getResponse().getStatus()); verify(logger).warn("Failed to get file from DataResource [{}] due to restricted rights.", "resource_hint"); } @@ -171,10 +172,10 @@ void getFilesDownloadManagerError() throws Exception when(xWikiRequest.getParameterMap()).thenReturn(formParameters); when(downloadManager.downloadMultipleFiles(formParameters)).thenThrow( new Exception("DOWNLOAD MANAGER EXCEPTION")); - Exception exception = assertThrows(Exception.class, () -> { + WebApplicationException exception = assertThrows(WebApplicationException.class, () -> { defaultAdminToolsResource.getFiles(); }); - assertEquals("HTTP 500 Internal Server Error", exception.getMessage()); + assertEquals(500, exception.getResponse().getStatus()); verify(logger).warn("Failed to download files. Root cause: [{}]", "Exception: DOWNLOAD MANAGER EXCEPTION"); } @@ -185,10 +186,10 @@ void getFilesNotAdmin() ReflectionUtils.setFieldValue(defaultAdminToolsResource, "logger", this.logger); when(authorizationManager.hasAccess(Right.ADMIN, user, wikiReference)).thenReturn(false); - Exception exception = assertThrows(Exception.class, () -> { + WebApplicationException exception = assertThrows(WebApplicationException.class, () -> { this.defaultAdminToolsResource.getFiles(); }); - assertEquals("HTTP 401 Unauthorized", exception.getMessage()); + assertEquals(401, exception.getResponse().getStatus()); verify(logger).warn("Failed to get files due to restricted rights."); } @@ -197,46 +198,14 @@ void getLastLogs() throws Exception { when(downloadManager.getFile(LogsDataResource.HINT, "30")).thenReturn(new byte[] { 2 }); when(xWikiRequest.getParameter("noLines")).thenReturn("30"); - assertEquals(200, defaultAdminToolsResource.getLastLogs("30").getStatus()); + assertEquals(200, defaultAdminToolsResource.getFile(LogsDataResource.HINT).getStatus()); } @Test - void getLastDownloadManagerError() throws Exception + void getLastLogsNoInput() throws Exception { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(defaultAdminToolsResource, "logger", this.logger); - - when(downloadManager.getFile(LogsDataResource.HINT, "1000")).thenThrow(new IOException("FILE NOT FOUND")); - - assertEquals(404, defaultAdminToolsResource.getLastLogs("").getStatus()); - verify(logger).warn("Could not retrieve logs from server. Root cause: [{}]", "IOException: FILE NOT FOUND"); - } - - @Test - void getLastLogsDownloadManagerError() throws Exception - { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(defaultAdminToolsResource, "logger", this.logger); - - when(downloadManager.getFile(LogsDataResource.HINT, "1000")).thenThrow(new Exception("INTERNAL ERROR")); - Exception exception = assertThrows(Exception.class, () -> { - this.defaultAdminToolsResource.getLastLogs(null); - }); - assertEquals("HTTP 500 Internal Server Error", exception.getMessage()); - verify(logger).warn("Failed to get logs. Root cause: [{}]", "Exception: INTERNAL ERROR"); - } - - @Test - void getLastLogsNotAdmin() - { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(defaultAdminToolsResource, "logger", this.logger); - - when(authorizationManager.hasAccess(Right.ADMIN, user, wikiReference)).thenReturn(false); - Exception exception = assertThrows(Exception.class, () -> { - this.defaultAdminToolsResource.getLastLogs("1000"); - }); - assertEquals("HTTP 401 Unauthorized", exception.getMessage()); - verify(logger).warn("Failed to get the logs due to restricted rights."); + when(downloadManager.getFile(LogsDataResource.HINT, "1000")).thenReturn(new byte[] { 2 }); + when(xWikiRequest.getParameter("noLines")).thenReturn(""); + assertEquals(200, defaultAdminToolsResource.getFile(LogsDataResource.HINT).getStatus()); } } diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml index 9bb40d66..c2b2d8cd 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml @@ -38,28 +38,27 @@ {{velocity output="false"}} #macro (viewLastNLinesMoldal $id) #set ($modalId = $id + "ViewLastNLinesModal") - #set ($formId = $id + "LastNLogLinesForm") - #set ($inputId = $id + "NoLines") {{html clean='false'}} - <div class="modal fade" id="$modalId" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal fade" id="${modalId}" tabindex="-1" role="dialog" aria-labelledby="${modalId}Label"> <div class="modal-dialog modal-sm" role="document"> <div class="modal-content"> <div class="logs-modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span></button> - <h1 class="modal-title" id="viewLastNLinesModalLabel"> + <h1 class="modal-title text-center"> $escapetool.xml($services.localization.render('adminTools.dashboard.logs.modal.title')) </h1> </div> <div class="modal-body"> - <form class="xform" id="$formId" action="$request.getContextPath()/rest/admintools/files/logs"> + <form class="xform" action="$request.getContextPath()/rest/admintools/files/logsDataResource"> <dl> <dt> - <label for="noLines">$escapetool.xml($services.localization.render('adminTools.dashboard.logs.modal.nLines.label')) </label> + <label for="noLines">$escapetool.xml($services.localization.render( + 'adminTools.dashboard.logs.modal.nLines.label')) </label> <span class="xHint">max 50000</span> </dt> - <dd><input type="number" id="$inputId" name="noLines" placeholder="1000"></dd> + <dd><input type="number" name="noLines" placeholder="1000"></dd> </dl> </form> </div> @@ -75,44 +74,66 @@ </div> {{/html}} #end - -#macro (downloadFiles $id) +#macro (downloadArchiveModal $id) #set ($modalId = $id + "DownloadFilesModal") - #set ($formId = $id + "DownloadForm") - + {{html clean='false'}} - <div class="modal fade" id="$modalId" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> + <div class="modal fade" id="${modalId}" tabindex="-1" role="dialog" aria-labelledby="${modalId}Label"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span></button> - <h1 class="modal-title downloadFilesModalTitle"> + <h1 class="modal-title text-center"> $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.title')) </h1> </div> <div class="modal-body"> - <form id="$formId" action="$request.getContextPath()/rest/admintools/files"> + <form class="xform" action="$request.getContextPath()/rest/admintools/files"> <div class="download-modal-content"> <dl> <dt><label><input type="checkbox" name="files" value="xwikiConfig" checked> - $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.xwikiConfig.title')) - </label> + $escapetool.xml($services.localization.render( + 'adminTools.dashboard.download.modal.xwikiConfig.title')) + </label> </dt> <dt><label><input type="checkbox" name="files" value="xwikiProperties" checked> - $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.xwikiProperties.title')) + $escapetool.xml($services.localization.render( + 'adminTools.dashboard.download.modal.xwikiProperties.title')) + </label> + </dt> + <dt> + <label><input type="checkbox" name="files" value="dataProviderResource" checked> + $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.provided')) </label> </dt> - <dt><label><input type="checkbox" name="files" value="dataProviderResource" checked> - $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.provided'))</label> + <dt> + <label><input type="checkbox" name="files" value="logsDataResource" checked> + $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.logs.title')) + </label> </dt> - <dt><label><input type="checkbox" name="files" value="logsDataResource" checked> Logs</label></dt> <dt> <div class="dateFields"> - <label for="from">$escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.date.from')) - </label> <input type="date" id="from" name="from"> - <label for="to">$escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.date.to')) - </label> <input type="date" id="to" name="to"> + <label for="${modalId}FromDate">$escapetool.xml($services.localization.render( + 'adminTools.dashboard.download.modal.date.from')) + </label> #set ($dateFromParams = { + 'id': "${modalId}FromDate", + 'name': 'from', + 'data-format': 'dd-MM-yyyy', + 'placeholder': 'Logs from date...', + 'container': "#${modalId} modal-body" + }) + #dateTimePicker($dateFromParams) + <label for="${modalId}ToDate">$escapetool.xml($services.localization.render( + 'adminTools.dashboard.download.modal.date.to')) + </label> #set ($dateToParams = { + 'id': "${modalId}ToDate", + 'name': 'to', + 'data-format': 'dd-MM-yyyy', + 'placeholder': 'Logs to date...', + 'container': "#${modalId} modal-body" + }) + #dateTimePicker($dateToParams) </div> </dt> </dl> diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml index 45c04f2c..a631519a 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml @@ -50,7 +50,7 @@ adminTools.dashboard.download.modal.provided=Configuration info adminTools.dashboard.download.modal.title=Select Files adminTools.dashboard.download.modal.xwikiConfig.title=xwiki.cfg adminTools.dashboard.download.modal.xwikiProperties.title=xwiki.properties -adminTools.dashboard.download.modal.logs.title=logs +adminTools.dashboard.download.modal.logs.title=Logs adminTools.dashboard.logs.modal.submit=View adminTools.dashboard.logs.modal.nLines.label=Number of extracted lines adminTools.dashboard.logs.modal.title=Show last n lines of log @@ -74,7 +74,7 @@ adminTools.dashboard.section.backend.xwiki.version=XWiki installation version ## Files adminTools.dashboard.section.download.description=Get the files you need. View them directly in the browser or download them as an archive. -adminTools.dashboard.section.download.modal.open=Export files needed for getting support +adminTools.dashboard.section.download.label=Export files needed for getting support adminTools.dashboard.section.download.title=Files adminTools.dashboard.section.download.view.configuration=XWiki configuration file adminTools.dashboard.section.download.view.description=View files content diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index 34e751c0..63183eb4 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -34,10 +34,7 @@ false xwiki/2.1 false - {{include reference="AdminTools.Code.Macros"/}} - -{{dashboard/}} - + {{dashboard/}} AdminTools.WebHome 0 @@ -321,62 +318,33 @@ $services.admintools.getConfigurationData('configuration') require(['jquery'], function($) { $(document).on('click', '#filesDownloadFilesModal .btn-primary', function(event) { event.preventDefault() - var downloadForm = $(document.getElementById("filesDownloadForm")); - var form = downloadForm.serialize() - var link = document.createElement('a'); - link.href = downloadForm.attr('action'); - link.href += "?" + form; - link.click(); - }); - - $(document).on('click', '#filesViewLastNLinesModal .btn-primary', function(event) { - event.preventDefault() - var downloadForm = $(document.getElementById("filesLastNLogLinesForm")); - var noLines = $("#filesNoLines").val(); - if(noLines == ""){ - noLines = "1000"; - } - var link = document.createElement('a'); - link.href = downloadForm.attr('action'); - debugger; - link.href += "/" + noLines; - link.target="_blank"; + const downloadForm = $('#filesDownloadFilesModal form'); // Updated selector + const link = document.createElement('a'); + link.href = downloadForm.attr('action') + "?" + downloadForm.serialize(); link.click(); }); - $(document).on('click', '#configurationViewLastNLinesModal .btn-primary', function(event) { + $(document).on('click', '#filesViewLastNLinesModal .btn-primary, #configurationViewLastNLinesModal .btn-primary', function(event) { event.preventDefault() - var downloadForm = $(document.getElementById("configurationLastNLogLinesForm")); - var noLines = $("#configurationNoLines").val(); - if(noLines == ""){ + const modal = $(event.currentTarget).closest('.modal') + const downloadForm = modal.find('form'); + let noLines = modal.find("input[name='noLines']").val(); + if(noLines == ''){ noLines = "1000"; } - var link = document.createElement('a'); - link.href = downloadForm.attr('action'); - debugger; - link.href += "/" + noLines; + const link = document.createElement('a'); + link.href = downloadForm.attr('action') + "?noLines=" + noLines; link.target="_blank"; link.click(); }); - - $(document).ready(function() { - var logsCheckbox = $('input[name="files"][value="logsDataResource"]'); - var dateFields = $('.dateFields'); - if (!logsCheckbox.is(':checked')) { - dateFields.hide(); + $(document).on('change', '#filesDownloadFilesModal input[name="files"][value="logsDataResource"]', function() { + if ($(this).is(':checked')) { + $('.dateFields').show(); } else { - dateFields.show(); + $('.dateFields').hide(); } - - logsCheckbox.change(function() { - if (this.checked) { - dateFields.show(); - } else { - dateFields.hide(); - } - }); -}); + }); }); @@ -510,20 +478,16 @@ $services.admintools.getConfigurationData('configuration') text-align: center; } -.download-button{ - text-align: center; -} - -.downloadFilesModalTitle{ - text-align: center; -} - .download-modal-content{ padding-left: 5rem; } .dateFields { margin: 2rem 4rem; +} + +.bootstrap-datetimepicker-widget { + z-index: 99999 !important; } From 9d2804e8b88cba8aea7ec41285dfcbf2230a374f Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Fri, 20 Oct 2023 11:33:35 +0300 Subject: [PATCH 46/72] Add support for downloading important files #8 * Created a separated page for Javascript functions * Added user format to date picker * Adapted LogsDataResource * Adapted tests * Added and modified translations --- .../download/resources/LogsDataResource.java | 11 +- .../rest/DefaultAdminToolsResource.java | 2 +- .../templates/configurationTemplate.vm | 1 + .../templates/filesSectionTemplate.vm | 1 + .../resources/LogsDataResourceTest.java | 27 ++- .../AdminTools/Code/AdminToolsJS.xml | 175 ++++++++++++++++++ .../main/resources/AdminTools/Code/Macros.xml | 53 +++--- .../AdminTools/Code/Translations.xml | 5 +- .../src/main/resources/AdminTools/WebHome.xml | 137 +------------- 9 files changed, 248 insertions(+), 164 deletions(-) create mode 100644 application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/LogsDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/LogsDataResource.java index 797b0ee2..e221bfca 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/LogsDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/LogsDataResource.java @@ -37,12 +37,15 @@ import javax.inject.Inject; import javax.inject.Named; +import javax.inject.Provider; import javax.inject.Singleton; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.xwiki.component.annotation.Component; +import com.xpn.xwiki.XWiki; +import com.xpn.xwiki.XWikiContext; import com.xwiki.admintools.download.DataResource; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; @@ -76,6 +79,9 @@ public class LogsDataResource implements DataResource @Inject private CurrentServer currentServer; + @Inject + private Provider contextProvider; + @Override public String getIdentifier() { @@ -170,9 +176,12 @@ private boolean checkFilters(File file, Map filters) Pattern pattern = currentServer.getCurrentServer().getLogsPattern(); Matcher matcher = pattern.matcher(file.getName()); if (matcher.find()) { + XWikiContext wikiContext = contextProvider.get(); + XWiki xWiki = wikiContext.getWiki(); + String userDateFormat = xWiki.getXWikiPreference("dateformat", "dd-MM-yyyy", wikiContext); String fileDateString = matcher.group(); LocalDate fileDate = LocalDate.parse(fileDateString); - DateTimeFormatter filtersFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); + DateTimeFormatter filtersFormatter = DateTimeFormatter.ofPattern(userDateFormat); if (filters.get(FROM_DATE_FILTER_KEY) != null && filters.get(TO_DATE_FILTER_KEY) != null) { LocalDate fromDate = LocalDate.parse(filters.get(FROM_DATE_FILTER_KEY), filtersFormatter); LocalDate toDate = LocalDate.parse(filters.get(TO_DATE_FILTER_KEY), filtersFormatter); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java index c3ab6b0f..a0b12469 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java @@ -117,7 +117,7 @@ public Response getFiles() byte[] filesArchive = downloadManager.downloadMultipleFiles(formParameters); // Set the appropriate response headers to indicate a zip file download. return Response.ok(filesArchive).type("application/zip") - .header("Content-Disposition", "attachment; filename=adminToolsFiles.zip").build(); + .header("Content-Disposition", "attachment; filename=AdminToolsFiles.zip").build(); } catch (Exception e) { logger.warn("Failed to download files. Root cause: [{}]", ExceptionUtils.getRootCauseMessage(e)); throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); diff --git a/application-admintools-default/src/main/resources/templates/configurationTemplate.vm b/application-admintools-default/src/main/resources/templates/configurationTemplate.vm index 906625d4..534672bc 100644 --- a/application-admintools-default/src/main/resources/templates/configurationTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/configurationTemplate.vm @@ -17,6 +17,7 @@ ## Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ## 02110-1301 USA, or see the FSF site: http://www.fsf.org. ## --------------------------------------------------------------------------- +#set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) #includeMacros("AdminTools.Code.Macros") #viewLastNLinesMoldal("configuration") {{html clean='false'}} diff --git a/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm b/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm index 46ca9667..58072843 100644 --- a/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm @@ -17,6 +17,7 @@ ## Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA ## 02110-1301 USA, or see the FSF site: http://www.fsf.org. ## --------------------------------------------------------------------------- +#set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) #includeMacros("AdminTools.Code.Macros") #set($adminToolsFilesPath = "$request.getContextPath()/rest/admintools/files") #viewLastNLinesMoldal("files") diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/LogsDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/LogsDataResourceTest.java index 3556e852..612a4119 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/LogsDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/LogsDataResourceTest.java @@ -34,6 +34,9 @@ import java.util.regex.Pattern; import java.util.zip.ZipOutputStream; +import javax.inject.Provider; + +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.AdditionalMatchers; import org.mockito.Mock; @@ -45,6 +48,8 @@ import org.xwiki.test.junit5.mockito.InjectMockComponents; import org.xwiki.test.junit5.mockito.MockComponent; +import com.xpn.xwiki.XWiki; +import com.xpn.xwiki.XWikiContext; import com.xwiki.admintools.ServerIdentifier; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; @@ -85,6 +90,15 @@ public class LogsDataResourceTest @MockComponent private ServerIdentifier serverIdentifier; + @MockComponent + private Provider contextProvider; + + @Mock + private XWikiContext wikiContext; + + @Mock + private XWiki xWiki; + private File testFile; private File testFile2; @@ -115,6 +129,14 @@ void setUp() throws IOException writer2.close(); } + @BeforeEach + void beforeEach() + { + when(contextProvider.get()).thenReturn(wikiContext); + when(wikiContext.getWiki()).thenReturn(xWiki); + when(xWiki.getXWikiPreference("dateformat", "dd-MM-yyyy", wikiContext)).thenReturn("dd-MM-yyyy"); + } + @Test void getIdentifier() { @@ -174,7 +196,7 @@ void getByteDataServerNotFound() } @Test - void getByteDataIncorrectInput() throws Exception + void getByteDataIncorrectInput() { when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(logsDataResource, "logger", this.logger); @@ -227,9 +249,10 @@ void addZipEntryFilesOutOfFiltersRange() throws IOException when(currentServer.getCurrentServer()).thenReturn(serverIdentifier); when(serverIdentifier.getLogsFolderPath()).thenReturn(logsDir.getAbsolutePath()); when(serverIdentifier.getLogsPattern()).thenReturn(Pattern.compile("\\d{4}-\\d{2}-\\d{2}")); + when(xWiki.getXWikiPreference("dateformat", "dd-MM-yyyy", wikiContext)).thenReturn("dd yy MM"); Map filters = new HashMap<>(); - filters.put("from", "10-10-2023"); + filters.put("from", "10 23 10"); filters.put("to", null); logsDataResource.addZipEntry(zipOutputStream, filters); diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml new file mode 100644 index 00000000..1d84c76c --- /dev/null +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -0,0 +1,175 @@ + + + + AdminTools.Code + AdminToolsJS + + + 0 + xwiki:XWiki.Admin + AdminTools.WebHome + xwiki:XWiki.Admin + xwiki:XWiki.Admin + 1.1 + AdminToolsJS + + false + xwiki/2.1 + true + + + AdminTools.Code.AdminToolsJS + 0 + XWiki.JavaScriptExtension + 133ab342-517a-44d7-a39c-b7e623954c4e + + XWiki.JavaScriptExtension + + + + + + + + + 0 + long + 0 + select + forbidden + 0 + 0 + cache + 5 + Caching policy + 0 + + |, + 1 + 0 + long|short|default|forbid + com.xpn.xwiki.objects.classes.StaticListClass + + + PureText + 0 + PureText + code + 2 + Code + 0 + 20 + 50 + 0 + com.xpn.xwiki.objects.classes.TextAreaClass + + + 0 + name + 1 + Name + 30 + 0 + com.xpn.xwiki.objects.classes.StringClass + + + 0 + select + yesno + parse + 4 + Parse content + 0 + com.xpn.xwiki.objects.classes.BooleanClass + + + 0 + 0 + select + forbidden + 0 + 0 + use + 3 + Use this extension + 0 + + |, + 1 + 0 + currentPage|onDemand|always + com.xpn.xwiki.objects.classes.StaticListClass + + + + default + + + require(['jquery'], function($) { + $(document).on('click', '#filesDownloadFilesModal .btn-primary', function(event) { + event.preventDefault(); + const downloadForm = $('#filesDownloadFilesModal form'); + + // Simulate a click on a link to initialize the download. + const link = document.createElement('a'); + link.href = downloadForm.attr('action') + '?' + downloadForm.serialize(); + link.click(); + }); + + $(document).on('click', '#filesViewLastNLinesModal .btn-primary, #configurationViewLastNLinesModal .btn-primary', + function(event) { + event.preventDefault(); + const modal = $(event.currentTarget).closest('.modal'); + const downloadForm = modal.find('form'); + let noLines = modal.find("input[name='noLines']").val(); + + // If the input is empty, the default value of 1000 will be requested. + if(noLines == '') { + noLines = '1000'; + } + + // Simulate a click on a link to request the last 'noLines' logs. + const link = document.createElement('a'); + link.href = downloadForm.attr('action') + '?noLines=' + noLines; + link.target='_blank'; + link.click(); + }); + + $(document).on('change', '#filesDownloadFilesModal input[name="files"][value="logsDataResource"]', function() { + if ($(this).is(':checked')) { + $('#filesDownloadFilesModal .dateFields').show(); + } else { + $('#filesDownloadFilesModal .dateFields').hide(); + } + }); +}); + + + AdminToolsJavaScript + + + 0 + + + onDemand + + + \ No newline at end of file diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml index c2b2d8cd..dc4d230f 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml @@ -35,9 +35,9 @@ false xwiki/2.1 true - {{velocity output="false"}} + {{velocity output='false'}} #macro (viewLastNLinesMoldal $id) - #set ($modalId = $id + "ViewLastNLinesModal") + #set ($modalId = $id + 'ViewLastNLinesModal') {{html clean='false'}} <div class="modal fade" id="${modalId}" tabindex="-1" role="dialog" aria-labelledby="${modalId}Label"> <div class="modal-dialog modal-sm" role="document"> @@ -45,8 +45,8 @@ <div class="logs-modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> - <span aria-hidden="true">&times;</span></button> - <h1 class="modal-title text-center"> + <span aria-hidden="true">&times;</span></button> + <h1 class="modal-title"> $escapetool.xml($services.localization.render('adminTools.dashboard.logs.modal.title')) </h1> </div> @@ -56,7 +56,8 @@ <dt> <label for="noLines">$escapetool.xml($services.localization.render( 'adminTools.dashboard.logs.modal.nLines.label')) </label> - <span class="xHint">max 50000</span> + <span class="xHint">$escapetool.xml($services.localization.render( + 'adminTools.dashboard.logs.modal.nLines.hint'))</span> </dt> <dd><input type="number" name="noLines" placeholder="1000"></dd> </dl> @@ -75,7 +76,7 @@ {{/html}} #end #macro (downloadArchiveModal $id) - #set ($modalId = $id + "DownloadFilesModal") + #set ($modalId = $id + 'DownloadFilesModal') {{html clean='false'}} <div class="modal fade" id="${modalId}" tabindex="-1" role="dialog" aria-labelledby="${modalId}Label"> @@ -83,8 +84,8 @@ <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> - <span aria-hidden="true">&times;</span></button> - <h1 class="modal-title text-center"> + <span aria-hidden="true">&times;</span></button> + <h1 class="modal-title"> $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.title')) </h1> </div> @@ -114,26 +115,30 @@ </dt> <dt> <div class="dateFields"> + #set ($defaultDateFormat = 'dd-MM-yyyy') + #set ($dateFormat = $xwiki.getXWikiPreference('dateformat', $defaultDateFormat)) <label for="${modalId}FromDate">$escapetool.xml($services.localization.render( 'adminTools.dashboard.download.modal.date.from')) - </label> #set ($dateFromParams = { - 'id': "${modalId}FromDate", - 'name': 'from', - 'data-format': 'dd-MM-yyyy', - 'placeholder': 'Logs from date...', - 'container': "#${modalId} modal-body" - }) - #dateTimePicker($dateFromParams) + </label> + #set ($dateFromParams = { + 'id': "${modalId}FromDate", + 'name': 'from', + 'data-format': $dateFormat, + 'placeholder': $escapetool.xml($services.localization.render( + 'adminTools.dashboard.download.modal.logs.filter.placeholder.from')) + }) + #dateTimePicker($dateFromParams) <label for="${modalId}ToDate">$escapetool.xml($services.localization.render( 'adminTools.dashboard.download.modal.date.to')) - </label> #set ($dateToParams = { - 'id': "${modalId}ToDate", - 'name': 'to', - 'data-format': 'dd-MM-yyyy', - 'placeholder': 'Logs to date...', - 'container': "#${modalId} modal-body" - }) - #dateTimePicker($dateToParams) + </label> + #set ($dateToParams = { + 'id': "${modalId}ToDate", + 'name': 'to', + 'data-format': $dateFormat, + 'placeholder': $escapetool.xml($services.localization.render( + 'adminTools.dashboard.download.modal.logs.filter.placeholder.to')) + }) + #dateTimePicker($dateToParams) </div> </dt> </dl> diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml index a631519a..7aa9d709 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml @@ -47,13 +47,16 @@ adminTools.dashboard.download.modal.button=Download adminTools.dashboard.download.modal.date.from=From adminTools.dashboard.download.modal.date.to=To adminTools.dashboard.download.modal.provided=Configuration info -adminTools.dashboard.download.modal.title=Select Files +adminTools.dashboard.download.modal.title=Get support files adminTools.dashboard.download.modal.xwikiConfig.title=xwiki.cfg adminTools.dashboard.download.modal.xwikiProperties.title=xwiki.properties adminTools.dashboard.download.modal.logs.title=Logs +adminTools.dashboard.download.modal.logs.filter.placeholder.from=Logs from date... +adminTools.dashboard.download.modal.logs.filter.placeholder.to=Logs to date... adminTools.dashboard.logs.modal.submit=View adminTools.dashboard.logs.modal.nLines.label=Number of extracted lines adminTools.dashboard.logs.modal.title=Show last n lines of log +adminTools.dashboard.logs.modal.nLines.hint=Limited at 50000 lines. If the input is empty, the default of 1000 lines will be returned. adminTools.dashboard.showLogs=View last n lines of log... ## Dashboard sections diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index 63183eb4..553820bb 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -165,7 +165,7 @@ $services.admintools.getConfigurationData('configuration') AdminTools.WebHome 2 XWiki.GadgetClass - ec745b5d-c64a-4597-a519-57fbd98b7115 + 8035a2a3-0eca-490c-a572-91a4d0e4b787 XWiki.GadgetClass @@ -216,8 +216,7 @@ $services.admintools.getConfigurationData('configuration') {{velocity}} - $services.admintools.getDownloadTemplate() - +$services.admintools.getDownloadTemplate() {{/velocity}} @@ -227,138 +226,6 @@ $services.admintools.getConfigurationData('configuration') - - AdminTools.WebHome - 0 - XWiki.JavaScriptExtension - db26a9ff-8a2e-4a46-83c2-697aa46eef7a - - XWiki.JavaScriptExtension - - - - - - - - - 0 - long - 0 - select - forbidden - 0 - 0 - cache - 5 - Caching policy - 0 - - |, - 1 - 0 - long|short|default|forbid - com.xpn.xwiki.objects.classes.StaticListClass - - - PureText - 0 - PureText - code - 2 - Code - 0 - 20 - 50 - 0 - com.xpn.xwiki.objects.classes.TextAreaClass - - - 0 - name - 1 - Name - 30 - 0 - com.xpn.xwiki.objects.classes.StringClass - - - 0 - select - yesno - parse - 4 - Parse content - 0 - com.xpn.xwiki.objects.classes.BooleanClass - - - 0 - 0 - select - forbidden - 0 - 0 - use - 3 - Use this extension - 0 - - |, - 1 - 0 - currentPage|onDemand|always - com.xpn.xwiki.objects.classes.StaticListClass - - - - default - - - require(['jquery'], function($) { - $(document).on('click', '#filesDownloadFilesModal .btn-primary', function(event) { - event.preventDefault() - const downloadForm = $('#filesDownloadFilesModal form'); // Updated selector - const link = document.createElement('a'); - link.href = downloadForm.attr('action') + "?" + downloadForm.serialize(); - link.click(); - }); - - $(document).on('click', '#filesViewLastNLinesModal .btn-primary, #configurationViewLastNLinesModal .btn-primary', function(event) { - event.preventDefault() - const modal = $(event.currentTarget).closest('.modal') - const downloadForm = modal.find('form'); - let noLines = modal.find("input[name='noLines']").val(); - if(noLines == ''){ - noLines = "1000"; - } - const link = document.createElement('a'); - link.href = downloadForm.attr('action') + "?noLines=" + noLines; - link.target="_blank"; - link.click(); - }); - - $(document).on('change', '#filesDownloadFilesModal input[name="files"][value="logsDataResource"]', function() { - if ($(this).is(':checked')) { - $('.dateFields').show(); - } else { - $('.dateFields').hide(); - } - }); -}); - - - - - AdminToolsJavaScript - - - 0 - - - currentPage - - AdminTools.WebHome 0 From bfb1e089e273c1dd6ad3167317311f6e9b418e35 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Tue, 24 Oct 2023 15:08:54 +0300 Subject: [PATCH 47/72] Add support for downloading important files #8 * Modified comments and packages, classes and functions names * Removed parameter from downloadArchiveModal --- .../admintools/download/DataResource.java | 2 +- .../admintools/rest/AdminToolsResource.java | 2 +- application-admintools-default/pom.xml | 2 +- .../internal/AdminToolsManager.java | 8 ++--- .../ImportantFilesManager.java} | 27 +++++++------- .../resources/DataProvidersDataResource.java | 2 +- .../resources/LogsDataResource.java | 6 ++-- .../XWikiConfigFileDataResource.java | 4 +-- .../XWikiPropertiesFileDataResource.java | 4 +-- .../rest/DefaultAdminToolsResource.java | 18 +++++----- .../script/AdminToolsScriptService.java | 4 +-- .../main/resources/META-INF/components.txt | 10 +++--- .../templates/filesSectionTemplate.vm | 6 ++-- .../ImportantFilesManagerTest.java} | 36 +++++++++---------- .../DataProvidersDataResourceTest.java | 2 +- .../resources/LogsDataResourceTest.java | 4 +-- .../XWikiConfigFileDataResourceTest.java | 2 +- .../XWikiPropertiesFileDataResourceTest.java | 2 +- .../rest/DefaultAdminToolsResourceTest.java | 20 +++++------ .../AdminTools/Code/AdminToolsJS.xml | 12 +++---- .../main/resources/AdminTools/Code/Macros.xml | 14 ++++---- .../src/main/resources/AdminTools/WebHome.xml | 8 ++--- 22 files changed, 96 insertions(+), 99 deletions(-) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/{download/DownloadManager.java => files/ImportantFilesManager.java} (84%) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/{download => files}/resources/DataProvidersDataResource.java (98%) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/{download => files}/resources/LogsDataResource.java (97%) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/{download => files}/resources/XWikiConfigFileDataResource.java (97%) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/{download => files}/resources/XWikiPropertiesFileDataResource.java (97%) rename application-admintools-default/src/test/java/com/xwiki/admintools/internal/{download/DownloadManagerTest.java => files/ImportantFilesManagerTest.java} (86%) rename application-admintools-default/src/test/java/com/xwiki/admintools/internal/{download => files}/resources/DataProvidersDataResourceTest.java (98%) rename application-admintools-default/src/test/java/com/xwiki/admintools/internal/{download => files}/resources/LogsDataResourceTest.java (98%) rename application-admintools-default/src/test/java/com/xwiki/admintools/internal/{download => files}/resources/XWikiConfigFileDataResourceTest.java (99%) rename application-admintools-default/src/test/java/com/xwiki/admintools/internal/{download => files}/resources/XWikiPropertiesFileDataResourceTest.java (99%) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java b/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java index 03e3da87..79531837 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java @@ -26,7 +26,7 @@ import org.xwiki.component.annotation.Role; /** - * Endpoint to access server files. + * Access server files. * * @version $Id$ * @since 1.0 diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java index d7020c36..06bb18be 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java @@ -28,7 +28,7 @@ import org.xwiki.rest.XWikiRestException; /** - * Provides the APIs needed by the Admin Tools server in order to download and view configuration files and logs. + * Provides the APIs needed by the Admin Tools server in order to files and view configuration files and logs. * * @version $Id$ * @since 1.0 diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index c2ebc849..2c0d7374 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -63,6 +63,6 @@ - 0.77 + 0.81 \ No newline at end of file diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index 53fde4e3..1db1bc7b 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -30,7 +30,7 @@ import com.xwiki.admintools.DataProvider; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; -import com.xwiki.admintools.internal.download.DownloadManager; +import com.xwiki.admintools.internal.files.ImportantFilesManager; /** * Manages the data providers. @@ -55,7 +55,7 @@ public class AdminToolsManager private CurrentServer currentServer; @Inject - private DownloadManager downloadManager; + private ImportantFilesManager importantFilesManager; /** * Get data generated in a specific format, using a template, by each provider and merge it. @@ -114,8 +114,8 @@ public List getSupportedServers() * * @return a {@link String} representation of the template. */ - public String getDownloadTemplate() + public String getFilesSection() { - return this.downloadManager.renderTemplate(); + return this.importantFilesManager.renderTemplate(); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/DownloadManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java similarity index 84% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/DownloadManager.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java index 394a99e5..f7b30635 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/DownloadManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.download; +package com.xwiki.admintools.internal.files; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -40,7 +40,7 @@ import com.xwiki.admintools.download.DataResource; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; -import com.xwiki.admintools.internal.download.resources.LogsDataResource; +import com.xwiki.admintools.internal.files.resources.LogsDataResource; /** * Endpoints used for accessing important server files. @@ -48,9 +48,9 @@ * @version $Id$ * @since 1.0 */ -@Component(roles = DownloadManager.class) +@Component(roles = ImportantFilesManager.class) @Singleton -public class DownloadManager +public class ImportantFilesManager { private static final String FROM = "from"; @@ -91,21 +91,21 @@ public byte[] getFile(String hint, String input) throws Exception } /** - * Retrieve files from the request and create an archive with the given entries. + * Get an archive that contains specific files. For some of these files, a period filtering might also be applied. * - * @param request {@link Map} With the - * @return {@link Byte} array representing the request archive. + * @param params parameters needed for filtering the requested files + * @return an archive with files */ - public byte[] downloadMultipleFiles(Map request) throws Exception + public byte[] getFilesArchive(Map params) throws Exception { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) { - for (String dataResourceHint : request.get("files")) { + for (String dataResourceHint : params.get("files")) { Map filters = null; if (dataResourceHint.equals(LogsDataResource.HINT)) { filters = new HashMap<>(); - filters.put(FROM, !Objects.equals(request.get(FROM)[0], "") ? request.get(FROM)[0] : null); - filters.put(TO, !Objects.equals(request.get(TO)[0], "") ? request.get(TO)[0] : null); + filters.put(FROM, !Objects.equals(params.get(FROM)[0], "") ? params.get(FROM)[0] : null); + filters.put(TO, !Objects.equals(params.get(TO)[0], "") ? params.get(TO)[0] : null); } DataResource archiver = findDataResource(dataResourceHint); if (archiver != null) { @@ -133,10 +133,7 @@ public byte[] downloadMultipleFiles(Map request) throws Except public String renderTemplate() { try { - String found = "false"; - if (currentServer.getCurrentServer() != null) { - found = "true"; - } + boolean found = currentServer.getCurrentServer() != null; ScriptContext scriptContext = this.scriptContextManager.getScriptContext(); scriptContext.setAttribute("found", found, ScriptContext.ENGINE_SCOPE); return this.templateManager.render("filesSectionTemplate.vm"); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/DataProvidersDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java similarity index 98% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/DataProvidersDataResource.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java index bd7c572e..07ce0aca 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/DataProvidersDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.download.resources; +package com.xwiki.admintools.internal.files.resources; import java.io.IOException; import java.util.HashMap; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/LogsDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java similarity index 97% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/LogsDataResource.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java index e221bfca..5f48bc6e 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/LogsDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.download.resources; +package com.xwiki.admintools.internal.files.resources; import java.io.BufferedInputStream; import java.io.File; @@ -52,7 +52,7 @@ import static java.lang.Integer.parseInt; /** - * Collection of functions used for accessing log files. + * {@link DataResource} implementation for accessing log files. * * @version $Id$ * @since 1.0 @@ -159,7 +159,7 @@ public void addZipEntry(ZipOutputStream zipOutputStream, Map fil } } } catch (Exception e) { - logger.warn("Failed to download logs. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); + logger.warn("Failed to files logs. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/XWikiConfigFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java similarity index 97% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/XWikiConfigFileDataResource.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java index f9bcdbee..1b2d4cd3 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/XWikiConfigFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.download.resources; +package com.xwiki.admintools.internal.files.resources; import java.io.BufferedReader; import java.io.File; @@ -41,7 +41,7 @@ import com.xwiki.admintools.internal.data.identifiers.CurrentServer; /** - * Collection of functions used for accessing XWiki configuration file. + * {@link DataResource} implementation for accessing the xwiki.cfg file. * * @version $Id$ * @since 1.0 diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/XWikiPropertiesFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java similarity index 97% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/XWikiPropertiesFileDataResource.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java index 7f42e350..f1f47342 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/download/resources/XWikiPropertiesFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.download.resources; +package com.xwiki.admintools.internal.files.resources; import java.io.BufferedReader; import java.io.File; @@ -41,7 +41,7 @@ import com.xwiki.admintools.internal.data.identifiers.CurrentServer; /** - * Collection of functions used for accessing XWiki properties file. + * {@link DataResource} implementation for accessing the xwiki.properties file. * * @version $Id$ * @since 1.0 diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java index a0b12469..e9657d0b 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java @@ -42,8 +42,8 @@ import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.web.XWikiRequest; -import com.xwiki.admintools.internal.download.DownloadManager; -import com.xwiki.admintools.internal.download.resources.LogsDataResource; +import com.xwiki.admintools.internal.files.ImportantFilesManager; +import com.xwiki.admintools.internal.files.resources.LogsDataResource; import com.xwiki.admintools.rest.AdminToolsResource; /** @@ -61,10 +61,10 @@ public class DefaultAdminToolsResource extends ModifiablePageResource implements private Logger logger; /** - * Handles download requests. + * Handles files requests. */ @Inject - private DownloadManager downloadManager; + private ImportantFilesManager importantFilesManager; @Inject private AuthorizationManager authorizationManager; @@ -86,9 +86,9 @@ public Response getFile(String hint) if (noLines == null || noLines.equals("")) { noLines = "1000"; } - fileContent = downloadManager.getFile(hint, noLines); + fileContent = importantFilesManager.getFile(hint, noLines); } else { - fileContent = downloadManager.getFile(hint, null); + fileContent = importantFilesManager.getFile(hint, null); } InputStream inputStream = new ByteArrayInputStream(fileContent); return Response.ok(inputStream).type(MediaType.TEXT_PLAIN_TYPE).build(); @@ -114,12 +114,12 @@ public Response getFiles() XWikiContext wikiContext = xcontextProvider.get(); XWikiRequest xWikiRequest = wikiContext.getRequest(); Map formParameters = xWikiRequest.getParameterMap(); - byte[] filesArchive = downloadManager.downloadMultipleFiles(formParameters); - // Set the appropriate response headers to indicate a zip file download. + byte[] filesArchive = importantFilesManager.getFilesArchive(formParameters); + // Set the appropriate response headers to indicate a zip file files. return Response.ok(filesArchive).type("application/zip") .header("Content-Disposition", "attachment; filename=AdminToolsFiles.zip").build(); } catch (Exception e) { - logger.warn("Failed to download files. Root cause: [{}]", ExceptionUtils.getRootCauseMessage(e)); + logger.warn("Failed to files files. Root cause: [{}]", ExceptionUtils.getRootCauseMessage(e)); throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index e7e67d37..56f70335 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -91,8 +91,8 @@ public List getSupportedServers() * * @return a {@link String} representation of the template. */ - public String getDownloadTemplate() + public String getFilesSection() { - return this.adminToolsManager.getDownloadTemplate(); + return this.adminToolsManager.getFilesSection(); } } diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index f59d3969..3477b34c 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -4,11 +4,11 @@ com.xwiki.admintools.internal.data.ConfigurationDataProvider com.xwiki.admintools.internal.data.SecurityDataProvider com.xwiki.admintools.internal.data.identifiers.CurrentServer com.xwiki.admintools.internal.data.identifiers.TomcatIdentifier -com.xwiki.admintools.internal.download.resources.XWikiPropertiesFileDataResource -com.xwiki.admintools.internal.download.resources.XWikiConfigFileDataResource -com.xwiki.admintools.internal.download.resources.LogsDataResource -com.xwiki.admintools.internal.download.resources.DataProvidersDataResource -com.xwiki.admintools.internal.download.DownloadManager +com.xwiki.admintools.internal.files.resources.XWikiPropertiesFileDataResource +com.xwiki.admintools.internal.files.resources.XWikiConfigFileDataResource +com.xwiki.admintools.internal.files.resources.LogsDataResource +com.xwiki.admintools.internal.files.resources.DataProvidersDataResource +com.xwiki.admintools.internal.files.ImportantFilesManager com.xwiki.admintools.internal.configuration.AdminToolsConfigurationSource com.xwiki.admintools.internal.configuration.DefaultAdminToolsConfiguration com.xwiki.admintools.internal.AdminToolsEventListener diff --git a/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm b/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm index 58072843..bf3a47bd 100644 --- a/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm @@ -21,9 +21,9 @@ #includeMacros("AdminTools.Code.Macros") #set($adminToolsFilesPath = "$request.getContextPath()/rest/admintools/files") #viewLastNLinesMoldal("files") -#downloadArchiveModal("files") +#downloadArchiveModal() {{html clean='false'}} -#if ($found == 'true') +#if ($found)

$services.icon.renderHTML('download') $escapetool.xml($services.localization.render('adminTools.dashboard.section.download.title'))

@@ -31,7 +31,7 @@
  • - + $escapetool.xml($services.localization.render('adminTools.dashboard.section.download.label'))
  • diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/DownloadManagerTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java similarity index 86% rename from application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/DownloadManagerTest.java rename to application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java index e4c3a74a..54321b57 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/DownloadManagerTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.download; +package com.xwiki.admintools.internal.files; import java.io.IOException; import java.util.ArrayList; @@ -43,7 +43,7 @@ import com.xwiki.admintools.ServerIdentifier; import com.xwiki.admintools.download.DataResource; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; -import com.xwiki.admintools.internal.download.resources.LogsDataResource; +import com.xwiki.admintools.internal.files.resources.LogsDataResource; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -56,17 +56,17 @@ import static org.mockito.Mockito.when; /** - * Unit test for {@link DownloadManager} + * Unit test for {@link ImportantFilesManager} * * @version $Id$ */ @ComponentTest -public class DownloadManagerTest +public class ImportantFilesManagerTest { private final String templatePath = "filesSectionTemplate.vm"; @InjectMockComponents - private DownloadManager downloadManager; + private ImportantFilesManager importantFilesManager; @MockComponent private Provider> dataResources; @@ -104,7 +104,7 @@ void getFile() throws Exception when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); when(archiverDataResource.getByteData("input")).thenReturn(new byte[] { 2 }); - assertArrayEquals(new byte[] { 2 }, downloadManager.getFile("data_resource_identifier", "input")); + assertArrayEquals(new byte[] { 2 }, importantFilesManager.getFile("data_resource_identifier", "input")); } @Test @@ -115,7 +115,7 @@ void getFileResourceNotFound() when(dataResources.get()).thenReturn(dataResourceList); when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); Exception exception = assertThrows(Exception.class, () -> { - downloadManager.getFile("data_resource_identifier_invalid", "input"); + importantFilesManager.getFile("data_resource_identifier_invalid", "input"); }); assertEquals("Error while processing file content.", exception.getMessage()); } @@ -129,7 +129,7 @@ void getFileDataResourceError() throws Exception when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); when(archiverDataResource.getByteData("input")).thenThrow(new IOException("IO Error")); Exception exception = assertThrows(Exception.class, () -> { - downloadManager.getFile("data_resource_identifier", "input"); + importantFilesManager.getFile("data_resource_identifier", "input"); }); assertEquals("Error while managing file.", exception.getMessage()); } @@ -154,7 +154,7 @@ void downloadMultipleFiles() throws Exception when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); when(archiverLogsDataResource.getIdentifier()).thenReturn(LogsDataResource.HINT); - downloadManager.downloadMultipleFiles(request); + importantFilesManager.getFilesArchive(request); verify(archiverDataResource).addZipEntry(any(ZipOutputStream.class), isNull()); verify(archiverLogsDataResource).addZipEntry(any(ZipOutputStream.class), eq(filters)); } @@ -163,7 +163,7 @@ void downloadMultipleFiles() throws Exception void downloadMultipleFilesNoArchiverFound() { when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(downloadManager, "logger", this.logger); + ReflectionUtils.setFieldValue(importantFilesManager, "logger", this.logger); String[] files = { "data_resource_identifier_invalid", LogsDataResource.HINT }; Map request = new HashMap<>(); @@ -173,7 +173,7 @@ void downloadMultipleFilesNoArchiverFound() when(dataResources.get()).thenReturn(dataResourceList); when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); Exception exception = assertThrows(Exception.class, () -> { - downloadManager.downloadMultipleFiles(request); + importantFilesManager.getFilesArchive(request); }); assertEquals("Error while generating the file archive.", exception.getMessage()); @@ -185,7 +185,7 @@ void downloadMultipleFilesNoArchiverFound() void downloadMultipleFilesInvalidRequest() { when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(downloadManager, "logger", this.logger); + ReflectionUtils.setFieldValue(importantFilesManager, "logger", this.logger); String[] files = { "data_resource_identifier", LogsDataResource.HINT }; Map request = new HashMap<>(); @@ -197,7 +197,7 @@ void downloadMultipleFilesInvalidRequest() when(dataResources.get()).thenReturn(dataResourceList); when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); Exception exception = assertThrows(Exception.class, () -> { - downloadManager.downloadMultipleFiles(request); + importantFilesManager.getFilesArchive(request); }); assertEquals("Error while generating the file archive.", exception.getMessage()); @@ -213,23 +213,23 @@ void renderTemplate() throws Exception when(scriptContextManager.getScriptContext()).thenReturn(scriptContext); when(templateManager.render(templatePath)).thenReturn("success"); - assertEquals("success", downloadManager.renderTemplate()); - verify(scriptContext).setAttribute("found", "true", ScriptContext.ENGINE_SCOPE); + assertEquals("success", importantFilesManager.renderTemplate()); + verify(scriptContext).setAttribute("found", true, ScriptContext.ENGINE_SCOPE); } @Test void renderTemplateWithRenderingError() throws Exception { when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(downloadManager, "logger", this.logger); + ReflectionUtils.setFieldValue(importantFilesManager, "logger", this.logger); when(currentServer.getCurrentServer()).thenReturn(null); // Mock the renderer. when(scriptContextManager.getScriptContext()).thenReturn(scriptContext); when(templateManager.render(templatePath)).thenThrow(new Exception("Render failed.")); - assertNull(downloadManager.renderTemplate()); - verify(scriptContext).setAttribute("found", "false", ScriptContext.ENGINE_SCOPE); + assertNull(importantFilesManager.renderTemplate()); + verify(scriptContext).setAttribute("found", false, ScriptContext.ENGINE_SCOPE); verify(logger).warn("Failed to render custom template. Root cause is: [{}]", "Exception: Render failed."); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/DataProvidersDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java similarity index 98% rename from application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/DataProvidersDataResourceTest.java rename to application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java index 9f7fc31e..b3104030 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/DataProvidersDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.download.resources; +package com.xwiki.admintools.internal.files.resources; import java.util.ArrayList; import java.util.HashMap; diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/LogsDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java similarity index 98% rename from application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/LogsDataResourceTest.java rename to application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java index 612a4119..ac5ae4e8 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/LogsDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.download.resources; +package com.xwiki.admintools.internal.files.resources; import java.io.BufferedInputStream; import java.io.BufferedWriter; @@ -272,7 +272,7 @@ void addZipEntryDateParseError() filters.put("from", "2023-10-03"); filters.put("to", "2023-10-05"); logsDataResource.addZipEntry(zipOutputStream, filters); - verify(logger).warn("Failed to download logs. Root cause is: [{}]", + verify(logger).warn("Failed to files logs. Root cause is: [{}]", "DateTimeParseException: Text 'server' could not be parsed at index 0"); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/XWikiConfigFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java similarity index 99% rename from application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/XWikiConfigFileDataResourceTest.java rename to application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java index b6f00a96..0aa11ccd 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/XWikiConfigFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.download.resources; +package com.xwiki.admintools.internal.files.resources; import java.io.BufferedReader; import java.io.BufferedWriter; diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/XWikiPropertiesFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java similarity index 99% rename from application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/XWikiPropertiesFileDataResourceTest.java rename to application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java index 163b7e0f..3845fa5b 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/download/resources/XWikiPropertiesFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java @@ -17,7 +17,7 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.download.resources; +package com.xwiki.admintools.internal.files.resources; import java.io.BufferedReader; import java.io.BufferedWriter; diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java index cfce9601..aec8ec07 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java @@ -42,8 +42,8 @@ import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.web.XWikiRequest; -import com.xwiki.admintools.internal.download.DownloadManager; -import com.xwiki.admintools.internal.download.resources.LogsDataResource; +import com.xwiki.admintools.internal.files.ImportantFilesManager; +import com.xwiki.admintools.internal.files.resources.LogsDataResource; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -68,7 +68,7 @@ public class DefaultAdminToolsResourceTest private DefaultAdminToolsResource defaultAdminToolsResource; @MockComponent - private DownloadManager downloadManager; + private ImportantFilesManager importantFilesManager; @MockComponent private AuthorizationManager authorizationManager; @@ -106,7 +106,7 @@ void setUp() @Test void getFile() throws Exception { - when(downloadManager.getFile("resource_hint", null)).thenReturn(new byte[] { 2 }); + when(importantFilesManager.getFile("resource_hint", null)).thenReturn(new byte[] { 2 }); assertEquals(200, defaultAdminToolsResource.getFile("resource_hint").getStatus()); } @@ -117,7 +117,7 @@ void getFileNotFound() throws Exception when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(defaultAdminToolsResource, "logger", this.logger); - when(downloadManager.getFile("resource_hint", null)).thenThrow(new IOException("FILE NOT FOUND")); + when(importantFilesManager.getFile("resource_hint", null)).thenThrow(new IOException("FILE NOT FOUND")); assertEquals(404, defaultAdminToolsResource.getFile("resource_hint").getStatus()); verify(logger).warn("Could not find file from DataResource [{}]. Root cause: [{}]", "resource_hint", @@ -157,7 +157,7 @@ void getFiles() throws Exception { Map formParameters = new HashMap<>(); when(xWikiRequest.getParameterMap()).thenReturn(formParameters); - when(downloadManager.downloadMultipleFiles(formParameters)).thenReturn(new byte[] { 2 }); + when(importantFilesManager.getFilesArchive(formParameters)).thenReturn(new byte[] { 2 }); assertEquals(200, defaultAdminToolsResource.getFiles().getStatus()); } @@ -170,13 +170,13 @@ void getFilesDownloadManagerError() throws Exception Map formParameters = new HashMap<>(); when(xWikiRequest.getParameterMap()).thenReturn(formParameters); - when(downloadManager.downloadMultipleFiles(formParameters)).thenThrow( + when(importantFilesManager.getFilesArchive(formParameters)).thenThrow( new Exception("DOWNLOAD MANAGER EXCEPTION")); WebApplicationException exception = assertThrows(WebApplicationException.class, () -> { defaultAdminToolsResource.getFiles(); }); assertEquals(500, exception.getResponse().getStatus()); - verify(logger).warn("Failed to download files. Root cause: [{}]", "Exception: DOWNLOAD MANAGER EXCEPTION"); + verify(logger).warn("Failed to files files. Root cause: [{}]", "Exception: DOWNLOAD MANAGER EXCEPTION"); } @Test @@ -196,7 +196,7 @@ void getFilesNotAdmin() @Test void getLastLogs() throws Exception { - when(downloadManager.getFile(LogsDataResource.HINT, "30")).thenReturn(new byte[] { 2 }); + when(importantFilesManager.getFile(LogsDataResource.HINT, "30")).thenReturn(new byte[] { 2 }); when(xWikiRequest.getParameter("noLines")).thenReturn("30"); assertEquals(200, defaultAdminToolsResource.getFile(LogsDataResource.HINT).getStatus()); } @@ -204,7 +204,7 @@ void getLastLogs() throws Exception @Test void getLastLogsNoInput() throws Exception { - when(downloadManager.getFile(LogsDataResource.HINT, "1000")).thenReturn(new byte[] { 2 }); + when(importantFilesManager.getFile(LogsDataResource.HINT, "1000")).thenReturn(new byte[] { 2 }); when(xWikiRequest.getParameter("noLines")).thenReturn(""); assertEquals(200, defaultAdminToolsResource.getFile(LogsDataResource.HINT).getStatus()); } diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index 1d84c76c..0870469e 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -124,9 +124,9 @@ require(['jquery'], function($) { - $(document).on('click', '#filesDownloadFilesModal .btn-primary', function(event) { + $(document).on('click', '#DownloadFilesModal .btn-primary', function(event) { event.preventDefault(); - const downloadForm = $('#filesDownloadFilesModal form'); + const downloadForm = $('#DownloadFilesModal form'); // Simulate a click on a link to initialize the download. const link = document.createElement('a'); @@ -142,7 +142,7 @@ let noLines = modal.find("input[name='noLines']").val(); // If the input is empty, the default value of 1000 will be requested. - if(noLines == '') { + if (noLines == '') { noLines = '1000'; } @@ -153,11 +153,11 @@ link.click(); }); - $(document).on('change', '#filesDownloadFilesModal input[name="files"][value="logsDataResource"]', function() { + $(document).on('change', '#DownloadFilesModal input[name="files"][value="logsDataResource"]', function() { if ($(this).is(':checked')) { - $('#filesDownloadFilesModal .dateFields').show(); + $('#DownloadFilesModal .dateFields').show(); } else { - $('#filesDownloadFilesModal .dateFields').hide(); + $('#DownloadFilesModal .dateFields').hide(); } }); }); diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml index dc4d230f..80ec42dd 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml @@ -75,11 +75,11 @@ </div> {{/html}} #end -#macro (downloadArchiveModal $id) - #set ($modalId = $id + 'DownloadFilesModal') +#macro (downloadArchiveModal) {{html clean='false'}} - <div class="modal fade" id="${modalId}" tabindex="-1" role="dialog" aria-labelledby="${modalId}Label"> + <div class="modal fade" id="DownloadFilesModal" tabindex="-1" role="dialog" aria-labelledby= + "DownloadFilesModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> @@ -117,22 +117,22 @@ <div class="dateFields"> #set ($defaultDateFormat = 'dd-MM-yyyy') #set ($dateFormat = $xwiki.getXWikiPreference('dateformat', $defaultDateFormat)) - <label for="${modalId}FromDate">$escapetool.xml($services.localization.render( + <label for="DownloadFilesModalFromDate">$escapetool.xml($services.localization.render( 'adminTools.dashboard.download.modal.date.from')) </label> #set ($dateFromParams = { - 'id': "${modalId}FromDate", + 'id': "DownloadFilesModalFromDate", 'name': 'from', 'data-format': $dateFormat, 'placeholder': $escapetool.xml($services.localization.render( 'adminTools.dashboard.download.modal.logs.filter.placeholder.from')) }) #dateTimePicker($dateFromParams) - <label for="${modalId}ToDate">$escapetool.xml($services.localization.render( + <label for="DownloadFilesModalToDate">$escapetool.xml($services.localization.render( 'adminTools.dashboard.download.modal.date.to')) </label> #set ($dateToParams = { - 'id': "${modalId}ToDate", + 'id': "DownloadFilesModalToDate", 'name': 'to', 'data-format': $dateFormat, 'placeholder': $escapetool.xml($services.localization.render( diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index 553820bb..ae495942 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -216,7 +216,7 @@ $services.admintools.getConfigurationData('configuration') {{velocity}} -$services.admintools.getDownloadTemplate() +$services.admintools.getFilesSection() {{/velocity}} @@ -334,18 +334,18 @@ $services.admintools.getDownloadTemplate() #template('colorThemeInit.vm') -.adminToolsDashboardItem{ +.adminToolsDashboardItem { background-color: $theme.pageBackgroundColor; border-color: $theme.pageContentBackgroundColor; min-height: 35rem; padding: 1rem 1.1rem; } -.logs-modal-content{ +.logs-modal-content { text-align: center; } -.download-modal-content{ +.download-modal-content { padding-left: 5rem; } From 90a2b4cd86e3731f7209f9de0a5252159ca93ecd Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Tue, 24 Oct 2023 17:54:10 +0300 Subject: [PATCH 48/72] Add support for downloading important files #8 --- .../xwiki/admintools/rest/AdminToolsResource.java | 2 +- .../files/resources/DataProvidersDataResource.java | 4 +++- .../internal/files/resources/LogsDataResource.java | 2 +- .../files/resources/XWikiConfigFileDataResource.java | 4 +++- .../resources/XWikiPropertiesFileDataResource.java | 5 +++-- .../internal/rest/DefaultAdminToolsResource.java | 2 +- .../main/resources/templates/filesSectionTemplate.vm | 2 +- .../resources/DataProvidersDataResourceTest.java | 2 ++ .../files/resources/LogsDataResourceTest.java | 2 +- .../resources/XWikiConfigFileDataResourceTest.java | 3 +++ .../XWikiPropertiesFileDataResourceTest.java | 3 +++ .../internal/rest/DefaultAdminToolsResourceTest.java | 2 +- .../src/main/resources/AdminTools/Code/Macros.xml | 12 ++++++------ 13 files changed, 29 insertions(+), 16 deletions(-) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java index 06bb18be..d7020c36 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java @@ -28,7 +28,7 @@ import org.xwiki.rest.XWikiRestException; /** - * Provides the APIs needed by the Admin Tools server in order to files and view configuration files and logs. + * Provides the APIs needed by the Admin Tools server in order to download and view configuration files and logs. * * @version $Id$ * @since 1.0 diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java index 07ce0aca..e3a174a3 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java @@ -97,7 +97,9 @@ private void addZipEntry(ZipOutputStream zipOutputStream) zipOutputStream.putNextEntry(zipEntry); zipOutputStream.write(buffer, 0, buffer.length); zipOutputStream.closeEntry(); - } catch (Exception ignored) { + } catch (Exception exception) { + logger.warn("Could not add gathered configuration to the archive. Root cause is: {}", + ExceptionUtils.getRootCauseMessage(exception)); } } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java index 5f48bc6e..0b4f2f8f 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java @@ -159,7 +159,7 @@ public void addZipEntry(ZipOutputStream zipOutputStream, Map fil } } } catch (Exception e) { - logger.warn("Failed to files logs. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); + logger.warn("Failed to get logs. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java index 1b2d4cd3..a3fafaeb 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java @@ -123,7 +123,9 @@ private void addZipEntry(ZipOutputStream zipOutputStream) zipOutputStream.putNextEntry(zipEntry); zipOutputStream.write(buffer, 0, buffer.length); zipOutputStream.closeEntry(); - } catch (Exception ignored) { + } catch (Exception exception) { + logger.warn("Could not add {} to the archive." + ERROR_SOURCE, XWIKI_CFG, + ExceptionUtils.getRootCauseMessage(exception)); } } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java index f1f47342..dfa3b592 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java @@ -95,7 +95,6 @@ public byte[] getByteData(String input) throws Exception } stringBuilder.append(currentLine).append(System.getProperty("line.separator")); } - reader.close(); return stringBuilder.toString().getBytes(); } } catch (IOException exception) { @@ -123,7 +122,9 @@ private void addZipEntry(ZipOutputStream zipOutputStream) zipOutputStream.putNextEntry(zipEntry); zipOutputStream.write(buffer, 0, buffer.length); zipOutputStream.closeEntry(); - } catch (Exception ignored) { + } catch (Exception exception) { + logger.warn("Could not add {} to the archive." + ERROR_SOURCE, XWIKI_PROPERTIES, + ExceptionUtils.getRootCauseMessage(exception)); } } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java index e9657d0b..2fa6c31b 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java @@ -119,7 +119,7 @@ public Response getFiles() return Response.ok(filesArchive).type("application/zip") .header("Content-Disposition", "attachment; filename=AdminToolsFiles.zip").build(); } catch (Exception e) { - logger.warn("Failed to files files. Root cause: [{}]", ExceptionUtils.getRootCauseMessage(e)); + logger.warn("Failed to get zip archive. Root cause: [{}]", ExceptionUtils.getRootCauseMessage(e)); throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); } } diff --git a/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm b/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm index bf3a47bd..a05de3c4 100644 --- a/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm @@ -31,7 +31,7 @@
    • - + $escapetool.xml($services.localization.render('adminTools.dashboard.section.download.label'))
    • diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java index b3104030..a364f708 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java @@ -140,5 +140,7 @@ void addZipEntryGetByteDataError() throws Exception verify(logger).warn("Error getting json from DataProvider data_provider_identifier. Root cause is: [{}]", "Exception: ERROR AT GET DATA AS JASON."); verify(zipOutputStream, never()).write(any(), eq(0), eq(0)); + verify(logger).warn("Could not add gathered configuration to the archive. Root cause is: {}", + "Exception: ERROR AT GET DATA AS JASON."); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java index ac5ae4e8..9291c500 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java @@ -272,7 +272,7 @@ void addZipEntryDateParseError() filters.put("from", "2023-10-03"); filters.put("to", "2023-10-05"); logsDataResource.addZipEntry(zipOutputStream, filters); - verify(logger).warn("Failed to files logs. Root cause is: [{}]", + verify(logger).warn("Failed to get logs. Root cause is: [{}]", "DateTimeParseException: Text 'server' could not be parsed at index 0"); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java index 0aa11ccd..bb0339e4 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java @@ -206,6 +206,9 @@ void addZipEntryGetByteFail() throws Exception verify(zipOutputStream, never()).write(any(), eq(0), anyInt()); verify(logger).warn("Could not find xwiki.cfg file. Root cause is: [{}]", "FileNotFoundException: " + cfgDir2.getAbsolutePath() + "/xwiki.cfg (No such file or directory)"); + verify(logger).warn("Could not add {} to the archive. Root cause is: [{}]", "xwiki.cfg", + "FileNotFoundException: " + cfgDir2.getAbsolutePath() + "/xwiki.cfg (No such file or " + + "directory)"); } private byte[] readLines() throws IOException diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java index 3845fa5b..0d8b09e0 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java @@ -208,6 +208,9 @@ void addZipEntryGetByteFail() throws Exception verify(logger).warn("Could not find xwiki.properties file. Root cause is: [{}]", "FileNotFoundException: " + propertiesDir2.getAbsolutePath() + "/xwiki.properties (No such file or " + "directory)"); + verify(logger).warn("Could not add {} to the archive. Root cause is: [{}]", "xwiki.properties", + "FileNotFoundException: " + propertiesDir2.getAbsolutePath() + "/xwiki.properties (No such file or " + + "directory)"); } private byte[] readLines() throws IOException diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java index aec8ec07..0a82f2fb 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java @@ -176,7 +176,7 @@ void getFilesDownloadManagerError() throws Exception defaultAdminToolsResource.getFiles(); }); assertEquals(500, exception.getResponse().getStatus()); - verify(logger).warn("Failed to files files. Root cause: [{}]", "Exception: DOWNLOAD MANAGER EXCEPTION"); + verify(logger).warn("Failed to get zip archive. Root cause: [{}]", "Exception: DOWNLOAD MANAGER EXCEPTION"); } @Test diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml index 80ec42dd..55f37973 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml @@ -78,8 +78,8 @@ #macro (downloadArchiveModal) {{html clean='false'}} - <div class="modal fade" id="DownloadFilesModal" tabindex="-1" role="dialog" aria-labelledby= - "DownloadFilesModalLabel"> + <div class="modal fade" id="downloadFilesModal" tabindex="-1" role="dialog" aria-labelledby= + "downloadFilesModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> @@ -117,22 +117,22 @@ <div class="dateFields"> #set ($defaultDateFormat = 'dd-MM-yyyy') #set ($dateFormat = $xwiki.getXWikiPreference('dateformat', $defaultDateFormat)) - <label for="DownloadFilesModalFromDate">$escapetool.xml($services.localization.render( + <label for="downloadFilesModalFromDate">$escapetool.xml($services.localization.render( 'adminTools.dashboard.download.modal.date.from')) </label> #set ($dateFromParams = { - 'id': "DownloadFilesModalFromDate", + 'id': "downloadFilesModalFromDate", 'name': 'from', 'data-format': $dateFormat, 'placeholder': $escapetool.xml($services.localization.render( 'adminTools.dashboard.download.modal.logs.filter.placeholder.from')) }) #dateTimePicker($dateFromParams) - <label for="DownloadFilesModalToDate">$escapetool.xml($services.localization.render( + <label for="downloadFilesModalToDate">$escapetool.xml($services.localization.render( 'adminTools.dashboard.download.modal.date.to')) </label> #set ($dateToParams = { - 'id': "DownloadFilesModalToDate", + 'id': "downloadFilesModalToDate", 'name': 'to', 'data-format': $dateFormat, 'placeholder': $escapetool.xml($services.localization.render( From 3eb3f115ec2ddac801a42233e4c1436e2b46164f Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Wed, 25 Oct 2023 09:43:12 +0300 Subject: [PATCH 49/72] Create a health check dashboard section #13 misc --- .../jobs/HealthCheckJobRequest.java | 19 +++- application-admintools-default/pom.xml | 15 +++ .../AdminToolsConfigEventListener.java | 105 ------------------ .../health/checks/CacheHealthCheck.java | 81 ++++++++++++++ .../health/checks/PerformanceHealthCheck.java | 92 +++++++++++++++ .../AbstractConfigurationHealthCheck.java | 31 +++++- .../ConfigurationDatabaseHealthCheck.java | 5 +- .../ConfigurationJavaHealthCheck.java | 8 +- .../ConfigurationOsHealthCheck.java | 8 +- .../SecuritySystemEncodingHealthCheck.java | 56 ++++++++++ .../SecurityXWikiEncodingHealthCheck.java | 56 ++++++++++ .../internal/health/job/HealthCheckJob.java | 2 +- .../internal/util/DefaultFileOperations.java | 101 ----------------- .../script/AdminToolsScriptService.java | 43 +++++++ .../main/resources/META-INF/components.txt | 8 ++ .../identifiers/TomcatIdentifierTest.java | 8 -- 16 files changed, 408 insertions(+), 230 deletions(-) delete mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsConfigEventListener.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/CacheHealthCheck.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java delete mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/DefaultFileOperations.java diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java b/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java index 43be5cd2..0d14c901 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java @@ -19,6 +19,9 @@ */ package com.xwiki.admintools.jobs; +import java.util.ArrayList; +import java.util.List; + import org.xwiki.job.AbstractRequest; import org.xwiki.job.Request; import org.xwiki.stability.Unstable; @@ -28,13 +31,19 @@ public class HealthCheckJobRequest extends AbstractRequest { public HealthCheckJobRequest() { + setDefaultId(); + } + + public HealthCheckJobRequest(String wiki) { + setDefaultId(); + getId().add(wiki); } - /** - * @param request the request to copy - */ - public HealthCheckJobRequest(Request request) + private void setDefaultId() { - super(request); + List id = new ArrayList<>(); + id.add("adminTools"); + id.add("healthCheck"); + setId(id); } } diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index 87145d42..0c28f258 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -61,6 +61,21 @@ ${commons.version} test + + org.xwiki.commons + xwiki-commons-cache-api + ${commons.version} + + + com.github.oshi + oshi-core + 5.8.0 + + + org.codehaus.groovy + groovy-jmx + 3.0.13 + 0.66 diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsConfigEventListener.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsConfigEventListener.java deleted file mode 100644 index 6d5ee259..00000000 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsConfigEventListener.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools.internal; - -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; - -import org.xwiki.bridge.event.DocumentDeletedEvent; -import org.xwiki.bridge.event.DocumentUpdatedEvent; -import org.xwiki.component.annotation.Component; -import org.xwiki.model.reference.DocumentReference; -import org.xwiki.model.reference.LocalDocumentReference; -import org.xwiki.model.reference.WikiReference; -import org.xwiki.observation.AbstractEventListener; -import org.xwiki.observation.event.Event; -import org.xwiki.wiki.descriptor.WikiDescriptorManager; - -import com.xpn.xwiki.doc.XWikiDocument; -import com.xwiki.admintools.internal.data.identifiers.CurrentServer; - -/** - * Listens to configuration updates. - * - * @version $Id$ - * @since 1.0 - */ -@Component -@Named(AdminToolsConfigEventListener.HINT) -@Singleton -public class AdminToolsConfigEventListener extends AbstractEventListener -{ - /** - * The hint for the component. - */ - public static final String HINT = "AdminToolsConfigEventListener"; - - private static final List SPACE = Arrays.asList("AdminTools", "Code"); - - private static final LocalDocumentReference CONFIG_DOC = new LocalDocumentReference(SPACE, "Configuration"); - - @Inject - private WikiDescriptorManager wikiManager; - - @Inject - private CurrentServer currentServer; - - /** - * Creates an event-listener filtering for ApplicationReadyEvent and DocumentUpdatedEvent. - */ - public AdminToolsConfigEventListener() - { - super(HINT, new DocumentUpdatedEvent(), new DocumentDeletedEvent()); - } - - /** - * Triggers a server search when the configuration page is modified. - * - * @param event The event listened to. - * @param source The object sending the event. - * @param data Data about the event. - */ - @Override - public void onEvent(Event event, Object source, Object data) - { - if (event instanceof DocumentUpdatedEvent || event instanceof DocumentDeletedEvent) { - XWikiDocument document = (XWikiDocument) source; - if (document != null && isAdminToolsConfigObject(document)) { - currentServer.updateCurrentServer(); - } - } - } - - private boolean isAdminToolsConfigObject(XWikiDocument doc) - { - DocumentReference configReference = new DocumentReference(CONFIG_DOC, this.getCurrentWikiReference()); - return Objects.equals(doc.getDocumentReference(), configReference); - } - - private WikiReference getCurrentWikiReference() - { - return new WikiReference(this.wikiManager.getCurrentWikiId()); - } -} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/CacheHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/CacheHealthCheck.java new file mode 100644 index 00000000..d5910aa4 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/CacheHealthCheck.java @@ -0,0 +1,81 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.slf4j.Logger; +import org.xwiki.cache.Cache; +import org.xwiki.cache.CacheManagerConfiguration; +import org.xwiki.component.annotation.Component; + +import com.xpn.xwiki.XWiki; +import com.xpn.xwiki.XWikiContext; +import com.xpn.xwiki.doc.XWikiDocument; +import com.xpn.xwiki.store.XWikiCacheStore; +import com.xwiki.admintools.health.HealthCheck; +import com.xwiki.admintools.health.HealthCheckResult; + +import java.lang.management.ManagementFactory; +import java.util.Set; + +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import groovy.jmx.GroovyMBean; + +@Component +@Named(CacheHealthCheck.HINT) +@Singleton +public class CacheHealthCheck implements HealthCheck +{ + public final static String HINT = "CACHE_HEALTH_CHECK"; + + @Inject + protected Provider xcontextProvider; + + @Inject + CacheManagerConfiguration cacheManagerConfiguration; + + @Inject + private Logger logger; + @Override + public HealthCheckResult check() + { + try { + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + ObjectName query = new ObjectName("org.xwiki.infinispan:component=Statistics,*"); + Set names = server.queryNames(query, null); + for (ObjectName objectName : names){ + GroovyMBean mbean = new GroovyMBean(server, objectName, true); + for(String attribute : mbean.listAttributeNames()) { + logger.warn(String.format("%s - %s", attribute, mbean.getProperty(attribute))); + String b = ""; + } + } + logger.error("dummy err"); + return new HealthCheckResult(); + } catch (Exception ignored){} + return new HealthCheckResult(); + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java new file mode 100644 index 00000000..1c9b2947 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java @@ -0,0 +1,92 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks; + +import java.io.File; +import java.lang.management.ManagementFactory; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.slf4j.Logger; +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.health.HealthCheck; +import com.xwiki.admintools.health.HealthCheckResult; + +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.HardwareAbstractionLayer; + +@Component +@Named(PerformanceHealthCheck.HINT) +@Singleton +public class PerformanceHealthCheck implements HealthCheck +{ + public final static String HINT = "PERFORMANCE_HEALTH_CHECK"; + + @Inject + private Logger logger; + + @Override + public HealthCheckResult check() + { + if (!hasFreeSpace() || !hasMinimumCPURequirements() || !hasMinimumMemoryRequirements()) { + logger.warn("There might be some performance issues!"); + return new HealthCheckResult("performance issues", "minimum sys req link"); + } + logger.info("System performance is OK for the XWiki installation!"); + return new HealthCheckResult(); + } + + private boolean hasFreeSpace() + { + File diskPartition; + if (System.getProperty("os.name").contains("Windows")) { + diskPartition = new File("C:"); + } else { + diskPartition = new File("/"); + } + long freePartitionSpace = diskPartition.getFreeSpace(); + float freeSpace = (float) freePartitionSpace / (1024 * 1024 * 1024); + + return freeSpace > 2; + } + + private boolean hasMinimumMemoryRequirements() + { + long memorySize = ((com.sun.management.OperatingSystemMXBean) ManagementFactory + .getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); + float totalMemory = (float) memorySize / (1024 * 1024 * 1024) + 1; + + return totalMemory > 2; + } + + private boolean hasMinimumCPURequirements() + { + SystemInfo systemInfo = new SystemInfo(); + HardwareAbstractionLayer hardware = systemInfo.getHardware(); + CentralProcessor processor = hardware.getProcessor(); + int cpuCores = processor.getPhysicalProcessorCount(); + long maxFreq = processor.getMaxFreq() / (1024 * 1024); + return cpuCores > 2 && maxFreq > 2048; + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java index 7bce76b6..bf35b05a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java @@ -20,27 +20,46 @@ package com.xwiki.admintools.internal.health.checks.configuration; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import javax.inject.Inject; -import javax.inject.Named; +import javax.inject.Provider; + +import org.slf4j.Logger; import com.xwiki.admintools.DataProvider; import com.xwiki.admintools.health.HealthCheck; -import com.xwiki.admintools.internal.data.ConfigurationDataProvider; public abstract class AbstractConfigurationHealthCheck implements HealthCheck { @Inject - @Named(ConfigurationDataProvider.HINT) - private DataProvider configurationDataProvider; + Logger logger; + + @Inject + private Provider> dataProviders; - protected Map getJson() + protected Map getJson(String hint) { + try { - return configurationDataProvider.provideJson(); + TimeUnit.SECONDS.sleep(1); + return findDataProvider(hint).getDataAsJSON(); } catch (Exception e) { return new HashMap<>(); } } + + private DataProvider findDataProvider(String hint) + { + for (DataProvider dataProvider : dataProviders.get()) + { + if(dataProvider.getIdentifier().equals(hint)) + { + return dataProvider; + } + } + return null; + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java index 942354f9..8923f030 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java @@ -25,6 +25,7 @@ import org.xwiki.component.annotation.Component; import com.xwiki.admintools.health.HealthCheckResult; +import com.xwiki.admintools.internal.data.ConfigurationDataProvider; @Component @Named(ConfigurationDatabaseHealthCheck.HINT) @@ -36,9 +37,11 @@ public class ConfigurationDatabaseHealthCheck extends AbstractConfigurationHealt @Override public HealthCheckResult check() { - if (getJson().get("database") == null) { + if (getJson(ConfigurationDataProvider.HINT).get("database") == null) { + logger.warn("There are issues regarding the database."); return new HealthCheckResult("database_not_detected", "xwiki_db_configuration"); } + logger.info("Database status OK"); return new HealthCheckResult(); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java index e47481a3..df3529cc 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java @@ -25,6 +25,7 @@ import org.xwiki.component.annotation.Component; import com.xwiki.admintools.health.HealthCheckResult; +import com.xwiki.admintools.internal.data.ConfigurationDataProvider; @Component @Named(ConfigurationJavaHealthCheck.HINT) @@ -42,16 +43,19 @@ public class ConfigurationJavaHealthCheck extends AbstractConfigurationHealthChe @Override public HealthCheckResult check() { - String javaVersionString = getJson().get("javaVersion"); + String javaVersionString = getJson(ConfigurationDataProvider.HINT).get("javaVersion"); if (javaVersionString == null) { + logger.warn("Java version not found."); return new HealthCheckResult("java_version_not_found", "java_installation_link"); } - String xwikiVersionString = getJson().get("xwikiVersion"); + String xwikiVersionString = getJson(ConfigurationDataProvider.HINT).get("xwikiVersion"); float xwikiVersion = parseFloat(xwikiVersionString); float javaVersion = parseFloat(javaVersionString); if (isJavaXWikiCompatible(xwikiVersion, javaVersion)) { + logger.warn("Java version is not compatible with the current XWiki installation."); return new HealthCheckResult("java_xwiki_comp", xwikiJavaCompatibilityLink); } + logger.info("Java is OK."); return new HealthCheckResult(); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java index 0cd70bfd..13039eda 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java @@ -25,6 +25,7 @@ import org.xwiki.component.annotation.Component; import com.xwiki.admintools.health.HealthCheckResult; +import com.xwiki.admintools.internal.data.ConfigurationDataProvider; @Component @Named(ConfigurationOsHealthCheck.HINT) @@ -36,9 +37,14 @@ public class ConfigurationOsHealthCheck extends AbstractConfigurationHealthCheck @Override public HealthCheckResult check() { - if (getJson().get("osName") == null || getJson().get("osVersion") == null || getJson().get("osArch") == null) { + if (getJson(ConfigurationDataProvider.HINT).get("osName") == null + || getJson(ConfigurationDataProvider.HINT).get("osVersion") == null + || getJson(ConfigurationDataProvider.HINT).get("osArch") == null) + { + logger.warn("There has been an error while gathering OS info."); return new HealthCheckResult("os_issue", "os_support"); } + logger.info("OS info retrieval was successful."); return new HealthCheckResult(); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java new file mode 100644 index 00000000..d711ea00 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java @@ -0,0 +1,56 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.configuration; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.health.HealthCheckResult; +import com.xwiki.admintools.internal.data.SecurityDataProvider; + +@Component +@Named(SecuritySystemEncodingHealthCheck.HINT) +@Singleton +public class SecuritySystemEncodingHealthCheck extends AbstractConfigurationHealthCheck +{ + public final static String HINT = "SECURITY_SYSTEM_ENCODING_HEALTH_CHECK"; + + private final List acceptedEncodings = new ArrayList<>(List.of("UTF8", "UTF-8", "utf8", "utf-8")); + + @Override + public HealthCheckResult check() + { + Map securityJson = getJson(SecurityDataProvider.HINT); + if (!acceptedEncodings.contains(securityJson.get("LANG").split("\\.")[1]) + || !acceptedEncodings.contains(securityJson.get("fileEncoding"))) + { + logger.warn("System encoding should be UTF-8!"); + return new HealthCheckResult("xwiki_encoding err", "xwiki config tutorial link"); + } + logger.info("System encoding is safe."); + return new HealthCheckResult(); + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java new file mode 100644 index 00000000..98a21723 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java @@ -0,0 +1,56 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.configuration; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.health.HealthCheckResult; +import com.xwiki.admintools.internal.data.SecurityDataProvider; + +@Component +@Named(SecurityXWikiEncodingHealthCheck.HINT) +@Singleton +public class SecurityXWikiEncodingHealthCheck extends AbstractConfigurationHealthCheck +{ + public final static String HINT = "SECURITY_XWIKI_ENCODING_HEALTH_CHECK"; + + private final List acceptedEncodings = new ArrayList<>(List.of("UTF8", "UTF-8", "utf8", "utf-8")); + + @Override + public HealthCheckResult check() + { + Map securityJson = getJson(SecurityDataProvider.HINT); + if (!acceptedEncodings.contains(securityJson.get("activeEncoding")) + || !acceptedEncodings.contains(securityJson.get("configurationEncoding"))) + { + logger.warn("XWiki encoding might be at risk!"); + return new HealthCheckResult("xwiki_encoding err", "xwiki config tutorial link"); + } + logger.info("XWiki encoding is configured correctly."); + return new HealthCheckResult(); + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java index f8bfda60..3e7d7eb2 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java @@ -42,7 +42,7 @@ public class HealthCheckJob extends AbstractJob { /** - * The PDF export job type. + * Admin Tools health check job type. */ public static final String JOB_TYPE = "admintools.healthcheck"; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/DefaultFileOperations.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/DefaultFileOperations.java deleted file mode 100644 index a914c020..00000000 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/util/DefaultFileOperations.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools.internal.util; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.Scanner; - -import org.xwiki.component.annotation.Component; -import org.xwiki.component.annotation.InstantiationStrategy; -import org.xwiki.component.descriptor.ComponentInstantiationStrategy; - -/** - * Collection of file operations. - * - * @version $Id$ - * @since 1.0 - */ -@Component(roles = DefaultFileOperations.class) -@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP) -public class DefaultFileOperations -{ - private Scanner scanner; - - private File file; - - /** - * Check if the searched file exists. - * - * @return {@code true} if the file exists, {@code false} otherwise. - */ - public boolean fileExists() - { - return file.exists(); - } - - /** - * Initialize the file. - * - * @param path to the file. - */ - public void openFile(String path) - { - file = new File(path); - } - - /** - * Initialize the scanner for the needed file. - * - * @throws FileNotFoundException - */ - public void initializeScanner() throws FileNotFoundException - { - scanner = new Scanner(file); - } - - /** - * Get the next line from the file. - * - * @return next line from the file. - */ - public String nextLine() - { - return scanner.nextLine(); - } - - /** - * Verify if there is a line left in the file. - * - * @return {@code true} if there is at least one line left, {@code false} otherwise. - */ - public boolean hasNextLine() - { - return scanner.hasNextLine(); - } - - /** - * Close the opened scanner. - */ - public void closeScanner() - { - scanner.close(); - } -} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index a1ffddac..2b87820a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -26,9 +26,13 @@ import javax.inject.Singleton; import org.xwiki.component.annotation.Component; +import org.xwiki.job.Job; +import org.xwiki.job.JobExecutor; import org.xwiki.script.service.ScriptService; import com.xwiki.admintools.internal.AdminToolsManager; +import com.xwiki.admintools.internal.health.job.HealthCheckJob; +import com.xwiki.admintools.jobs.HealthCheckJobRequest; /** * Admin Tools script services. @@ -44,6 +48,9 @@ public class AdminToolsScriptService implements ScriptService @Inject private AdminToolsManager adminToolsManager; + @Inject + private JobExecutor jobExecutor; + /** * Retrieve all the configuration information in a format given by the associated templates generated by the data * providers. @@ -85,4 +92,40 @@ public List getSupportedServers() { return this.adminToolsManager.getSupportedServers(); } + + /** + * TBC. + * + * @return TBC. + */ + public Job runHealthChecks() + { + try { + return this.jobExecutor.execute(HealthCheckJob.JOB_TYPE, new HealthCheckJobRequest()); + } catch (Exception e) { + return null; + } + } + + /** + * TBC. + * + * @param wiki TBC. + * @return TBC. + */ + public Job runHealthChecks(String wiki) + { + try { + HealthCheckJobRequest healthCheckJobRequest = new HealthCheckJobRequest(wiki); + + Job job = this.jobExecutor.getJob(healthCheckJobRequest.getId()); + if (job == null) { + return this.jobExecutor.execute(HealthCheckJob.JOB_TYPE, healthCheckJobRequest); + } else { + return job; + } + } catch (Exception e) { + return null; + } + } } diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index 4f71b6db..d6082735 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -7,3 +7,11 @@ com.xwiki.admintools.internal.data.identifiers.TomcatIdentifier com.xwiki.admintools.internal.configuration.AdminToolsConfigurationSource com.xwiki.admintools.internal.configuration.DefaultAdminToolsConfiguration com.xwiki.admintools.internal.AdminToolsEventListener +com.xwiki.admintools.internal.health.checks.configuration.ConfigurationDatabaseHealthCheck +com.xwiki.admintools.internal.health.checks.configuration.ConfigurationJavaHealthCheck +com.xwiki.admintools.internal.health.checks.configuration.ConfigurationOsHealthCheck +com.xwiki.admintools.internal.health.checks.configuration.SecuritySystemEncodingHealthCheck +com.xwiki.admintools.internal.health.checks.configuration.SecurityXWikiEncodingHealthCheck +com.xwiki.admintools.internal.health.checks.PerformanceHealthCheck +com.xwiki.admintools.internal.health.checks.CacheHealthCheck +com.xwiki.admintools.internal.health.job.HealthCheckJob diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifierTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifierTest.java index 05465422..f14994ae 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifierTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifierTest.java @@ -101,14 +101,6 @@ void isUsedValidSystemPathMissingCatalinaProperties() configDirectory.delete(); } - // Test with neither providedConfigServerPath nor catalina.base/CATALINA_HOME set. - @Test - void isUsedPathNotFound() - { - when(adminToolsConfig.getServerPath()).thenReturn(null); - assertFalse(tomcatIdentifier.isUsed()); - } - @Test void getIdentifier() { From 6436d00e77fc2c40ea300be6860994a166e17805 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Wed, 25 Oct 2023 10:25:20 +0300 Subject: [PATCH 50/72] Add support for downloading important files #8 * forgot to edit JS file --- .../main/resources/AdminTools/Code/AdminToolsJS.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index 0870469e..5caac115 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -124,9 +124,9 @@ require(['jquery'], function($) { - $(document).on('click', '#DownloadFilesModal .btn-primary', function(event) { + $(document).on('click', '#downloadFilesModal .btn-primary', function(event) { event.preventDefault(); - const downloadForm = $('#DownloadFilesModal form'); + const downloadForm = $('#downloadFilesModal form'); // Simulate a click on a link to initialize the download. const link = document.createElement('a'); @@ -153,11 +153,11 @@ link.click(); }); - $(document).on('change', '#DownloadFilesModal input[name="files"][value="logsDataResource"]', function() { + $(document).on('change', '#downloadFilesModal input[name="files"][value="logsDataResource"]', function() { if ($(this).is(':checked')) { - $('#DownloadFilesModal .dateFields').show(); + $('#downloadFilesModal .dateFields').show(); } else { - $('#DownloadFilesModal .dateFields').hide(); + $('#downloadFilesModal .dateFields').hide(); } }); }); From 2e6b90858c146082e1d2921bbccc8d00f4bed75b Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Wed, 25 Oct 2023 10:27:00 +0300 Subject: [PATCH 51/72] Create a health check dashboard section #13 * merged #8 --- .../main/resources/AdminTools/Code/AdminToolsJS.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index 0870469e..5caac115 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -124,9 +124,9 @@ require(['jquery'], function($) { - $(document).on('click', '#DownloadFilesModal .btn-primary', function(event) { + $(document).on('click', '#downloadFilesModal .btn-primary', function(event) { event.preventDefault(); - const downloadForm = $('#DownloadFilesModal form'); + const downloadForm = $('#downloadFilesModal form'); // Simulate a click on a link to initialize the download. const link = document.createElement('a'); @@ -153,11 +153,11 @@ link.click(); }); - $(document).on('change', '#DownloadFilesModal input[name="files"][value="logsDataResource"]', function() { + $(document).on('change', '#downloadFilesModal input[name="files"][value="logsDataResource"]', function() { if ($(this).is(':checked')) { - $('#DownloadFilesModal .dateFields').show(); + $('#downloadFilesModal .dateFields').show(); } else { - $('#DownloadFilesModal .dateFields').hide(); + $('#downloadFilesModal .dateFields').hide(); } }); }); From 23d690618ebb2f63a2d382afa0f593a6d89d65bc Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Wed, 25 Oct 2023 18:32:13 +0300 Subject: [PATCH 52/72] Add support for downloading important files #8 * Modified files exception handling --- .../data/ConfigurationDataProvider.java | 9 +++--- .../files/resources/LogsDataResource.java | 4 +-- .../XWikiConfigFileDataResource.java | 13 ++++---- .../XWikiPropertiesFileDataResource.java | 13 ++++---- .../rest/DefaultAdminToolsResource.java | 2 +- .../data/ConfigurationDataProviderTest.java | 2 +- .../XWikiConfigFileDataResourceTest.java | 29 ++++++++++++----- .../XWikiPropertiesFileDataResourceTest.java | 31 +++++++++++++------ .../rest/DefaultAdminToolsResourceTest.java | 2 +- 9 files changed, 68 insertions(+), 37 deletions(-) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index f3c10d53..79cc22c3 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -22,6 +22,7 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileReader; +import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; @@ -112,7 +113,7 @@ private String getJavaVersion() * * @return the name of the used database or {@code null} in case an error occurred or the used DB is not supported. */ - private String identifyDB() throws Exception + private String identifyDB() { String usedDB = null; try { @@ -137,9 +138,9 @@ private String identifyDB() throws Exception this.logger.warn("Failed to find database. Used database may not be supported!"); } } catch (NullPointerException e) { - throw new Exception("Failed to identify used Database.", e); - } catch (Exception exception) { - this.logger.warn("Failed to open database configuration file. Root cause is: [{}]", + throw new NullPointerException("Failed to identify used Database."); + } catch (IOException exception) { + this.logger.warn("Error while handling database configuration file. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(exception)); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java index 0b4f2f8f..5411cec2 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java @@ -121,10 +121,10 @@ public byte[] getByteData(String input) throws Exception String.format("Could not find log files at %s.", currentServer.getCurrentServer().getLastLogFilePath()); logger.warn(errMessage + ERROR_SOURCE, ExceptionUtils.getRootCauseMessage(exception)); throw new IOException(errMessage, exception); - } catch (Exception exception) { + } catch (RuntimeException exception) { String errMessage = "Failed to retrieve logs."; logger.warn(errMessage + ERROR_SOURCE, ExceptionUtils.getRootCauseMessage(exception)); - throw new Exception(errMessage, exception); + throw new RuntimeException(errMessage, exception); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java index a3fafaeb..45da0dfe 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java @@ -99,13 +99,14 @@ public byte[] getByteData(String input) throws Exception return stringBuilder.toString().getBytes(); } } catch (IOException exception) { - String errMessage = String.format("Could not find %s file.", XWIKI_CFG); - logger.warn(errMessage + ERROR_SOURCE, ExceptionUtils.getRootCauseMessage(exception)); - throw new IOException(errMessage, exception); - } catch (Exception e) { - String errMessage = String.format("Failed to get content of %s.", XWIKI_CFG); + throw new IOException(String.format("Error while handling %s file.", XWIKI_CFG), exception); + } catch (NullPointerException e) { + logger.warn("Server not found. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); + throw new NullPointerException("Server not found."); + } catch (RuntimeException e) { + String errMessage = "Error while retrieving data from Admin Tools configuration."; logger.warn(errMessage + ERROR_SOURCE, ExceptionUtils.getRootCauseMessage(e)); - throw new Exception(errMessage, e); + throw new RuntimeException(errMessage, e); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java index dfa3b592..bab2dd81 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java @@ -98,13 +98,14 @@ public byte[] getByteData(String input) throws Exception return stringBuilder.toString().getBytes(); } } catch (IOException exception) { - String errMessage = String.format("Could not find %s file.", XWIKI_PROPERTIES); - logger.warn(errMessage + ERROR_SOURCE, ExceptionUtils.getRootCauseMessage(exception)); - throw new IOException(errMessage, exception); - } catch (Exception e) { - String errMessage = String.format("Failed to get content of %s.", XWIKI_PROPERTIES); + throw new IOException(String.format("Error while handling %s file.", XWIKI_PROPERTIES), exception); + } catch (NullPointerException e) { + logger.warn("Server not found. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); + throw new NullPointerException("Server not found."); + } catch (RuntimeException e) { + String errMessage = "Error while retrieving data from Admin Tools configuration."; logger.warn(errMessage + ERROR_SOURCE, ExceptionUtils.getRootCauseMessage(e)); - throw new Exception(errMessage, e); + throw new RuntimeException(errMessage, e); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java index 2fa6c31b..fe0f3354 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java @@ -93,7 +93,7 @@ public Response getFile(String hint) InputStream inputStream = new ByteArrayInputStream(fileContent); return Response.ok(inputStream).type(MediaType.TEXT_PLAIN_TYPE).build(); } catch (IOException e) { - logger.warn("Could not find file from DataResource [{}]. Root cause: [{}]", hint, + logger.warn("Error while handling file from DataResource [{}]. Root cause: [{}]", hint, ExceptionUtils.getRootCauseMessage(e)); return Response.status(Response.Status.NOT_FOUND).build(); } catch (Exception e) { diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java index 3c4bd666..a14d7558 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java @@ -195,7 +195,7 @@ void getDataAsJsonIdentifyDBFileNotFound() throws Exception json.put("xwikiCfgPath", cfgFolderPath); assertEquals(json, configurationDataProvider.getDataAsJSON()); - verify(this.logger).warn("Failed to open database configuration file. Root cause is: [{}]", + verify(this.logger).warn("Error while handling database configuration file. Root cause is: [{}]", "FileNotFoundException: " + cfgFolderPath + "hibernate.cfg.xml (No such file or directory)"); configDirectory.delete(); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java index bb0339e4..8d424e42 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java @@ -150,9 +150,26 @@ void getByteDataFileNotFound() Exception exception = assertThrows(Exception.class, () -> { configFileDataResource.getByteData(null); }); - assertEquals("Could not find xwiki.cfg file.", exception.getMessage()); - verify(logger).warn("Could not find xwiki.cfg file. Root cause is: [{}]", - "FileNotFoundException: " + cfgDir2.getAbsolutePath() + "/xwiki.cfg (No such file or directory)"); + assertEquals("Error while handling xwiki.cfg file.", exception.getMessage()); + } + + @Test + void getByteDataConfigError() throws Exception + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(configFileDataResource, "logger", this.logger); + + File propertiesDir2 = new File(tmpDir, "xwiki_properties_folder_fail"); + propertiesDir2.mkdir(); + propertiesDir2.deleteOnExit(); + + when(adminToolsConfiguration.getExcludedLines()).thenThrow(new RuntimeException("CONFIGURATION ERROR")); + Exception exception = assertThrows(Exception.class, () -> { + configFileDataResource.getByteData(null); + }); + assertEquals("Error while retrieving data from Admin Tools configuration.", exception.getMessage()); + verify(logger).warn("Error while retrieving data from Admin Tools configuration. Root cause is: [{}]", + "RuntimeException: CONFIGURATION ERROR"); } @Test @@ -171,8 +188,8 @@ void getByteDataServerNotFound() throws Exception Exception exception = assertThrows(Exception.class, () -> { configFileDataResource.getByteData(null); }); - assertEquals("Failed to get content of xwiki.cfg.", exception.getMessage()); - verify(logger).warn("Failed to get content of xwiki.cfg. Root cause is: [{}]", + assertEquals("Server not found.", exception.getMessage()); + verify(logger).warn("Server not found. Root cause is: [{}]", "NullPointerException: SERVER NOT FOUND"); } @@ -204,8 +221,6 @@ void addZipEntryGetByteFail() throws Exception configFileDataResource.addZipEntry(zipOutputStream, null); verify(zipOutputStream, never()).write(any(), eq(0), anyInt()); - verify(logger).warn("Could not find xwiki.cfg file. Root cause is: [{}]", - "FileNotFoundException: " + cfgDir2.getAbsolutePath() + "/xwiki.cfg (No such file or directory)"); verify(logger).warn("Could not add {} to the archive. Root cause is: [{}]", "xwiki.cfg", "FileNotFoundException: " + cfgDir2.getAbsolutePath() + "/xwiki.cfg (No such file or " + "directory)"); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java index 0d8b09e0..eceeb320 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java @@ -150,10 +150,7 @@ void getByteDataFileNotFound() Exception exception = assertThrows(Exception.class, () -> { propertiesFileDataResource.getByteData(null); }); - assertEquals("Could not find xwiki.properties file.", exception.getMessage()); - verify(logger).warn("Could not find xwiki.properties file. Root cause is: [{}]", - "FileNotFoundException: " + propertiesDir2.getAbsolutePath() + "/xwiki.properties (No such file or " - + "directory)"); + assertEquals("Error while handling xwiki.properties file.", exception.getMessage()); } @Test @@ -172,11 +169,30 @@ void getByteDataServerNotFound() throws Exception Exception exception = assertThrows(Exception.class, () -> { propertiesFileDataResource.getByteData(null); }); - assertEquals("Failed to get content of xwiki.properties.", exception.getMessage()); - verify(logger).warn("Failed to get content of xwiki.properties. Root cause is: [{}]", + assertEquals("Server not found.", exception.getMessage()); + verify(logger).warn("Server not found. Root cause is: [{}]", "NullPointerException: SERVER NOT FOUND"); } + @Test + void getByteDataConfigError() throws Exception + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(propertiesFileDataResource, "logger", this.logger); + + File propertiesDir2 = new File(tmpDir, "xwiki_properties_folder_fail"); + propertiesDir2.mkdir(); + propertiesDir2.deleteOnExit(); + + when(adminToolsConfiguration.getExcludedLines()).thenThrow(new RuntimeException("CONFIGURATION ERROR")); + Exception exception = assertThrows(Exception.class, () -> { + propertiesFileDataResource.getByteData(null); + }); + assertEquals("Error while retrieving data from Admin Tools configuration.", exception.getMessage()); + verify(logger).warn("Error while retrieving data from Admin Tools configuration. Root cause is: [{}]", + "RuntimeException: CONFIGURATION ERROR"); + } + @Test void addZipEntry() throws Exception { @@ -205,9 +221,6 @@ void addZipEntryGetByteFail() throws Exception propertiesFileDataResource.addZipEntry(zipOutputStream, null); verify(zipOutputStream, never()).write(any(), eq(0), anyInt()); - verify(logger).warn("Could not find xwiki.properties file. Root cause is: [{}]", - "FileNotFoundException: " + propertiesDir2.getAbsolutePath() + "/xwiki.properties (No such file or " - + "directory)"); verify(logger).warn("Could not add {} to the archive. Root cause is: [{}]", "xwiki.properties", "FileNotFoundException: " + propertiesDir2.getAbsolutePath() + "/xwiki.properties (No such file or " + "directory)"); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java index 0a82f2fb..21d21ab7 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java @@ -120,7 +120,7 @@ void getFileNotFound() throws Exception when(importantFilesManager.getFile("resource_hint", null)).thenThrow(new IOException("FILE NOT FOUND")); assertEquals(404, defaultAdminToolsResource.getFile("resource_hint").getStatus()); - verify(logger).warn("Could not find file from DataResource [{}]. Root cause: [{}]", "resource_hint", + verify(logger).warn("Error while handling file from DataResource [{}]. Root cause: [{}]", "resource_hint", "IOException: FILE NOT FOUND"); } From 0eec0f86ff8ddc57090396368f7563035b9396a7 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Fri, 27 Oct 2023 15:25:18 +0300 Subject: [PATCH 53/72] Add support for downloading important files #8 * Modified exception handling * Added comments --- .../com/xwiki/admintools/DataProvider.java | 2 +- .../admintools/download/DataResource.java | 6 ++-- .../DefaultAdminToolsConfiguration.java | 14 ++------ .../data/ConfigurationDataProvider.java | 5 ++- .../internal/data/SecurityDataProvider.java | 4 +-- .../resources/DataProvidersDataResource.java | 4 +-- .../files/resources/LogsDataResource.java | 28 ++++++++-------- .../XWikiConfigFileDataResource.java | 18 +++++------ .../XWikiPropertiesFileDataResource.java | 22 ++++++------- .../DefaultAdminToolsConfigurationTest.java | 15 +++++---- .../data/ConfigurationDataProviderTest.java | 12 ++++--- .../data/SecurityDataProviderTest.java | 2 +- .../DataProvidersDataResourceTest.java | 4 --- .../files/resources/LogsDataResourceTest.java | 16 ++-------- .../XWikiConfigFileDataResourceTest.java | 26 ++------------- .../XWikiPropertiesFileDataResourceTest.java | 32 +++---------------- 16 files changed, 72 insertions(+), 138 deletions(-) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java index 6c23d141..75e39d6f 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java @@ -50,7 +50,7 @@ public interface DataProvider * Provides the info structured in a json. * * @return a {@link Map} with the generated info. - * @throws Exception + * @throws Exception if there are any errors while gathering the needed data. */ Map getDataAsJSON() throws Exception; } diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java b/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java index 79531837..84dfc5fb 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java @@ -39,16 +39,16 @@ public interface DataResource * * @param zipOutputStream {@link ZipOutputStream} represents the zip archive in which the entry is written. * @param filters store filters that can be used for file selection. - * @throws IOException */ - void addZipEntry(ZipOutputStream zipOutputStream, Map filters) throws Exception; + void addZipEntry(ZipOutputStream zipOutputStream, Map filters); /** * Retrieve the content of a system file. * * @param input Can be used to send additional info to the component. * @return the content of the file as an {@link Byte} array. - * @throws IOException + * @throws IOException when there are errors while handling searched files. + * @throws NumberFormatException when there is an invalid numeric input. */ byte[] getByteData(String input) throws Exception; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java index 7bf4235e..19b9cdea 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java @@ -54,21 +54,13 @@ public class DefaultAdminToolsConfiguration implements AdminToolsConfiguration @Override public String getServerPath() { - return this.getProperty(SERVER_LOCATION, ""); + return this.mainConfiguration.getProperty(SERVER_LOCATION, ""); } @Override public List getExcludedLines() { - return new ArrayList<>(List.of(this.getProperty(EXCLUDED_LINES, "NO_EXCLUDED_LINE").split(","))); - } - - private T getProperty(String key, T defaultValue) - { - T value = this.mainConfiguration.getProperty(key, defaultValue); - if (value == null) { - throw new RuntimeException(String.format("The %s is missing.", key)); - } - return value; + return new ArrayList<>( + List.of(this.mainConfiguration.getProperty(EXCLUDED_LINES, "NO_EXCLUDED_LINE").split(","))); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index 79cc22c3..1a69d06c 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -94,6 +94,8 @@ public Map getDataAsJSON() throws Exception systemInfo.putAll(this.getOSInfo()); return systemInfo; } catch (Exception e) { + logger.warn("Failed to generate the instance configuration data. Root cause is: [{}]", + ExceptionUtils.getRootCauseMessage(e)); throw new Exception("Failed to generate the instance configuration data.", e); } } @@ -137,8 +139,6 @@ private String identifyDB() if (usedDB == null) { this.logger.warn("Failed to find database. Used database may not be supported!"); } - } catch (NullPointerException e) { - throw new NullPointerException("Failed to identify used Database."); } catch (IOException exception) { this.logger.warn("Error while handling database configuration file. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(exception)); @@ -166,7 +166,6 @@ private ServerIdentifier getCurrentServer() { ServerIdentifier serverIdentifier = currentServer.getCurrentServer(); if (serverIdentifier == null) { - logger.warn("Failed to retrieve used server. Server not found."); throw new NullPointerException("Failed to retrieve the used server. Server not found."); } return serverIdentifier; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java index b6565599..14ace7d5 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java @@ -88,6 +88,8 @@ public Map getDataAsJSON() throws Exception securityDetails.put("fileEncoding", System.getProperty("file.encoding")); return securityDetails; } catch (Exception e) { + logger.warn("Failed to generate the instance security data. Root cause is: [{}]", + ExceptionUtils.getRootCauseMessage(e)); throw new Exception("Failed to generate the instance security data.", e); } } @@ -107,8 +109,6 @@ private Map getXwikiSecurityInfo() throws Exception results.put("configurationEncoding", this.configurationSource.getProperty("xwiki.encoding", String.class)); return results; } catch (Exception e) { - this.logger.warn("Failed to generate xwiki security info. Root cause is: [{}]", - ExceptionUtils.getRootCauseMessage(e)); throw new Exception("Failed to generate xwiki security info.", e); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java index e3a174a3..386fa761 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java @@ -19,7 +19,6 @@ */ package com.xwiki.admintools.internal.files.resources; -import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -61,7 +60,7 @@ public class DataProvidersDataResource implements DataResource private Logger logger; @Override - public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) throws IOException + public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) { addZipEntry(zipOutputStream); } @@ -76,7 +75,6 @@ public byte[] getByteData(String input) throws Exception } catch (Exception e) { String errMessage = String.format("Error getting json from DataProvider %s.", dataProvider.getIdentifier()); - logger.warn(errMessage + " Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); throw new Exception(errMessage, e); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java index 5411cec2..77ce7457 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java @@ -46,6 +46,7 @@ import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiContext; +import com.xwiki.admintools.ServerIdentifier; import com.xwiki.admintools.download.DataResource; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; @@ -89,10 +90,15 @@ public String getIdentifier() } @Override - public byte[] getByteData(String input) throws Exception + public byte[] getByteData(String input) throws IOException, NumberFormatException { try { - File file = new File(currentServer.getCurrentServer().getLastLogFilePath()); + // verify if null and throw if it is + ServerIdentifier usedServer = currentServer.getCurrentServer(); + if (usedServer == null) { + throw new NullPointerException("Server not found! Configure path in extension configuration."); + } + File file = new File(usedServer.getLastLogFilePath()); try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) { int lines = parseInt(input); @@ -104,6 +110,7 @@ public byte[] getByteData(String input) throws Exception long startPosition = fileLength - 1; for (long i = 0; i < lines && startPosition > 0 && i < 50000; startPosition--) { randomAccessFile.seek(startPosition - 1); + int currentByte = randomAccessFile.read(); if (currentByte == '\n' || currentByte == '\r') { // Found a newline character, add the line to the list. @@ -117,14 +124,11 @@ public byte[] getByteData(String input) throws Exception return String.join("\n", logLines).getBytes(); } } catch (IOException exception) { - String errMessage = - String.format("Could not find log files at %s.", currentServer.getCurrentServer().getLastLogFilePath()); - logger.warn(errMessage + ERROR_SOURCE, ExceptionUtils.getRootCauseMessage(exception)); + String errMessage = String.format("Error while accessing log files at %s.", + currentServer.getCurrentServer().getLastLogFilePath()); throw new IOException(errMessage, exception); - } catch (RuntimeException exception) { - String errMessage = "Failed to retrieve logs."; - logger.warn(errMessage + ERROR_SOURCE, ExceptionUtils.getRootCauseMessage(exception)); - throw new RuntimeException(errMessage, exception); + } catch (NumberFormatException exception) { + throw new NumberFormatException(String.format("Input [%s] is not a valid number!", input)); } } @@ -139,10 +143,8 @@ public void addZipEntry(ZipOutputStream zipOutputStream, Map fil for (File file : listOfFiles != null ? listOfFiles : new File[0]) { // Check if the selected file is of file type and check filters. if (file.isFile()) { - if (filters != null) { - if (!checkFilters(file, filters)) { - continue; - } + if (filters != null && (!checkFilters(file, filters))) { + continue; } // Create a new zip entry and add the content. try (FileInputStream fileInputStream = new FileInputStream(file)) { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java index 45da0dfe..93aa7164 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java @@ -36,6 +36,7 @@ import org.slf4j.Logger; import org.xwiki.component.annotation.Component; +import com.xwiki.admintools.ServerIdentifier; import com.xwiki.admintools.configuration.AdminToolsConfiguration; import com.xwiki.admintools.download.DataResource; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; @@ -71,17 +72,21 @@ public class XWikiConfigFileDataResource implements DataResource private Logger logger; @Override - public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) throws Exception + public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) { addZipEntry(zipOutputStream); } @Override - public byte[] getByteData(String input) throws Exception + public byte[] getByteData(String input) throws IOException { try { + ServerIdentifier usedServer = currentServer.getCurrentServer(); + if (usedServer == null) { + throw new NullPointerException("Server not found! Configure path in extension configuration."); + } List excludedLinesHints = adminToolsConfig.getExcludedLines(); - String filePath = currentServer.getCurrentServer().getXwikiCfgFolderPath() + XWIKI_CFG; + String filePath = usedServer.getXwikiCfgFolderPath() + XWIKI_CFG; File inputFile = new File(filePath); try (BufferedReader reader = new BufferedReader(new FileReader(inputFile))) { StringBuilder stringBuilder = new StringBuilder(); @@ -100,13 +105,6 @@ public byte[] getByteData(String input) throws Exception } } catch (IOException exception) { throw new IOException(String.format("Error while handling %s file.", XWIKI_CFG), exception); - } catch (NullPointerException e) { - logger.warn("Server not found. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); - throw new NullPointerException("Server not found."); - } catch (RuntimeException e) { - String errMessage = "Error while retrieving data from Admin Tools configuration."; - logger.warn(errMessage + ERROR_SOURCE, ExceptionUtils.getRootCauseMessage(e)); - throw new RuntimeException(errMessage, e); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java index bab2dd81..5204758d 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java @@ -36,6 +36,7 @@ import org.slf4j.Logger; import org.xwiki.component.annotation.Component; +import com.xwiki.admintools.ServerIdentifier; import com.xwiki.admintools.configuration.AdminToolsConfiguration; import com.xwiki.admintools.download.DataResource; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; @@ -58,7 +59,7 @@ public class XWikiPropertiesFileDataResource implements DataResource private static final String XWIKI_PROPERTIES = "xwiki.properties"; - private static final String ERROR_SOURCE = " Root cause is: [{}]"; + private static final String ERROR_SOURCE = " "; @Inject @Named("default") @@ -71,17 +72,21 @@ public class XWikiPropertiesFileDataResource implements DataResource private Logger logger; @Override - public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) throws IOException + public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) { addZipEntry(zipOutputStream); } @Override - public byte[] getByteData(String input) throws Exception + public byte[] getByteData(String input) throws IOException { try { + ServerIdentifier usedServer = currentServer.getCurrentServer(); + if (usedServer == null) { + throw new NullPointerException("Server not found! Configure path in extension configuration."); + } List excludedLinesHints = adminToolsConfig.getExcludedLines(); - String filePath = currentServer.getCurrentServer().getXwikiCfgFolderPath() + XWIKI_PROPERTIES; + String filePath = usedServer.getXwikiCfgFolderPath() + XWIKI_PROPERTIES; File inputFile = new File(filePath); try (BufferedReader reader = new BufferedReader(new FileReader(inputFile))) { StringBuilder stringBuilder = new StringBuilder(); @@ -99,13 +104,6 @@ public byte[] getByteData(String input) throws Exception } } catch (IOException exception) { throw new IOException(String.format("Error while handling %s file.", XWIKI_PROPERTIES), exception); - } catch (NullPointerException e) { - logger.warn("Server not found. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(e)); - throw new NullPointerException("Server not found."); - } catch (RuntimeException e) { - String errMessage = "Error while retrieving data from Admin Tools configuration."; - logger.warn(errMessage + ERROR_SOURCE, ExceptionUtils.getRootCauseMessage(e)); - throw new RuntimeException(errMessage, e); } } @@ -124,7 +122,7 @@ private void addZipEntry(ZipOutputStream zipOutputStream) zipOutputStream.write(buffer, 0, buffer.length); zipOutputStream.closeEntry(); } catch (Exception exception) { - logger.warn("Could not add {} to the archive." + ERROR_SOURCE, XWIKI_PROPERTIES, + logger.error("Could not add [{}] to the archive. Root cause is: [{}]", XWIKI_PROPERTIES, ExceptionUtils.getRootCauseMessage(exception)); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfigurationTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfigurationTest.java index c7e6a092..69ce6cab 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfigurationTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfigurationTest.java @@ -19,6 +19,8 @@ */ package com.xwiki.admintools.internal.configuration; +import java.util.List; + import javax.inject.Named; import org.junit.jupiter.api.Test; @@ -27,8 +29,8 @@ import org.xwiki.test.junit5.mockito.InjectMockComponents; import org.xwiki.test.junit5.mockito.MockComponent; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; /** @@ -43,7 +45,7 @@ public class DefaultAdminToolsConfigurationTest private DefaultAdminToolsConfiguration defaultAdminToolsConfiguration; @MockComponent - @Named("admintools.configuration.current") + @Named(AdminToolsConfigurationSource.HINT) private ConfigurationSource adminToolsConfigurationSource; @Test @@ -54,11 +56,10 @@ void getServerPath() } @Test - void getServerPathMissingValue() + void getExcludedLines() { - RuntimeException exception = assertThrows(RuntimeException.class, () -> { - this.defaultAdminToolsConfiguration.getServerPath(); - }); - assertEquals("The serverLocation is missing.", exception.getMessage()); + when(this.adminToolsConfigurationSource.getProperty("excludedLines", "NO_EXCLUDED_LINE")).thenReturn( + "excluded_line"); + assertEquals(List.of("excluded_line".split(",")), this.defaultAdminToolsConfiguration.getExcludedLines()); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java index a14d7558..977af58f 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java @@ -211,7 +211,8 @@ void getDataAsJsonIdentifyDBCurrentServerNotFound() this.configurationDataProvider.getDataAsJSON(); }); assertEquals("Failed to generate the instance configuration data.", exception.getMessage()); - verify(this.logger).warn("Failed to retrieve used server. Server not found."); + verify(this.logger).warn("Failed to generate the instance configuration data. Root cause is: [{}]", + "NullPointerException: Failed to retrieve the used server. Server not found."); } @Test @@ -264,7 +265,8 @@ void getDataAsJsonWithErrorExecution() this.configurationDataProvider.getDataAsJSON(); }); assertEquals("Failed to generate the instance configuration data.", exception.getMessage()); - verify(this.logger).warn("Failed to retrieve used server. Server not found."); + verify(this.logger).warn("Failed to generate the instance configuration data. Root cause is: [{}]", + "NullPointerException: Failed to retrieve the used server. Server not found."); } @Test @@ -364,7 +366,8 @@ void getRenderedDataWithFailedJsonGenerate() throws Exception assertEquals("success", configurationDataProvider.getRenderedData()); assertThrows(Exception.class, () -> configurationDataProvider.getDataAsJSON()); - verify(this.logger, times(2)).warn("Failed to retrieve used server. Server not found."); + verify(this.logger, times(2)).warn("Failed to generate the instance configuration data. Root cause is: [{}]", + "NullPointerException: Failed to retrieve the used server. Server not found."); verify(scriptContext).setAttribute(ConfigurationDataProvider.HINT, json, ScriptContext.ENGINE_SCOPE); } @@ -387,7 +390,8 @@ void getRenderedDataExecutionFail() throws Exception }); assertEquals("Failed to generate the instance configuration data.", exception.getMessage()); - verify(this.logger, times(2)).warn("Failed to retrieve used server. Server not found."); + verify(this.logger, times(2)).warn("Failed to generate the instance configuration data. Root cause is: [{}]", + "NullPointerException: Failed to retrieve the used server. Server not found."); verify(this.logger).warn("Failed to render custom template. Root cause is: [{}]", "Exception: Render failed."); verify(scriptContext).setAttribute(ConfigurationDataProvider.HINT, json, ScriptContext.ENGINE_SCOPE); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/SecurityDataProviderTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/SecurityDataProviderTest.java index 7cb237e6..2a969f18 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/SecurityDataProviderTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/SecurityDataProviderTest.java @@ -198,7 +198,7 @@ void getRenderedDataWithRenderingError() throws Exception // Verify the result and method invocations. assertEquals(null, securityDataProvider.getRenderedData()); - verify(this.logger).warn("Failed to generate xwiki security info. Root cause is: [{}]", + verify(this.logger).warn("Failed to generate the instance security data. Root cause is: [{}]", "NullPointerException: ConfigurationSourceNotFound"); verify(this.logger).warn("Failed to render custom template. Root cause is: [{}]", "Exception: Render failed."); verify(scriptContext).setAttribute(SecurityDataProvider.HINT, json, ScriptContext.ENGINE_SCOPE); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java index a364f708..e07fe0a5 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java @@ -108,8 +108,6 @@ void getByteDataThrowError() throws Exception this.dataProviderResource.getByteData(null); }); assertEquals("Error getting json from DataProvider data_provider_identifier.", exception.getMessage()); - verify(logger).warn("Error getting json from DataProvider data_provider_identifier. Root cause is: [{}]", - "Exception: TEST - PROVIDER ERROR AT GET DATA AS JASON!"); } @Test @@ -137,8 +135,6 @@ void addZipEntryGetByteDataError() throws Exception when(dataProvider.getDataAsJSON()).thenThrow(new Exception("ERROR AT GET DATA AS JASON.")); dataProviderResource.addZipEntry(zipOutputStream, null); - verify(logger).warn("Error getting json from DataProvider data_provider_identifier. Root cause is: [{}]", - "Exception: ERROR AT GET DATA AS JASON."); verify(zipOutputStream, never()).write(any(), eq(0), eq(0)); verify(logger).warn("Could not add gathered configuration to the archive. Root cause is: {}", "Exception: ERROR AT GET DATA AS JASON."); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java index 9291c500..a5d6c7fb 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java @@ -170,11 +170,8 @@ void getByteDataFileNotFound() IOException exception = assertThrows(IOException.class, () -> { logsDataResource.getByteData(null); }); - assertEquals(String.format("Could not find log files at %s.", testFile.getAbsolutePath()), + assertEquals(String.format("Error while accessing log files at %s.", testFile.getAbsolutePath()), exception.getMessage()); - verify(logger).warn( - String.format("Could not find log files at %s. Root cause is: [{}]", testFile.getAbsolutePath()), - String.format("FileNotFoundException: %s (No such file or directory)", testFile.getAbsolutePath())); } @Test @@ -183,15 +180,11 @@ void getByteDataServerNotFound() when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(logsDataResource, "logger", this.logger); - when(currentServer.getCurrentServer()).thenReturn(serverIdentifier); - when(serverIdentifier.getLastLogFilePath()).thenThrow(new NullPointerException("SERVER NOT FOUND")); Exception exception = assertThrows(Exception.class, () -> { this.logsDataResource.getByteData("44"); }); - assertEquals(String.format("Failed to retrieve logs.", logsDir.getAbsolutePath()), + assertEquals("Server not found! Configure path in extension configuration.", exception.getMessage()); - verify(logger).warn(String.format("Failed to retrieve logs. Root cause is: [{}]", logsDir.getAbsolutePath()), - String.format("NullPointerException: SERVER NOT FOUND", logsDir.getAbsolutePath())); logsDir.delete(); } @@ -206,10 +199,7 @@ void getByteDataIncorrectInput() Exception exception = assertThrows(Exception.class, () -> { logsDataResource.getByteData("not a number"); }); - assertEquals("Failed to retrieve logs.", exception.getMessage()); - - verify(logger).warn("Failed to retrieve logs. Root cause is: [{}]", - "NumberFormatException: For input string: " + "\"not a number\""); + assertEquals("Input [not a number] is not a valid number!", exception.getMessage()); } @Test diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java index 8d424e42..acb18bcc 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java @@ -153,25 +153,6 @@ void getByteDataFileNotFound() assertEquals("Error while handling xwiki.cfg file.", exception.getMessage()); } - @Test - void getByteDataConfigError() throws Exception - { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(configFileDataResource, "logger", this.logger); - - File propertiesDir2 = new File(tmpDir, "xwiki_properties_folder_fail"); - propertiesDir2.mkdir(); - propertiesDir2.deleteOnExit(); - - when(adminToolsConfiguration.getExcludedLines()).thenThrow(new RuntimeException("CONFIGURATION ERROR")); - Exception exception = assertThrows(Exception.class, () -> { - configFileDataResource.getByteData(null); - }); - assertEquals("Error while retrieving data from Admin Tools configuration.", exception.getMessage()); - verify(logger).warn("Error while retrieving data from Admin Tools configuration. Root cause is: [{}]", - "RuntimeException: CONFIGURATION ERROR"); - } - @Test void getByteDataServerNotFound() throws Exception { @@ -183,14 +164,11 @@ void getByteDataServerNotFound() throws Exception cfgDir2.deleteOnExit(); when(adminToolsConfiguration.getExcludedLines()).thenReturn(excludedLines); - when(currentServer.getCurrentServer()).thenReturn(serverIdentifier); - when(serverIdentifier.getXwikiCfgFolderPath()).thenThrow(new NullPointerException("SERVER NOT FOUND")); + when(currentServer.getCurrentServer()).thenReturn(null); Exception exception = assertThrows(Exception.class, () -> { configFileDataResource.getByteData(null); }); - assertEquals("Server not found.", exception.getMessage()); - verify(logger).warn("Server not found. Root cause is: [{}]", - "NullPointerException: SERVER NOT FOUND"); + assertEquals("Server not found! Configure path in extension configuration.", exception.getMessage()); } @Test diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java index eceeb320..f5c2bf68 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java @@ -164,33 +164,11 @@ void getByteDataServerNotFound() throws Exception propertiesDir2.deleteOnExit(); when(adminToolsConfiguration.getExcludedLines()).thenReturn(excludedLines); - when(currentServer.getCurrentServer()).thenReturn(serverIdentifier); - when(serverIdentifier.getXwikiCfgFolderPath()).thenThrow(new NullPointerException("SERVER NOT FOUND")); - Exception exception = assertThrows(Exception.class, () -> { - propertiesFileDataResource.getByteData(null); - }); - assertEquals("Server not found.", exception.getMessage()); - verify(logger).warn("Server not found. Root cause is: [{}]", - "NullPointerException: SERVER NOT FOUND"); - } - - @Test - void getByteDataConfigError() throws Exception - { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(propertiesFileDataResource, "logger", this.logger); - - File propertiesDir2 = new File(tmpDir, "xwiki_properties_folder_fail"); - propertiesDir2.mkdir(); - propertiesDir2.deleteOnExit(); - - when(adminToolsConfiguration.getExcludedLines()).thenThrow(new RuntimeException("CONFIGURATION ERROR")); + when(currentServer.getCurrentServer()).thenReturn(null); Exception exception = assertThrows(Exception.class, () -> { propertiesFileDataResource.getByteData(null); }); - assertEquals("Error while retrieving data from Admin Tools configuration.", exception.getMessage()); - verify(logger).warn("Error while retrieving data from Admin Tools configuration. Root cause is: [{}]", - "RuntimeException: CONFIGURATION ERROR"); + assertEquals("Server not found! Configure path in extension configuration.", exception.getMessage()); } @Test @@ -221,9 +199,9 @@ void addZipEntryGetByteFail() throws Exception propertiesFileDataResource.addZipEntry(zipOutputStream, null); verify(zipOutputStream, never()).write(any(), eq(0), anyInt()); - verify(logger).warn("Could not add {} to the archive. Root cause is: [{}]", "xwiki.properties", - "FileNotFoundException: " + propertiesDir2.getAbsolutePath() + "/xwiki.properties (No such file or " - + "directory)"); + verify(logger).error("Could not add [{}] to the archive. Root cause is: [{}]", "xwiki.properties", + "FileNotFoundException: " + propertiesDir2.getAbsolutePath() + + "/xwiki.properties (No such file or directory)"); } private byte[] readLines() throws IOException From 65dd92cc43724256416485d5d8909fa9506c057a Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Mon, 30 Oct 2023 11:39:24 +0200 Subject: [PATCH 54/72] Create a health check dashboard section #13 draft * Created a page to run the job * Created a page to access job progress * Created a page to display useful links * Modified jobFinishedMessage macro to adapt to healthCheck messages style * Created JS for handling job start request, page refresh, job restart and status display on refresh when the job is finnished * Created dashboard item to display job progress, log, start button and link to help page. --- .../AdminTools/Code/AdminToolsJS.xml | 140 +++++++++++++----- .../AdminTools/Code/HealthCheckJob.xml | 60 ++++++++ .../AdminTools/Code/HealthCheckResources.xml | 64 ++++++++ .../main/resources/AdminTools/Code/Macros.xml | 25 ++++ .../main/resources/AdminTools/HelpLinks.xml | 113 ++++++++++++++ .../src/main/resources/AdminTools/WebHome.xml | 129 +++++++++++++++- 6 files changed, 493 insertions(+), 38 deletions(-) create mode 100644 application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml create mode 100644 application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml create mode 100644 application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index 5caac115..43d22763 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -124,43 +124,113 @@ require(['jquery'], function($) { - $(document).on('click', '#downloadFilesModal .btn-primary', function(event) { - event.preventDefault(); - const downloadForm = $('#downloadFilesModal form'); - - // Simulate a click on a link to initialize the download. - const link = document.createElement('a'); - link.href = downloadForm.attr('action') + '?' + downloadForm.serialize(); - link.click(); - }); - - $(document).on('click', '#filesViewLastNLinesModal .btn-primary, #configurationViewLastNLinesModal .btn-primary', - function(event) { - event.preventDefault(); - const modal = $(event.currentTarget).closest('.modal'); - const downloadForm = modal.find('form'); - let noLines = modal.find("input[name='noLines']").val(); - - // If the input is empty, the default value of 1000 will be requested. - if (noLines == '') { - noLines = '1000'; - } - - // Simulate a click on a link to request the last 'noLines' logs. - const link = document.createElement('a'); - link.href = downloadForm.attr('action') + '?noLines=' + noLines; - link.target='_blank'; - link.click(); - }); - - $(document).on('change', '#downloadFilesModal input[name="files"][value="logsDataResource"]', function() { - if ($(this).is(':checked')) { + $(document).ready(function(){ + if ($('#healthCheck').length) { + let jobState = $('input[name="jobState"]').val(); + if (jobState == "RUNNING") { + let documentReference = XWiki.Model.resolve('wiki:AdminTools.Code.HealthCheckResources', XWiki.EntityType.DOCUMENT); + const resourcesUrl = new XWiki.Document(documentReference).getURL('get'); + $.get(resourcesUrl, function(data) { + let jobMinJsURL = $(data).find('input[name="jobMinJsURL"]').val(); + require.config({ + paths: { + 'health-check-job': $('#healthCheckResources input[name="jobMinJsURL"]').val() + } + }); + require(['health-check-job'], function(){}); + // Inject the content into the job-status div + let healthCheckJobStatusURL = $(data).find('input[name="healthCheckJobStatusURL"]').val(); + $('.job-status').attr('data-url', healthCheckJobStatusURL); + $('#admin_tools_job_start').prop("disabled", true); + }); + } + else { + $('.job-status').show(); + } + } + }); + + $(document).on('click', '#admin_tools_job_start', function(event) { + event.preventDefault(); + require.undef('health-check-job'); + $(".log").empty(); + $('#admin_tools_job_start').prop("disabled", true); + let documentReference = XWiki.Model.resolve('wiki:AdminTools.Code.HealthCheckResources', XWiki.EntityType.DOCUMENT); + const resourcesUrl = new XWiki.Document(documentReference).getURL('get'); + $.get(resourcesUrl, function(data) { + let progressBar = $(data).find('div.ui-progress'); + $('#healthCheck .successmessage').replaceWith(progressBar) + $('#healthCheck .warningmessage').replaceWith(progressBar) + $('#healthCheck .errormessage').replaceWith(progressBar) + + let jobMinJsURL = $(data).find('input[name="jobMinJsURL"]').val(); + require.config({ + paths: { + 'health-check-job': jobMinJsURL + } + }); + require(['health-check-job'], function(){}); + // Inject the content into the job-status div + let healthCheckJobStatusURL = $(data).find('input[name="healthCheckJobStatusURL"]').val(); + + $('.job-status').attr('data-url', healthCheckJobStatusURL); + + // Function to poll job status + function pollJobStatus() { + $.get(healthCheckJobStatusURL, function(jobStatus) { + //console.log(jobStatus); + if (jobStatus.state === 'FINISHED') { + $('#admin_tools_job_start').prop("disabled", false); + //console.log('Job finished!'); + } else { + // If the job is not done, continue polling + setTimeout(pollJobStatus, 1000); // Poll every second + } + }); + } + // Start polling + pollJobStatus(); + }); + $('.job-status').show(); + }); + + $(document).on('click', '#downloadFilesModal .btn-primary', function(event) { + event.preventDefault(); + const downloadForm = $('#downloadFilesModal form'); + + // Simulate a click on a link to initialize the download. + const link = document.createElement('a'); + link.href = downloadForm.attr('action') + '?' + downloadForm.serialize(); + link.click(); + }); + + $(document).on('click', '#filesViewLastNLinesModal .btn-primary, #configurationViewLastNLinesModal .btn-primary', + function(event) { + event.preventDefault(); + const modal = $(event.currentTarget).closest('.modal'); + const downloadForm = modal.find('form'); + let noLines = modal.find("input[name='noLines']").val(); + + // If the input is empty, the default value of 1000 will be requested. + if (noLines == '') { + noLines = '1000'; + } + + // Simulate a click on a link to request the last 'noLines' logs. + const link = document.createElement('a'); + link.href = downloadForm.attr('action') + '?noLines=' + noLines; + link.target='_blank'; + link.click(); + }); + + $(document).on('change', '#downloadFilesModal input[name="files"][value="logsDataResource"]', function() { + if ($(this).is(':checked')) { $('#downloadFilesModal .dateFields').show(); - } else { + } else { $('#downloadFilesModal .dateFields').hide(); - } - }); -}); + } + }); + }); AdminToolsJavaScript diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml new file mode 100644 index 00000000..189f133d --- /dev/null +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml @@ -0,0 +1,60 @@ + + + + AdminTools.Code + HealthCheckJob + + + 0 + xwiki:XWiki.Admin + AdminTools.WebHome + xwiki:XWiki.Admin + xwiki:XWiki.Admin + 1.1 + HealthCheckJob + + false + xwiki/2.1 + true + {{velocity}} +#template('job_macros.vm') +#includeMacros("AdminTools.Code.Macros") + +#set($jobId = $request.getParameterValues('jobId')) +#set($translationPrefix = $request.getParameter('translationPrefix')) +#set($jobStatus = $services.job.getJobStatus($jobId)) + +#if ($jobStatus) + #outputJobStatusJSON($jobStatus, $translationPrefix) +#else + $response.setStatus(404) + + {{html}} + <div class="box errormessage"> + $services.localization.render("${translationPrefix}.notFound") + </div> +{{/html}} + +#end +{{/velocity}} + + + \ No newline at end of file diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml new file mode 100644 index 00000000..17d2e48c --- /dev/null +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml @@ -0,0 +1,64 @@ + + + + AdminTools.Code + HealthCheckResources + + + 0 + xwiki:XWiki.Admin + Main.WebHome + xwiki:XWiki.Admin + xwiki:XWiki.Admin + 1.1 + HealthCheckResources + + false + xwiki/2.1 + true + {{template name="job_macros.vm"/}} + +{{velocity}} +#set ($adminToolsHealthJob = $services.admintools.runHealthChecks($services.wiki.getCurrentWikiId())) +#set ($healthJobStatusURL = $xwiki.getURL('AdminTools.Code.HealthCheckJob', 'get', $escapetool.url({ + 'jobId': $adminToolsHealthJob.request.id, + 'outputSyntax': 'plain' +}))) +#set($jobMinJsURL = $xwiki.getSkinFile('uicomponents/job/job.min.js')) +{{html clean=false}} +<div hidden> + <input type="text" name="healthCheckJobStatusURL" value=$healthJobStatusURL></input> + <input type="text" name="jobMinJsURL" value=$jobMinJsURL></input> + + <div class="ui-progress"> + <div class="box info hidden" id="state-none-hint"> + This job is waiting to start, please be patient: another job might be running on the same pages. + </div> + <div class="ui-progress-background"> + <div class="ui-progress-bar green" style="width:0%"></div> + </div> + </div> +</div> +{{/html}} + +{{/velocity}} + + \ No newline at end of file diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml index 55f37973..96040930 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml @@ -75,6 +75,7 @@ </div> {{/html}} #end + #macro (downloadArchiveModal) {{html clean='false'}} @@ -156,5 +157,29 @@ </div> {{/html}} #end + +#macro (jobFinishedMessage $status $translationPrefix $successKey $errorKey $canceledKey $warningKey) + #if ($status.error) + #set($messageKeys = [$errorKey, "${translationPrefix}.finish.error", "job.status.${status.jobType}.error", 'job.status.error']) + #set($healthCheckReportMessage = $services.localization.render($messageKeys)) + #set($messageClass = 'errormessage') + #elseif ($status.canceled) + #set($messageKeys = [$canceledKey, "${translationPrefix}.finish.canceled", "job.status.${status.jobType}.canceled", 'job.status.canceled']) + #set($healthCheckReportMessage = $services.localization.render($messageKeys)) + #set($messageClass = 'warningmessage') + #elseif ($status.logTail.hasLogLevel('error')) + #set($healthCheckReportMessage = 'Critical issues were found, please consult the log!') + #set($messageClass = 'errormessage') + #elseif ($status.logTail.hasLogLevel('warn')) + #set($healthCheckReportMessage = 'Some issues have been found, for more details please see the log.') + #set($messageClass = 'warningmessage') + #else + #set($healthCheckReportMessage = 'No issue found!') + #set($messageClass = 'successmessage') + #end + <div class="box $messageClass"> + $healthCheckReportMessage + </div> +#end {{/velocity}} \ No newline at end of file diff --git a/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml b/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml new file mode 100644 index 00000000..325923f9 --- /dev/null +++ b/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml @@ -0,0 +1,113 @@ + + + + AdminTools + HelpLinks + + + 0 + xwiki:XWiki.Admin + AdminTools.WebHome + xwiki:XWiki.Admin + xwiki:XWiki.Admin + 1.1 + Help links + + false + xwiki/2.1 + true + {{box cssClass="floatinginfobox" title="**Contents**"}} +{{toc/}} +{{/box}} + +{{velocity}} + += Performance issues = + +{{html}} + <ul> + <li><a href="https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HSizing" target="_blank"> + Hardware requirements</a></li> + <li><a href="https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HMemory" target="_blank"> + Memory recommendations</a></li> + <li><a href="https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HDocumentCache" + target="_blank">Cache recommendations</a></li> + </ul> +{{/html}} + += Server issues = + +{{html}} + <ul> + <li><a href="https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/ServletContainerSupportStrategy/" + target="_blank">Supported servers</a></li> + <li><a + href="https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationTomcat/#HRecommendations" + target="_blank">Tomcat recommendations</a></li> + </ul> +{{/html}} + += Database issues = + +{{html}} + <ul> + <li> + <a href="https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/DatabaseSupportStrategy" target="_blank"> + Supported databases</a> + </li> + <li><a href= + "https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/#HSpecificdatabasesinstructions" + target="_blank">Specific databases instructions</a></li> + <li><a href= + "https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationMySQL/#HInstallationSteps" + target="_blank">MySQL installation guide</a></li> + <li><a href= + "https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationMySQL/#HTroubleshooting" + target="_blank">MySQL troubleshoot</a></li> + </ul> +{{/html}} + += Other issues = +== Java == + +{{html}} + <ul> + <li><a href= + "https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationTomcat/#HGeneralMemorySettings" + target="_blank">Java memory</a></li> + <li><a + href="https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/JavaSupportStrategy/" target="_blank"> + Java support</a></li> + </ul> +{{/html}} + +== Browser == + +{{html}} + <ul> + <li><a href="https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/BrowserSupportStrategy" target="_blank"> + Browser support</a></li> + </ul> +{{/html}} + +{{/velocity}} + + \ No newline at end of file diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index ae495942..fbe07648 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -29,7 +29,7 @@ xwiki:XWiki.Admin xwiki:XWiki.Admin 1.1 - AdminTools + Admin Tools false xwiki/2.1 @@ -87,7 +87,7 @@ - AdminToolsConfigEventListener + AdminToolsEventListener org.xwiki.observation.EventListener @@ -217,7 +217,8 @@ $services.admintools.getConfigurationData('configuration') {{velocity}} $services.admintools.getFilesSection() -{{/velocity}} +{{/velocity}} + 2, 1 @@ -226,6 +227,117 @@ $services.admintools.getFilesSection()
+ + AdminTools.WebHome + 3 + XWiki.GadgetClass + e26584bd-f916-43fd-b57c-4030ba639a9a + + XWiki.GadgetClass + + + + + + + + + 0 + --- + content + 2 + 0 + content + 5 + 40 + 0 + + + com.xpn.xwiki.objects.classes.TextAreaClass + + + 0 + position + 3 + 0 + position + 30 + 0 + + + com.xpn.xwiki.objects.classes.StringClass + + + <disabled>0</disabled> + <name>title</name> + <number>1</number> + <picker>0</picker> + <prettyName>title</prettyName> + <size>30</size> + <unmodifiable>0</unmodifiable> + <validationMessage/> + <validationRegExp/> + <classType>com.xpn.xwiki.objects.classes.StringClass</classType> + + + + {{template name="job_macros.vm"/}} + +{{velocity}} +#includeMacros("AdminTools.Code.Macros") +#set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) +#set ($jobId = ['adminTools', 'healthCheck', $services.wiki.getCurrentWikiId()]) +#set($healthJobStatus = $services.job.getJobStatus($jobId)) +#set($jobMinJsURL = $xwiki.getSkinFile('uicomponents/job/job.min.js')) + +{{html clean='false'}} +<div id="healthCheckResources" hidden> + <input type="text" name="jobMinJsURL" value=$jobMinJsURL></input> + <input type="text" name="jobState" value=$job.state></input> +</div> +<div class="adminToolsDashboardItem" id="healthCheck"> +<div class="healthCheckWrapper"> +<div class="healthCheckLastCheck"> + Time since the last health check: $services.date.displayTimeAgo($healthJobStatus.getEndDate()) +</div> + <a href="$xwiki.getURL("AdminTools.HelpLinks")"><strong>Useful links</strong></a> + <div class="buttonwrapper"> + <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" value="startHealthCheck">Start health check</button> + </div> +</div> + <div hidden class="xcontent job-status" data-url=""> + #set($titleKey = "${translationPrefix}.label") + #if ($services.localization.get($titleKey)) + <h2>$services.localization.render($titleKey)</h2> + #set($titleHintKey = "${translationPrefix}.hint") + #if ($services.localization.get($titleHintKey)) + <p class="text-muted small">$services.localization.render($titleHintKey)</p> + #end + #end + #if ($healthJobStatus.state != 'FINISHED') + #displayJobProgressBar($jobStatus) + #else + #jobFinishedMessage($healthJobStatus, $translationPrefix, $successKey, $errorKey, $canceledKey) + #end + #if ($showLogs || $isAdvancedUser || $isSuperAdmin) + #if ($healthJobStatus.state != 'FINISHED') + #displayJobStatusLog($jobStatus true) + #else + #displayJobStatusLog($healthJobStatus true) + #end + #end + </div> +</div> +{{/html}} +{{/velocity}} + + + 1, 2 + + + + + AdminTools.WebHome 0 @@ -355,6 +467,17 @@ $services.admintools.getFilesSection() .bootstrap-datetimepicker-widget { z-index: 99999 !important; +} + +.healthCheckWrapper { + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: 2rem; +} + +.healthCheckWrapper button { + margin-top: 2rem; } From 05ef0b5cc77222b7448e7ee625737ce4b0d41746 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Mon, 30 Oct 2023 20:33:21 +0200 Subject: [PATCH 55/72] Create a health check dashboard section #13 draft * Integrated JobRunner in JS * Refactored JS * Refactored HeallthCheck dashboard code * Refactored HealthCheckResources code --- .../health/checks/PerformanceHealthCheck.java | 25 +- .../ConfigurationDatabaseHealthCheck.java | 2 +- .../ConfigurationJavaHealthCheck.java | 6 +- .../SecuritySystemEncodingHealthCheck.java | 9 +- .../SecurityXWikiEncodingHealthCheck.java | 8 +- .../script/AdminToolsScriptService.java | 17 +- application-admintools-ui/pom.xml | 1 + .../AdminTools/Code/AdminToolsJS.xml | 223 ++++++++++-------- .../AdminTools/Code/HealthCheckResources.xml | 71 ++++-- .../main/resources/AdminTools/HelpLinks.xml | 4 +- .../src/main/resources/AdminTools/WebHome.xml | 47 ++-- 11 files changed, 241 insertions(+), 172 deletions(-) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java index 1c9b2947..4dc8dfad 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java @@ -50,10 +50,9 @@ public class PerformanceHealthCheck implements HealthCheck public HealthCheckResult check() { if (!hasFreeSpace() || !hasMinimumCPURequirements() || !hasMinimumMemoryRequirements()) { - logger.warn("There might be some performance issues!"); return new HealthCheckResult("performance issues", "minimum sys req link"); } - logger.info("System performance is OK for the XWiki installation!"); + logger.info("System performance status OK!"); return new HealthCheckResult(); } @@ -68,7 +67,12 @@ private boolean hasFreeSpace() long freePartitionSpace = diskPartition.getFreeSpace(); float freeSpace = (float) freePartitionSpace / (1024 * 1024 * 1024); - return freeSpace > 2; + if(freeSpace > 2) { + return true; + } else { + logger.warn("There is not enough free space for the XWiki installation!"); + return false; + } } private boolean hasMinimumMemoryRequirements() @@ -77,7 +81,12 @@ private boolean hasMinimumMemoryRequirements() .getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); float totalMemory = (float) memorySize / (1024 * 1024 * 1024) + 1; - return totalMemory > 2; + if (totalMemory > 2) { + return true; + } else { + logger.warn("There is not enough memory to safely run the XWiki installation!"); + return false; + } } private boolean hasMinimumCPURequirements() @@ -87,6 +96,12 @@ private boolean hasMinimumCPURequirements() CentralProcessor processor = hardware.getProcessor(); int cpuCores = processor.getPhysicalProcessorCount(); long maxFreq = processor.getMaxFreq() / (1024 * 1024); - return cpuCores > 2 && maxFreq > 2048; + + if (cpuCores > 2 && maxFreq > 2048) { + return true; + } else { + logger.warn("The CPU does not satisfy the minimum system requirements!"); + return false; + } } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java index 8923f030..7564e335 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java @@ -38,7 +38,7 @@ public class ConfigurationDatabaseHealthCheck extends AbstractConfigurationHealt public HealthCheckResult check() { if (getJson(ConfigurationDataProvider.HINT).get("database") == null) { - logger.warn("There are issues regarding the database."); + logger.warn("Database not found!"); return new HealthCheckResult("database_not_detected", "xwiki_db_configuration"); } logger.info("Database status OK"); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java index df3529cc..43b86bdf 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java @@ -45,17 +45,17 @@ public HealthCheckResult check() { String javaVersionString = getJson(ConfigurationDataProvider.HINT).get("javaVersion"); if (javaVersionString == null) { - logger.warn("Java version not found."); + logger.warn("Java version not found!"); return new HealthCheckResult("java_version_not_found", "java_installation_link"); } String xwikiVersionString = getJson(ConfigurationDataProvider.HINT).get("xwikiVersion"); float xwikiVersion = parseFloat(xwikiVersionString); float javaVersion = parseFloat(javaVersionString); if (isJavaXWikiCompatible(xwikiVersion, javaVersion)) { - logger.warn("Java version is not compatible with the current XWiki installation."); + logger.warn("Java version is not compatible with the current XWiki installation!"); return new HealthCheckResult("java_xwiki_comp", xwikiJavaCompatibilityLink); } - logger.info("Java is OK."); + logger.info("Java status OK."); return new HealthCheckResult(); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java index d711ea00..e5db1e14 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java @@ -44,13 +44,14 @@ public class SecuritySystemEncodingHealthCheck extends AbstractConfigurationHeal public HealthCheckResult check() { Map securityJson = getJson(SecurityDataProvider.HINT); - if (!acceptedEncodings.contains(securityJson.get("LANG").split("\\.")[1]) - || !acceptedEncodings.contains(securityJson.get("fileEncoding"))) + String langEnc = securityJson.get("LANG").split("\\.")[1]; + String fileEnc = securityJson.get("fileEncoding"); + if (!acceptedEncodings.contains(langEnc) || !acceptedEncodings.contains(fileEnc)) { - logger.warn("System encoding should be UTF-8!"); + logger.warn("System encoding is [{}] should be UTF-8!", fileEnc); return new HealthCheckResult("xwiki_encoding err", "xwiki config tutorial link"); } - logger.info("System encoding is safe."); + logger.info("System encoding OK."); return new HealthCheckResult(); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java index 98a21723..0c1a42de 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java @@ -44,10 +44,12 @@ public class SecurityXWikiEncodingHealthCheck extends AbstractConfigurationHealt public HealthCheckResult check() { Map securityJson = getJson(SecurityDataProvider.HINT); - if (!acceptedEncodings.contains(securityJson.get("activeEncoding")) - || !acceptedEncodings.contains(securityJson.get("configurationEncoding"))) + String activeEnc = securityJson.get("activeEncoding"); + String configEnc = securityJson.get("configurationEncoding"); + if (!acceptedEncodings.contains(activeEnc) + || !acceptedEncodings.contains(configEnc)) { - logger.warn("XWiki encoding might be at risk!"); + logger.warn("XWiki encoding is [{}]. The encoding should be UTF-8!", activeEnc); return new HealthCheckResult("xwiki_encoding err", "xwiki config tutorial link"); } logger.info("XWiki encoding is configured correctly."); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index db282c59..da1968fd 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -120,14 +120,12 @@ public Job runHealthChecks() /** * TBC. * - * @param wiki TBC. + * @param healthCheckJobRequest TBC. * @return TBC. */ - public Job runHealthChecks(String wiki) + public Job runHealthChecks(HealthCheckJobRequest healthCheckJobRequest) { try { - HealthCheckJobRequest healthCheckJobRequest = new HealthCheckJobRequest(wiki); - Job job = this.jobExecutor.getJob(healthCheckJobRequest.getId()); if (job == null) { return this.jobExecutor.execute(HealthCheckJob.JOB_TYPE, healthCheckJobRequest); @@ -138,4 +136,15 @@ public Job runHealthChecks(String wiki) return null; } } + + /** + * TBC. + * + * @param wiki TBC. + * @return TBC. + */ + public HealthCheckJobRequest createJobRequest(String wiki) + { + return new HealthCheckJobRequest(wiki); + } } diff --git a/application-admintools-ui/pom.xml b/application-admintools-ui/pom.xml index c395ceb4..7cd62bd8 100644 --- a/application-admintools-ui/pom.xml +++ b/application-admintools-ui/pom.xml @@ -82,6 +82,7 @@ .*/AdminTools/WebHome\.xml + .*/AdminTools/HelpLinks\.xml diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index 43d22763..c4b73f50 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -123,114 +123,133 @@ default - require(['jquery'], function($) { - $(document).ready(function(){ - if ($('#healthCheck').length) { - let jobState = $('input[name="jobState"]').val(); - if (jobState == "RUNNING") { - let documentReference = XWiki.Model.resolve('wiki:AdminTools.Code.HealthCheckResources', XWiki.EntityType.DOCUMENT); - const resourcesUrl = new XWiki.Document(documentReference).getURL('get'); - $.get(resourcesUrl, function(data) { - let jobMinJsURL = $(data).find('input[name="jobMinJsURL"]').val(); - require.config({ - paths: { - 'health-check-job': $('#healthCheckResources input[name="jobMinJsURL"]').val() - } - }); - require(['health-check-job'], function(){}); - // Inject the content into the job-status div - let healthCheckJobStatusURL = $(data).find('input[name="healthCheckJobStatusURL"]').val(); - $('.job-status').attr('data-url', healthCheckJobStatusURL); - $('#admin_tools_job_start').prop("disabled", true); - }); - } - else { - $('.job-status').show(); - } + require(['jquery', 'xwiki-meta', 'xwiki-job-runner'], function($, xwikiMeta, JobRunner) { + + const getResourceURL = function() { + let documentReference = XWiki.Model.resolve('AdminTools.Code.HealthCheckResources', XWiki.EntityType.DOCUMENT); + return new XWiki.Document(documentReference).getURL('get'); + } + const runHealthCheckJob = function() { + var data = []; + data.push( + {name: 'outputSyntax', value: 'plain'}, + {name: 'sheet', value: 'wiki:AdminTools.Code.HealthCheckResources'}, + {name: 'action', value: 'healthCheck'}, + {name: 'form_token', value: xwikiMeta.form_token} + ); + return Promise.resolve(new JobRunner({ + createStatusRequest: function(jobId) { + return { + url: getResourceURL(), + data: { + outputSyntax: 'plain', + sheet: 'AdminTools.Code.HealthCheckResources', + data: 'jobStatus', + jobId: jobId.join('/') + } + }; } + }).run(getResourceURL(), data)).catch((reason) => { + return Promise.reject(reason); + }).finally(() => { + $('#admin_tools_job_start').prop("disabled", false); }); - - $(document).on('click', '#admin_tools_job_start', function(event) { - event.preventDefault(); - require.undef('health-check-job'); - $(".log").empty(); - $('#admin_tools_job_start').prop("disabled", true); - let documentReference = XWiki.Model.resolve('wiki:AdminTools.Code.HealthCheckResources', XWiki.EntityType.DOCUMENT); - const resourcesUrl = new XWiki.Document(documentReference).getURL('get'); - $.get(resourcesUrl, function(data) { - let progressBar = $(data).find('div.ui-progress'); - $('#healthCheck .successmessage').replaceWith(progressBar) - $('#healthCheck .warningmessage').replaceWith(progressBar) - $('#healthCheck .errormessage').replaceWith(progressBar) - - let jobMinJsURL = $(data).find('input[name="jobMinJsURL"]').val(); - require.config({ - paths: { - 'health-check-job': jobMinJsURL - } - }); - require(['health-check-job'], function(){}); - // Inject the content into the job-status div - let healthCheckJobStatusURL = $(data).find('input[name="healthCheckJobStatusURL"]').val(); - - $('.job-status').attr('data-url', healthCheckJobStatusURL); - - // Function to poll job status - function pollJobStatus() { - $.get(healthCheckJobStatusURL, function(jobStatus) { - //console.log(jobStatus); - if (jobStatus.state === 'FINISHED') { - $('#admin_tools_job_start').prop("disabled", false); - //console.log('Job finished!'); - } else { - // If the job is not done, continue polling - setTimeout(pollJobStatus, 1000); // Poll every second - } - }); + } + + const reinitialiseProgressBar = function() { + $.get(getResourceURL(), function(data) { + let progressBar = $(data).find('div.ui-progress'); + $('#healthCheck .successmessage').replaceWith(progressBar) + $('#healthCheck .warningmessage').replaceWith(progressBar) + $('#healthCheck .errormessage').replaceWith(progressBar) + }); + } + + const initialiseJobJS = function() { + require.undef('health-check-job'); + $.get(getResourceURL(), function(data) { + let jobMinJsURL = $(data).find('input[name="jobMinJsURL"]').val(); + + require.config({ + paths: { + 'health-check-job': jobMinJsURL } - // Start polling - pollJobStatus(); }); - $('.job-status').show(); - }); - - $(document).on('click', '#downloadFilesModal .btn-primary', function(event) { - event.preventDefault(); - const downloadForm = $('#downloadFilesModal form'); - - // Simulate a click on a link to initialize the download. - const link = document.createElement('a'); - link.href = downloadForm.attr('action') + '?' + downloadForm.serialize(); - link.click(); + require(['health-check-job'], function(){}); }); - - $(document).on('click', '#filesViewLastNLinesModal .btn-primary, #configurationViewLastNLinesModal .btn-primary', - function(event) { - event.preventDefault(); - const modal = $(event.currentTarget).closest('.modal'); - const downloadForm = modal.find('form'); - let noLines = modal.find("input[name='noLines']").val(); - - // If the input is empty, the default value of 1000 will be requested. - if (noLines == '') { - noLines = '1000'; - } - - // Simulate a click on a link to request the last 'noLines' logs. - const link = document.createElement('a'); - link.href = downloadForm.attr('action') + '?noLines=' + noLines; - link.target='_blank'; - link.click(); - }); - - $(document).on('change', '#downloadFilesModal input[name="files"][value="logsDataResource"]', function() { - if ($(this).is(':checked')) { - $('#downloadFilesModal .dateFields').show(); - } else { - $('#downloadFilesModal .dateFields').hide(); - } + } + + $(document).ready(function(){ + if ($('#healthCheck').length) { + $.get(getResourceURL(), function(data) { + let jobState = $(data).find('input[name="jobState"]').val(); + if (jobState == "RUNNING") { + initialiseJobJS() + runHealthCheckJob() + // Inject the content into the job-status div + let healthCheckJobStatusURL = $(data).find('input[name="healthCheckJobStatusURL"]').val(); + $('.job-status').attr('data-url', healthCheckJobStatusURL); + $('#admin_tools_job_start').prop("disabled", true); + $('.job-status').show(); + } else { + $('.job-status').show(); + } + }); + } + }); + + $(document).on('click', '#admin_tools_job_start', function(event) { + event.preventDefault(); + $(".log").empty(); + $('#admin_tools_job_start').prop("disabled", true); + $.get(getResourceURL(), function(data) { + reinitialiseProgressBar() + initialiseJobJS() + runHealthCheckJob() + // Inject the content into the job-status div + let healthCheckJobStatusURL = $(data).find('input[name="healthCheckJobStatusURL"]').val(); + $('.job-status').attr('data-url', healthCheckJobStatusURL); }); - }); + $('.job-status').show(); + }); + + $(document).on('click', '#downloadFilesModal .btn-primary', function(event) { + event.preventDefault(); + const downloadForm = $('#downloadFilesModal form'); + + // Simulate a click on a link to initialize the download. + const link = document.createElement('a'); + link.href = downloadForm.attr('action') + '?' + downloadForm.serialize(); + link.click(); + }); + + $(document).on('click', '#filesViewLastNLinesModal .btn-primary, #configurationViewLastNLinesModal .btn-primary', + function(event) { + event.preventDefault(); + const modal = $(event.currentTarget).closest('.modal'); + const downloadForm = modal.find('form'); + let noLines = modal.find("input[name='noLines']").val(); + + // If the input is empty, the default value of 1000 will be requested. + if (noLines == '') { + noLines = '1000'; + } + + // Simulate a click on a link to request the last 'noLines' logs. + const link = document.createElement('a'); + link.href = downloadForm.attr('action') + '?noLines=' + noLines; + link.target='_blank'; + link.click(); + }); + + $(document).on('change', '#downloadFilesModal input[name="files"][value="logsDataResource"]', function() { + if ($(this).is(':checked')) { + $('#downloadFilesModal .dateFields').show(); + } else { + $('#downloadFilesModal .dateFields').hide(); + } + }); +}); AdminToolsJavaScript diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml index 17d2e48c..bd2b7306 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml @@ -36,28 +36,59 @@ true {{template name="job_macros.vm"/}} -{{velocity}} -#set ($adminToolsHealthJob = $services.admintools.runHealthChecks($services.wiki.getCurrentWikiId())) -#set ($healthJobStatusURL = $xwiki.getURL('AdminTools.Code.HealthCheckJob', 'get', $escapetool.url({ - 'jobId': $adminToolsHealthJob.request.id, - 'outputSyntax': 'plain' -}))) -#set($jobMinJsURL = $xwiki.getSkinFile('uicomponents/job/job.min.js')) -{{html clean=false}} -<div hidden> - <input type="text" name="healthCheckJobStatusURL" value=$healthJobStatusURL></input> - <input type="text" name="jobMinJsURL" value=$jobMinJsURL></input> +{{velocity output="false"}} +#macro (returnHealthCheckJobStatusJSON $healthCheckJobId) + #set ($healthCheckJobStatus = $services.job.getJobStatus($healthCheckJobId)) + #set ($healthCheckJobStatusJSON = { + 'id': $healthCheckJobStatus.request.id, + 'state': $healthCheckJobStatus.state, + 'progress': { + 'offset': $healthCheckJobStatus.progress.offset + } + }) + #jsonResponse($healthCheckJobStatusJSON) +#end +{{/velocity}} - <div class="ui-progress"> - <div class="box info hidden" id="state-none-hint"> - This job is waiting to start, please be patient: another job might be running on the same pages. - </div> - <div class="ui-progress-background"> - <div class="ui-progress-bar green" style="width:0%"></div> +{{velocity}} +#if ($xcontext.action == 'get') + #if ("$!request.action" != '' && !$services.csrf.isTokenValid($request.form_token)) + #set ($discard = $response.sendError(401, 'CSRF token verification failed!')) + #elseif ($request.action == 'healthCheck') + #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) + #set ($healthCheckJob = $services.admintools.runHealthChecks($healthCheckJobRequest)) + #returnHealthCheckJobStatusJSON($healthCheckJobRequest.id) + #elseif ($request.data == 'jobStatus') + #set ($healthCheckJobId = $request.jobId.split('/')) + #returnHealthCheckJobStatusJSON($healthCheckJobId) + #else + #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) + #set ($jobId = $healthCheckJobRequest.id) + #set ($healthJobStatusURL = $xwiki.getURL('AdminTools.Code.HealthCheckJob', 'get', $escapetool.url({ + 'jobId': $jobId, + 'outputSyntax': 'plain' + }))) + #set ($healthJobStatus = $services.job.getJobStatus($jobId)) + #set ($jobMinJsURL = $xwiki.getSkinFile('uicomponents/job/job.min.js')) + {{html clean=false}} + <div hidden> + <input type="text" name="healthCheckJobStatusURL" value=$healthJobStatusURL></input> + <input type="text" name="jobMinJsURL" value=$jobMinJsURL></input> + <input type="text" name="jobState" value=$healthJobStatus.state></input> + <div class="ui-progress"> + <div class="box info hidden" id="state-none-hint"> + This job is waiting to start, please be patient: another job might be running on the same pages. + </div> + <div class="ui-progress-background"> + <div class="ui-progress-bar green" style="width:0%"></div> + </div> + </div> </div> - </div> -</div> -{{/html}} + {{/html}} + #end +#end + + {{/velocity}} diff --git a/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml b/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml index 325923f9..49074a2c 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml @@ -22,7 +22,7 @@ AdminTools HelpLinks - + en 0 xwiki:XWiki.Admin AdminTools.WebHome @@ -33,7 +33,7 @@ false xwiki/2.1 - true + false {{box cssClass="floatinginfobox" title="**Contents**"}} {{toc/}} {{/box}} diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index fbe07648..01729fb3 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -152,7 +152,8 @@ {{velocity}} $services.admintools.getConfigurationData('configuration') -{{/velocity}} +{{/velocity}} + 1, 1 @@ -284,36 +285,27 @@ $services.admintools.getFilesSection() {{template name="job_macros.vm"/}} {{velocity}} -#includeMacros("AdminTools.Code.Macros") -#set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) -#set ($jobId = ['adminTools', 'healthCheck', $services.wiki.getCurrentWikiId()]) -#set($healthJobStatus = $services.job.getJobStatus($jobId)) -#set($jobMinJsURL = $xwiki.getSkinFile('uicomponents/job/job.min.js')) + #includeMacros("AdminTools.Code.Macros") + #set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) + #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) + #set ($jobId = $healthCheckJobRequest.id) + #set ($healthJobStatus = $services.job.getJobStatus($jobId)) {{html clean='false'}} -<div id="healthCheckResources" hidden> - <input type="text" name="jobMinJsURL" value=$jobMinJsURL></input> - <input type="text" name="jobState" value=$job.state></input> -</div> <div class="adminToolsDashboardItem" id="healthCheck"> -<div class="healthCheckWrapper"> -<div class="healthCheckLastCheck"> - Time since the last health check: $services.date.displayTimeAgo($healthJobStatus.getEndDate()) -</div> - <a href="$xwiki.getURL("AdminTools.HelpLinks")"><strong>Useful links</strong></a> - <div class="buttonwrapper"> - <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" value="startHealthCheck">Start health check</button> + <h2>$services.icon.renderHTML('bug') + Health check</h2> + <p>Check if your instance is configured correctly and is properly running. For any issues, check out this <a href="$xwiki.getURL("AdminTools.HelpLinks")"><strong>solutions</strong></a>.</p> + <hr/> + <div class="healthCheckWrapper"> + <div class="healthCheckLastCheck"> + Time since the last health check: $services.date.displayTimeAgo($healthJobStatus.getEndDate()) + </div> + <div class="buttonwrapper"> + <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" value="startHealthCheck">Start health check</button> + </div> </div> -</div> <div hidden class="xcontent job-status" data-url=""> - #set($titleKey = "${translationPrefix}.label") - #if ($services.localization.get($titleKey)) - <h2>$services.localization.render($titleKey)</h2> - #set($titleHintKey = "${translationPrefix}.hint") - #if ($services.localization.get($titleHintKey)) - <p class="text-muted small">$services.localization.render($titleHintKey)</p> - #end - #end #if ($healthJobStatus.state != 'FINISHED') #displayJobProgressBar($jobStatus) #else @@ -326,7 +318,7 @@ $services.admintools.getFilesSection() #displayJobStatusLog($healthJobStatus true) #end #end - </div> + </div> </div> {{/html}} {{/velocity}} @@ -472,7 +464,6 @@ $services.admintools.getFilesSection() .healthCheckWrapper { display: flex; flex-direction: column; - align-items: center; margin-bottom: 2rem; } From 16e4914086e2cc6102c64ad557145ef4a19626f2 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Tue, 31 Oct 2023 10:28:47 +0200 Subject: [PATCH 56/72] Add support for downloading important files #8 * Modified comments * Modified Exception and logger messages --- .../java/com/xwiki/admintools/DataProvider.java | 1 - .../com/xwiki/admintools/ServerIdentifier.java | 1 - .../configuration/AdminToolsConfiguration.java | 3 --- .../xwiki/admintools/download/DataResource.java | 1 - .../admintools/rest/AdminToolsResource.java | 1 - .../internal/AdminToolsEventListener.java | 1 - .../admintools/internal/AdminToolsManager.java | 1 - .../AdminToolsConfigurationSource.java | 1 - .../DefaultAdminToolsConfiguration.java | 3 --- .../internal/data/AbstractDataProvider.java | 1 - .../internal/data/ConfigurationDataProvider.java | 3 +-- .../internal/data/SecurityDataProvider.java | 1 - .../identifiers/AbstractServerIdentifier.java | 1 - .../internal/data/identifiers/CurrentServer.java | 1 - .../data/identifiers/TomcatIdentifier.java | 1 - .../internal/files/ImportantFilesManager.java | 16 +++++++++------- .../resources/DataProvidersDataResource.java | 11 +++++------ .../files/resources/LogsDataResource.java | 13 ++++--------- .../resources/XWikiConfigFileDataResource.java | 7 ++----- .../XWikiPropertiesFileDataResource.java | 5 +---- .../internal/rest/DefaultAdminToolsResource.java | 1 - .../script/AdminToolsScriptService.java | 1 - .../data/ConfigurationDataProviderTest.java | 8 ++++---- .../files/ImportantFilesManagerTest.java | 12 +++++------- .../resources/DataProvidersDataResourceTest.java | 4 ++-- .../files/resources/LogsDataResourceTest.java | 13 ++++++------- .../XWikiConfigFileDataResourceTest.java | 2 +- .../XWikiPropertiesFileDataResourceTest.java | 2 +- .../resources/AdminTools/Code/AdminToolsJS.xml | 4 ++-- .../main/resources/AdminTools/Code/Macros.xml | 4 ++-- 30 files changed, 45 insertions(+), 79 deletions(-) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java index 75e39d6f..44cec9da 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/DataProvider.java @@ -27,7 +27,6 @@ * Gathers specific data and returns it in a specific format, using a template. * * @version $Id$ - * @since 1.0 */ @Role public interface DataProvider diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java index 03d7bb04..aff5c6fe 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/ServerIdentifier.java @@ -27,7 +27,6 @@ * Exposes methods for accessing server specific information, like configurations, logs or other XWiki and server * files. * @version $Id$ - * @since 1.0 */ @Role public interface ServerIdentifier diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/configuration/AdminToolsConfiguration.java b/application-admintools-api/src/main/java/com/xwiki/admintools/configuration/AdminToolsConfiguration.java index 4b1bfbd5..c841e24e 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/configuration/AdminToolsConfiguration.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/configuration/AdminToolsConfiguration.java @@ -22,16 +22,13 @@ import java.util.List; import org.xwiki.component.annotation.Role; -import org.xwiki.stability.Unstable; /** * Admin Tools configurations. * * @version $Id$ - * @since 1.0 */ @Role -@Unstable public interface AdminToolsConfiguration { /** diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java b/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java index 84dfc5fb..78465325 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java @@ -29,7 +29,6 @@ * Access server files. * * @version $Id$ - * @since 1.0 */ @Role public interface DataResource diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java index d7020c36..e25bffa0 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/rest/AdminToolsResource.java @@ -31,7 +31,6 @@ * Provides the APIs needed by the Admin Tools server in order to download and view configuration files and logs. * * @version $Id$ - * @since 1.0 */ @Path("/admintools") public interface AdminToolsResource extends XWikiRestComponent diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsEventListener.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsEventListener.java index 0047a015..26b78fdc 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsEventListener.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsEventListener.java @@ -44,7 +44,6 @@ * Listens to configuration updates. * * @version $Id$ - * @since 1.0 */ @Component @Named(AdminToolsEventListener.HINT) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index 1db1bc7b..8a388397 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -36,7 +36,6 @@ * Manages the data providers. * * @version $Id$ - * @since 1.0 */ @Component(roles = AdminToolsManager.class) @Singleton diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/AdminToolsConfigurationSource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/AdminToolsConfigurationSource.java index f31ed564..a6d09b1d 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/AdminToolsConfigurationSource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/AdminToolsConfigurationSource.java @@ -34,7 +34,6 @@ * Admin tools configuration source corresponding to the current wiki. * * @version $Id$ - * @since 1.0 */ @Component @Named(AdminToolsConfigurationSource.HINT) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java index 19b9cdea..d76cb1b6 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfiguration.java @@ -28,7 +28,6 @@ import org.xwiki.component.annotation.Component; import org.xwiki.configuration.ConfigurationSource; -import org.xwiki.stability.Unstable; import com.xwiki.admintools.configuration.AdminToolsConfiguration; @@ -36,11 +35,9 @@ * Default implementation of {@link AdminToolsConfiguration}. * * @version $Id$ - * @since 1.0 */ @Component @Singleton -@Unstable public class DefaultAdminToolsConfiguration implements AdminToolsConfiguration { private static final String SERVER_LOCATION = "serverLocation"; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java index 5daf1a9e..8e6a128a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/AbstractDataProvider.java @@ -37,7 +37,6 @@ * {@link DataProvider} implementations to simplify the code. * * @version $Id$ - * @since 1.0 */ public abstract class AbstractDataProvider implements DataProvider { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index 1a69d06c..b36e2d42 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -44,7 +44,6 @@ * Extension of {@link AbstractDataProvider} for retrieving configuration data. * * @version $Id$ - * @since 1.0 */ @Component @Named(ConfigurationDataProvider.HINT) @@ -166,7 +165,7 @@ private ServerIdentifier getCurrentServer() { ServerIdentifier serverIdentifier = currentServer.getCurrentServer(); if (serverIdentifier == null) { - throw new NullPointerException("Failed to retrieve the used server. Server not found."); + throw new NullPointerException("Failed to retrieve the current used server, check your configurations."); } return serverIdentifier; } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java index 14ace7d5..a84bd7db 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/SecurityDataProvider.java @@ -37,7 +37,6 @@ * info. * * @version $Id$ - * @since 1.0 */ @Component @Named(SecurityDataProvider.HINT) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java index ca8e360f..d6d51bd5 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/AbstractServerIdentifier.java @@ -31,7 +31,6 @@ * Common methods for {@link ServerIdentifier} classes. * * @version $Id$ - * @since 1.0 */ public abstract class AbstractServerIdentifier implements ServerIdentifier { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java index 92214c0f..35b7551d 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java @@ -38,7 +38,6 @@ * Manages the server identifiers and offers endpoints to retrieve info about their paths. * * @version $Id$ - * @since 1.0 */ @Component(roles = CurrentServer.class) @Singleton diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java index fcb89b2a..10c5d2c7 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java @@ -33,7 +33,6 @@ * {@link ServerIdentifier} implementation used for identifying a Tomcat server and retrieving it's info. * * @version $Id$ - * @since 1.0 */ @Component @Named(TomcatIdentifier.HINT) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java index f7b30635..dfba3412 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java @@ -46,7 +46,6 @@ * Endpoints used for accessing important server files. * * @version $Id$ - * @since 1.0 */ @Component(roles = ImportantFilesManager.class) @Singleton @@ -56,6 +55,8 @@ public class ImportantFilesManager private static final String TO = "to"; + private static final String TEMPLATE_NAME = "filesSectionTemplate.vm"; + @Inject private Provider> dataResources; @@ -80,8 +81,11 @@ public class ImportantFilesManager */ public byte[] getFile(String hint, String input) throws Exception { + DataResource fileViewerProvider = findDataResource(hint); + if (fileViewerProvider == null) { + throw new NullPointerException("File provider not found!"); + } try { - DataResource fileViewerProvider = findDataResource(hint); return fileViewerProvider.getByteData(input); } catch (IOException e) { throw new IOException("Error while managing file.", e); @@ -119,9 +123,7 @@ public byte[] getFilesArchive(Map params) throws Exception byteArrayOutputStream.close(); return byteArrayOutputStream.toByteArray(); } catch (Exception e) { - logger.warn("Error while generating the file archive. Root cause is: [{}]", - ExceptionUtils.getRootCauseMessage(e)); - throw new Exception("Error while generating the file archive.", e); + throw new Exception("Error while generating the files archive.", e); } } @@ -136,9 +138,9 @@ public String renderTemplate() boolean found = currentServer.getCurrentServer() != null; ScriptContext scriptContext = this.scriptContextManager.getScriptContext(); scriptContext.setAttribute("found", found, ScriptContext.ENGINE_SCOPE); - return this.templateManager.render("filesSectionTemplate.vm"); + return this.templateManager.render(TEMPLATE_NAME); } catch (Exception e) { - this.logger.warn("Failed to render custom template. Root cause is: [{}]", + this.logger.warn("Failed to render [{}] template. Root cause is: [{}]", TEMPLATE_NAME, ExceptionUtils.getRootCauseMessage(e)); return null; } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java index 386fa761..58a9ca2c 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java @@ -41,7 +41,6 @@ * Merges data from all {@link DataProvider} to be retrieved as a file. * * @version $Id$ - * @since 1.0 */ @Component @Named(DataProvidersDataResource.HINT) @@ -51,7 +50,7 @@ public class DataProvidersDataResource implements DataResource /** * Component identifier. */ - public static final String HINT = "dataProviderResource"; + public static final String HINT = "dataProvider"; @Inject private Provider> dataProviders; @@ -73,9 +72,9 @@ public byte[] getByteData(String input) throws Exception try { providersResults.put(dataProvider.getIdentifier(), dataProvider.getDataAsJSON()); } catch (Exception e) { - String errMessage = - String.format("Error getting json from DataProvider %s.", dataProvider.getIdentifier()); - throw new Exception(errMessage, e); + throw new Exception( + String.format("Error while getting JSON data for [%s] DataProvider.", dataProvider.getIdentifier()), + e); } } return providersResults.toString().getBytes(); @@ -96,7 +95,7 @@ private void addZipEntry(ZipOutputStream zipOutputStream) zipOutputStream.write(buffer, 0, buffer.length); zipOutputStream.closeEntry(); } catch (Exception exception) { - logger.warn("Could not add gathered configuration to the archive. Root cause is: {}", + logger.warn("Could not add gathered configuration to the archive. Root cause is: [{}]", ExceptionUtils.getRootCauseMessage(exception)); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java index 77ce7457..a1a6390a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java @@ -56,7 +56,6 @@ * {@link DataResource} implementation for accessing log files. * * @version $Id$ - * @since 1.0 */ @Component @Named(LogsDataResource.HINT) @@ -66,14 +65,12 @@ public class LogsDataResource implements DataResource /** * Component identifier. */ - public static final String HINT = "logsDataResource"; + public static final String HINT = "logs"; private static final String FROM_DATE_FILTER_KEY = "from"; private static final String TO_DATE_FILTER_KEY = "to"; - private static final String ERROR_SOURCE = " Root cause is: [{}]"; - @Inject private Logger logger; @@ -93,7 +90,6 @@ public String getIdentifier() public byte[] getByteData(String input) throws IOException, NumberFormatException { try { - // verify if null and throw if it is ServerIdentifier usedServer = currentServer.getCurrentServer(); if (usedServer == null) { throw new NullPointerException("Server not found! Configure path in extension configuration."); @@ -124,11 +120,10 @@ public byte[] getByteData(String input) throws IOException, NumberFormatExceptio return String.join("\n", logLines).getBytes(); } } catch (IOException exception) { - String errMessage = String.format("Error while accessing log files at %s.", - currentServer.getCurrentServer().getLastLogFilePath()); - throw new IOException(errMessage, exception); + throw new IOException(String.format("Error while accessing log files at [%s].", + currentServer.getCurrentServer().getLastLogFilePath()), exception); } catch (NumberFormatException exception) { - throw new NumberFormatException(String.format("Input [%s] is not a valid number!", input)); + throw new NumberFormatException(String.format("The given [%s] lines number is not a valid number.", input)); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java index 93aa7164..ccfed297 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java @@ -45,7 +45,6 @@ * {@link DataResource} implementation for accessing the xwiki.cfg file. * * @version $Id$ - * @since 1.0 */ @Component @Named(XWikiConfigFileDataResource.HINT) @@ -59,8 +58,6 @@ public class XWikiConfigFileDataResource implements DataResource private static final String XWIKI_CFG = "xwiki.cfg"; - private static final String ERROR_SOURCE = " Root cause is: [{}]"; - @Inject @Named("default") private AdminToolsConfiguration adminToolsConfig; @@ -104,7 +101,7 @@ public byte[] getByteData(String input) throws IOException return stringBuilder.toString().getBytes(); } } catch (IOException exception) { - throw new IOException(String.format("Error while handling %s file.", XWIKI_CFG), exception); + throw new IOException(String.format("Error while handling [%s] file.", XWIKI_CFG), exception); } } @@ -123,7 +120,7 @@ private void addZipEntry(ZipOutputStream zipOutputStream) zipOutputStream.write(buffer, 0, buffer.length); zipOutputStream.closeEntry(); } catch (Exception exception) { - logger.warn("Could not add {} to the archive." + ERROR_SOURCE, XWIKI_CFG, + logger.warn("Could not add {} to the archive. Root cause is: [{}]", XWIKI_CFG, ExceptionUtils.getRootCauseMessage(exception)); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java index 5204758d..8c8960ef 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java @@ -45,7 +45,6 @@ * {@link DataResource} implementation for accessing the xwiki.properties file. * * @version $Id$ - * @since 1.0 */ @Component @Named(XWikiPropertiesFileDataResource.HINT) @@ -59,8 +58,6 @@ public class XWikiPropertiesFileDataResource implements DataResource private static final String XWIKI_PROPERTIES = "xwiki.properties"; - private static final String ERROR_SOURCE = " "; - @Inject @Named("default") private AdminToolsConfiguration adminToolsConfig; @@ -103,7 +100,7 @@ public byte[] getByteData(String input) throws IOException return stringBuilder.toString().getBytes(); } } catch (IOException exception) { - throw new IOException(String.format("Error while handling %s file.", XWIKI_PROPERTIES), exception); + throw new IOException(String.format("Error while handling [%s] file.", XWIKI_PROPERTIES), exception); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java index fe0f3354..19d2cf30 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java @@ -50,7 +50,6 @@ * Default implementation of {@link AdminToolsResource}. * * @version $Id$ - * @since 1.0 */ @Component @Named("com.xwiki.admintools.internal.rest.DefaultAdminToolsResource") diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index 56f70335..8a9b77b6 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -34,7 +34,6 @@ * Admin Tools script services. * * @version $Id$ - * @since 1.0 */ @Component @Named("admintools") diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java index 977af58f..8330e583 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java @@ -212,7 +212,7 @@ void getDataAsJsonIdentifyDBCurrentServerNotFound() }); assertEquals("Failed to generate the instance configuration data.", exception.getMessage()); verify(this.logger).warn("Failed to generate the instance configuration data. Root cause is: [{}]", - "NullPointerException: Failed to retrieve the used server. Server not found."); + "NullPointerException: Failed to retrieve the current used server, check your configurations."); } @Test @@ -266,7 +266,7 @@ void getDataAsJsonWithErrorExecution() }); assertEquals("Failed to generate the instance configuration data.", exception.getMessage()); verify(this.logger).warn("Failed to generate the instance configuration data. Root cause is: [{}]", - "NullPointerException: Failed to retrieve the used server. Server not found."); + "NullPointerException: Failed to retrieve the current used server, check your configurations."); } @Test @@ -367,7 +367,7 @@ void getRenderedDataWithFailedJsonGenerate() throws Exception assertEquals("success", configurationDataProvider.getRenderedData()); assertThrows(Exception.class, () -> configurationDataProvider.getDataAsJSON()); verify(this.logger, times(2)).warn("Failed to generate the instance configuration data. Root cause is: [{}]", - "NullPointerException: Failed to retrieve the used server. Server not found."); + "NullPointerException: Failed to retrieve the current used server, check your configurations."); verify(scriptContext).setAttribute(ConfigurationDataProvider.HINT, json, ScriptContext.ENGINE_SCOPE); } @@ -391,7 +391,7 @@ void getRenderedDataExecutionFail() throws Exception assertEquals("Failed to generate the instance configuration data.", exception.getMessage()); verify(this.logger, times(2)).warn("Failed to generate the instance configuration data. Root cause is: [{}]", - "NullPointerException: Failed to retrieve the used server. Server not found."); + "NullPointerException: Failed to retrieve the current used server, check your configurations."); verify(this.logger).warn("Failed to render custom template. Root cause is: [{}]", "Exception: Render failed."); verify(scriptContext).setAttribute(ConfigurationDataProvider.HINT, json, ScriptContext.ENGINE_SCOPE); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java index 54321b57..b10ec214 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java @@ -117,7 +117,7 @@ void getFileResourceNotFound() Exception exception = assertThrows(Exception.class, () -> { importantFilesManager.getFile("data_resource_identifier_invalid", "input"); }); - assertEquals("Error while processing file content.", exception.getMessage()); + assertEquals("File provider not found!", exception.getMessage()); } @Test @@ -176,9 +176,7 @@ void downloadMultipleFilesNoArchiverFound() importantFilesManager.getFilesArchive(request); }); - assertEquals("Error while generating the file archive.", exception.getMessage()); - verify(logger).warn("Error while generating the file archive. Root cause is: [{}]", - "NullPointerException: "); + assertEquals("Error while generating the files archive.", exception.getMessage()); } @Test @@ -200,8 +198,7 @@ void downloadMultipleFilesInvalidRequest() importantFilesManager.getFilesArchive(request); }); - assertEquals("Error while generating the file archive.", exception.getMessage()); - verify(logger).warn("Error while generating the file archive. Root cause is: [{}]", "NullPointerException: "); + assertEquals("Error while generating the files archive.", exception.getMessage()); } @Test @@ -230,6 +227,7 @@ void renderTemplateWithRenderingError() throws Exception assertNull(importantFilesManager.renderTemplate()); verify(scriptContext).setAttribute("found", false, ScriptContext.ENGINE_SCOPE); - verify(logger).warn("Failed to render custom template. Root cause is: [{}]", "Exception: Render failed."); + verify(logger).warn("Failed to render [{}] template. Root cause is: [{}]", "filesSectionTemplate.vm", + "Exception: Render failed."); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java index e07fe0a5..ec865f87 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java @@ -107,7 +107,7 @@ void getByteDataThrowError() throws Exception Exception exception = assertThrows(Exception.class, () -> { this.dataProviderResource.getByteData(null); }); - assertEquals("Error getting json from DataProvider data_provider_identifier.", exception.getMessage()); + assertEquals("Error while getting JSON data for [data_provider_identifier] DataProvider.", exception.getMessage()); } @Test @@ -136,7 +136,7 @@ void addZipEntryGetByteDataError() throws Exception dataProviderResource.addZipEntry(zipOutputStream, null); verify(zipOutputStream, never()).write(any(), eq(0), eq(0)); - verify(logger).warn("Could not add gathered configuration to the archive. Root cause is: {}", + verify(logger).warn("Could not add gathered configuration to the archive. Root cause is: [{}]", "Exception: ERROR AT GET DATA AS JASON."); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java index a5d6c7fb..6391c0b8 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java @@ -170,7 +170,7 @@ void getByteDataFileNotFound() IOException exception = assertThrows(IOException.class, () -> { logsDataResource.getByteData(null); }); - assertEquals(String.format("Error while accessing log files at %s.", testFile.getAbsolutePath()), + assertEquals(String.format("Error while accessing log files at [%s].", testFile.getAbsolutePath()), exception.getMessage()); } @@ -183,8 +183,7 @@ void getByteDataServerNotFound() Exception exception = assertThrows(Exception.class, () -> { this.logsDataResource.getByteData("44"); }); - assertEquals("Server not found! Configure path in extension configuration.", - exception.getMessage()); + assertEquals("Server not found! Configure path in extension configuration.", exception.getMessage()); logsDir.delete(); } @@ -196,10 +195,10 @@ void getByteDataIncorrectInput() when(currentServer.getCurrentServer()).thenReturn(serverIdentifier); when(serverIdentifier.getLastLogFilePath()).thenReturn(testFile.getAbsolutePath()); - Exception exception = assertThrows(Exception.class, () -> { - logsDataResource.getByteData("not a number"); - }); - assertEquals("Input [not a number] is not a valid number!", exception.getMessage()); + String invalidInput = "not a number"; + Exception exception = assertThrows(Exception.class, () -> logsDataResource.getByteData(invalidInput)); + assertEquals(String.format("The given [%s] lines number is not a valid number.", invalidInput), + exception.getMessage()); } @Test diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java index acb18bcc..655e275b 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java @@ -150,7 +150,7 @@ void getByteDataFileNotFound() Exception exception = assertThrows(Exception.class, () -> { configFileDataResource.getByteData(null); }); - assertEquals("Error while handling xwiki.cfg file.", exception.getMessage()); + assertEquals("Error while handling [xwiki.cfg] file.", exception.getMessage()); } @Test diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java index f5c2bf68..34443604 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java @@ -150,7 +150,7 @@ void getByteDataFileNotFound() Exception exception = assertThrows(Exception.class, () -> { propertiesFileDataResource.getByteData(null); }); - assertEquals("Error while handling xwiki.properties file.", exception.getMessage()); + assertEquals("Error while handling [xwiki.properties] file.", exception.getMessage()); } @Test diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index 5caac115..06b3fa23 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -155,9 +155,9 @@ $(document).on('change', '#downloadFilesModal input[name="files"][value="logsDataResource"]', function() { if ($(this).is(':checked')) { - $('#downloadFilesModal .dateFields').show(); + $('#downloadFilesModal .dateFields').show(); } else { - $('#downloadFilesModal .dateFields').hide(); + $('#downloadFilesModal .dateFields').hide(); } }); }); diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml index 55f37973..467152ea 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml @@ -51,7 +51,7 @@ </h1> </div> <div class="modal-body"> - <form class="xform" action="$request.getContextPath()/rest/admintools/files/logsDataResource"> + <form class="xform" action="$request.getContextPath()/rest/admintools/files/logs"> <dl> <dt> <label for="noLines">$escapetool.xml($services.localization.render( @@ -109,7 +109,7 @@ </label> </dt> <dt> - <label><input type="checkbox" name="files" value="logsDataResource" checked> + <label><input type="checkbox" name="files" value="logs" checked> $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.logs.title')) </label> </dt> From f732720ddd18bb99b346b443e5a98ae37b3c4eda Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Tue, 31 Oct 2023 14:21:53 +0200 Subject: [PATCH 57/72] Add support for downloading important files #8 * Code refactoring for filters handling --- .../admintools/download/DataResource.java | 4 +- .../internal/files/ImportantFilesManager.java | 33 ++++----- .../resources/DataProvidersDataResource.java | 4 +- .../files/resources/LogsDataResource.java | 59 ++++++++++++---- .../XWikiConfigFileDataResource.java | 4 +- .../XWikiPropertiesFileDataResource.java | 4 +- .../rest/DefaultAdminToolsResource.java | 17 ++--- .../script/AdminToolsScriptService.java | 3 + .../files/ImportantFilesManagerTest.java | 42 ++++++----- .../DataProvidersDataResourceTest.java | 3 - .../files/resources/LogsDataResourceTest.java | 69 +++++++++++-------- .../XWikiConfigFileDataResourceTest.java | 6 -- .../XWikiPropertiesFileDataResourceTest.java | 6 -- .../rest/DefaultAdminToolsResourceTest.java | 13 ++-- .../main/resources/AdminTools/Code/Macros.xml | 2 +- .../src/main/resources/AdminTools/WebHome.xml | 4 +- 16 files changed, 148 insertions(+), 125 deletions(-) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java b/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java index 78465325..e97be4d0 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java @@ -39,7 +39,7 @@ public interface DataResource * @param zipOutputStream {@link ZipOutputStream} represents the zip archive in which the entry is written. * @param filters store filters that can be used for file selection. */ - void addZipEntry(ZipOutputStream zipOutputStream, Map filters); + void addZipEntry(ZipOutputStream zipOutputStream, Map filters); /** * Retrieve the content of a system file. @@ -49,7 +49,7 @@ public interface DataResource * @throws IOException when there are errors while handling searched files. * @throws NumberFormatException when there is an invalid numeric input. */ - byte[] getByteData(String input) throws Exception; + byte[] getByteData(Map input) throws Exception; /** * Get the hint of a component. diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java index dfba3412..426afe94 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java @@ -21,10 +21,9 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; +import java.util.stream.Collectors; import java.util.zip.ZipOutputStream; import javax.inject.Inject; @@ -40,7 +39,6 @@ import com.xwiki.admintools.download.DataResource; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; -import com.xwiki.admintools.internal.files.resources.LogsDataResource; /** * Endpoints used for accessing important server files. @@ -51,12 +49,10 @@ @Singleton public class ImportantFilesManager { - private static final String FROM = "from"; - - private static final String TO = "to"; - private static final String TEMPLATE_NAME = "filesSectionTemplate.vm"; + private static final String REQUESTED_FILES_KEY = "files"; + @Inject private Provider> dataResources; @@ -76,17 +72,18 @@ public class ImportantFilesManager * Access system file content. * * @param hint file type identifier. - * @param input {@link String} representing the file type. + * @param params {@link Map} containing the needed filters. * @return filtered file content as a {@link Byte} array */ - public byte[] getFile(String hint, String input) throws Exception + public byte[] getFile(String hint, Map params) throws Exception { DataResource fileViewerProvider = findDataResource(hint); if (fileViewerProvider == null) { - throw new NullPointerException("File provider not found!"); + throw new NullPointerException( + String.format("Could not find a DataResource implementation for [%s].", hint)); } try { - return fileViewerProvider.getByteData(input); + return fileViewerProvider.getByteData(params); } catch (IOException e) { throw new IOException("Error while managing file.", e); } catch (Exception e) { @@ -104,16 +101,14 @@ public byte[] getFilesArchive(Map params) throws Exception { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) { - for (String dataResourceHint : params.get("files")) { - Map filters = null; - if (dataResourceHint.equals(LogsDataResource.HINT)) { - filters = new HashMap<>(); - filters.put(FROM, !Objects.equals(params.get(FROM)[0], "") ? params.get(FROM)[0] : null); - filters.put(TO, !Objects.equals(params.get(TO)[0], "") ? params.get(TO)[0] : null); - } + for (String dataResourceHint : params.get(REQUESTED_FILES_KEY)) { DataResource archiver = findDataResource(dataResourceHint); + // Get only the filters and exclude the requested files. + Map filteredParams = + params.entrySet().stream().filter(entry -> !entry.getKey().equals(REQUESTED_FILES_KEY)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); if (archiver != null) { - archiver.addZipEntry(zipOutputStream, filters); + archiver.addZipEntry(zipOutputStream, filteredParams); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java index 58a9ca2c..9c3046b5 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResource.java @@ -59,13 +59,13 @@ public class DataProvidersDataResource implements DataResource private Logger logger; @Override - public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) + public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) { addZipEntry(zipOutputStream); } @Override - public byte[] getByteData(String input) throws Exception + public byte[] getByteData(Map params) throws Exception { Map> providersResults = new HashMap<>(); for (DataProvider dataProvider : dataProviders.get()) { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java index a1a6390a..b295cf3d 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/LogsDataResource.java @@ -28,8 +28,10 @@ import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.ZipEntry; @@ -67,9 +69,13 @@ public class LogsDataResource implements DataResource */ public static final String HINT = "logs"; - private static final String FROM_DATE_FILTER_KEY = "from"; + private static final String FROM = "from"; - private static final String TO_DATE_FILTER_KEY = "to"; + private static final String TO = "to"; + + private static final String NO_LINES = "noLines"; + + private static final String DEFAULT_NO_LINES = "1000"; @Inject private Logger logger; @@ -87,7 +93,7 @@ public String getIdentifier() } @Override - public byte[] getByteData(String input) throws IOException, NumberFormatException + public byte[] getByteData(Map params) throws IOException, NumberFormatException { try { ServerIdentifier usedServer = currentServer.getCurrentServer(); @@ -97,7 +103,7 @@ public byte[] getByteData(String input) throws IOException, NumberFormatExceptio File file = new File(usedServer.getLastLogFilePath()); try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r")) { - int lines = parseInt(input); + int lines = getLines(params); long fileLength = randomAccessFile.length(); List logLines = new ArrayList<>(); @@ -123,13 +129,15 @@ public byte[] getByteData(String input) throws IOException, NumberFormatExceptio throw new IOException(String.format("Error while accessing log files at [%s].", currentServer.getCurrentServer().getLastLogFilePath()), exception); } catch (NumberFormatException exception) { - throw new NumberFormatException(String.format("The given [%s] lines number is not a valid number.", input)); + throw new NumberFormatException( + String.format("The given [%s] lines number is not a valid number.", params.get(NO_LINES)[0])); } } @Override - public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) + public void addZipEntry(ZipOutputStream zipOutputStream, Map params) { + Map filters = getFilters(params); byte[] buffer = new byte[2048]; try { File logsFolder = new File(currentServer.getCurrentServer().getLogsFolderPath()); @@ -160,6 +168,31 @@ public void addZipEntry(ZipOutputStream zipOutputStream, Map fil } } + private static Map getFilters(Map params) + { + Map filters = new HashMap<>(); + if (params != null) { + filters.put(FROM, !Objects.equals(params.get(FROM)[0], "") ? params.get(FROM)[0] : null); + filters.put(TO, !Objects.equals(params.get(TO)[0], "") ? params.get(TO)[0] : null); + } + return filters; + } + + private int getLines(Map params) + { + String noLines; + if (params == null) { + noLines = DEFAULT_NO_LINES; + } else { + noLines = params.get(NO_LINES)[0]; + if (noLines == null || noLines.isEmpty()) { + noLines = DEFAULT_NO_LINES; + } + } + int lines = parseInt(noLines); + return lines; + } + /** * Check that the file date is in the filter range. Returns {@code true} if no filter is provided. * @@ -179,15 +212,15 @@ private boolean checkFilters(File file, Map filters) String fileDateString = matcher.group(); LocalDate fileDate = LocalDate.parse(fileDateString); DateTimeFormatter filtersFormatter = DateTimeFormatter.ofPattern(userDateFormat); - if (filters.get(FROM_DATE_FILTER_KEY) != null && filters.get(TO_DATE_FILTER_KEY) != null) { - LocalDate fromDate = LocalDate.parse(filters.get(FROM_DATE_FILTER_KEY), filtersFormatter); - LocalDate toDate = LocalDate.parse(filters.get(TO_DATE_FILTER_KEY), filtersFormatter); + if (filters.get(FROM) != null && filters.get(TO) != null) { + LocalDate fromDate = LocalDate.parse(filters.get(FROM), filtersFormatter); + LocalDate toDate = LocalDate.parse(filters.get(TO), filtersFormatter); return fileDate.isAfter(fromDate.minusDays(1)) && fileDate.isBefore(toDate.plusDays(1)); - } else if (filters.get(FROM_DATE_FILTER_KEY) != null) { - LocalDate fromDate = LocalDate.parse(filters.get(FROM_DATE_FILTER_KEY), filtersFormatter); + } else if (filters.get(FROM) != null) { + LocalDate fromDate = LocalDate.parse(filters.get(FROM), filtersFormatter); return fileDate.isAfter(fromDate.minusDays(1)); - } else if (filters.get(TO_DATE_FILTER_KEY) != null) { - LocalDate toDate = LocalDate.parse(filters.get(TO_DATE_FILTER_KEY), filtersFormatter); + } else if (filters.get(TO) != null) { + LocalDate toDate = LocalDate.parse(filters.get(TO), filtersFormatter); return fileDate.isBefore(toDate.plusDays(1)); } else { return true; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java index ccfed297..fd91ac2e 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java @@ -69,13 +69,13 @@ public class XWikiConfigFileDataResource implements DataResource private Logger logger; @Override - public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) + public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) { addZipEntry(zipOutputStream); } @Override - public byte[] getByteData(String input) throws IOException + public byte[] getByteData(Map input) throws IOException { try { ServerIdentifier usedServer = currentServer.getCurrentServer(); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java index 8c8960ef..4127b6dc 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java @@ -69,13 +69,13 @@ public class XWikiPropertiesFileDataResource implements DataResource private Logger logger; @Override - public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) + public void addZipEntry(ZipOutputStream zipOutputStream, Map filters) { addZipEntry(zipOutputStream); } @Override - public byte[] getByteData(String input) throws IOException + public byte[] getByteData(Map input) throws IOException { try { ServerIdentifier usedServer = currentServer.getCurrentServer(); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java index 19d2cf30..482468c2 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResource.java @@ -43,7 +43,6 @@ import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.web.XWikiRequest; import com.xwiki.admintools.internal.files.ImportantFilesManager; -import com.xwiki.admintools.internal.files.resources.LogsDataResource; import com.xwiki.admintools.rest.AdminToolsResource; /** @@ -78,17 +77,11 @@ public Response getFile(String hint) } try { byte[] fileContent; - if (hint.equals(LogsDataResource.HINT)) { - XWikiContext wikiContext = xcontextProvider.get(); - XWikiRequest xWikiRequest = wikiContext.getRequest(); - String noLines = xWikiRequest.getParameter("noLines"); - if (noLines == null || noLines.equals("")) { - noLines = "1000"; - } - fileContent = importantFilesManager.getFile(hint, noLines); - } else { - fileContent = importantFilesManager.getFile(hint, null); - } + XWikiContext wikiContext = xcontextProvider.get(); + XWikiRequest xWikiRequest = wikiContext.getRequest(); + Map formParameters = xWikiRequest.getParameterMap(); + + fileContent = importantFilesManager.getFile(hint, formParameters); InputStream inputStream = new ByteArrayInputStream(fileContent); return Response.ok(inputStream).type(MediaType.TEXT_PLAIN_TYPE).build(); } catch (IOException e) { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index 8a9b77b6..2622322b 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -27,17 +27,20 @@ import org.xwiki.component.annotation.Component; import org.xwiki.script.service.ScriptService; +import org.xwiki.stability.Unstable; import com.xwiki.admintools.internal.AdminToolsManager; /** * Admin Tools script services. * + * @since 1.0 * @version $Id$ */ @Component @Named("admintools") @Singleton +@Unstable public class AdminToolsScriptService implements ScriptService { @Inject diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java index b10ec214..0b391a2b 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java @@ -49,9 +49,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.AdditionalMatchers.aryEq; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -95,6 +98,8 @@ public class ImportantFilesManagerTest @Mock private Logger logger; + private final Map params = Map.of("input", new String[]{"good_input"}); + @Test void getFile() throws Exception { @@ -102,9 +107,9 @@ void getFile() throws Exception dataResourceList.add(archiverDataResource); when(dataResources.get()).thenReturn(dataResourceList); when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); - when(archiverDataResource.getByteData("input")).thenReturn(new byte[] { 2 }); + when(archiverDataResource.getByteData(params)).thenReturn(new byte[] { 2 }); - assertArrayEquals(new byte[] { 2 }, importantFilesManager.getFile("data_resource_identifier", "input")); + assertArrayEquals(new byte[] { 2 }, importantFilesManager.getFile("data_resource_identifier", params)); } @Test @@ -115,9 +120,10 @@ void getFileResourceNotFound() when(dataResources.get()).thenReturn(dataResourceList); when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); Exception exception = assertThrows(Exception.class, () -> { - importantFilesManager.getFile("data_resource_identifier_invalid", "input"); + importantFilesManager.getFile("data_resource_identifier_invalid", params); }); - assertEquals("File provider not found!", exception.getMessage()); + assertEquals("Could not find a DataResource implementation for [data_resource_identifier_invalid].", + exception.getMessage()); } @Test @@ -127,9 +133,9 @@ void getFileDataResourceError() throws Exception dataResourceList.add(archiverDataResource); when(dataResources.get()).thenReturn(dataResourceList); when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); - when(archiverDataResource.getByteData("input")).thenThrow(new IOException("IO Error")); + when(archiverDataResource.getByteData(params)).thenThrow(new IOException("IO Error")); Exception exception = assertThrows(Exception.class, () -> { - importantFilesManager.getFile("data_resource_identifier", "input"); + importantFilesManager.getFile("data_resource_identifier", params); }); assertEquals("Error while managing file.", exception.getMessage()); } @@ -142,9 +148,9 @@ void downloadMultipleFiles() throws Exception request.put("files", files); request.put("from", new String[] { "" }); request.put("to", new String[] { "" }); - Map filters = new HashMap<>(); - filters.put("from", !Objects.equals(request.get("from")[0], "") ? request.get("from")[0] : null); - filters.put("to", !Objects.equals(request.get("to")[0], "") ? request.get("to")[0] : null); + Map filters = new HashMap<>(); + filters.put("from", new String[] { "" }); + filters.put("to", new String[] { "" }); List dataResourceList = new ArrayList<>(); dataResourceList.add(archiverDataResource); @@ -155,16 +161,13 @@ void downloadMultipleFiles() throws Exception when(archiverLogsDataResource.getIdentifier()).thenReturn(LogsDataResource.HINT); importantFilesManager.getFilesArchive(request); - verify(archiverDataResource).addZipEntry(any(ZipOutputStream.class), isNull()); - verify(archiverLogsDataResource).addZipEntry(any(ZipOutputStream.class), eq(filters)); + verify(archiverDataResource).addZipEntry(any(ZipOutputStream.class), any()); + verify(archiverLogsDataResource).addZipEntry(any(ZipOutputStream.class), any()); } @Test - void downloadMultipleFilesNoArchiverFound() + void downloadMultipleFilesNoArchiverFound() throws Exception { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(importantFilesManager, "logger", this.logger); - String[] files = { "data_resource_identifier_invalid", LogsDataResource.HINT }; Map request = new HashMap<>(); request.put("files", files); @@ -172,19 +175,14 @@ void downloadMultipleFilesNoArchiverFound() dataResourceList.add(archiverDataResource); when(dataResources.get()).thenReturn(dataResourceList); when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); - Exception exception = assertThrows(Exception.class, () -> { - importantFilesManager.getFilesArchive(request); - }); - assertEquals("Error while generating the files archive.", exception.getMessage()); + importantFilesManager.getFilesArchive(request); + verify(archiverDataResource, never()).addZipEntry(any(ZipOutputStream.class), any()); } @Test void downloadMultipleFilesInvalidRequest() { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(importantFilesManager, "logger", this.logger); - String[] files = { "data_resource_identifier", LogsDataResource.HINT }; Map request = new HashMap<>(); request.put("files", files); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java index ec865f87..a5ccd9ea 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java @@ -100,9 +100,6 @@ void getByteDataSuccess() throws Exception @Test void getByteDataThrowError() throws Exception { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(dataProviderResource, "logger", this.logger); - when(dataProvider.getDataAsJSON()).thenThrow(new Exception("TEST - PROVIDER ERROR AT GET DATA AS JASON!")); Exception exception = assertThrows(Exception.class, () -> { this.dataProviderResource.getByteData(null); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java index 6391c0b8..7d3baf8d 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java @@ -72,6 +72,8 @@ @ComponentTest public class LogsDataResourceTest { + private final Map params = Map.of("noLines", new String[] { "44" }); + @Mock ZipOutputStream zipOutputStream; @@ -153,15 +155,12 @@ void getByteDataSuccess() throws Exception when(serverIdentifier.getLastLogFilePath()).thenReturn(testFile.getAbsolutePath()); readLines(44); - assertArrayEquals(String.join("\n", logLines).getBytes(), logsDataResource.getByteData("44")); + assertArrayEquals(String.join("\n", logLines).getBytes(), logsDataResource.getByteData(params)); } @Test void getByteDataFileNotFound() { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(logsDataResource, "logger", this.logger); - File testFile = new File("server.2023-10-06.log"); assertFalse(testFile.exists()); @@ -177,11 +176,8 @@ void getByteDataFileNotFound() @Test void getByteDataServerNotFound() { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(logsDataResource, "logger", this.logger); - Exception exception = assertThrows(Exception.class, () -> { - this.logsDataResource.getByteData("44"); + this.logsDataResource.getByteData(params); }); assertEquals("Server not found! Configure path in extension configuration.", exception.getMessage()); logsDir.delete(); @@ -190,17 +186,39 @@ void getByteDataServerNotFound() @Test void getByteDataIncorrectInput() { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(logsDataResource, "logger", this.logger); - when(currentServer.getCurrentServer()).thenReturn(serverIdentifier); when(serverIdentifier.getLastLogFilePath()).thenReturn(testFile.getAbsolutePath()); String invalidInput = "not a number"; - Exception exception = assertThrows(Exception.class, () -> logsDataResource.getByteData(invalidInput)); + Map params = Map.of("noLines", new String[] { "not a number" }); + Exception exception = assertThrows(Exception.class, () -> logsDataResource.getByteData(params)); assertEquals(String.format("The given [%s] lines number is not a valid number.", invalidInput), exception.getMessage()); } + @Test + void getByteDataNullInput() throws IOException + { + when(currentServer.getCurrentServer()).thenReturn(serverIdentifier); + when(serverIdentifier.getLastLogFilePath()).thenReturn(testFile.getAbsolutePath()); + + readLines(1000); + + assertArrayEquals(String.join("\n", logLines).getBytes(), + logsDataResource.getByteData(null)); + } + + @Test + void getByteDataNullNoLines() throws IOException + { + when(currentServer.getCurrentServer()).thenReturn(serverIdentifier); + when(serverIdentifier.getLastLogFilePath()).thenReturn(testFile.getAbsolutePath()); + Map params = Map.of("noLines", new String[] { null }); + readLines(1000); + + assertArrayEquals(String.join("\n", logLines).getBytes(), + logsDataResource.getByteData(params)); + } + @Test void addZipEntrySuccessNoFilters() throws IOException { @@ -218,9 +236,9 @@ void addZipEntrySuccessWithFilters() throws IOException when(serverIdentifier.getLogsFolderPath()).thenReturn(logsDir.getAbsolutePath()); when(serverIdentifier.getLogsPattern()).thenReturn(Pattern.compile("\\d{4}-\\d{2}-\\d{2}")); - Map filters = new HashMap<>(); - filters.put("from", "06-10-2023"); - filters.put("to", "07-10-2023"); + Map filters = new HashMap<>(); + filters.put("from", new String[]{"06-10-2023"}); + filters.put("to", new String[]{"07-10-2023"}); readLines(400); logsDataResource.addZipEntry(zipOutputStream, filters); byte[] buff = new byte[2048]; @@ -240,9 +258,9 @@ void addZipEntryFilesOutOfFiltersRange() throws IOException when(serverIdentifier.getLogsPattern()).thenReturn(Pattern.compile("\\d{4}-\\d{2}-\\d{2}")); when(xWiki.getXWikiPreference("dateformat", "dd-MM-yyyy", wikiContext)).thenReturn("dd yy MM"); - Map filters = new HashMap<>(); - filters.put("from", "10 23 10"); - filters.put("to", null); + Map filters = new HashMap<>(); + filters.put("from", new String[]{"10 23 10"}); + filters.put("to", new String[]{ null }); logsDataResource.addZipEntry(zipOutputStream, filters); verify(zipOutputStream, never()).closeEntry(); @@ -257,9 +275,9 @@ void addZipEntryDateParseError() when(currentServer.getCurrentServer()).thenReturn(serverIdentifier); when(serverIdentifier.getLogsFolderPath()).thenReturn(logsDir.getAbsolutePath()); when(serverIdentifier.getLogsPattern()).thenReturn(Pattern.compile("\\bserver\\b")); - Map filters = new HashMap<>(); - filters.put("from", "2023-10-03"); - filters.put("to", "2023-10-05"); + Map filters = new HashMap<>(); + filters.put("from", new String[]{"2023-10-03"}); + filters.put("to", new String[]{"2023-10-05"}); logsDataResource.addZipEntry(zipOutputStream, filters); verify(logger).warn("Failed to get logs. Root cause is: [{}]", "DateTimeParseException: Text 'server' could not be parsed at index 0"); @@ -268,15 +286,12 @@ void addZipEntryDateParseError() @Test void addZipEntryPatternNotFound() throws IOException { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(logsDataResource, "logger", this.logger); - when(currentServer.getCurrentServer()).thenReturn(serverIdentifier); when(serverIdentifier.getLogsFolderPath()).thenReturn(logsDir.getAbsolutePath()); when(serverIdentifier.getLogsPattern()).thenReturn(Pattern.compile("\\d{4}_\\d{2}_\\d{2}")); - Map filters = new HashMap<>(); - filters.put("from", "2023-10-03"); - filters.put("to", "2023-10-05"); + Map filters = new HashMap<>(); + filters.put("from", new String[]{"2023-10-03"}); + filters.put("to", new String[]{"2023-10-05"}); logsDataResource.addZipEntry(zipOutputStream, filters); verify(zipOutputStream, never()).closeEntry(); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java index 655e275b..3ae1b1db 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java @@ -137,9 +137,6 @@ void getByteData() throws Exception @Test void getByteDataFileNotFound() { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(configFileDataResource, "logger", this.logger); - File cfgDir2 = new File(tmpDir, "xwiki_cfg_folder_fail"); cfgDir2.mkdir(); cfgDir2.deleteOnExit(); @@ -156,9 +153,6 @@ void getByteDataFileNotFound() @Test void getByteDataServerNotFound() throws Exception { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(configFileDataResource, "logger", this.logger); - File cfgDir2 = new File(tmpDir, "xwiki_cfg_folder_fail"); cfgDir2.mkdir(); cfgDir2.deleteOnExit(); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java index 34443604..cf020768 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java @@ -137,9 +137,6 @@ void getByteData() throws Exception @Test void getByteDataFileNotFound() { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(propertiesFileDataResource, "logger", this.logger); - File propertiesDir2 = new File(tmpDir, "xwiki_properties_folder_fail"); propertiesDir2.mkdir(); propertiesDir2.deleteOnExit(); @@ -156,9 +153,6 @@ void getByteDataFileNotFound() @Test void getByteDataServerNotFound() throws Exception { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(propertiesFileDataResource, "logger", this.logger); - File propertiesDir2 = new File(tmpDir, "xwiki_properties_folder_fail"); propertiesDir2.mkdir(); propertiesDir2.deleteOnExit(); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java index 21d21ab7..87ff0e9e 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java @@ -85,6 +85,8 @@ public class DefaultAdminToolsResourceTest @Mock private Logger logger; + private final Map params = Map.of("noLines", new String[]{"1000"}); + @BeforeComponent void beforeComponent() { @@ -101,13 +103,13 @@ void setUp() when(xWikiContext.getWikiReference()).thenReturn(wikiReference); when(authorizationManager.hasAccess(Right.ADMIN, user, wikiReference)).thenReturn(true); when(xWikiContext.getRequest()).thenReturn(xWikiRequest); + when(xWikiRequest.getParameterMap()).thenReturn(params); } @Test void getFile() throws Exception { - when(importantFilesManager.getFile("resource_hint", null)).thenReturn(new byte[] { 2 }); - + when(importantFilesManager.getFile("resource_hint", params)).thenReturn(new byte[] { 2 }); assertEquals(200, defaultAdminToolsResource.getFile("resource_hint").getStatus()); } @@ -117,7 +119,7 @@ void getFileNotFound() throws Exception when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(defaultAdminToolsResource, "logger", this.logger); - when(importantFilesManager.getFile("resource_hint", null)).thenThrow(new IOException("FILE NOT FOUND")); + when(importantFilesManager.getFile("resource_hint", params)).thenThrow(new IOException("FILE NOT FOUND")); assertEquals(404, defaultAdminToolsResource.getFile("resource_hint").getStatus()); verify(logger).warn("Error while handling file from DataResource [{}]. Root cause: [{}]", "resource_hint", @@ -196,15 +198,14 @@ void getFilesNotAdmin() @Test void getLastLogs() throws Exception { - when(importantFilesManager.getFile(LogsDataResource.HINT, "30")).thenReturn(new byte[] { 2 }); - when(xWikiRequest.getParameter("noLines")).thenReturn("30"); + when(importantFilesManager.getFile(LogsDataResource.HINT, params)).thenReturn(new byte[] { 2 }); assertEquals(200, defaultAdminToolsResource.getFile(LogsDataResource.HINT).getStatus()); } @Test void getLastLogsNoInput() throws Exception { - when(importantFilesManager.getFile(LogsDataResource.HINT, "1000")).thenReturn(new byte[] { 2 }); + when(importantFilesManager.getFile(LogsDataResource.HINT, params)).thenReturn(new byte[] { 2 }); when(xWikiRequest.getParameter("noLines")).thenReturn(""); assertEquals(200, defaultAdminToolsResource.getFile(LogsDataResource.HINT).getStatus()); } diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml index 467152ea..ede8020d 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml @@ -104,7 +104,7 @@ </label> </dt> <dt> - <label><input type="checkbox" name="files" value="dataProviderResource" checked> + <label><input type="checkbox" name="files" value="dataProvider" checked> $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.provided')) </label> </dt> diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index ae495942..6501ca85 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -29,7 +29,7 @@ xwiki:XWiki.Admin xwiki:XWiki.Admin 1.1 - AdminTools + Admin Tools false xwiki/2.1 @@ -87,7 +87,7 @@ - AdminToolsConfigEventListener + AdminToolsEventListener org.xwiki.observation.EventListener From c264f936f4c6114920a4bf5172d294f1654df0e6 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Wed, 1 Nov 2023 12:53:52 +0200 Subject: [PATCH 58/72] Add support for downloading important files #8 --- .../admintools/download/DataResource.java | 4 +- .../XWikiConfigFileDataResource.java | 2 +- .../XWikiPropertiesFileDataResource.java | 2 +- .../src/main/resources/AdminTools/WebHome.xml | 61 ------------------- 4 files changed, 4 insertions(+), 65 deletions(-) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java b/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java index e97be4d0..2fc1f70c 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/download/DataResource.java @@ -44,12 +44,12 @@ public interface DataResource /** * Retrieve the content of a system file. * - * @param input Can be used to send additional info to the component. + * @param params Can be used to send additional info to the component. * @return the content of the file as an {@link Byte} array. * @throws IOException when there are errors while handling searched files. * @throws NumberFormatException when there is an invalid numeric input. */ - byte[] getByteData(Map input) throws Exception; + byte[] getByteData(Map params) throws Exception; /** * Get the hint of a component. diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java index fd91ac2e..4550f128 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResource.java @@ -75,7 +75,7 @@ public void addZipEntry(ZipOutputStream zipOutputStream, Map f } @Override - public byte[] getByteData(Map input) throws IOException + public byte[] getByteData(Map params) throws IOException { try { ServerIdentifier usedServer = currentServer.getCurrentServer(); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java index 4127b6dc..28caf86a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResource.java @@ -75,7 +75,7 @@ public void addZipEntry(ZipOutputStream zipOutputStream, Map f } @Override - public byte[] getByteData(Map input) throws IOException + public byte[] getByteData(Map params) throws IOException { try { ServerIdentifier usedServer = currentServer.getCurrentServer(); diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index 6501ca85..b8ea0073 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -35,67 +35,6 @@ xwiki/2.1 false {{dashboard/}} - - AdminTools.WebHome - 0 - XWiki.ComponentClass - 0c51bf0c-1de8-49b1-bf13-701ba2160c5b - - XWiki.ComponentClass - - - - - - - - - 0 - roleHint - 2 - Component Role Hint - 30 - 0 - com.xpn.xwiki.objects.classes.StringClass - - - 0 - roleType - 1 - Component Role Type - 30 - 0 - com.xpn.xwiki.objects.classes.StringClass - - - 0 - 0 - select - forbidden - 0 - 0 - scope - 3 - Component Scope - 0 - - |, - 1 - 0 - wiki=Current Wiki|user=Current User|global=Global - com.xpn.xwiki.objects.classes.StaticListClass - - - - AdminToolsEventListener - - - org.xwiki.observation.EventListener - - - wiki - - AdminTools.WebHome 1 From e10c232605a29e10dffbc9440f428cbef37289f2 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Wed, 1 Nov 2023 14:00:45 +0200 Subject: [PATCH 59/72] Add support for downloading important files #8 * Merged with main branch --- application-admintools-default/pom.xml | 2 +- .../admintools/internal/data/ConfigurationDataProvider.java | 1 + .../internal/data/identifiers/TomcatIdentifier.java | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index d75a5691..c7138581 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -68,6 +68,6 @@ - 0.81 + 0.79 \ No newline at end of file diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java index 7ca0a9e9..c39af63a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/ConfigurationDataProvider.java @@ -26,6 +26,7 @@ import javax.inject.Named; import javax.inject.Singleton; +import org.apache.commons.lang.exception.ExceptionUtils; import org.xwiki.activeinstalls2.internal.data.DatabasePing; import org.xwiki.component.annotation.Component; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java index c18b196f..96065e7e 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifier.java @@ -20,8 +20,8 @@ package com.xwiki.admintools.internal.data.identifiers; import java.io.File; -import java.util.regex.Pattern; import java.util.Map; +import java.util.regex.Pattern; import javax.inject.Inject; import javax.inject.Named; @@ -34,7 +34,7 @@ import com.xwiki.admintools.internal.PingProvider; /** - * {@link ServerIdentifier} implementation used for identifying a Tomcat server and retrieving it's info. + * {@link ServerIdentifier} implementation used for identifying a Tomcat server and retrieving its info. * * @version $Id$ */ From 1ca23e2cc75c2e09feafd1d1c5ca4d7bc0ec11fd Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Wed, 1 Nov 2023 14:35:35 +0200 Subject: [PATCH 60/72] Create a health check dashboard section #13 * Small UI modifications --- .../AdminTools/Code/AdminToolsJS.xml | 6 +- .../AdminTools/Code/HealthCheckResources.xml | 24 ++-- .../src/main/resources/AdminTools/WebHome.xml | 113 +++++------------- 3 files changed, 39 insertions(+), 104 deletions(-) diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index c4b73f50..1da26185 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -129,6 +129,7 @@ let documentReference = XWiki.Model.resolve('AdminTools.Code.HealthCheckResources', XWiki.EntityType.DOCUMENT); return new XWiki.Document(documentReference).getURL('get'); } + const runHealthCheckJob = function() { var data = []; data.push( @@ -169,7 +170,6 @@ require.undef('health-check-job'); $.get(getResourceURL(), function(data) { let jobMinJsURL = $(data).find('input[name="jobMinJsURL"]').val(); - require.config({ paths: { 'health-check-job': jobMinJsURL @@ -191,7 +191,7 @@ $('.job-status').attr('data-url', healthCheckJobStatusURL); $('#admin_tools_job_start').prop("disabled", true); $('.job-status').show(); - } else { + } else if (jobState == "FINISHED") { $('.job-status').show(); } }); @@ -203,9 +203,9 @@ $(".log").empty(); $('#admin_tools_job_start').prop("disabled", true); $.get(getResourceURL(), function(data) { + runHealthCheckJob() reinitialiseProgressBar() initialiseJobJS() - runHealthCheckJob() // Inject the content into the job-status div let healthCheckJobStatusURL = $(data).find('input[name="healthCheckJobStatusURL"]').val(); $('.job-status').attr('data-url', healthCheckJobStatusURL); diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml index bd2b7306..b4ba2b78 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml @@ -62,6 +62,7 @@ #set ($healthCheckJobId = $request.jobId.split('/')) #returnHealthCheckJobStatusJSON($healthCheckJobId) #else + #set ($jobMinJsURL = $xwiki.getSkinFile('uicomponents/job/job.min.js')) #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) #set ($jobId = $healthCheckJobRequest.id) #set ($healthJobStatusURL = $xwiki.getURL('AdminTools.Code.HealthCheckJob', 'get', $escapetool.url({ @@ -69,27 +70,20 @@ 'outputSyntax': 'plain' }))) #set ($healthJobStatus = $services.job.getJobStatus($jobId)) - #set ($jobMinJsURL = $xwiki.getSkinFile('uicomponents/job/job.min.js')) + #set ($percent = $healthJobStatus.progress.offset) + #if (!$percent) + #set ($percent = 0) + #end + #set ($percent = $numbertool.toNumber($mathtool.mul($percent, 100)).intValue()) {{html clean=false}} <div hidden> <input type="text" name="healthCheckJobStatusURL" value=$healthJobStatusURL></input> - <input type="text" name="jobMinJsURL" value=$jobMinJsURL></input> + <input type="text" id="jobMinJsURL" name="jobMinJsURL" value=$jobMinJsURL></input> <input type="text" name="jobState" value=$healthJobStatus.state></input> - <div class="ui-progress"> - <div class="box info hidden" id="state-none-hint"> - This job is waiting to start, please be patient: another job might be running on the same pages. - </div> - <div class="ui-progress-background"> - <div class="ui-progress-bar green" style="width:0%"></div> - </div> - </div> + #displayJobProgressBar($healthJobStatus) </div> {{/html}} #end #end - - - -{{/velocity}} - +{{/velocity}} \ No newline at end of file diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index 01729fb3..57e67013 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -35,67 +35,6 @@ xwiki/2.1 false {{dashboard/}} - - AdminTools.WebHome - 0 - XWiki.ComponentClass - 0c51bf0c-1de8-49b1-bf13-701ba2160c5b - - XWiki.ComponentClass - - - - - - - - - 0 - roleHint - 2 - Component Role Hint - 30 - 0 - com.xpn.xwiki.objects.classes.StringClass - - - 0 - roleType - 1 - Component Role Type - 30 - 0 - com.xpn.xwiki.objects.classes.StringClass - - - 0 - 0 - select - forbidden - 0 - 0 - scope - 3 - Component Scope - 0 - - |, - 1 - 0 - wiki=Current Wiki|user=Current User|global=Global - com.xpn.xwiki.objects.classes.StaticListClass - - - - AdminToolsEventListener - - - org.xwiki.observation.EventListener - - - wiki - - AdminTools.WebHome 1 @@ -290,38 +229,40 @@ $services.admintools.getFilesSection() #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) #set ($jobId = $healthCheckJobRequest.id) #set ($healthJobStatus = $services.job.getJobStatus($jobId)) - {{html clean='false'}} -<div class="adminToolsDashboardItem" id="healthCheck"> - <h2>$services.icon.renderHTML('bug') - Health check</h2> - <p>Check if your instance is configured correctly and is properly running. For any issues, check out this <a href="$xwiki.getURL("AdminTools.HelpLinks")"><strong>solutions</strong></a>.</p> - <hr/> - <div class="healthCheckWrapper"> - <div class="healthCheckLastCheck"> - Time since the last health check: $services.date.displayTimeAgo($healthJobStatus.getEndDate()) + <div class="adminToolsDashboardItem" id="healthCheck"> + <h2>$services.icon.renderHTML('bug') + Health check</h2> + <p>Check if your instance is configured correctly and is properly running. For any issues, check out this + <a href="$xwiki.getURL("AdminTools.HelpLinks")"><strong>solutions</strong></a>.</p> + <hr/> + <div class="healthCheckWrapper"> + <div class="healthCheckLastCheck"> + Time since the last health check: $services.date.displayTimeAgo($healthJobStatus.getEndDate()) + </div> + <div class="buttonwrapper"> + <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" + value="startHealthCheck">Start health check</button> + </div> </div> - <div class="buttonwrapper"> - <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" value="startHealthCheck">Start health check</button> - </div> - </div> - <div hidden class="xcontent job-status" data-url=""> - #if ($healthJobStatus.state != 'FINISHED') - #displayJobProgressBar($jobStatus) - #else - #jobFinishedMessage($healthJobStatus, $translationPrefix, $successKey, $errorKey, $canceledKey) - #end - #if ($showLogs || $isAdvancedUser || $isSuperAdmin) + <div hidden class="xcontent job-status" data-url=""> #if ($healthJobStatus.state != 'FINISHED') - #displayJobStatusLog($jobStatus true) + #displayJobProgressBar($jobStatus) #else - #displayJobStatusLog($healthJobStatus true) + #jobFinishedMessage($healthJobStatus, $translationPrefix, $successKey, $errorKey, $canceledKey) + #end + #if ($showLogs || $isAdvancedUser || $isSuperAdmin) + #if ($healthJobStatus.state != 'FINISHED') + #displayJobStatusLog($jobStatus true) + #else + #displayJobStatusLog($healthJobStatus true) + #end #end - #end + </div> </div> -</div> {{/html}} -{{/velocity}} +{{/velocity}} + 1, 2 From 376a4675d008a77f3f047628242320b38d5de220 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Wed, 1 Nov 2023 19:43:25 +0200 Subject: [PATCH 61/72] Create a health check dashboard section #13 * Added translations * Integrated transaltions in Java * Added MemoryHealthCheck --- .../health/checks/CacheHealthCheck.java | 81 ------------- .../health/checks/MemoryHealthCheck.java | 109 ++++++++++++++++++ .../health/checks/PerformanceHealthCheck.java | 26 +++-- .../AbstractConfigurationHealthCheck.java | 13 +-- .../ConfigurationDatabaseHealthCheck.java | 6 +- .../ConfigurationJavaHealthCheck.java | 8 +- .../ConfigurationOsHealthCheck.java | 4 +- .../SecuritySystemEncodingHealthCheck.java | 9 +- .../SecurityXWikiEncodingHealthCheck.java | 10 +- .../main/resources/META-INF/components.txt | 2 +- .../AdminTools/Code/Translations.xml | 61 +++++++--- .../src/main/resources/AdminTools/WebHome.xml | 12 +- 12 files changed, 204 insertions(+), 137 deletions(-) delete mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/CacheHealthCheck.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/CacheHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/CacheHealthCheck.java deleted file mode 100644 index d5910aa4..00000000 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/CacheHealthCheck.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools.internal.health.checks; - -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Provider; -import javax.inject.Singleton; - -import org.slf4j.Logger; -import org.xwiki.cache.Cache; -import org.xwiki.cache.CacheManagerConfiguration; -import org.xwiki.component.annotation.Component; - -import com.xpn.xwiki.XWiki; -import com.xpn.xwiki.XWikiContext; -import com.xpn.xwiki.doc.XWikiDocument; -import com.xpn.xwiki.store.XWikiCacheStore; -import com.xwiki.admintools.health.HealthCheck; -import com.xwiki.admintools.health.HealthCheckResult; - -import java.lang.management.ManagementFactory; -import java.util.Set; - -import javax.management.MBeanServer; -import javax.management.ObjectName; - -import groovy.jmx.GroovyMBean; - -@Component -@Named(CacheHealthCheck.HINT) -@Singleton -public class CacheHealthCheck implements HealthCheck -{ - public final static String HINT = "CACHE_HEALTH_CHECK"; - - @Inject - protected Provider xcontextProvider; - - @Inject - CacheManagerConfiguration cacheManagerConfiguration; - - @Inject - private Logger logger; - @Override - public HealthCheckResult check() - { - try { - MBeanServer server = ManagementFactory.getPlatformMBeanServer(); - ObjectName query = new ObjectName("org.xwiki.infinispan:component=Statistics,*"); - Set names = server.queryNames(query, null); - for (ObjectName objectName : names){ - GroovyMBean mbean = new GroovyMBean(server, objectName, true); - for(String attribute : mbean.listAttributeNames()) { - logger.warn(String.format("%s - %s", attribute, mbean.getProperty(attribute))); - String b = ""; - } - } - logger.error("dummy err"); - return new HealthCheckResult(); - } catch (Exception ignored){} - return new HealthCheckResult(); - } -} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java new file mode 100644 index 00000000..5ebea8ea --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java @@ -0,0 +1,109 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.slf4j.Logger; +import org.xwiki.cache.CacheManagerConfiguration; +import org.xwiki.component.annotation.Component; +import org.xwiki.configuration.ConfigurationSource; +import org.xwiki.localization.ContextualLocalizationManager; + +import com.xpn.xwiki.XWiki; +import com.xpn.xwiki.XWikiContext; +import com.xwiki.admintools.health.HealthCheck; +import com.xwiki.admintools.health.HealthCheckResult; + +@Component +@Named(MemoryHealthCheck.HINT) +@Singleton +public class MemoryHealthCheck implements HealthCheck +{ + public static final String HINT = "CACHE_HEALTH_CHECK"; + + @Inject + protected ContextualLocalizationManager localization; + + @Inject + protected Provider xcontextProvider; + + @Inject + CacheManagerConfiguration cacheManagerConfiguration; + + @Inject + @Named("xwikicfg") + private ConfigurationSource configurationSource; + + @Inject + private Logger logger; + + @Override + public HealthCheckResult check() + { + boolean cacheOk = isEnoughCache(); + boolean memoryOk = hasEnoughMemory(); + if (cacheOk && memoryOk) { + return new HealthCheckResult(); + } + return new HealthCheckResult("There are memory issues!", "dummy memory help link"); + } + + private boolean isEnoughCache() + { + String storeCacheCapacity = configurationSource.getProperty("xwiki.store.cache.capacity"); + if (storeCacheCapacity == null || storeCacheCapacity.equals("500")) { + logger.warn(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.cache.warn")); + return false; + } + logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.cache.info")); + return true; + } + + private boolean hasEnoughMemory() + { + XWiki wiki = xcontextProvider.get().getWiki(); + float maxMemory = wiki.maxMemory(); + float totalFreeMemory = (maxMemory - (wiki.totalMemory() - wiki.freeMemory())) / (1024.0f * 1024); + float maxMemoryGB = maxMemory / (1024.0f * 1024 * 1024); + + if (maxMemoryGB < 1) { + logger.error(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.memory.mem.maxcapacity.error"), maxMemoryGB * 1024); + return false; + } + if (totalFreeMemory < 512) { + logger.error( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.mem.free.error"), + totalFreeMemory); + return false; + } else if (totalFreeMemory < 1024) { + logger.warn( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.mem.free.warn"), + totalFreeMemory); + return true; + } + logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.mem.info")); + return true; + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java index 4dc8dfad..304afdac 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java @@ -28,6 +28,7 @@ import org.slf4j.Logger; import org.xwiki.component.annotation.Component; +import org.xwiki.localization.ContextualLocalizationManager; import com.xwiki.admintools.health.HealthCheck; import com.xwiki.admintools.health.HealthCheckResult; @@ -43,16 +44,22 @@ public class PerformanceHealthCheck implements HealthCheck { public final static String HINT = "PERFORMANCE_HEALTH_CHECK"; + @Inject + protected ContextualLocalizationManager localization; + @Inject private Logger logger; @Override public HealthCheckResult check() { - if (!hasFreeSpace() || !hasMinimumCPURequirements() || !hasMinimumMemoryRequirements()) { + boolean hasFreeSpace = hasFreeSpace(); + boolean hasMinimumCPURequirements = hasMinimumCPURequirements(); + boolean hasMinimumMemoryRequirements = hasMinimumMemoryRequirements(); + if (!hasFreeSpace || !hasMinimumCPURequirements || !hasMinimumMemoryRequirements) { return new HealthCheckResult("performance issues", "minimum sys req link"); } - logger.info("System performance status OK!"); + logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.performance.info")); return new HealthCheckResult(); } @@ -67,24 +74,26 @@ private boolean hasFreeSpace() long freePartitionSpace = diskPartition.getFreeSpace(); float freeSpace = (float) freePartitionSpace / (1024 * 1024 * 1024); - if(freeSpace > 2) { + if (freeSpace > 2) { return true; } else { - logger.warn("There is not enough free space for the XWiki installation!"); + logger.warn( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.performance.space.warn")); return false; } } private boolean hasMinimumMemoryRequirements() { - long memorySize = ((com.sun.management.OperatingSystemMXBean) ManagementFactory - .getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); + long memorySize = + ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); float totalMemory = (float) memorySize / (1024 * 1024 * 1024) + 1; if (totalMemory > 2) { return true; } else { - logger.warn("There is not enough memory to safely run the XWiki installation!"); + logger.warn( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.performance.memory.warn")); return false; } } @@ -100,7 +109,8 @@ private boolean hasMinimumCPURequirements() if (cpuCores > 2 && maxFreq > 2048) { return true; } else { - logger.warn("The CPU does not satisfy the minimum system requirements!"); + logger.warn( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.performance.cpu.warn")); return false; } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java index bf35b05a..74d2904c 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java @@ -22,18 +22,21 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; import javax.inject.Inject; import javax.inject.Provider; import org.slf4j.Logger; +import org.xwiki.localization.ContextualLocalizationManager; import com.xwiki.admintools.DataProvider; import com.xwiki.admintools.health.HealthCheck; public abstract class AbstractConfigurationHealthCheck implements HealthCheck { + @Inject + protected ContextualLocalizationManager localization; + @Inject Logger logger; @@ -42,9 +45,7 @@ public abstract class AbstractConfigurationHealthCheck implements HealthCheck protected Map getJson(String hint) { - try { - TimeUnit.SECONDS.sleep(1); return findDataProvider(hint).getDataAsJSON(); } catch (Exception e) { return new HashMap<>(); @@ -53,10 +54,8 @@ protected Map getJson(String hint) private DataProvider findDataProvider(String hint) { - for (DataProvider dataProvider : dataProviders.get()) - { - if(dataProvider.getIdentifier().equals(hint)) - { + for (DataProvider dataProvider : dataProviders.get()) { + if (dataProvider.getIdentifier().equals(hint)) { return dataProvider; } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java index 7564e335..1f868818 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java @@ -37,11 +37,11 @@ public class ConfigurationDatabaseHealthCheck extends AbstractConfigurationHealt @Override public HealthCheckResult check() { - if (getJson(ConfigurationDataProvider.HINT).get("database") == null) { - logger.warn("Database not found!"); + if (getJson(ConfigurationDataProvider.HINT).get("databaseName") == null) { + logger.warn(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.database.warn")); return new HealthCheckResult("database_not_detected", "xwiki_db_configuration"); } - logger.info("Database status OK"); + logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.database.info")); return new HealthCheckResult(); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java index 43b86bdf..0ae2f514 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java @@ -45,17 +45,19 @@ public HealthCheckResult check() { String javaVersionString = getJson(ConfigurationDataProvider.HINT).get("javaVersion"); if (javaVersionString == null) { - logger.warn("Java version not found!"); + logger.warn(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.warn.found")); return new HealthCheckResult("java_version_not_found", "java_installation_link"); } String xwikiVersionString = getJson(ConfigurationDataProvider.HINT).get("xwikiVersion"); float xwikiVersion = parseFloat(xwikiVersionString); float javaVersion = parseFloat(javaVersionString); if (isJavaXWikiCompatible(xwikiVersion, javaVersion)) { - logger.warn("Java version is not compatible with the current XWiki installation!"); + logger.warn( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.warn.incompatible")); return new HealthCheckResult("java_xwiki_comp", xwikiJavaCompatibilityLink); } - logger.info("Java status OK."); + logger.info( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.info")); return new HealthCheckResult(); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java index 13039eda..db3a64f8 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java @@ -41,10 +41,10 @@ public HealthCheckResult check() || getJson(ConfigurationDataProvider.HINT).get("osVersion") == null || getJson(ConfigurationDataProvider.HINT).get("osArch") == null) { - logger.warn("There has been an error while gathering OS info."); + logger.warn(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.os.warn")); return new HealthCheckResult("os_issue", "os_support"); } - logger.info("OS info retrieval was successful."); + logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.os.info")); return new HealthCheckResult(); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java index e5db1e14..18788fc7 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java @@ -46,12 +46,13 @@ public HealthCheckResult check() Map securityJson = getJson(SecurityDataProvider.HINT); String langEnc = securityJson.get("LANG").split("\\.")[1]; String fileEnc = securityJson.get("fileEncoding"); - if (!acceptedEncodings.contains(langEnc) || !acceptedEncodings.contains(fileEnc)) - { - logger.warn("System encoding is [{}] should be UTF-8!", fileEnc); + if (!acceptedEncodings.contains(langEnc) || !acceptedEncodings.contains(fileEnc)) { + logger.warn( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.system.warn"), + fileEnc); return new HealthCheckResult("xwiki_encoding err", "xwiki config tutorial link"); } - logger.info("System encoding OK."); + logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.system.info")); return new HealthCheckResult(); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java index 0c1a42de..ca0760f2 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java @@ -46,13 +46,13 @@ public HealthCheckResult check() Map securityJson = getJson(SecurityDataProvider.HINT); String activeEnc = securityJson.get("activeEncoding"); String configEnc = securityJson.get("configurationEncoding"); - if (!acceptedEncodings.contains(activeEnc) - || !acceptedEncodings.contains(configEnc)) - { - logger.warn("XWiki encoding is [{}]. The encoding should be UTF-8!", activeEnc); + if (!acceptedEncodings.contains(activeEnc) || !acceptedEncodings.contains(configEnc)) { + logger.warn( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.xwiki.warn"), + activeEnc); return new HealthCheckResult("xwiki_encoding err", "xwiki config tutorial link"); } - logger.info("XWiki encoding is configured correctly."); + logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.xwiki.info")); return new HealthCheckResult(); } } diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index 8c7d3aa8..40a784bf 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -18,7 +18,7 @@ com.xwiki.admintools.internal.health.checks.configuration.ConfigurationOsHealthC com.xwiki.admintools.internal.health.checks.configuration.SecuritySystemEncodingHealthCheck com.xwiki.admintools.internal.health.checks.configuration.SecurityXWikiEncodingHealthCheck com.xwiki.admintools.internal.health.checks.PerformanceHealthCheck -com.xwiki.admintools.internal.health.checks.CacheHealthCheck +com.xwiki.admintools.internal.health.checks.MemoryHealthCheck com.xwiki.admintools.internal.health.job.HealthCheckJob com.xwiki.admintools.internal.rest.DefaultAdminToolsResource com.xwiki.admintools.internal.PingProvider diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml index 7aa9d709..b7fb5309 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml @@ -42,23 +42,6 @@ AdminTools.Code.ConfigurationClass_serverLocation=Server location AdminTools.Code.ConfigurationClass_serverLocation.hint=Path to the server location admin.admintools.description=Configure Admin Tools Application -## Modals -adminTools.dashboard.download.modal.button=Download -adminTools.dashboard.download.modal.date.from=From -adminTools.dashboard.download.modal.date.to=To -adminTools.dashboard.download.modal.provided=Configuration info -adminTools.dashboard.download.modal.title=Get support files -adminTools.dashboard.download.modal.xwikiConfig.title=xwiki.cfg -adminTools.dashboard.download.modal.xwikiProperties.title=xwiki.properties -adminTools.dashboard.download.modal.logs.title=Logs -adminTools.dashboard.download.modal.logs.filter.placeholder.from=Logs from date... -adminTools.dashboard.download.modal.logs.filter.placeholder.to=Logs to date... -adminTools.dashboard.logs.modal.submit=View -adminTools.dashboard.logs.modal.nLines.label=Number of extracted lines -adminTools.dashboard.logs.modal.title=Show last n lines of log -adminTools.dashboard.logs.modal.nLines.hint=Limited at 50000 lines. If the input is empty, the default of 1000 lines will be returned. -adminTools.dashboard.showLogs=View last n lines of log... - ## Dashboard sections ## Config adminTools.dashboard.section.backend.configuration.error=Server path was not found. Please manually add the path to the server on the Admin Tools configuration page. @@ -84,6 +67,33 @@ adminTools.dashboard.section.download.view.description=View files content adminTools.dashboard.section.download.view.properties=XWiki properties file adminTools.dashboard.section.download.warning=Before downloading and sending the files, please make sure you introduced the lines that may contain sensitive info in Admin Tools configuration page! +## Health check +adminTools.dashboard.section.healthcheck.database.info=Database status OK +adminTools.dashboard.section.healthcheck.database.warn=Database not found! +adminTools.dashboard.section.healthcheck.description=Check if your instance is configured correctly and is properly running. For any issues, check out this +adminTools.dashboard.section.healthcheck.description.link=solutions +adminTools.dashboard.section.healthcheck.java.info=Java status OK +adminTools.dashboard.section.healthcheck.java.warn.found=Java version not found! +adminTools.dashboard.section.healthcheck.java.warn.incompatible=Java version is not compatible with the current XWiki installation! +adminTools.dashboard.section.healthcheck.memory.cache.info=Cache status OK +adminTools.dashboard.section.healthcheck.memory.cache.warn=Store cache capacity is set at 500. Check Cache recommendations in solutions. +adminTools.dashboard.section.healthcheck.memory.mem.free.error=Your JVM instance has only [{}]MB free memory left! Consult the solution link for support! +adminTools.dashboard.section.healthcheck.memory.mem.free.warn=Your instance memory is running low. Currently only [{}]MB free left. +adminTools.dashboard.section.healthcheck.memory.mem.info=Memory status OK +adminTools.dashboard.section.healthcheck.memory.mem.maxcapacity.error=JVM memory is less than 1024MB. Currently: [{}]MB +adminTools.dashboard.section.healthcheck.os.info=OS info retrieval OK +adminTools.dashboard.section.healthcheck.os.warn=There has been an error while gathering OS info! +adminTools.dashboard.section.healthcheck.performance.cpu.warn=The CPU does not satisfy the minimum system requirements! +adminTools.dashboard.section.healthcheck.performance.info=System performance OK +adminTools.dashboard.section.healthcheck.performance.memory.warn=There is not enough memory to safely run the XWiki installation! +adminTools.dashboard.section.healthcheck.performance.space.warn=There is not enough free space for the XWiki installation! +adminTools.dashboard.section.healthcheck.security.system.info=System encoding OK +adminTools.dashboard.section.healthcheck.security.system.warn=System encoding is [{}] but should be UTF-8! +adminTools.dashboard.section.healthcheck.security.xwiki.info=XWiki encoding OK +adminTools.dashboard.section.healthcheck.security.xwiki.warn=XWiki encoding is [{}]. The encoding should be UTF-8! +adminTools.dashboard.section.healthcheck.title=Health check + + ## Security adminTools.dashboard.section.security.activeEncoding=Active encoding adminTools.dashboard.section.security.configurationEncoding=Configuration encoding @@ -94,7 +104,22 @@ adminTools.dashboard.section.security.lang=Used language adminTools.dashboard.section.security.pwd=Working directory adminTools.dashboard.section.security.title=Security - +## Modals +adminTools.dashboard.download.modal.button=Download +adminTools.dashboard.download.modal.date.from=From +adminTools.dashboard.download.modal.date.to=To +adminTools.dashboard.download.modal.logs.filter.placeholder.from=Logs from date... +adminTools.dashboard.download.modal.logs.filter.placeholder.to=Logs to date... +adminTools.dashboard.download.modal.logs.title=Logs +adminTools.dashboard.download.modal.provided=Configuration info +adminTools.dashboard.download.modal.title=Get support files +adminTools.dashboard.download.modal.xwikiConfig.title=xwiki.cfg +adminTools.dashboard.download.modal.xwikiProperties.title=xwiki.properties +adminTools.dashboard.logs.modal.nLines.hint=Limited at 50000 lines. If the input is empty, the default of 1000 lines will be returned. +adminTools.dashboard.logs.modal.nLines.label=Number of extracted lines +adminTools.dashboard.logs.modal.submit=View +adminTools.dashboard.logs.modal.title=Show last n lines of log +adminTools.dashboard.showLogs=View last n lines of log... AdminTools.Code.Translations 0 diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index 57e67013..a06e9daf 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -228,13 +228,15 @@ $services.admintools.getFilesSection() #set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) #set ($jobId = $healthCheckJobRequest.id) - #set ($healthJobStatus = $services.job.getJobStatus($jobId)) -{{html clean='false'}} + #if ($jobId) + #set ($healthJobStatus = $services.job.getJobStatus($jobId)) + #end{{html clean='false'}} <div class="adminToolsDashboardItem" id="healthCheck"> <h2>$services.icon.renderHTML('bug') - Health check</h2> - <p>Check if your instance is configured correctly and is properly running. For any issues, check out this - <a href="$xwiki.getURL("AdminTools.HelpLinks")"><strong>solutions</strong></a>.</p> + $escapetool.xml($services.localization.render('adminTools.dashboard.section.healthcheck.title'))</h2> + <p>$escapetool.xml($services.localization.render('adminTools.dashboard.section.healthcheck.description')) + <a href="$xwiki.getURL('AdminTools.HelpLinks')"><strong>$escapetool.xml($services.localization.render( + 'adminTools.dashboard.section.healthcheck.description.link'))</strong></a>.</p> <hr/> <div class="healthCheckWrapper"> <div class="healthCheckLastCheck"> From 5022e3ee714ae31c798a778419c4d034b3fa3aa5 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Thu, 2 Nov 2023 16:16:26 +0200 Subject: [PATCH 62/72] Create a health check dashboard section #13 * Modified translations * Added unit tests * Added comments --- .../xwiki/admintools/health/HealthCheck.java | 12 +- .../admintools/health/HealthCheckResult.java | 59 ++++++- .../jobs/HealthCheckJobRequest.java | 18 +- .../admintools/jobs/HealthCheckJobStatus.java | 28 ++- .../health/checks/MemoryHealthCheck.java | 23 ++- .../health/checks/PerformanceHealthCheck.java | 13 +- .../AbstractConfigurationHealthCheck.java | 22 ++- .../ConfigurationDatabaseHealthCheck.java | 10 +- .../ConfigurationJavaHealthCheck.java | 43 +++-- .../ConfigurationOsHealthCheck.java | 10 +- .../SecuritySystemEncodingHealthCheck.java | 46 ++++- .../SecurityXWikiEncodingHealthCheck.java | 47 ++++- .../internal/health/job/HealthCheckJob.java | 17 +- .../script/AdminToolsScriptService.java | 28 +-- .../health/checks/MemoryHealthCheckTest.java | 165 ++++++++++++++++++ .../checks/PerformanceHealthCheckTest.java | 89 ++++++++++ .../ConfigurationDatabaseHealthCheckTest.java | 119 +++++++++++++ .../ConfigurationJavaHealthCheckTest.java | 134 ++++++++++++++ .../ConfigurationOsHealthCheckTest.java | 111 ++++++++++++ ...SecuritySystemEncodingHealthCheckTest.java | 125 +++++++++++++ .../SecurityXWikiEncodingHealthCheckTest.java | 125 +++++++++++++ .../AdminTools/Code/Translations.xml | 13 +- 22 files changed, 1166 insertions(+), 91 deletions(-) create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheckTest.java diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheck.java b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheck.java index 50420afe..1af54c3d 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheck.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheck.java @@ -19,15 +19,21 @@ */ package com.xwiki.admintools.health; -import java.util.Map; - import org.xwiki.component.annotation.Role; +/** + * Check for issues in the current wiki. + * + * @version $Id$ + */ @Role public interface HealthCheck { /** - * @return + * Execute the health check on the wiki instance. + * + * @return a {@link HealthCheckResult} with {@code null} values if no issue was found, or with initialized values + * otherwise. */ HealthCheckResult check(); } diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java index 4fc06a82..877f701a 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java @@ -19,31 +19,76 @@ */ package com.xwiki.admintools.health; +import org.xwiki.stability.Unstable; + +/** + * Result of a health check. Stores the error message and recommendation. + * + * @version $Id$ + * @since 1.0 + */ +@Unstable public class HealthCheckResult { - String errorMessage; + private String errorMessage; - String link; + private String recommendation; - public HealthCheckResult(String errMsg, String link) + /** + * Used for registering an error. + * + * @param errMsg Error message representing the summary of the found issue. + * @param recommendation Suggestion for fixing the issue. + */ + public HealthCheckResult(String errMsg, String recommendation) { this.errorMessage = errMsg; - this.link = link; + this.recommendation = recommendation; } + /** + * Used for initializing an empty body result. + */ public HealthCheckResult() { errorMessage = null; - link = null; + recommendation = null; } + /** + * Get the error body. + * @return a summary of the error. + */ public String getErrorMessage() { return errorMessage; } - public String getLink() + /** + * Get the recommendation for the set error. + * + * @return a suggestion for fixing the error. + */ + public String getRecommendation() + { + return recommendation; + } + + /** + * Set the message error. + * @param err summary of the error. + */ + public void setErrorMessage(String err) + { + this.errorMessage = err; + } + + /** + * Set the error recommendation. + * @param recommendation summary of the fix. + */ + public void setRecommendation(String recommendation) { - return link; + this.recommendation = recommendation; } } diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java b/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java index 0d14c901..135d5beb 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java @@ -23,18 +23,32 @@ import java.util.List; import org.xwiki.job.AbstractRequest; -import org.xwiki.job.Request; import org.xwiki.stability.Unstable; +/** + * Represents a request to start a health check on current wiki. + * + * @version $Id$ + * @since 1.0 + */ @Unstable public class HealthCheckJobRequest extends AbstractRequest { + /** + * Default constructor. + */ public HealthCheckJobRequest() { setDefaultId(); } - public HealthCheckJobRequest(String wiki) { + /** + * Creates a request specific to the wiki from which the call was made. + * + * @param wiki the wiki ID from which the request was made. + */ + public HealthCheckJobRequest(String wiki) + { setDefaultId(); getId().add(wiki); } diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobStatus.java b/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobStatus.java index 981e2eb8..fccd9914 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobStatus.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobStatus.java @@ -23,23 +23,43 @@ import java.util.List; import org.xwiki.job.DefaultJobStatus; -import org.xwiki.job.event.status.JobStatus; import org.xwiki.logging.LoggerManager; import org.xwiki.observation.ObservationManager; +import org.xwiki.stability.Unstable; import com.xwiki.admintools.health.HealthCheckResult; +/** + * The status of the health check job. + * + * @version $Id$ + * @since 1.0 + */ +@Unstable public class HealthCheckJobStatus extends DefaultJobStatus { private final List healthCheckResults = new LinkedList<>(); - public HealthCheckJobStatus(HealthCheckJobRequest request, - JobStatus parentJobStatus, ObservationManager observationManager, LoggerManager loggerManager) + /** + * Create a new health check job status. + * + * @param jobType the job type + * @param request the request provided when the job was started + * @param observationManager the observation manager + * @param loggerManager the logger manager + */ + public HealthCheckJobStatus(String jobType, HealthCheckJobRequest request, ObservationManager observationManager, + LoggerManager loggerManager) { - super("admintools.healthcheck", request, parentJobStatus, observationManager, loggerManager); + super(jobType, request, null, observationManager, loggerManager); setCancelable(true); } + /** + * Get the list issues list from the job. + * + * @return list with {@link HealthCheckResult} containing errors. + */ public List getHealthCheckResults() { return healthCheckResults; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java index 5ebea8ea..a931193a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java @@ -25,7 +25,6 @@ import javax.inject.Singleton; import org.slf4j.Logger; -import org.xwiki.cache.CacheManagerConfiguration; import org.xwiki.component.annotation.Component; import org.xwiki.configuration.ConfigurationSource; import org.xwiki.localization.ContextualLocalizationManager; @@ -35,11 +34,19 @@ import com.xwiki.admintools.health.HealthCheck; import com.xwiki.admintools.health.HealthCheckResult; +/** + * Implementation of {@link HealthCheck} for checking instance memory performance. + * + * @version $Id$ + */ @Component @Named(MemoryHealthCheck.HINT) @Singleton public class MemoryHealthCheck implements HealthCheck { + /** + * Component identifier. + */ public static final String HINT = "CACHE_HEALTH_CHECK"; @Inject @@ -48,9 +55,6 @@ public class MemoryHealthCheck implements HealthCheck @Inject protected Provider xcontextProvider; - @Inject - CacheManagerConfiguration cacheManagerConfiguration; - @Inject @Named("xwikicfg") private ConfigurationSource configurationSource; @@ -72,8 +76,15 @@ public HealthCheckResult check() private boolean isEnoughCache() { String storeCacheCapacity = configurationSource.getProperty("xwiki.store.cache.capacity"); - if (storeCacheCapacity == null || storeCacheCapacity.equals("500")) { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.cache.warn")); + if (storeCacheCapacity == null) { + + logger.warn( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.cache.null.warn")); + return false; + } + if (Integer.parseInt(storeCacheCapacity) <= 500) { + logger.warn(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.memory.cache.value.warn"), storeCacheCapacity); return false; } logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.cache.info")); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java index 304afdac..f106844c 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java @@ -37,12 +37,20 @@ import oshi.hardware.CentralProcessor; import oshi.hardware.HardwareAbstractionLayer; +/** + * Implementation of {@link HealthCheck} for checking system hardware meets XWiki requirements. + * + * @version $Id$ + */ @Component @Named(PerformanceHealthCheck.HINT) @Singleton public class PerformanceHealthCheck implements HealthCheck { - public final static String HINT = "PERFORMANCE_HEALTH_CHECK"; + /** + * Component identifier. + */ + public static final String HINT = "PERFORMANCE_HEALTH_CHECK"; @Inject protected ContextualLocalizationManager localization; @@ -86,7 +94,8 @@ private boolean hasFreeSpace() private boolean hasMinimumMemoryRequirements() { long memorySize = - ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); + ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()) + .getTotalPhysicalMemorySize(); float totalMemory = (float) memorySize / (1024 * 1024 * 1024) + 1; if (totalMemory > 2) { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java index 74d2904c..d9e85002 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java @@ -32,21 +32,39 @@ import com.xwiki.admintools.DataProvider; import com.xwiki.admintools.health.HealthCheck; +/** + * {@link HealthCheck} implementations to simplify the code. + * + * @version $Id$ + */ public abstract class AbstractConfigurationHealthCheck implements HealthCheck { + /** + * Used to render the translations inside the logger. + */ @Inject protected ContextualLocalizationManager localization; @Inject - Logger logger; + protected Logger logger; @Inject private Provider> dataProviders; + /** + * Get the JSON needed in the health checks execution. + * + * @param hint identifies the {@link DataProvider} for which JSON is required. + * @return a {@link Map} with the {@link DataProvider} info, or an empty {@link Map} in case of an error. + */ protected Map getJson(String hint) { try { - return findDataProvider(hint).getDataAsJSON(); + DataProvider dataProvider = findDataProvider(hint); + if (dataProvider == null) { + throw new NullPointerException("Could not find a matching DataProvider."); + } + return dataProvider.getDataAsJSON(); } catch (Exception e) { return new HashMap<>(); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java index 1f868818..e323ccaf 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java @@ -27,12 +27,20 @@ import com.xwiki.admintools.health.HealthCheckResult; import com.xwiki.admintools.internal.data.ConfigurationDataProvider; +/** + * Extension of {@link AbstractConfigurationHealthCheck} for checking the database configuration. + * + * @version $Id$ + */ @Component @Named(ConfigurationDatabaseHealthCheck.HINT) @Singleton public class ConfigurationDatabaseHealthCheck extends AbstractConfigurationHealthCheck { - public final static String HINT = "CONFIG_DB_HEALTH_CHECK"; + /** + * Component identifier. + */ + public static final String HINT = "CONFIG_DB_HEALTH_CHECK"; @Override public HealthCheckResult check() diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java index 0ae2f514..8a0b8aa7 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java @@ -27,19 +27,21 @@ import com.xwiki.admintools.health.HealthCheckResult; import com.xwiki.admintools.internal.data.ConfigurationDataProvider; +/** + * Extension of {@link AbstractConfigurationHealthCheck} for checking the Java configuration. + * + * @version $Id$ + */ @Component @Named(ConfigurationJavaHealthCheck.HINT) @Singleton public class ConfigurationJavaHealthCheck extends AbstractConfigurationHealthCheck { - public final static String HINT = "CONFIG_JAVA_HEALTH_CHECK"; - - private static final String xwikiJavaCompatibilityLink = - "https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/JavaSupportStrategy/"; - /** - * @return + * Component identifier. */ + public static final String HINT = "CONFIG_JAVA_HEALTH_CHECK"; + @Override public HealthCheckResult check() { @@ -54,10 +56,9 @@ public HealthCheckResult check() if (isJavaXWikiCompatible(xwikiVersion, javaVersion)) { logger.warn( localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.warn.incompatible")); - return new HealthCheckResult("java_xwiki_comp", xwikiJavaCompatibilityLink); + return new HealthCheckResult("java_xwiki_not_compatible", "java_issue_rec"); } - logger.info( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.info")); + logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.info")); return new HealthCheckResult(); } @@ -69,13 +70,23 @@ private static float parseFloat(String javaVersionString) private boolean isJavaXWikiCompatible(float xwikiVersion, float javaVersion) { - return inInterval(xwikiVersion, 0, 6) && javaVersion != 1.6 - || inInterval(xwikiVersion, 6, 8.1f) && javaVersion != 1.7 - || inInterval(xwikiVersion, 8.1f, 11.3f) && javaVersion != 1.8 || inInterval(xwikiVersion, 11.2f, 14) && ( - javaVersion != 1.8 || inInterval(javaVersion, 10.99f, 12)) - || inInterval(xwikiVersion, 13.9f, 14.10f) && javaVersion >= 11 - || inInterval(xwikiVersion, 14.10f, Float.MAX_VALUE) && (inInterval(javaVersion, 10.99f, 12) || inInterval( - javaVersion, 16.99f, 18)); + boolean isCompatible = false; + + if (inInterval(xwikiVersion, 0, 6)) { + isCompatible = javaVersion != 1.6; + } else if (inInterval(xwikiVersion, 6, 8.1f)) { + isCompatible = javaVersion != 1.7; + } else if (inInterval(xwikiVersion, 8.1f, 11.3f)) { + isCompatible = javaVersion != 1.8; + } else if (inInterval(xwikiVersion, 11.2f, 14)) { + isCompatible = (javaVersion != 1.8) || inInterval(javaVersion, 10.99f, 12); + } else if (inInterval(xwikiVersion, 13.9f, 14.10f)) { + isCompatible = javaVersion >= 11; + } else if (inInterval(xwikiVersion, 14.10f, Float.MAX_VALUE)) { + isCompatible = inInterval(javaVersion, 10.99f, 12) || inInterval(javaVersion, 16.99f, 18); + } + + return isCompatible; } private boolean inInterval(float checkedValue, float lowerBound, float upperBound) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java index db3a64f8..64a2f479 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java @@ -27,12 +27,20 @@ import com.xwiki.admintools.health.HealthCheckResult; import com.xwiki.admintools.internal.data.ConfigurationDataProvider; +/** + * Extension of {@link AbstractConfigurationHealthCheck} for checking the OS configuration. + * + * @version $Id$ + */ @Component @Named(ConfigurationOsHealthCheck.HINT) @Singleton public class ConfigurationOsHealthCheck extends AbstractConfigurationHealthCheck { - public final static String HINT = "CONFIG_OS_HEALTH_CHECK"; + /** + * Component identifier. + */ + public static final String HINT = "CONFIG_OS_HEALTH_CHECK"; @Override public HealthCheckResult check() diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java index 18788fc7..e648ed05 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java @@ -31,12 +31,20 @@ import com.xwiki.admintools.health.HealthCheckResult; import com.xwiki.admintools.internal.data.SecurityDataProvider; +/** + * Extension of {@link AbstractConfigurationHealthCheck} for checking system security configuration. + * + * @version $Id$ + */ @Component @Named(SecuritySystemEncodingHealthCheck.HINT) @Singleton public class SecuritySystemEncodingHealthCheck extends AbstractConfigurationHealthCheck { - public final static String HINT = "SECURITY_SYSTEM_ENCODING_HEALTH_CHECK"; + /** + * Component identifier. + */ + public static final String HINT = "SECURITY_SYSTEM_ENCODING_HEALTH_CHECK"; private final List acceptedEncodings = new ArrayList<>(List.of("UTF8", "UTF-8", "utf8", "utf-8")); @@ -44,15 +52,37 @@ public class SecuritySystemEncodingHealthCheck extends AbstractConfigurationHeal public HealthCheckResult check() { Map securityJson = getJson(SecurityDataProvider.HINT); - String langEnc = securityJson.get("LANG").split("\\.")[1]; - String fileEnc = securityJson.get("fileEncoding"); - if (!acceptedEncodings.contains(langEnc) || !acceptedEncodings.contains(fileEnc)) { - logger.warn( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.system.warn"), - fileEnc); - return new HealthCheckResult("xwiki_encoding err", "xwiki config tutorial link"); + String langEnc = securityJson.getOrDefault("LANG", "invalid.invalid").split("\\.")[1]; + String fileEnc = securityJson.getOrDefault("fileEncoding", "invalid"); + boolean isSafeLangEnc = isSafeLanguageEncoding(langEnc); + boolean isSafeFileEnc = isSafeFileEncoding(fileEnc); + + if (!isSafeLangEnc || !isSafeFileEnc) { + return new HealthCheckResult("xwiki_encoding_err", "xwiki config tutorial link"); } logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.system.info")); return new HealthCheckResult(); } + + private boolean isSafeLanguageEncoding(String langEnc) + { + if (acceptedEncodings.contains(langEnc)) { + return true; + } + logger.warn( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.system.lang.warn"), + langEnc); + return false; + } + + private boolean isSafeFileEncoding(String fileEnc) + { + if (acceptedEncodings.contains(fileEnc)) { + return true; + } + logger.warn( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.system.file.warn"), + fileEnc); + return false; + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java index ca0760f2..540ed27a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java @@ -31,12 +31,22 @@ import com.xwiki.admintools.health.HealthCheckResult; import com.xwiki.admintools.internal.data.SecurityDataProvider; +/** + * Extension of {@link AbstractConfigurationHealthCheck} for checking XWiki security configuration. + * + * @version $Id$ + */ @Component @Named(SecurityXWikiEncodingHealthCheck.HINT) @Singleton public class SecurityXWikiEncodingHealthCheck extends AbstractConfigurationHealthCheck { - public final static String HINT = "SECURITY_XWIKI_ENCODING_HEALTH_CHECK"; + /** + * Component identifier. + */ + public static final String HINT = "SECURITY_XWIKI_ENCODING_HEALTH_CHECK"; + + private static final String INVALID = "INVALID"; private final List acceptedEncodings = new ArrayList<>(List.of("UTF8", "UTF-8", "utf8", "utf-8")); @@ -44,15 +54,36 @@ public class SecurityXWikiEncodingHealthCheck extends AbstractConfigurationHealt public HealthCheckResult check() { Map securityJson = getJson(SecurityDataProvider.HINT); - String activeEnc = securityJson.get("activeEncoding"); - String configEnc = securityJson.get("configurationEncoding"); - if (!acceptedEncodings.contains(activeEnc) || !acceptedEncodings.contains(configEnc)) { - logger.warn( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.xwiki.warn"), - activeEnc); - return new HealthCheckResult("xwiki_encoding err", "xwiki config tutorial link"); + String activeEnc = securityJson.getOrDefault("activeEncoding", INVALID); + String configEnc = securityJson.getOrDefault("configurationEncoding", INVALID); + boolean isActiveEncSafe = isSafeActiveEncoding(activeEnc); + boolean isConfigEncSafe = isSafeConfigEncoding(configEnc); + if (!isActiveEncSafe || !isConfigEncSafe) { + return new HealthCheckResult("xwiki_encoding_err", "xwiki config tutorial link"); } logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.xwiki.info")); return new HealthCheckResult(); } + + private boolean isSafeActiveEncoding(String activeEnc) + { + if (acceptedEncodings.contains(activeEnc)) { + return true; + } + logger.warn( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.xwiki.active.warn"), + activeEnc); + return false; + } + + private boolean isSafeConfigEncoding(String configEnc) + { + if (acceptedEncodings.contains(configEnc)) { + return true; + } + logger.warn( + localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.xwiki.config.warn"), + configEnc); + return false; + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java index 3e7d7eb2..830d0c57 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java @@ -28,15 +28,18 @@ import org.xwiki.component.annotation.Component; import org.xwiki.job.AbstractJob; -import org.xwiki.job.Job; import org.xwiki.job.event.status.CancelableJobStatus; -import org.xwiki.job.event.status.JobStatus; import com.xwiki.admintools.health.HealthCheck; import com.xwiki.admintools.health.HealthCheckResult; import com.xwiki.admintools.jobs.HealthCheckJobRequest; import com.xwiki.admintools.jobs.HealthCheckJobStatus; +/** + * The Admin Tools health check job. + * + * @version $Id$ + */ @Component @Named(HealthCheckJob.JOB_TYPE) public class HealthCheckJob extends AbstractJob @@ -58,11 +61,12 @@ public String getType() @Override protected HealthCheckJobStatus createNewStatus(HealthCheckJobRequest request) { - Job currentJob = this.jobContext.getCurrentJob(); - JobStatus currentJobStatus = currentJob != null ? currentJob.getStatus() : null; - return new HealthCheckJobStatus(request, currentJobStatus, observationManager, loggerManager); + return new HealthCheckJobStatus(JOB_TYPE, request, observationManager, loggerManager); } + /** + * Run the health check job. + */ @Override protected void runInternal() { @@ -76,7 +80,10 @@ protected void runInternal() break; } else { progressManager.startStep(this); + // We start the check for the current HealthCheck in the iterator. HealthCheckResult checkResult = healthCheckIterator.next().check(); + // If the check return a result with a null error message then no issue was found, so we do not + // add the result to the status HealthCheckResult list. if (checkResult.getErrorMessage() != null) { status.getHealthCheckResults().add(checkResult); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index 730e9c8c..10197347 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -38,8 +38,8 @@ /** * Admin Tools script services. * - * @since 1.0 * @version $Id$ + * @since 1.0 */ @Component @Named("admintools") @@ -106,24 +106,10 @@ public String getFilesSection() } /** - * TBC. - * - * @return TBC. - */ - public Job runHealthChecks() - { - try { - return this.jobExecutor.execute(HealthCheckJob.JOB_TYPE, new HealthCheckJobRequest()); - } catch (Exception e) { - return null; - } - } - - /** - * TBC. + * Start the execution of the given Admin Tools health check request. * - * @param healthCheckJobRequest TBC. - * @return TBC. + * @param healthCheckJobRequest the health check request to be executed. + * @return the asynchronous background job that will execute the request. */ public Job runHealthChecks(HealthCheckJobRequest healthCheckJobRequest) { @@ -140,10 +126,10 @@ public Job runHealthChecks(HealthCheckJobRequest healthCheckJobRequest) } /** - * TBC. + * Create health check request. * - * @param wiki TBC. - * @return TBC. + * @param wiki the ID of the wiki from where the request was made. + * @return a new health check request, initialized based on the given wiki ID. */ public HealthCheckJobRequest createJobRequest(String wiki) { diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java new file mode 100644 index 00000000..250dfc04 --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java @@ -0,0 +1,165 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks; + +import javax.inject.Named; +import javax.inject.Provider; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.configuration.ConfigurationSource; +import org.xwiki.localization.ContextualLocalizationManager; +import org.xwiki.test.annotation.BeforeComponent; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xpn.xwiki.XWiki; +import com.xpn.xwiki.XWikiContext; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +public class MemoryHealthCheckTest +{ + @MockComponent + private static ContextualLocalizationManager localization; + + @MockComponent + private Provider xcontextProvider; + + @MockComponent + @Named("xwikicfg") + private ConfigurationSource configurationSource; + + @MockComponent + private XWikiContext context; + + @Mock + private XWiki xwiki; + + @InjectMockComponents + private MemoryHealthCheck memoryHealthCheck; + + @Mock + private Logger logger; + + @BeforeComponent + static void setUp() throws Exception + { + when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.cache.info")).thenReturn( + "Cache status OK"); + when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.mem.info")).thenReturn( + "Memory status OK"); + when(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.memory.cache.null.warn")).thenReturn( + "Store cache capacity is set at 500. Check Cache recommendations in solutions."); + when(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.memory.cache.value.warn")).thenReturn( + "Store cache capacity is set at [{}]. Check Cache recommendations in solutions."); + when(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.memory.mem.free.error")).thenReturn( + "Your JVM instance has only [{}]MB free memory left! Consult the solution link for support!"); + when(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.memory.mem.free.warn")).thenReturn( + "Your instance memory is running low. Currently only [{}]MB free left."); + when(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.memory.mem.maxcapacity.error")).thenReturn( + "JVM memory is less than 1024MB. Currently: [{}]MB"); + } + + @BeforeEach + void beforeEach() + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(memoryHealthCheck, "logger", this.logger); + + when(xcontextProvider.get()).thenReturn(context); + when(context.getWiki()).thenReturn(xwiki); + when(configurationSource.getProperty("xwiki.store.cache.capacity")).thenReturn("1000"); + } + + @Test + void check() + { + when(xwiki.maxMemory()).thenReturn((long) (8 * Math.pow(1024, 3))); + when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); + when(xwiki.freeMemory()).thenReturn((long) (0.5 * Math.pow(1024, 3))); + + assertNull(memoryHealthCheck.check().getErrorMessage()); + verify(logger).info("Cache status OK"); + verify(logger).info("Memory status OK"); + } + + @Test + void checkCacheIssues() + { + when(xwiki.maxMemory()).thenReturn((long) (8 * Math.pow(1024, 3))); + when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); + when(xwiki.freeMemory()).thenReturn((long) (0.5 * Math.pow(1024, 3))); + when(configurationSource.getProperty("xwiki.store.cache.capacity")).thenReturn("400"); + assertEquals("There are memory issues!", memoryHealthCheck.check().getErrorMessage()); + verify(logger).warn("Store cache capacity is set at [{}]. Check Cache recommendations in solutions.", "400"); + verify(logger).info("Memory status OK"); + } + + @Test + void checkMaxMemoryIssues() + { + when(xwiki.maxMemory()).thenReturn((long) (0.5 * Math.pow(1024, 3))); + when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); + when(xwiki.freeMemory()).thenReturn((long) (0.5 * Math.pow(1024, 3))); + + assertEquals("There are memory issues!", memoryHealthCheck.check().getErrorMessage()); + verify(logger).info("Cache status OK"); + verify(logger).error("JVM memory is less than 1024MB. Currently: [{}]MB", 512.0f); + } + + @Test + void checkCriticalFreeMemory() + { + when(xwiki.maxMemory()).thenReturn((long) (1.7 * Math.pow(1024, 3))); + when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); + when(xwiki.freeMemory()).thenReturn((long) (0.2 * Math.pow(1024, 3))); + + assertEquals("There are memory issues!", memoryHealthCheck.check().getErrorMessage()); + verify(logger).info("Cache status OK"); + verify(logger).error( + "Your JVM instance has only [{}]MB free memory left! Consult the solution link for support!", 409.6001f); + } + + @Test + void checkLowFreeMemory() + { + when(xwiki.maxMemory()).thenReturn((long) (2 * Math.pow(1024, 3))); + when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); + when(xwiki.freeMemory()).thenReturn((long) (0.2 * Math.pow(1024, 3))); + + assertNull(memoryHealthCheck.check().getErrorMessage()); + verify(logger).info("Cache status OK"); + verify(logger).warn("Your instance memory is running low. Currently only [{}]MB free left.", 716.80005f); + } +} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheckTest.java new file mode 100644 index 00000000..69bc7621 --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheckTest.java @@ -0,0 +1,89 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks; + +import java.io.File; +import java.lang.management.ManagementFactory; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.localization.ContextualLocalizationManager; +import org.xwiki.test.annotation.BeforeComponent; +import org.xwiki.test.junit5.XWikiTempDir; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.sun.management.OperatingSystemMXBean; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +public class PerformanceHealthCheckTest +{ + @MockComponent + private static ContextualLocalizationManager localization; + + @XWikiTempDir + private File tmpDir; + + private File logsDir; + + @InjectMockComponents + private PerformanceHealthCheck performanceHealthCheck; + + @Mock + private Logger logger; + + @Mock + private OperatingSystemMXBean osMXBean; + + @Mock + ManagementFactory managementFactory; + + @BeforeComponent + static void setUp() throws Exception + { + when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.performance.info")).thenReturn( + "System performance OK"); + } + + @BeforeEach + void beforeEach() + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(performanceHealthCheck, "logger", this.logger); + + logsDir = new File("/"); + } + + @Test + void check() + { + assertNull(performanceHealthCheck.check().getErrorMessage()); + verify(logger).info("System performance OK"); + } +} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java new file mode 100644 index 00000000..f1d78dab --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java @@ -0,0 +1,119 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.configuration; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.inject.Provider; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.localization.ContextualLocalizationManager; +import org.xwiki.test.annotation.BeforeComponent; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xwiki.admintools.DataProvider; +import com.xwiki.admintools.internal.data.ConfigurationDataProvider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +public class ConfigurationDatabaseHealthCheckTest +{ + @MockComponent + private static Provider> dataProviders; + + @MockComponent + private static DataProvider firstDataProvider; + + @MockComponent + private static DataProvider secondDataProvider; + + @MockComponent + private static ContextualLocalizationManager localization; + + @InjectMockComponents + private ConfigurationDatabaseHealthCheck databaseHealthCheck; + + @Mock + private Logger logger; + + @BeforeComponent + static void setUp() throws Exception + { + List dataProviderList = new ArrayList<>(); + dataProviderList.add(firstDataProvider); + dataProviderList.add(secondDataProvider); + when(dataProviders.get()).thenReturn(dataProviderList); + Map jsonResponse = Map.of("databaseName", "testDBName"); + when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); + when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); + + when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.database.info")) + .thenReturn("Database status OK"); + when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.database.warn")) + .thenReturn("Database not found!"); + } + + @BeforeEach + void beforeEach() + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(databaseHealthCheck, "logger", this.logger); + + when(firstDataProvider.getIdentifier()).thenReturn(ConfigurationDataProvider.HINT); + when(secondDataProvider.getIdentifier()).thenReturn("second"); + } + + @Test + void check() + { + assertNull(databaseHealthCheck.check().getErrorMessage()); + verify(logger).info("Database status OK"); + } + + @Test + void checkNullProvider() + { + when(firstDataProvider.getIdentifier()).thenReturn("first"); + + assertEquals("database_not_detected", databaseHealthCheck.check().getErrorMessage()); + verify(logger).warn("Database not found!"); + } + + @Test + void checkNullJson() throws Exception + { + when(firstDataProvider.getDataAsJSON()).thenThrow(new Exception("error while ggenerating the json")); + + assertEquals("database_not_detected", databaseHealthCheck.check().getErrorMessage()); + verify(logger).warn("Database not found!"); + } +} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java new file mode 100644 index 00000000..cbde8313 --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java @@ -0,0 +1,134 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.configuration; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.inject.Provider; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.localization.ContextualLocalizationManager; +import org.xwiki.test.annotation.BeforeComponent; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xwiki.admintools.DataProvider; +import com.xwiki.admintools.internal.data.ConfigurationDataProvider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +public class ConfigurationJavaHealthCheckTest +{ + @MockComponent + private static Provider> dataProviders; + + @MockComponent + private static DataProvider firstDataProvider; + + @MockComponent + private static DataProvider secondDataProvider; + + @MockComponent + private static ContextualLocalizationManager localization; + + @InjectMockComponents + private ConfigurationJavaHealthCheck javaHealthCheck; + + @Mock + private Logger logger; + + @BeforeComponent + static void setUp() throws Exception + { + List dataProviderList = new ArrayList<>(); + dataProviderList.add(firstDataProvider); + dataProviderList.add(secondDataProvider); + when(dataProviders.get()).thenReturn(dataProviderList); + + when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); + + when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.info")) + .thenReturn("Java status OK"); + when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.warn.found")) + .thenReturn("Java version not found!"); + when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.warn.incompatible")) + .thenReturn("Java version is not compatible with the current XWiki installation!"); + } + + @BeforeEach + void beforeEach() throws Exception + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(javaHealthCheck, "logger", this.logger); + + when(firstDataProvider.getIdentifier()).thenReturn(ConfigurationDataProvider.HINT); + when(secondDataProvider.getIdentifier()).thenReturn("second"); + + Map jsonResponse = Map.of("javaVersion", "11.0.2", + "xwikiVersion", "14.10.2"); + when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); + } + + @Test + void check() + { + assertNull(javaHealthCheck.check().getErrorMessage()); + verify(logger).info("Java status OK"); + } + + @Test + void checkNullProvider() + { + when(firstDataProvider.getIdentifier()).thenReturn("first"); + + assertEquals("java_version_not_found", javaHealthCheck.check().getErrorMessage()); + verify(logger).warn("Java version not found!"); + } + + @Test + void checkNullJson() throws Exception + { + when(firstDataProvider.getDataAsJSON()).thenThrow(new Exception("error while ggenerating the json")); + + assertEquals("java_version_not_found", javaHealthCheck.check().getErrorMessage()); + verify(logger).warn("Java version not found!"); + } + + @Test + void checkJavaVersionIncompatible() throws Exception + { + Map jsonResponse = Map.of("javaVersion", "11.0.2", + "xwikiVersion", "6.10.2"); + when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); + assertEquals("java_xwiki_not_compatible", javaHealthCheck.check().getErrorMessage()); + verify(logger).warn("Java version is not compatible with the current XWiki installation!"); + } +} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java new file mode 100644 index 00000000..c1eee470 --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java @@ -0,0 +1,111 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.configuration; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.inject.Provider; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.localization.ContextualLocalizationManager; +import org.xwiki.test.annotation.BeforeComponent; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xwiki.admintools.DataProvider; +import com.xwiki.admintools.internal.data.ConfigurationDataProvider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +public class ConfigurationOsHealthCheckTest +{ + @MockComponent + private static Provider> dataProviders; + + @MockComponent + private static DataProvider firstDataProvider; + + @MockComponent + private static DataProvider secondDataProvider; + + @MockComponent + private static ContextualLocalizationManager localization; + + @InjectMockComponents + private ConfigurationOsHealthCheck osHealthCheck; + + @Mock + private Logger logger; + + @BeforeComponent + static void setUp() throws Exception + { + List dataProviderList = new ArrayList<>(); + dataProviderList.add(firstDataProvider); + dataProviderList.add(secondDataProvider); + when(dataProviders.get()).thenReturn(dataProviderList); + Map jsonResponse = + Map.of("osName", "testDBName", "osVersion", "os_version", "osArch", "os_arch"); + when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); + when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); + + when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.os.info")).thenReturn( + "OS info retrieval OK"); + when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.os.warn")).thenReturn( + "There has been an error while gathering OS info!"); + } + + @BeforeEach + void beforeEach() + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(osHealthCheck, "logger", this.logger); + + when(firstDataProvider.getIdentifier()).thenReturn(ConfigurationDataProvider.HINT); + when(secondDataProvider.getIdentifier()).thenReturn("second"); + } + + @Test + void check() + { + assertNull(osHealthCheck.check().getErrorMessage()); + verify(logger).info("OS info retrieval OK"); + } + + @Test + void checkNullJson() throws Exception + { + when(firstDataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); + + assertEquals("os_issue", osHealthCheck.check().getErrorMessage()); + verify(logger).warn("There has been an error while gathering OS info!"); + } +} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheckTest.java new file mode 100644 index 00000000..5a804f16 --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheckTest.java @@ -0,0 +1,125 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.configuration; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.inject.Provider; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.localization.ContextualLocalizationManager; +import org.xwiki.test.annotation.BeforeComponent; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xwiki.admintools.DataProvider; +import com.xwiki.admintools.internal.data.SecurityDataProvider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +public class SecuritySystemEncodingHealthCheckTest +{ + @MockComponent + private static Provider> dataProviders; + + @MockComponent + private static DataProvider firstDataProvider; + + @MockComponent + private static DataProvider secondDataProvider; + + @MockComponent + private static ContextualLocalizationManager localization; + + @InjectMockComponents + private SecuritySystemEncodingHealthCheck systemEncodingHealthCheck; + + @Mock + private Logger logger; + + @BeforeComponent + static void setUp() throws Exception + { + List dataProviderList = new ArrayList<>(); + dataProviderList.add(firstDataProvider); + dataProviderList.add(secondDataProvider); + when(dataProviders.get()).thenReturn(dataProviderList); + + when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); + + when(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.security.system.info")).thenReturn("System encoding OK"); + when(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.security.system.lang.warn")).thenReturn( + "System language encoding is [{}] but should be UTF-8!"); + when(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.security.system.file.warn")).thenReturn( + "System file encoding is [{}] but should be UTF-8!"); + } + + @BeforeEach + void beforeEach() throws Exception + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(systemEncodingHealthCheck, "logger", this.logger); + + when(firstDataProvider.getIdentifier()).thenReturn(SecurityDataProvider.HINT); + when(secondDataProvider.getIdentifier()).thenReturn("second"); + Map jsonResponse = Map.of("LANG", "en.UTF8", "fileEncoding", "UTF8"); + when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); + } + + @Test + void check() + { + assertNull(systemEncodingHealthCheck.check().getErrorMessage()); + verify(logger).info("System encoding OK"); + } + + @Test + void checkNullJson() throws Exception + { + when(firstDataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); + + assertEquals("xwiki_encoding_err", systemEncodingHealthCheck.check().getErrorMessage()); + verify(logger).warn("System language encoding is [{}] but should be UTF-8!", "invalid"); + verify(logger).warn("System file encoding is [{}] but should be UTF-8!", "invalid"); + } + + @Test + void checkUnsafeEncoding() throws Exception + { + Map jsonResponse = Map.of("LANG", "en.UTF8", "fileEncoding", "ISO-8859-1"); + when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); + assertEquals("xwiki_encoding_err", systemEncodingHealthCheck.check().getErrorMessage()); + verify(logger).warn("System file encoding is [{}] but should be UTF-8!", "ISO-8859-1"); + } +} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheckTest.java new file mode 100644 index 00000000..5212ed30 --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheckTest.java @@ -0,0 +1,125 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.configuration; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.inject.Provider; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.localization.ContextualLocalizationManager; +import org.xwiki.test.annotation.BeforeComponent; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xwiki.admintools.DataProvider; +import com.xwiki.admintools.internal.data.SecurityDataProvider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +public class SecurityXWikiEncodingHealthCheckTest +{ + @MockComponent + private static Provider> dataProviders; + + @MockComponent + private static DataProvider firstDataProvider; + + @MockComponent + private static DataProvider secondDataProvider; + + @MockComponent + private static ContextualLocalizationManager localization; + + @InjectMockComponents + private SecurityXWikiEncodingHealthCheck xwikiEncodingHealthCheck; + + @Mock + private Logger logger; + + @BeforeComponent + static void setUp() throws Exception + { + List dataProviderList = new ArrayList<>(); + dataProviderList.add(firstDataProvider); + dataProviderList.add(secondDataProvider); + when(dataProviders.get()).thenReturn(dataProviderList); + + when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); + + when(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.security.xwiki.info")).thenReturn("XWiki encoding OK"); + when(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.security.xwiki.active.warn")).thenReturn( + "XWiki active encoding is [{}] but should be UTF-8!"); + when(localization.getTranslationPlain( + "adminTools.dashboard.section.healthcheck.security.xwiki.config.warn")).thenReturn( + "XWiki configuration encoding is [{}] but should be UTF-8!"); + } + + @BeforeEach + void beforeEach() throws Exception + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(xwikiEncodingHealthCheck, "logger", this.logger); + + when(firstDataProvider.getIdentifier()).thenReturn(SecurityDataProvider.HINT); + when(secondDataProvider.getIdentifier()).thenReturn("second"); + Map jsonResponse = Map.of("activeEncoding", "UTF8", "configurationEncoding", "UTF8"); + when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); + } + + @Test + void check() + { + assertNull(xwikiEncodingHealthCheck.check().getErrorMessage()); + verify(logger).info("XWiki encoding OK"); + } + + @Test + void checkNullJson() throws Exception + { + when(firstDataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); + + assertEquals("xwiki_encoding_err", xwikiEncodingHealthCheck.check().getErrorMessage()); + verify(logger).warn("XWiki configuration encoding is [{}] but should be UTF-8!", "INVALID"); + verify(logger).warn("XWiki active encoding is [{}] but should be UTF-8!", "INVALID"); + } + + @Test + void checkUnsafeEncoding() throws Exception + { + Map jsonResponse = Map.of("activeEncoding", "UTF8", "configurationEncoding", "ISO-8859-1"); + when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); + assertEquals("xwiki_encoding_err", xwikiEncodingHealthCheck.check().getErrorMessage()); + verify(logger).warn("XWiki configuration encoding is [{}] but should be UTF-8!", "ISO-8859-1"); + } +} diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml index b7fb5309..36ef836b 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml @@ -76,7 +76,8 @@ adminTools.dashboard.section.healthcheck.java.info=Java status OK adminTools.dashboard.section.healthcheck.java.warn.found=Java version not found! adminTools.dashboard.section.healthcheck.java.warn.incompatible=Java version is not compatible with the current XWiki installation! adminTools.dashboard.section.healthcheck.memory.cache.info=Cache status OK -adminTools.dashboard.section.healthcheck.memory.cache.warn=Store cache capacity is set at 500. Check Cache recommendations in solutions. +adminTools.dashboard.section.healthcheck.memory.cache.null.warn=Store cache capacity is set at 500. See cache recommendations in solutions. +adminTools.dashboard.section.healthcheck.memory.cache.value.warn=Store cache capacity is set at [{}]. See cache recommendations in solutions. adminTools.dashboard.section.healthcheck.memory.mem.free.error=Your JVM instance has only [{}]MB free memory left! Consult the solution link for support! adminTools.dashboard.section.healthcheck.memory.mem.free.warn=Your instance memory is running low. Currently only [{}]MB free left. adminTools.dashboard.section.healthcheck.memory.mem.info=Memory status OK @@ -88,12 +89,13 @@ adminTools.dashboard.section.healthcheck.performance.info=System performance OK adminTools.dashboard.section.healthcheck.performance.memory.warn=There is not enough memory to safely run the XWiki installation! adminTools.dashboard.section.healthcheck.performance.space.warn=There is not enough free space for the XWiki installation! adminTools.dashboard.section.healthcheck.security.system.info=System encoding OK -adminTools.dashboard.section.healthcheck.security.system.warn=System encoding is [{}] but should be UTF-8! +adminTools.dashboard.section.healthcheck.security.system.file.warn=System file encoding is [{}] but should be UTF-8! +adminTools.dashboard.section.healthcheck.security.system.lang.warn=System language encoding is [{}] but should be UTF-8! adminTools.dashboard.section.healthcheck.security.xwiki.info=XWiki encoding OK -adminTools.dashboard.section.healthcheck.security.xwiki.warn=XWiki encoding is [{}]. The encoding should be UTF-8! +adminTools.dashboard.section.healthcheck.security.xwiki.active.warn=XWiki active encoding is [{}]. The encoding should be UTF-8! +adminTools.dashboard.section.healthcheck.security.xwiki.config.warn=XWiki configuration encoding is [{}]. The encoding should be UTF-8! adminTools.dashboard.section.healthcheck.title=Health check - ## Security adminTools.dashboard.section.security.activeEncoding=Active encoding adminTools.dashboard.section.security.configurationEncoding=Configuration encoding @@ -104,6 +106,7 @@ adminTools.dashboard.section.security.lang=Used language adminTools.dashboard.section.security.pwd=Working directory adminTools.dashboard.section.security.title=Security + ## Modals adminTools.dashboard.download.modal.button=Download adminTools.dashboard.download.modal.date.from=From @@ -115,7 +118,7 @@ adminTools.dashboard.download.modal.provided=Configuration info adminTools.dashboard.download.modal.title=Get support files adminTools.dashboard.download.modal.xwikiConfig.title=xwiki.cfg adminTools.dashboard.download.modal.xwikiProperties.title=xwiki.properties -adminTools.dashboard.logs.modal.nLines.hint=Limited at 50000 lines. If the input is empty, the default of 1000 lines will be returned. +adminTools.dashboard.logs.modal.nLines.hint=The maximum number of lines is 50000, since the complete logs can also be downloaded. If no value is defined, 1000 will be used as a default value. adminTools.dashboard.logs.modal.nLines.label=Number of extracted lines adminTools.dashboard.logs.modal.submit=View adminTools.dashboard.logs.modal.title=Show last n lines of log From 382126ce8e9a01da443cf7279c3b9a9cbf7d0649 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Thu, 2 Nov 2023 17:03:08 +0200 Subject: [PATCH 63/72] Create a health check dashboard section #13 * Merged main --- application-admintools-default/pom.xml | 2 +- .../AdminTools/Code/AdminToolsJS.xml | 2 +- .../src/main/resources/AdminTools/WebHome.xml | 118 ++++++++++++++++++ 3 files changed, 120 insertions(+), 2 deletions(-) diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index d8c62de0..f4dc0f8f 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -83,6 +83,6 @@ - 0.79 + 0.78 \ No newline at end of file diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index 1da26185..5d5f9237 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -242,7 +242,7 @@ link.click(); }); - $(document).on('change', '#downloadFilesModal input[name="files"][value="logsDataResource"]', function() { + $(document).on('change', '#downloadFilesModal input[name="files"][value="logs"]', function() { if ($(this).is(':checked')) { $('#downloadFilesModal .dateFields').show(); } else { diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index b8ea0073..7252040c 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -165,6 +165,114 @@ $services.admintools.getFilesSection() + + AdminTools.WebHome + 3 + XWiki.GadgetClass + e26584bd-f916-43fd-b57c-4030ba639a9a + + XWiki.GadgetClass + + + + + + + + + 0 + --- + content + 2 + 0 + content + 5 + 40 + 0 + + + com.xpn.xwiki.objects.classes.TextAreaClass + + + 0 + position + 3 + 0 + position + 30 + 0 + + + com.xpn.xwiki.objects.classes.StringClass + + + <disabled>0</disabled> + <name>title</name> + <number>1</number> + <picker>0</picker> + <prettyName>title</prettyName> + <size>30</size> + <unmodifiable>0</unmodifiable> + <validationMessage/> + <validationRegExp/> + <classType>com.xpn.xwiki.objects.classes.StringClass</classType> + + + + {{template name="job_macros.vm"/}} + +{{velocity}} + + #includeMacros("AdminTools.Code.Macros") + #set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) + #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) + #set ($jobId = $healthCheckJobRequest.id) + #if ($jobId) + #set ($healthJobStatus = $services.job.getJobStatus($jobId)) + #end +{{html clean='false'}} + <div class="adminToolsDashboardItem" id="healthCheck"> + <h2>$services.icon.renderHTML('bug') + $escapetool.xml($services.localization.render('adminTools.dashboard.section.healthcheck.title'))</h2> + <p>$escapetool.xml($services.localization.render('adminTools.dashboard.section.healthcheck.description')) + <a href="$xwiki.getURL('AdminTools.HelpLinks')"><strong>$escapetool.xml($services.localization.render( + 'adminTools.dashboard.section.healthcheck.description.link'))</strong></a>.</p> + <hr/> + <div class="healthCheckWrapper"> + <div class="healthCheckLastCheck"> + Time since the last health check: $services.date.displayTimeAgo($healthJobStatus.getEndDate()) + </div> + <div class="buttonwrapper"> + <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" + value="startHealthCheck">Start health check</button> + </div> + </div> + <div hidden class="xcontent job-status" data-url=""> + #if ($healthJobStatus.state != 'FINISHED') + #displayJobProgressBar($jobStatus) + #else + #jobFinishedMessage($healthJobStatus, $translationPrefix, $successKey, $errorKey, $canceledKey) + #end + #if ($showLogs || $isAdvancedUser || $isSuperAdmin) + #if ($healthJobStatus.state != 'FINISHED') + #displayJobStatusLog($jobStatus true) + #else + #displayJobStatusLog($healthJobStatus true) + #end + #end + </div> + </div> +{{/html}} +{{/velocity}} + + + + 1, 2 + + + + + AdminTools.WebHome 0 @@ -294,6 +402,16 @@ $services.admintools.getFilesSection() .bootstrap-datetimepicker-widget { z-index: 99999 !important; +} + +.healthCheckWrapper { + display: flex; + flex-direction: column; + margin-bottom: 2rem; +} + +.healthCheckWrapper button { + margin-top: 2rem; } From 0579d6077eba37b96be3f8f1c77f395c451a2d1d Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Fri, 3 Nov 2023 14:30:13 +0200 Subject: [PATCH 64/72] Create a health check dashboard section #13 * Refactored JavaScript, Macros, job resource and dashboard * Moved the code for health check inside a macro * Created tests for HealthCheckJob --- application-admintools-default/pom.xml | 2 +- .../internal/health/job/HealthCheckJob.java | 29 +++--- .../checks/PerformanceHealthCheckTest.java | 89 ------------------- .../health/job/HealthCheckJobTest.java | 79 ++++++++++++++++ .../AdminTools/Code/AdminToolsJS.xml | 49 +++++----- .../AdminTools/Code/HealthCheckResources.xml | 34 +++---- .../main/resources/AdminTools/Code/Macros.xml | 47 ++++++++++ .../src/main/resources/AdminTools/WebHome.xml | 45 +--------- 8 files changed, 177 insertions(+), 197 deletions(-) delete mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index f4dc0f8f..710d70c5 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -83,6 +83,6 @@ - 0.78 + 0.77 \ No newline at end of file diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java index 830d0c57..c53667be 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java @@ -28,7 +28,6 @@ import org.xwiki.component.annotation.Component; import org.xwiki.job.AbstractJob; -import org.xwiki.job.event.status.CancelableJobStatus; import com.xwiki.admintools.health.HealthCheck; import com.xwiki.admintools.health.HealthCheckResult; @@ -74,22 +73,20 @@ protected void runInternal() this.progressManager.pushLevelProgress(healthCheckList.size(), this); Iterator healthCheckIterator = healthCheckList.iterator(); try { - if (status instanceof CancelableJobStatus && !((CancelableJobStatus) status).isCanceled()) { - while (healthCheckIterator.hasNext()) { - if (status.isCanceled()) { - break; - } else { - progressManager.startStep(this); - // We start the check for the current HealthCheck in the iterator. - HealthCheckResult checkResult = healthCheckIterator.next().check(); - // If the check return a result with a null error message then no issue was found, so we do not - // add the result to the status HealthCheckResult list. - if (checkResult.getErrorMessage() != null) { - status.getHealthCheckResults().add(checkResult); - } - Thread.yield(); - progressManager.endStep(this); + while (healthCheckIterator.hasNext()) { + if (status.isCanceled()) { + break; + } else { + progressManager.startStep(this); + // We start the check for the current HealthCheck in the iterator. + HealthCheckResult checkResult = healthCheckIterator.next().check(); + // If the check return a result with a null error message then no issue was found, so we do not + // add the result to the status HealthCheckResult list. + if (checkResult.getErrorMessage() != null) { + status.getHealthCheckResults().add(checkResult); } + Thread.yield(); + progressManager.endStep(this); } } } finally { diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheckTest.java deleted file mode 100644 index 69bc7621..00000000 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheckTest.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools.internal.health.checks; - -import java.io.File; -import java.lang.management.ManagementFactory; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.slf4j.Logger; -import org.xwiki.component.util.ReflectionUtils; -import org.xwiki.localization.ContextualLocalizationManager; -import org.xwiki.test.annotation.BeforeComponent; -import org.xwiki.test.junit5.XWikiTempDir; -import org.xwiki.test.junit5.mockito.ComponentTest; -import org.xwiki.test.junit5.mockito.InjectMockComponents; -import org.xwiki.test.junit5.mockito.MockComponent; - -import com.sun.management.OperatingSystemMXBean; - -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ComponentTest -public class PerformanceHealthCheckTest -{ - @MockComponent - private static ContextualLocalizationManager localization; - - @XWikiTempDir - private File tmpDir; - - private File logsDir; - - @InjectMockComponents - private PerformanceHealthCheck performanceHealthCheck; - - @Mock - private Logger logger; - - @Mock - private OperatingSystemMXBean osMXBean; - - @Mock - ManagementFactory managementFactory; - - @BeforeComponent - static void setUp() throws Exception - { - when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.performance.info")).thenReturn( - "System performance OK"); - } - - @BeforeEach - void beforeEach() - { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(performanceHealthCheck, "logger", this.logger); - - logsDir = new File("/"); - } - - @Test - void check() - { - assertNull(performanceHealthCheck.check().getErrorMessage()); - verify(logger).info("System performance OK"); - } -} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java new file mode 100644 index 00000000..7b197cac --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java @@ -0,0 +1,79 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.job; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Provider; + +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xwiki.admintools.health.HealthCheck; +import com.xwiki.admintools.health.HealthCheckResult; +import com.xwiki.admintools.jobs.HealthCheckJobRequest; +import com.xwiki.admintools.jobs.HealthCheckJobStatus; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +@ComponentTest +public class HealthCheckJobTest +{ + @InjectMockComponents + private HealthCheckJob healthCheckJob; + + @MockComponent + private Provider> listProvider; + + @Mock + private HealthCheck firstHealthCheck; + + @Mock + private HealthCheck secondHealthCheck; + + @Test + void createNewStatus() + { + assertEquals(HealthCheckJobStatus.class, + healthCheckJob.createNewStatus(new HealthCheckJobRequest()).getClass()); + } + + @Test + void runInternal() + { + List healthCheckList = new ArrayList<>(); + healthCheckList.add(firstHealthCheck); + healthCheckList.add(secondHealthCheck); + + when(listProvider.get()).thenReturn(healthCheckList); + when(firstHealthCheck.check()).thenReturn(new HealthCheckResult("err", "err_rec")); + when(secondHealthCheck.check()).thenReturn(new HealthCheckResult()); + + healthCheckJob.initialize(new HealthCheckJobRequest()); + healthCheckJob.runInternal(); + HealthCheckJobStatus healthCheckJobStatus = healthCheckJob.getStatus(); + assertEquals(1, healthCheckJobStatus.getHealthCheckResults().size()); + } +} diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index 5d5f9237..4d6a152c 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -124,11 +124,10 @@ require(['jquery', 'xwiki-meta', 'xwiki-job-runner'], function($, xwikiMeta, JobRunner) { - const getResourceURL = function() { let documentReference = XWiki.Model.resolve('AdminTools.Code.HealthCheckResources', XWiki.EntityType.DOCUMENT); return new XWiki.Document(documentReference).getURL('get'); - } + }; const runHealthCheckJob = function() { var data = []; @@ -155,7 +154,7 @@ }).finally(() => { $('#admin_tools_job_start').prop("disabled", false); }); - } + }; const reinitialiseProgressBar = function() { $.get(getResourceURL(), function(data) { @@ -164,8 +163,12 @@ $('#healthCheck .warningmessage').replaceWith(progressBar) $('#healthCheck .errormessage').replaceWith(progressBar) }); - } + }; + // Need to call job.min.js only after the job has started its execution and the result message has been changed for + // the progress bar. Otherwise, job.js won't see .ui-progress and will not initialize and run a new JobRunner + // with the requested configuration. To make sure the job .ui-progress is seen, we need to undefine and request the + // resource again. const initialiseJobJS = function() { require.undef('health-check-job'); $.get(getResourceURL(), function(data) { @@ -177,24 +180,19 @@ }); require(['health-check-job'], function(){}); }); - } + }; - $(document).ready(function(){ + $(document).ready(function() { if ($('#healthCheck').length) { - $.get(getResourceURL(), function(data) { - let jobState = $(data).find('input[name="jobState"]').val(); - if (jobState == "RUNNING") { - initialiseJobJS() - runHealthCheckJob() - // Inject the content into the job-status div - let healthCheckJobStatusURL = $(data).find('input[name="healthCheckJobStatusURL"]').val(); - $('.job-status').attr('data-url', healthCheckJobStatusURL); - $('#admin_tools_job_start').prop("disabled", true); - $('.job-status').show(); - } else if (jobState == "FINISHED") { - $('.job-status').show(); - } - }); + let jobState = $('input[name="jobState"]').val(); + if (jobState == "RUNNING") { + initialiseJobJS(); + runHealthCheckJob(); + $('#admin_tools_job_start').prop("disabled", true); + $('.job-status').show(); + } else if (jobState == "FINISHED") { + $('.job-status').show(); + } } }); @@ -202,14 +200,9 @@ event.preventDefault(); $(".log").empty(); $('#admin_tools_job_start').prop("disabled", true); - $.get(getResourceURL(), function(data) { - runHealthCheckJob() - reinitialiseProgressBar() - initialiseJobJS() - // Inject the content into the job-status div - let healthCheckJobStatusURL = $(data).find('input[name="healthCheckJobStatusURL"]').val(); - $('.job-status').attr('data-url', healthCheckJobStatusURL); - }); + runHealthCheckJob(); + reinitialiseProgressBar(); + initialiseJobJS(); $('.job-status').show(); }); diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml index b4ba2b78..b227424d 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml @@ -48,6 +48,18 @@ }) #jsonResponse($healthCheckJobStatusJSON) #end + +#macro (getHealthCheckResources) + #set ($jobMinJsURL = $xwiki.getSkinFile('uicomponents/job/job.min.js')) + #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) + #set ($healthJobStatus = $services.job.getJobStatus($healthCheckJobRequest.id)) + {{html clean=false}} + <div hidden> + <input type="text" id="jobMinJsURL" name="jobMinJsURL" value=$jobMinJsURL></input> + #displayJobProgressBar($healthJobStatus) + </div> + {{/html}} +#end {{/velocity}} {{velocity}} @@ -62,27 +74,7 @@ #set ($healthCheckJobId = $request.jobId.split('/')) #returnHealthCheckJobStatusJSON($healthCheckJobId) #else - #set ($jobMinJsURL = $xwiki.getSkinFile('uicomponents/job/job.min.js')) - #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) - #set ($jobId = $healthCheckJobRequest.id) - #set ($healthJobStatusURL = $xwiki.getURL('AdminTools.Code.HealthCheckJob', 'get', $escapetool.url({ - 'jobId': $jobId, - 'outputSyntax': 'plain' - }))) - #set ($healthJobStatus = $services.job.getJobStatus($jobId)) - #set ($percent = $healthJobStatus.progress.offset) - #if (!$percent) - #set ($percent = 0) - #end - #set ($percent = $numbertool.toNumber($mathtool.mul($percent, 100)).intValue()) - {{html clean=false}} - <div hidden> - <input type="text" name="healthCheckJobStatusURL" value=$healthJobStatusURL></input> - <input type="text" id="jobMinJsURL" name="jobMinJsURL" value=$jobMinJsURL></input> - <input type="text" name="jobState" value=$healthJobStatus.state></input> - #displayJobProgressBar($healthJobStatus) - </div> - {{/html}} + #getHealthCheckResources() #end #end {{/velocity}} diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml index 036499d5..e94d01c3 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml @@ -181,5 +181,52 @@ $healthCheckReportMessage </div> #end + +#macro (healthCheckUI) + #set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) + #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) + #set ($jobId = $healthCheckJobRequest.id) + #set ($healthJobStatusURL = $xwiki.getURL('AdminTools.Code.HealthCheckJob', 'get', $escapetool.url({ + 'jobId': $jobId, + 'outputSyntax': 'plain' + }))) + #if ($jobId) + #set ($healthJobStatus = $services.job.getJobStatus($jobId)) + #end + {{html clean='false'}} + <input type="hidden" name="jobState" value="${healthJobStatus.state}"></input> + <div class="adminToolsDashboardItem" id="healthCheck"> + <h2>$services.icon.renderHTML('bug') + $escapetool.xml($services.localization.render('adminTools.dashboard.section.healthcheck.title'))</h2> + <p>$escapetool.xml($services.localization.render('adminTools.dashboard.section.healthcheck.description')) + <a href="$xwiki.getURL('AdminTools.HelpLinks')"><strong>$escapetool.xml($services.localization.render( + 'adminTools.dashboard.section.healthcheck.description.link'))</strong></a>.</p> + <hr/> + <div class="healthCheckWrapper"> + <div class="healthCheckLastCheck"> + Time since the last health check: $services.date.displayTimeAgo($healthJobStatus.getEndDate()) + </div> + <div class="buttonwrapper"> + <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" + value="startHealthCheck">Start health check</button> + </div> + </div> + <div hidden class="xcontent job-status" data-url="${healthJobStatusURL}"> + #if ($healthJobStatus.state != 'FINISHED') + #displayJobProgressBar($jobStatus) + #else + #jobFinishedMessage($healthJobStatus, $translationPrefix, $successKey, $errorKey, $canceledKey) + #end + #if ($showLogs || $isAdvancedUser || $isSuperAdmin) + #if ($healthJobStatus.state != 'FINISHED') + #displayJobStatusLog($jobStatus true) + #else + #displayJobStatusLog($healthJobStatus true) + #end + #end + </div> + </div> + {{/html}} +#end {{/velocity}} \ No newline at end of file diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index 7252040c..5fd48cfb 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -222,49 +222,9 @@ $services.admintools.getFilesSection() {{template name="job_macros.vm"/}} {{velocity}} - #includeMacros("AdminTools.Code.Macros") - #set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) - #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) - #set ($jobId = $healthCheckJobRequest.id) - #if ($jobId) - #set ($healthJobStatus = $services.job.getJobStatus($jobId)) - #end -{{html clean='false'}} - <div class="adminToolsDashboardItem" id="healthCheck"> - <h2>$services.icon.renderHTML('bug') - $escapetool.xml($services.localization.render('adminTools.dashboard.section.healthcheck.title'))</h2> - <p>$escapetool.xml($services.localization.render('adminTools.dashboard.section.healthcheck.description')) - <a href="$xwiki.getURL('AdminTools.HelpLinks')"><strong>$escapetool.xml($services.localization.render( - 'adminTools.dashboard.section.healthcheck.description.link'))</strong></a>.</p> - <hr/> - <div class="healthCheckWrapper"> - <div class="healthCheckLastCheck"> - Time since the last health check: $services.date.displayTimeAgo($healthJobStatus.getEndDate()) - </div> - <div class="buttonwrapper"> - <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" - value="startHealthCheck">Start health check</button> - </div> - </div> - <div hidden class="xcontent job-status" data-url=""> - #if ($healthJobStatus.state != 'FINISHED') - #displayJobProgressBar($jobStatus) - #else - #jobFinishedMessage($healthJobStatus, $translationPrefix, $successKey, $errorKey, $canceledKey) - #end - #if ($showLogs || $isAdvancedUser || $isSuperAdmin) - #if ($healthJobStatus.state != 'FINISHED') - #displayJobStatusLog($jobStatus true) - #else - #displayJobStatusLog($healthJobStatus true) - #end - #end - </div> - </div> -{{/html}} -{{/velocity}} - + #healthCheckUI() +{{/velocity}} 1, 2 @@ -400,6 +360,7 @@ $services.admintools.getFilesSection() margin: 2rem 4rem; } +/* Make sure the date picker is always on top */ .bootstrap-datetimepicker-widget { z-index: 99999 !important; } From f3148cbf7dcfc1c6af83dff1467d3d26942a10f1 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Tue, 7 Nov 2023 11:42:39 +0200 Subject: [PATCH 65/72] Create a health check dashboard section #13 * Modified translations * Added comments in default POM --- application-admintools-default/pom.xml | 6 +- .../health/checks/MemoryHealthCheck.java | 14 +-- .../health/checks/PerformanceHealthCheck.java | 8 +- .../ConfigurationDatabaseHealthCheck.java | 4 +- .../ConfigurationJavaHealthCheck.java | 6 +- .../ConfigurationOsHealthCheck.java | 4 +- .../SecuritySystemEncodingHealthCheck.java | 6 +- .../SecurityXWikiEncodingHealthCheck.java | 6 +- .../templates/configurationTemplate.vm | 28 ++--- .../templates/filesSectionTemplate.vm | 18 +-- .../resources/templates/securityTemplate.vm | 16 +-- .../health/checks/MemoryHealthCheckTest.java | 14 +-- .../ConfigurationDatabaseHealthCheckTest.java | 4 +- .../ConfigurationJavaHealthCheckTest.java | 6 +- .../ConfigurationOsHealthCheckTest.java | 4 +- ...SecuritySystemEncodingHealthCheckTest.java | 6 +- .../SecurityXWikiEncodingHealthCheckTest.java | 6 +- .../main/resources/AdminTools/Code/Macros.xml | 11 +- .../AdminTools/Code/Translations.xml | 109 +++++++++--------- 19 files changed, 137 insertions(+), 139 deletions(-) diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index 710d70c5..e165cdf0 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -71,16 +71,12 @@ xwiki-commons-cache-api ${commons.version} + com.github.oshi oshi-core 5.8.0 - - org.codehaus.groovy - groovy-jmx - 3.0.13 - 0.77 diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java index a931193a..96e63ee2 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java @@ -79,15 +79,15 @@ private boolean isEnoughCache() if (storeCacheCapacity == null) { logger.warn( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.cache.null.warn")); + localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.null")); return false; } if (Integer.parseInt(storeCacheCapacity) <= 500) { logger.warn(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.memory.cache.value.warn"), storeCacheCapacity); + "adminTools.dashboard.healthcheck.memory.cache.low"), storeCacheCapacity); return false; } - logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.cache.info")); + logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.info")); return true; } @@ -100,21 +100,21 @@ private boolean hasEnoughMemory() if (maxMemoryGB < 1) { logger.error(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.memory.mem.maxcapacity.error"), maxMemoryGB * 1024); + "adminTools.dashboard.healthcheck.memory.maxcapacity.error"), maxMemoryGB * 1024); return false; } if (totalFreeMemory < 512) { logger.error( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.mem.free.error"), + localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.error"), totalFreeMemory); return false; } else if (totalFreeMemory < 1024) { logger.warn( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.mem.free.warn"), + localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.warn"), totalFreeMemory); return true; } - logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.mem.info")); + logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.info")); return true; } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java index f106844c..1db03c0e 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java @@ -67,7 +67,7 @@ public HealthCheckResult check() if (!hasFreeSpace || !hasMinimumCPURequirements || !hasMinimumMemoryRequirements) { return new HealthCheckResult("performance issues", "minimum sys req link"); } - logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.performance.info")); + logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.info")); return new HealthCheckResult(); } @@ -86,7 +86,7 @@ private boolean hasFreeSpace() return true; } else { logger.warn( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.performance.space.warn")); + localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.space.warn")); return false; } } @@ -102,7 +102,7 @@ private boolean hasMinimumMemoryRequirements() return true; } else { logger.warn( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.performance.memory.warn")); + localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.memory.warn")); return false; } } @@ -119,7 +119,7 @@ private boolean hasMinimumCPURequirements() return true; } else { logger.warn( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.performance.cpu.warn")); + localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.cpu.warn")); return false; } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java index e323ccaf..45ada3a5 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java @@ -46,10 +46,10 @@ public class ConfigurationDatabaseHealthCheck extends AbstractConfigurationHealt public HealthCheckResult check() { if (getJson(ConfigurationDataProvider.HINT).get("databaseName") == null) { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.database.warn")); + logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.warn")); return new HealthCheckResult("database_not_detected", "xwiki_db_configuration"); } - logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.database.info")); + logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.info")); return new HealthCheckResult(); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java index 8a0b8aa7..eb8dccfa 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java @@ -47,7 +47,7 @@ public HealthCheckResult check() { String javaVersionString = getJson(ConfigurationDataProvider.HINT).get("javaVersion"); if (javaVersionString == null) { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.warn.found")); + logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.found")); return new HealthCheckResult("java_version_not_found", "java_installation_link"); } String xwikiVersionString = getJson(ConfigurationDataProvider.HINT).get("xwikiVersion"); @@ -55,10 +55,10 @@ public HealthCheckResult check() float javaVersion = parseFloat(javaVersionString); if (isJavaXWikiCompatible(xwikiVersion, javaVersion)) { logger.warn( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.warn.incompatible")); + localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.incompatible")); return new HealthCheckResult("java_xwiki_not_compatible", "java_issue_rec"); } - logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.info")); + logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.info")); return new HealthCheckResult(); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java index 64a2f479..c79ef82b 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java @@ -49,10 +49,10 @@ public HealthCheckResult check() || getJson(ConfigurationDataProvider.HINT).get("osVersion") == null || getJson(ConfigurationDataProvider.HINT).get("osArch") == null) { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.os.warn")); + logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.os.warn")); return new HealthCheckResult("os_issue", "os_support"); } - logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.os.info")); + logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.os.info")); return new HealthCheckResult(); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java index e648ed05..7c551bb7 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java @@ -60,7 +60,7 @@ public HealthCheckResult check() if (!isSafeLangEnc || !isSafeFileEnc) { return new HealthCheckResult("xwiki_encoding_err", "xwiki config tutorial link"); } - logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.system.info")); + logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.info")); return new HealthCheckResult(); } @@ -70,7 +70,7 @@ private boolean isSafeLanguageEncoding(String langEnc) return true; } logger.warn( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.system.lang.warn"), + localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.lang.warn"), langEnc); return false; } @@ -81,7 +81,7 @@ private boolean isSafeFileEncoding(String fileEnc) return true; } logger.warn( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.system.file.warn"), + localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.file.warn"), fileEnc); return false; } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java index 540ed27a..c34e6ad6 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java @@ -61,7 +61,7 @@ public HealthCheckResult check() if (!isActiveEncSafe || !isConfigEncSafe) { return new HealthCheckResult("xwiki_encoding_err", "xwiki config tutorial link"); } - logger.info(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.xwiki.info")); + logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.xwiki.info")); return new HealthCheckResult(); } @@ -71,7 +71,7 @@ private boolean isSafeActiveEncoding(String activeEnc) return true; } logger.warn( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.xwiki.active.warn"), + localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.xwiki.active.warn"), activeEnc); return false; } @@ -82,7 +82,7 @@ private boolean isSafeConfigEncoding(String configEnc) return true; } logger.warn( - localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.security.xwiki.config.warn"), + localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.xwiki.config.warn"), configEnc); return false; } diff --git a/application-admintools-default/src/main/resources/templates/configurationTemplate.vm b/application-admintools-default/src/main/resources/templates/configurationTemplate.vm index 09d790c6..2281d2eb 100644 --- a/application-admintools-default/src/main/resources/templates/configurationTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/configurationTemplate.vm @@ -24,12 +24,12 @@ #if ($configuration['serverFound'] == 'true')

$services.icon.renderHTML('world') - $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.title'))

-

$escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.description'))

+ $escapetool.xml($services.localization.render('adminTools.dashboard.backend.title')) +

$escapetool.xml($services.localization.render('adminTools.dashboard.backend.description'))


  • - $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.xwiki.version')): + $escapetool.xml($services.localization.render('adminTools.dashboard.backend.xwiki.version')): $configuration['xwikiVersion']
    • @@ -39,42 +39,42 @@
  • - $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.java')): + $escapetool.xml($services.localization.render('adminTools.dashboard.backend.java')): $configuration['javaVersion']
  • - $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.usedServer')) + $escapetool.xml($services.localization.render('adminTools.dashboard.backend.usedServer')) $configuration['usedServerName'] - $configuration['usedServerVersion']
  • -
  • $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.os.legend')) +
  • $escapetool.xml($services.localization.render('adminTools.dashboard.backend.os.legend'))
      -
    • $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.os.name')): +
    • $escapetool.xml($services.localization.render('adminTools.dashboard.backend.os.name')): $configuration['osName']
    • -
    • $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.os.version')): +
    • $escapetool.xml($services.localization.render('adminTools.dashboard.backend.os.version')): $configuration['osVersion']
    • -
    • $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.os.architecture')): +
    • $escapetool.xml($services.localization.render('adminTools.dashboard.backend.os.architecture')): $configuration['osArch']
  • #if ($configuration['databaseName'] != $null) -
  • $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.usedDB')) +
  • $escapetool.xml($services.localization.render('adminTools.dashboard.backend.usedDB')) $configuration['databaseName'] - $configuration['databaseVersion']
  • #else #set($warningDatabaseMessage = $escapetool.xml( - $services.localization.render('adminTools.dashboard.section.backend.supportedDB.error')) + ':') + $services.localization.render('adminTools.dashboard.backend.supportedDB.error')) + ':') #set($warningDatabaseMessage = $warningDatabaseMessage + $stringtool.join($services.admintools.getSupportedDatabases(), ', '))
  • $escapetool.xml( - $services.localization.render('adminTools.dashboard.section.backend.usedDB')) #warning($warningDatabaseMessage) + $services.localization.render('adminTools.dashboard.backend.usedDB')) #warning($warningDatabaseMessage)
  • #end
#else #set($warningMessage = - $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.configuration.error'))+ '
') + $escapetool.xml($services.localization.render('adminTools.dashboard.backend.configuration.error'))+ '
') #set($warningMessage = $warningMessage + - $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.supportedServers.error')) + ':' + $escapetool.xml($services.localization.render('adminTools.dashboard.backend.supportedServers.error')) + ':' + $stringtool.join($services.admintools.getSupportedServers(), ', ')) #warning($warningMessage) #end diff --git a/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm b/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm index a05de3c4..a0207cfd 100644 --- a/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/filesSectionTemplate.vm @@ -26,27 +26,27 @@ #if ($found)

$services.icon.renderHTML('download') - $escapetool.xml($services.localization.render('adminTools.dashboard.section.download.title'))

-

$escapetool.xml($services.localization.render('adminTools.dashboard.section.download.description'))

+ $escapetool.xml($services.localization.render('adminTools.dashboard.download.title')) +

$escapetool.xml($services.localization.render('adminTools.dashboard.download.description'))


- #warning($escapetool.xml($services.localization.render('adminTools.dashboard.section.download.warning'))) + #warning($escapetool.xml($services.localization.render('adminTools.dashboard.download.warning')))
#else #set($warningMessage = - $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.configuration.error'))+ '
') + $escapetool.xml($services.localization.render('adminTools.dashboard.backend.configuration.error'))+ '
') #set($warningMessage = $warningMessage + - $escapetool.xml($services.localization.render('adminTools.dashboard.section.backend.supportedServers.error')) + $escapetool.xml($services.localization.render('adminTools.dashboard.backend.supportedServers.error')) + $stringtool.join($services.admintools.getSupportedServers(), ', ')) #warning($warningMessage) #end diff --git a/application-admintools-default/src/main/resources/templates/securityTemplate.vm b/application-admintools-default/src/main/resources/templates/securityTemplate.vm index fa334e4e..e82c3f1a 100644 --- a/application-admintools-default/src/main/resources/templates/securityTemplate.vm +++ b/application-admintools-default/src/main/resources/templates/securityTemplate.vm @@ -21,32 +21,32 @@ #if($security['serverFound'] == 'true')

$services.icon.renderHTML('lock') - $escapetool.xml($services.localization.render('adminTools.dashboard.section.security.title'))

-

$escapetool.xml($services.localization.render('adminTools.dashboard.section.security.description'))

+ $escapetool.xml($services.localization.render('adminTools.dashboard.security.title')) +

$escapetool.xml($services.localization.render('adminTools.dashboard.security.description'))


  • - $escapetool.xml($services.localization.render('adminTools.dashboard.section.security.activeEncoding')): + $escapetool.xml($services.localization.render('adminTools.dashboard.security.activeEncoding')): $security['activeEncoding']
  • - $escapetool.xml($services.localization.render('adminTools.dashboard.section.security.configurationEncoding')): + $escapetool.xml($services.localization.render('adminTools.dashboard.security.configurationEncoding')): $security['configurationEncoding']
  • - $escapetool.xml($services.localization.render('adminTools.dashboard.section.security.PWD')): $security['PWD'] + $escapetool.xml($services.localization.render('adminTools.dashboard.security.PWD')): $security['PWD']
  • - $escapetool.xml($services.localization.render('adminTools.dashboard.section.security.LANG')): $security['LANG'] + $escapetool.xml($services.localization.render('adminTools.dashboard.security.LANG')): $security['LANG']
  • - $escapetool.xml($services.localization.render('adminTools.dashboard.section.security.fileEncoding')): + $escapetool.xml($services.localization.render('adminTools.dashboard.security.fileEncoding')): $security['fileEncoding']
#else - #set($warningMessage = $escapetool.xml($services.localization.render('adminTools.dashboard.section.security.error'))) + #set($warningMessage = $escapetool.xml($services.localization.render('adminTools.dashboard.security.error'))) #warning($warningMessage) #end {{/html}} \ No newline at end of file diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java index 250dfc04..e372c223 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java @@ -70,24 +70,24 @@ public class MemoryHealthCheckTest @BeforeComponent static void setUp() throws Exception { - when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.cache.info")).thenReturn( + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.info")).thenReturn( "Cache status OK"); - when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.memory.mem.info")).thenReturn( + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.info")).thenReturn( "Memory status OK"); when(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.memory.cache.null.warn")).thenReturn( + "adminTools.dashboard.healthcheck.memory.cache.null")).thenReturn( "Store cache capacity is set at 500. Check Cache recommendations in solutions."); when(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.memory.cache.value.warn")).thenReturn( + "adminTools.dashboard.healthcheck.memory.cache.low")).thenReturn( "Store cache capacity is set at [{}]. Check Cache recommendations in solutions."); when(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.memory.mem.free.error")).thenReturn( + "adminTools.dashboard.healthcheck.memory.free.error")).thenReturn( "Your JVM instance has only [{}]MB free memory left! Consult the solution link for support!"); when(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.memory.mem.free.warn")).thenReturn( + "adminTools.dashboard.healthcheck.memory.free.warn")).thenReturn( "Your instance memory is running low. Currently only [{}]MB free left."); when(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.memory.mem.maxcapacity.error")).thenReturn( + "adminTools.dashboard.healthcheck.memory.maxcapacity.error")).thenReturn( "JVM memory is less than 1024MB. Currently: [{}]MB"); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java index f1d78dab..32088fa3 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java @@ -76,9 +76,9 @@ static void setUp() throws Exception when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); - when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.database.info")) + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.info")) .thenReturn("Database status OK"); - when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.database.warn")) + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.warn")) .thenReturn("Database not found!"); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java index cbde8313..4c618cd5 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java @@ -75,11 +75,11 @@ static void setUp() throws Exception when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); - when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.info")) + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.info")) .thenReturn("Java status OK"); - when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.warn.found")) + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.found")) .thenReturn("Java version not found!"); - when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.java.warn.incompatible")) + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.incompatible")) .thenReturn("Java version is not compatible with the current XWiki installation!"); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java index c1eee470..0cc9d48e 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java @@ -77,9 +77,9 @@ static void setUp() throws Exception when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); - when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.os.info")).thenReturn( + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.os.info")).thenReturn( "OS info retrieval OK"); - when(localization.getTranslationPlain("adminTools.dashboard.section.healthcheck.os.warn")).thenReturn( + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.os.warn")).thenReturn( "There has been an error while gathering OS info!"); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheckTest.java index 5a804f16..3592f5e4 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheckTest.java @@ -76,12 +76,12 @@ static void setUp() throws Exception when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); when(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.security.system.info")).thenReturn("System encoding OK"); + "adminTools.dashboard.healthcheck.security.system.info")).thenReturn("System encoding OK"); when(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.security.system.lang.warn")).thenReturn( + "adminTools.dashboard.healthcheck.security.system.lang.warn")).thenReturn( "System language encoding is [{}] but should be UTF-8!"); when(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.security.system.file.warn")).thenReturn( + "adminTools.dashboard.healthcheck.security.system.file.warn")).thenReturn( "System file encoding is [{}] but should be UTF-8!"); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheckTest.java index 5212ed30..f9a3e1a7 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheckTest.java @@ -76,12 +76,12 @@ static void setUp() throws Exception when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); when(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.security.xwiki.info")).thenReturn("XWiki encoding OK"); + "adminTools.dashboard.healthcheck.security.xwiki.info")).thenReturn("XWiki encoding OK"); when(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.security.xwiki.active.warn")).thenReturn( + "adminTools.dashboard.healthcheck.security.xwiki.active.warn")).thenReturn( "XWiki active encoding is [{}] but should be UTF-8!"); when(localization.getTranslationPlain( - "adminTools.dashboard.section.healthcheck.security.xwiki.config.warn")).thenReturn( + "adminTools.dashboard.healthcheck.security.xwiki.config.warn")).thenReturn( "XWiki configuration encoding is [{}] but should be UTF-8!"); } diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml index e94d01c3..b98acdcf 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml @@ -193,14 +193,17 @@ #if ($jobId) #set ($healthJobStatus = $services.job.getJobStatus($jobId)) #end + #set($solutionLink = $xwiki.getURL('AdminTools.HelpLinks')) + #set ($description = $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.description', [ + '__STARTLINK__', + '__ENDLINK__' + ])).replace('__STARTLINK__', "<a href='$solutionLink'><strong>").replace('__ENDLINK__', '</strong></a>')) {{html clean='false'}} <input type="hidden" name="jobState" value="${healthJobStatus.state}"></input> <div class="adminToolsDashboardItem" id="healthCheck"> <h2>$services.icon.renderHTML('bug') - $escapetool.xml($services.localization.render('adminTools.dashboard.section.healthcheck.title'))</h2> - <p>$escapetool.xml($services.localization.render('adminTools.dashboard.section.healthcheck.description')) - <a href="$xwiki.getURL('AdminTools.HelpLinks')"><strong>$escapetool.xml($services.localization.render( - 'adminTools.dashboard.section.healthcheck.description.link'))</strong></a>.</p> + $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.title'))</h2> + <p>$description</p> <hr/> <div class="healthCheckWrapper"> <div class="healthCheckLastCheck"> diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml index 36ef836b..82c607a8 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml @@ -44,67 +44,66 @@ admin.admintools.description=Configure Admin Tools Application ## Dashboard sections ## Config -adminTools.dashboard.section.backend.configuration.error=Server path was not found. Please manually add the path to the server on the Admin Tools configuration page. -adminTools.dashboard.section.backend.description=Get info about your backend -adminTools.dashboard.section.backend.java=Detected java version -adminTools.dashboard.section.backend.os.architecture=OS architecture -adminTools.dashboard.section.backend.os.legend=OS info -adminTools.dashboard.section.backend.os.name=OS name -adminTools.dashboard.section.backend.os.version=OS version -adminTools.dashboard.section.backend.supportedDB.error=Database not found. Currently supported databases -adminTools.dashboard.section.backend.supportedServers.error=Currently supported servers -adminTools.dashboard.section.backend.title=Backend -adminTools.dashboard.section.backend.usedDB=Used database -adminTools.dashboard.section.backend.usedServer=Used server -adminTools.dashboard.section.backend.xwiki.version=XWiki installation version +adminTools.dashboard.backend.configuration.error=Server path was not found. Please manually add the path to the server on the Admin Tools configuration page. +adminTools.dashboard.backend.description=Get info about your backend +adminTools.dashboard.backend.java=Detected java version +adminTools.dashboard.backend.os.architecture=OS architecture +adminTools.dashboard.backend.os.legend=OS info +adminTools.dashboard.backend.os.name=OS name +adminTools.dashboard.backend.os.version=OS version +adminTools.dashboard.backend.supportedDB.error=Database not found. Currently supported databases +adminTools.dashboard.backend.supportedServers.error=Currently supported servers +adminTools.dashboard.backend.title=Backend +adminTools.dashboard.backend.usedDB=Used database +adminTools.dashboard.backend.usedServer=Used server +adminTools.dashboard.backend.xwiki.version=XWiki installation version ## Files -adminTools.dashboard.section.download.description=Get the files you need. View them directly in the browser or download them as an archive. -adminTools.dashboard.section.download.label=Export files needed for getting support -adminTools.dashboard.section.download.title=Files -adminTools.dashboard.section.download.view.configuration=XWiki configuration file -adminTools.dashboard.section.download.view.description=View files content -adminTools.dashboard.section.download.view.properties=XWiki properties file -adminTools.dashboard.section.download.warning=Before downloading and sending the files, please make sure you introduced the lines that may contain sensitive info in Admin Tools configuration page! +adminTools.dashboard.download.description=Get the files you need. View them directly in the browser or download them as an archive. +adminTools.dashboard.download.label=Export files needed for getting support +adminTools.dashboard.download.title=Files +adminTools.dashboard.download.view.configuration=XWiki configuration file +adminTools.dashboard.download.view.description=View files content +adminTools.dashboard.download.view.properties=XWiki properties file +adminTools.dashboard.download.warning=Before downloading and sending the files, please make sure you introduced the lines that may contain sensitive info in Admin Tools configuration page! ## Health check -adminTools.dashboard.section.healthcheck.database.info=Database status OK -adminTools.dashboard.section.healthcheck.database.warn=Database not found! -adminTools.dashboard.section.healthcheck.description=Check if your instance is configured correctly and is properly running. For any issues, check out this -adminTools.dashboard.section.healthcheck.description.link=solutions -adminTools.dashboard.section.healthcheck.java.info=Java status OK -adminTools.dashboard.section.healthcheck.java.warn.found=Java version not found! -adminTools.dashboard.section.healthcheck.java.warn.incompatible=Java version is not compatible with the current XWiki installation! -adminTools.dashboard.section.healthcheck.memory.cache.info=Cache status OK -adminTools.dashboard.section.healthcheck.memory.cache.null.warn=Store cache capacity is set at 500. See cache recommendations in solutions. -adminTools.dashboard.section.healthcheck.memory.cache.value.warn=Store cache capacity is set at [{}]. See cache recommendations in solutions. -adminTools.dashboard.section.healthcheck.memory.mem.free.error=Your JVM instance has only [{}]MB free memory left! Consult the solution link for support! -adminTools.dashboard.section.healthcheck.memory.mem.free.warn=Your instance memory is running low. Currently only [{}]MB free left. -adminTools.dashboard.section.healthcheck.memory.mem.info=Memory status OK -adminTools.dashboard.section.healthcheck.memory.mem.maxcapacity.error=JVM memory is less than 1024MB. Currently: [{}]MB -adminTools.dashboard.section.healthcheck.os.info=OS info retrieval OK -adminTools.dashboard.section.healthcheck.os.warn=There has been an error while gathering OS info! -adminTools.dashboard.section.healthcheck.performance.cpu.warn=The CPU does not satisfy the minimum system requirements! -adminTools.dashboard.section.healthcheck.performance.info=System performance OK -adminTools.dashboard.section.healthcheck.performance.memory.warn=There is not enough memory to safely run the XWiki installation! -adminTools.dashboard.section.healthcheck.performance.space.warn=There is not enough free space for the XWiki installation! -adminTools.dashboard.section.healthcheck.security.system.info=System encoding OK -adminTools.dashboard.section.healthcheck.security.system.file.warn=System file encoding is [{}] but should be UTF-8! -adminTools.dashboard.section.healthcheck.security.system.lang.warn=System language encoding is [{}] but should be UTF-8! -adminTools.dashboard.section.healthcheck.security.xwiki.info=XWiki encoding OK -adminTools.dashboard.section.healthcheck.security.xwiki.active.warn=XWiki active encoding is [{}]. The encoding should be UTF-8! -adminTools.dashboard.section.healthcheck.security.xwiki.config.warn=XWiki configuration encoding is [{}]. The encoding should be UTF-8! -adminTools.dashboard.section.healthcheck.title=Health check +adminTools.dashboard.healthcheck.database.info=Database status OK +adminTools.dashboard.healthcheck.database.warn=Database not found! +adminTools.dashboard.healthcheck.description=Check if your instance is configured correctly and is properly running. For any issues, check out this {0}solutions{1}. +adminTools.dashboard.healthcheck.java.info=Java status OK +adminTools.dashboard.healthcheck.java.warn.found=Java version not found! +adminTools.dashboard.healthcheck.java.warn.incompatible=Java version is not compatible with the current XWiki installation! +adminTools.dashboard.healthcheck.memory.cache.info=Cache status OK +adminTools.dashboard.healthcheck.memory.cache.null=Store cache capacity is set at 500. See cache recommendations in solutions. +adminTools.dashboard.healthcheck.memory.cache.low=Store cache capacity is set at [{}]. See cache recommendations in solutions. +adminTools.dashboard.healthcheck.memory.free.error=Your JVM instance has only [{}]MB free memory left! Consult the solution link for support! +adminTools.dashboard.healthcheck.memory.free.warn=Your instance memory is running low. Currently only [{}]MB free left. +adminTools.dashboard.healthcheck.memory.info=Memory status OK +adminTools.dashboard.healthcheck.memory.maxcapacity.error=JVM memory is less than 1024MB. Currently: [{}]MB +adminTools.dashboard.healthcheck.os.info=OS info retrieval OK +adminTools.dashboard.healthcheck.os.warn=There has been an error while gathering OS info! +adminTools.dashboard.healthcheck.performance.cpu.warn=The CPU does not satisfy the minimum system requirements! +adminTools.dashboard.healthcheck.performance.info=System performance OK +adminTools.dashboard.healthcheck.performance.memory.warn=There is not enough memory to safely run the XWiki installation! +adminTools.dashboard.healthcheck.performance.space.warn=There is not enough free space for the XWiki installation! +adminTools.dashboard.healthcheck.security.system.info=System encoding OK +adminTools.dashboard.healthcheck.security.system.file.warn=System file encoding is [{}] but should be UTF-8! +adminTools.dashboard.healthcheck.security.system.lang.warn=System language encoding is [{}] but should be UTF-8! +adminTools.dashboard.healthcheck.security.xwiki.info=XWiki encoding OK +adminTools.dashboard.healthcheck.security.xwiki.active.warn=XWiki active encoding is [{}]. The encoding should be UTF-8! +adminTools.dashboard.healthcheck.security.xwiki.config.warn=XWiki configuration encoding is [{}]. The encoding should be UTF-8! +adminTools.dashboard.healthcheck.title=Health check ## Security -adminTools.dashboard.section.security.activeEncoding=Active encoding -adminTools.dashboard.section.security.configurationEncoding=Configuration encoding -adminTools.dashboard.section.security.description=See an overview of your security information. -adminTools.dashboard.section.security.error=Error while gathering security information. -adminTools.dashboard.section.security.fileEncoding=File encoding -adminTools.dashboard.section.security.lang=Used language -adminTools.dashboard.section.security.pwd=Working directory -adminTools.dashboard.section.security.title=Security +adminTools.dashboard.security.activeEncoding=Active encoding +adminTools.dashboard.security.configurationEncoding=Configuration encoding +adminTools.dashboard.security.description=See an overview of your security information. +adminTools.dashboard.security.error=Error while gathering security information. +adminTools.dashboard.security.fileEncoding=File encoding +adminTools.dashboard.security.lang=Used language +adminTools.dashboard.security.pwd=Working directory +adminTools.dashboard.security.title=Security ## Modals From 163e3cd153db6bcd4d18ad91fb89f253950d3f83 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Thu, 9 Nov 2023 16:19:19 +0200 Subject: [PATCH 66/72] Create a health check dashboard section #13 * Refactored the way a component is found in the entire project * Refactored tests * Merged the security health checks * Added translations * Refactored Help links page * Replaced hidden inputs for data comunication between server and client with attributes * JS refactoring * job velocity refactoring * Replaced OperatingSystemMXBean for finding physical memory with JVM independent com.github.oshi * Removed the script for creating a request. The client will now only access the job runner script and will send the ID that will be used * Other minor modifications --- .../xwiki/admintools/health/HealthCheck.java | 3 + .../admintools/health/HealthCheckResult.java | 9 +- .../jobs/HealthCheckJobRequest.java | 7 +- .../internal/AdminToolsManager.java | 25 +- .../internal/files/ImportantFilesManager.java | 17 +- .../health/checks/MemoryHealthCheck.java | 19 +- .../health/checks/PerformanceHealthCheck.java | 30 ++- .../AbstractConfigurationHealthCheck.java | 19 +- .../ConfigurationDatabaseHealthCheck.java | 2 +- .../ConfigurationJavaHealthCheck.java | 7 +- .../ConfigurationOsHealthCheck.java | 8 +- ....java => SecurityEncodingHealthCheck.java} | 42 ++- .../SecurityXWikiEncodingHealthCheck.java | 89 ------- .../internal/health/job/HealthCheckJob.java | 2 +- .../script/AdminToolsScriptService.java | 24 +- .../main/resources/META-INF/components.txt | 3 +- .../internal/AdminToolsEventListenerTest.java | 8 +- .../DefaultAdminToolsConfigurationTest.java | 3 +- .../data/ConfigurationDataProviderTest.java | 12 +- .../data/SecurityDataProviderTest.java | 10 +- .../data/identifiers/CurrentServerTest.java | 2 +- .../identifiers/TomcatIdentifierTest.java | 2 +- .../files/ImportantFilesManagerTest.java | 79 ++---- .../DataProvidersDataResourceTest.java | 11 +- .../files/resources/LogsDataResourceTest.java | 30 +-- .../XWikiConfigFileDataResourceTest.java | 5 +- .../XWikiPropertiesFileDataResourceTest.java | 2 +- .../health/checks/MemoryHealthCheckTest.java | 23 +- .../ConfigurationDatabaseHealthCheckTest.java | 39 ++- .../ConfigurationJavaHealthCheckTest.java | 51 ++-- .../ConfigurationOsHealthCheckTest.java | 26 +- ...a => SecurityEncodingHealthCheckTest.java} | 43 ++- .../SecurityXWikiEncodingHealthCheckTest.java | 125 --------- .../health/job/HealthCheckJobTest.java | 2 +- .../rest/DefaultAdminToolsResourceTest.java | 14 +- .../AdminTools/Code/AdminToolsJS.xml | 24 +- .../AdminTools/Code/Configuration.xml | 21 +- .../AdminTools/Code/ConfigurationClass.xml | 7 +- .../AdminTools/Code/HealthCheckJob.xml | 23 +- .../AdminTools/Code/HealthCheckResources.xml | 27 +- .../main/resources/AdminTools/Code/Macros.xml | 246 +++++++++--------- .../AdminTools/Code/Translations.xml | 35 ++- .../main/resources/AdminTools/HelpLinks.xml | 105 +++----- .../src/main/resources/AdminTools/WebHome.xml | 20 +- 44 files changed, 537 insertions(+), 764 deletions(-) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/{SecuritySystemEncodingHealthCheck.java => SecurityEncodingHealthCheck.java} (64%) delete mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java rename application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/{SecuritySystemEncodingHealthCheckTest.java => SecurityEncodingHealthCheckTest.java} (66%) delete mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheckTest.java diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheck.java b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheck.java index 1af54c3d..85820595 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheck.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheck.java @@ -20,13 +20,16 @@ package com.xwiki.admintools.health; import org.xwiki.component.annotation.Role; +import org.xwiki.stability.Unstable; /** * Check for issues in the current wiki. * + * @since 1.0 * @version $Id$ */ @Role +@Unstable public interface HealthCheck { /** diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java index 877f701a..2f2148a7 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java @@ -37,12 +37,12 @@ public class HealthCheckResult /** * Used for registering an error. * - * @param errMsg Error message representing the summary of the found issue. + * @param errorMessage Error message representing the summary of the found issue. * @param recommendation Suggestion for fixing the issue. */ - public HealthCheckResult(String errMsg, String recommendation) + public HealthCheckResult(String errorMessage, String recommendation) { - this.errorMessage = errMsg; + this.errorMessage = errorMessage; this.recommendation = recommendation; } @@ -51,8 +51,7 @@ public HealthCheckResult(String errMsg, String recommendation) */ public HealthCheckResult() { - errorMessage = null; - recommendation = null; + this(null, null); } /** diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java b/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java index 135d5beb..9b048946 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java @@ -45,12 +45,11 @@ public HealthCheckJobRequest() /** * Creates a request specific to the wiki from which the call was made. * - * @param wiki the wiki ID from which the request was made. + * @param requestId the ID for the request. */ - public HealthCheckJobRequest(String wiki) + public HealthCheckJobRequest(List requestId) { - setDefaultId(); - getId().add(wiki); + setId(requestId); } private void setDefaultId() diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index 8a388397..f317c2e4 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -23,10 +23,14 @@ import java.util.List; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; +import org.slf4j.Logger; import org.xwiki.component.annotation.Component; +import org.xwiki.component.manager.ComponentLookupException; +import org.xwiki.component.manager.ComponentManager; import com.xwiki.admintools.DataProvider; import com.xwiki.admintools.internal.data.identifiers.CurrentServer; @@ -41,6 +45,11 @@ @Singleton public class AdminToolsManager { + private static final String GET_DATA_PROVIDER_ERROR_MESSAGE = "Could not find the requested Data Provider!"; + + @Inject + private Logger logger; + /** * A list of all the data providers for Admin Tools. */ @@ -56,6 +65,10 @@ public class AdminToolsManager @Inject private ImportantFilesManager importantFilesManager; + @Inject + @Named("context") + private ComponentManager contextComponentManager; + /** * Get data generated in a specific format, using a template, by each provider and merge it. * @@ -78,14 +91,14 @@ public String generateData() * @param hint {@link String} represents the data provider identifier. * @return a {@link String} representing a template */ - public String generateData(String hint) + public String generateData(String hint) throws ComponentLookupException { - for (DataProvider dataProvider : this.dataProviderProvider.get()) { - if (dataProvider.getIdentifier().equals(hint)) { - return dataProvider.getRenderedData(); - } + DataProvider dataProvider = contextComponentManager.getInstance(DataProvider.class, hint); + if (dataProvider == null) { + logger.error(GET_DATA_PROVIDER_ERROR_MESSAGE); + throw new NullPointerException(GET_DATA_PROVIDER_ERROR_MESSAGE); } - return null; + return dataProvider.getRenderedData(); } /** diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java index 426afe94..7e15e5c2 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/files/ImportantFilesManager.java @@ -21,19 +21,20 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.zip.ZipOutputStream; import javax.inject.Inject; -import javax.inject.Provider; +import javax.inject.Named; import javax.inject.Singleton; import javax.script.ScriptContext; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.xwiki.component.annotation.Component; +import org.xwiki.component.manager.ComponentLookupException; +import org.xwiki.component.manager.ComponentManager; import org.xwiki.script.ScriptContextManager; import org.xwiki.template.TemplateManager; @@ -54,7 +55,8 @@ public class ImportantFilesManager private static final String REQUESTED_FILES_KEY = "files"; @Inject - private Provider> dataResources; + @Named("context") + private ComponentManager contextComponentManager; @Inject private TemplateManager templateManager; @@ -141,13 +143,8 @@ public String renderTemplate() } } - private DataResource findDataResource(String hint) + private DataResource findDataResource(String hint) throws ComponentLookupException { - for (DataResource archiverDataResource : dataResources.get()) { - if (archiverDataResource.getIdentifier().equals(hint)) { - return archiverDataResource; - } - } - return null; + return contextComponentManager.getInstance(DataResource.class, hint); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java index 96e63ee2..87a7cc12 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java @@ -47,7 +47,7 @@ public class MemoryHealthCheck implements HealthCheck /** * Component identifier. */ - public static final String HINT = "CACHE_HEALTH_CHECK"; + public static final String HINT = "MEMORY_HEALTH_CHECK"; @Inject protected ContextualLocalizationManager localization; @@ -78,13 +78,12 @@ private boolean isEnoughCache() String storeCacheCapacity = configurationSource.getProperty("xwiki.store.cache.capacity"); if (storeCacheCapacity == null) { - logger.warn( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.null")); + logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.null")); return false; } if (Integer.parseInt(storeCacheCapacity) <= 500) { - logger.warn(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.memory.cache.low"), storeCacheCapacity); + logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.low"), + storeCacheCapacity); return false; } logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.info")); @@ -99,18 +98,16 @@ private boolean hasEnoughMemory() float maxMemoryGB = maxMemory / (1024.0f * 1024 * 1024); if (maxMemoryGB < 1) { - logger.error(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.memory.maxcapacity.error"), maxMemoryGB * 1024); + logger.error(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.maxcapacity.error"), + maxMemoryGB * 1024); return false; } if (totalFreeMemory < 512) { - logger.error( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.error"), + logger.error(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.error"), totalFreeMemory); return false; } else if (totalFreeMemory < 1024) { - logger.warn( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.warn"), + logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.warn"), totalFreeMemory); return true; } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java index 1db03c0e..e396976a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java @@ -20,7 +20,6 @@ package com.xwiki.admintools.internal.health.checks; import java.io.File; -import java.lang.management.ManagementFactory; import javax.inject.Inject; import javax.inject.Named; @@ -28,6 +27,8 @@ import org.slf4j.Logger; import org.xwiki.component.annotation.Component; +import org.xwiki.component.phase.Initializable; +import org.xwiki.component.phase.InitializationException; import org.xwiki.localization.ContextualLocalizationManager; import com.xwiki.admintools.health.HealthCheck; @@ -45,7 +46,7 @@ @Component @Named(PerformanceHealthCheck.HINT) @Singleton -public class PerformanceHealthCheck implements HealthCheck +public class PerformanceHealthCheck implements HealthCheck, Initializable { /** * Component identifier. @@ -58,6 +59,15 @@ public class PerformanceHealthCheck implements HealthCheck @Inject private Logger logger; + private HardwareAbstractionLayer hardware; + + @Override + public void initialize() throws InitializationException + { + SystemInfo systemInfo = new SystemInfo(); + this.hardware = systemInfo.getHardware(); + } + @Override public HealthCheckResult check() { @@ -85,32 +95,25 @@ private boolean hasFreeSpace() if (freeSpace > 2) { return true; } else { - logger.warn( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.space.warn")); + logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.space.warn")); return false; } } private boolean hasMinimumMemoryRequirements() { - long memorySize = - ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()) - .getTotalPhysicalMemorySize(); - float totalMemory = (float) memorySize / (1024 * 1024 * 1024) + 1; + float totalMemory = (float) hardware.getMemory().getTotal() / (1024 * 1024 * 1024) + 1; if (totalMemory > 2) { return true; } else { - logger.warn( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.memory.warn")); + logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.memory.warn")); return false; } } private boolean hasMinimumCPURequirements() { - SystemInfo systemInfo = new SystemInfo(); - HardwareAbstractionLayer hardware = systemInfo.getHardware(); CentralProcessor processor = hardware.getProcessor(); int cpuCores = processor.getPhysicalProcessorCount(); long maxFreq = processor.getMaxFreq() / (1024 * 1024); @@ -118,8 +121,7 @@ private boolean hasMinimumCPURequirements() if (cpuCores > 2 && maxFreq > 2048) { return true; } else { - logger.warn( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.cpu.warn")); + logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.cpu.warn")); return false; } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java index d9e85002..a977e1fc 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java @@ -20,13 +20,14 @@ package com.xwiki.admintools.internal.health.checks.configuration; import java.util.HashMap; -import java.util.List; import java.util.Map; import javax.inject.Inject; -import javax.inject.Provider; +import javax.inject.Named; import org.slf4j.Logger; +import org.xwiki.component.manager.ComponentLookupException; +import org.xwiki.component.manager.ComponentManager; import org.xwiki.localization.ContextualLocalizationManager; import com.xwiki.admintools.DataProvider; @@ -49,7 +50,8 @@ public abstract class AbstractConfigurationHealthCheck implements HealthCheck protected Logger logger; @Inject - private Provider> dataProviders; + @Named("context") + private ComponentManager contextComponentManager; /** * Get the JSON needed in the health checks execution. @@ -57,7 +59,7 @@ public abstract class AbstractConfigurationHealthCheck implements HealthCheck * @param hint identifies the {@link DataProvider} for which JSON is required. * @return a {@link Map} with the {@link DataProvider} info, or an empty {@link Map} in case of an error. */ - protected Map getJson(String hint) + protected Map getJSON(String hint) { try { DataProvider dataProvider = findDataProvider(hint); @@ -70,13 +72,8 @@ protected Map getJson(String hint) } } - private DataProvider findDataProvider(String hint) + private DataProvider findDataProvider(String hint) throws ComponentLookupException { - for (DataProvider dataProvider : dataProviders.get()) { - if (dataProvider.getIdentifier().equals(hint)) { - return dataProvider; - } - } - return null; + return this.contextComponentManager.getInstance(DataProvider.class, hint); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java index 45ada3a5..b1850df6 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java @@ -45,7 +45,7 @@ public class ConfigurationDatabaseHealthCheck extends AbstractConfigurationHealt @Override public HealthCheckResult check() { - if (getJson(ConfigurationDataProvider.HINT).get("databaseName") == null) { + if (getJSON(ConfigurationDataProvider.HINT).get("databaseName") == null) { logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.warn")); return new HealthCheckResult("database_not_detected", "xwiki_db_configuration"); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java index eb8dccfa..03ddb74f 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java @@ -45,17 +45,16 @@ public class ConfigurationJavaHealthCheck extends AbstractConfigurationHealthChe @Override public HealthCheckResult check() { - String javaVersionString = getJson(ConfigurationDataProvider.HINT).get("javaVersion"); + String javaVersionString = getJSON(ConfigurationDataProvider.HINT).get("javaVersion"); if (javaVersionString == null) { logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.found")); return new HealthCheckResult("java_version_not_found", "java_installation_link"); } - String xwikiVersionString = getJson(ConfigurationDataProvider.HINT).get("xwikiVersion"); + String xwikiVersionString = getJSON(ConfigurationDataProvider.HINT).get("xwikiVersion"); float xwikiVersion = parseFloat(xwikiVersionString); float javaVersion = parseFloat(javaVersionString); if (isJavaXWikiCompatible(xwikiVersion, javaVersion)) { - logger.warn( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.incompatible")); + logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.incompatible")); return new HealthCheckResult("java_xwiki_not_compatible", "java_issue_rec"); } logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.info")); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java index c79ef82b..82d18678 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java @@ -19,6 +19,8 @@ */ package com.xwiki.admintools.internal.health.checks.configuration; +import java.util.Map; + import javax.inject.Named; import javax.inject.Singleton; @@ -45,10 +47,8 @@ public class ConfigurationOsHealthCheck extends AbstractConfigurationHealthCheck @Override public HealthCheckResult check() { - if (getJson(ConfigurationDataProvider.HINT).get("osName") == null - || getJson(ConfigurationDataProvider.HINT).get("osVersion") == null - || getJson(ConfigurationDataProvider.HINT).get("osArch") == null) - { + Map dataJSON = getJSON(ConfigurationDataProvider.HINT); + if (dataJSON.get("osName") == null || dataJSON.get("osVersion") == null || dataJSON.get("osArch") == null) { logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.os.warn")); return new HealthCheckResult("os_issue", "os_support"); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheck.java similarity index 64% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheck.java index 7c551bb7..522c426a 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheck.java @@ -37,52 +37,48 @@ * @version $Id$ */ @Component -@Named(SecuritySystemEncodingHealthCheck.HINT) +@Named(SecurityEncodingHealthCheck.HINT) @Singleton -public class SecuritySystemEncodingHealthCheck extends AbstractConfigurationHealthCheck +public class SecurityEncodingHealthCheck extends AbstractConfigurationHealthCheck { /** * Component identifier. */ public static final String HINT = "SECURITY_SYSTEM_ENCODING_HEALTH_CHECK"; + private static final String INVALID = "INVALID"; + private final List acceptedEncodings = new ArrayList<>(List.of("UTF8", "UTF-8", "utf8", "utf-8")); @Override public HealthCheckResult check() { - Map securityJson = getJson(SecurityDataProvider.HINT); + Map securityJson = getJSON(SecurityDataProvider.HINT); + String activeEnc = securityJson.getOrDefault("activeEncoding", INVALID); + String configEnc = securityJson.getOrDefault("configurationEncoding", INVALID); String langEnc = securityJson.getOrDefault("LANG", "invalid.invalid").split("\\.")[1]; - String fileEnc = securityJson.getOrDefault("fileEncoding", "invalid"); - boolean isSafeLangEnc = isSafeLanguageEncoding(langEnc); - boolean isSafeFileEnc = isSafeFileEncoding(fileEnc); + String fileEnc = securityJson.getOrDefault("fileEncoding", INVALID); + + boolean isSafeLangEnc = isSafeEncoding(langEnc, "adminTools.dashboard.healthcheck.security.system.lang.warn"); + boolean isSafeFileEnc = isSafeEncoding(fileEnc, "adminTools.dashboard.healthcheck.security.system.file.warn"); + boolean isActiveEncSafe = + isSafeEncoding(activeEnc, "adminTools.dashboard.healthcheck.security.xwiki.active.warn"); + boolean isConfigEncSafe = + isSafeEncoding(configEnc, "adminTools.dashboard.healthcheck.security.xwiki.config.warn"); - if (!isSafeLangEnc || !isSafeFileEnc) { + if (!isSafeLangEnc || !isSafeFileEnc || !isActiveEncSafe || !isConfigEncSafe) { return new HealthCheckResult("xwiki_encoding_err", "xwiki config tutorial link"); } logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.info")); return new HealthCheckResult(); } - private boolean isSafeLanguageEncoding(String langEnc) - { - if (acceptedEncodings.contains(langEnc)) { - return true; - } - logger.warn( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.lang.warn"), - langEnc); - return false; - } - - private boolean isSafeFileEncoding(String fileEnc) + private boolean isSafeEncoding(String encoding, String message) { - if (acceptedEncodings.contains(fileEnc)) { + if (acceptedEncodings.contains(encoding)) { return true; } - logger.warn( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.file.warn"), - fileEnc); + logger.warn(localization.getTranslationPlain(message), encoding); return false; } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java deleted file mode 100644 index c34e6ad6..00000000 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheck.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools.internal.health.checks.configuration; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.inject.Named; -import javax.inject.Singleton; - -import org.xwiki.component.annotation.Component; - -import com.xwiki.admintools.health.HealthCheckResult; -import com.xwiki.admintools.internal.data.SecurityDataProvider; - -/** - * Extension of {@link AbstractConfigurationHealthCheck} for checking XWiki security configuration. - * - * @version $Id$ - */ -@Component -@Named(SecurityXWikiEncodingHealthCheck.HINT) -@Singleton -public class SecurityXWikiEncodingHealthCheck extends AbstractConfigurationHealthCheck -{ - /** - * Component identifier. - */ - public static final String HINT = "SECURITY_XWIKI_ENCODING_HEALTH_CHECK"; - - private static final String INVALID = "INVALID"; - - private final List acceptedEncodings = new ArrayList<>(List.of("UTF8", "UTF-8", "utf8", "utf-8")); - - @Override - public HealthCheckResult check() - { - Map securityJson = getJson(SecurityDataProvider.HINT); - String activeEnc = securityJson.getOrDefault("activeEncoding", INVALID); - String configEnc = securityJson.getOrDefault("configurationEncoding", INVALID); - boolean isActiveEncSafe = isSafeActiveEncoding(activeEnc); - boolean isConfigEncSafe = isSafeConfigEncoding(configEnc); - if (!isActiveEncSafe || !isConfigEncSafe) { - return new HealthCheckResult("xwiki_encoding_err", "xwiki config tutorial link"); - } - logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.xwiki.info")); - return new HealthCheckResult(); - } - - private boolean isSafeActiveEncoding(String activeEnc) - { - if (acceptedEncodings.contains(activeEnc)) { - return true; - } - logger.warn( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.xwiki.active.warn"), - activeEnc); - return false; - } - - private boolean isSafeConfigEncoding(String configEnc) - { - if (acceptedEncodings.contains(configEnc)) { - return true; - } - logger.warn( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.xwiki.config.warn"), - configEnc); - return false; - } -} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java index c53667be..c867bcb7 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java @@ -85,8 +85,8 @@ protected void runInternal() if (checkResult.getErrorMessage() != null) { status.getHealthCheckResults().add(checkResult); } - Thread.yield(); progressManager.endStep(this); + Thread.yield(); } } } finally { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index 10197347..c2f16ab9 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -26,6 +26,7 @@ import javax.inject.Singleton; import org.xwiki.component.annotation.Component; +import org.xwiki.component.manager.ComponentLookupException; import org.xwiki.job.Job; import org.xwiki.job.JobExecutor; import org.xwiki.script.service.ScriptService; @@ -70,7 +71,7 @@ public String getConfigurationData() * @param hint {@link String} representing the data provider * @return a {@link String} representing a specific template. */ - public String getConfigurationData(String hint) + public String getConfigurationData(String hint) throws ComponentLookupException { return this.adminToolsManager.generateData(hint); } @@ -106,16 +107,18 @@ public String getFilesSection() } /** - * Start the execution of the given Admin Tools health check request. + * Check if an Admin Tools Health Check job for the wiki from where the request was made exists. If it does, return + * the job instance, else create a new Admin Tools health check request for the given wiki and start the execution. * - * @param healthCheckJobRequest the health check request to be executed. + * @param requestId the ID to be used for the request. * @return the asynchronous background job that will execute the request. */ - public Job runHealthChecks(HealthCheckJobRequest healthCheckJobRequest) + public Job runHealthChecks(List requestId) { try { - Job job = this.jobExecutor.getJob(healthCheckJobRequest.getId()); + Job job = this.jobExecutor.getJob(requestId); if (job == null) { + HealthCheckJobRequest healthCheckJobRequest = new HealthCheckJobRequest(requestId); return this.jobExecutor.execute(HealthCheckJob.JOB_TYPE, healthCheckJobRequest); } else { return job; @@ -124,15 +127,4 @@ public Job runHealthChecks(HealthCheckJobRequest healthCheckJobRequest) return null; } } - - /** - * Create health check request. - * - * @param wiki the ID of the wiki from where the request was made. - * @return a new health check request, initialized based on the given wiki ID. - */ - public HealthCheckJobRequest createJobRequest(String wiki) - { - return new HealthCheckJobRequest(wiki); - } } diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index 40a784bf..c970db2d 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -15,8 +15,7 @@ com.xwiki.admintools.internal.AdminToolsEventListener com.xwiki.admintools.internal.health.checks.configuration.ConfigurationDatabaseHealthCheck com.xwiki.admintools.internal.health.checks.configuration.ConfigurationJavaHealthCheck com.xwiki.admintools.internal.health.checks.configuration.ConfigurationOsHealthCheck -com.xwiki.admintools.internal.health.checks.configuration.SecuritySystemEncodingHealthCheck -com.xwiki.admintools.internal.health.checks.configuration.SecurityXWikiEncodingHealthCheck +com.xwiki.admintools.internal.health.checks.configuration.SecurityEncodingHealthCheck com.xwiki.admintools.internal.health.checks.PerformanceHealthCheck com.xwiki.admintools.internal.health.checks.MemoryHealthCheck com.xwiki.admintools.internal.health.job.HealthCheckJob diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/AdminToolsEventListenerTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/AdminToolsEventListenerTest.java index 306e4fbb..243168e3 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/AdminToolsEventListenerTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/AdminToolsEventListenerTest.java @@ -44,16 +44,16 @@ import static org.mockito.Mockito.when; @ComponentTest -public class AdminToolsEventListenerTest +class AdminToolsEventListenerTest { private final List SPACE = Arrays.asList("AdminTools", "Code"); - @Mock - private XWikiDocument xWikiDocument; - @InjectMockComponents private AdminToolsEventListener adminToolsEventListener; + @Mock + private XWikiDocument xWikiDocument; + @MockComponent private WikiDescriptorManager wikiDescriptorManager; diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfigurationTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfigurationTest.java index 69ce6cab..2cd27dde 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfigurationTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/configuration/DefaultAdminToolsConfigurationTest.java @@ -29,7 +29,6 @@ import org.xwiki.test.junit5.mockito.InjectMockComponents; import org.xwiki.test.junit5.mockito.MockComponent; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.when; @@ -39,7 +38,7 @@ * @version $Id$ */ @ComponentTest -public class DefaultAdminToolsConfigurationTest +class DefaultAdminToolsConfigurationTest { @InjectMockComponents private DefaultAdminToolsConfiguration defaultAdminToolsConfiguration; diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java index 2de89566..dd2993f3 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/ConfigurationDataProviderTest.java @@ -42,8 +42,8 @@ import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiContext; import com.xwiki.admintools.ServerIdentifier; -import com.xwiki.admintools.internal.data.identifiers.CurrentServer; import com.xwiki.admintools.internal.PingProvider; +import com.xwiki.admintools.internal.data.identifiers.CurrentServer; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -58,12 +58,15 @@ * @version $Id$ */ @ComponentTest -public class ConfigurationDataProviderTest +class ConfigurationDataProviderTest { - static Map defaultJson; + private static Map defaultJson; private final String templatePath = "configurationTemplate.vm"; + @InjectMockComponents + private ConfigurationDataProvider configurationDataProvider; + @MockComponent private Provider xcontextProvider; @@ -73,9 +76,6 @@ public class ConfigurationDataProviderTest @Mock private XWiki wiki; - @InjectMockComponents - private ConfigurationDataProvider configurationDataProvider; - @MockComponent private CurrentServer currentServer; diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/SecurityDataProviderTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/SecurityDataProviderTest.java index 2a969f18..fd264b15 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/SecurityDataProviderTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/SecurityDataProviderTest.java @@ -54,18 +54,18 @@ * @version $Id$ */ @ComponentTest -public class SecurityDataProviderTest +class SecurityDataProviderTest { - static Map defaultJson; + private static Map defaultJson; private final String templatePath = "securityTemplate.vm"; - @MockComponent - private Provider xcontextProvider; - @InjectMockComponents private SecurityDataProvider securityDataProvider; + @MockComponent + private Provider xcontextProvider; + @MockComponent @Named("xwikicfg") private ConfigurationSource configurationSource; diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/CurrentServerTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/CurrentServerTest.java index 7aad17ae..89f67794 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/CurrentServerTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/CurrentServerTest.java @@ -45,7 +45,7 @@ * @version $Id$ */ @ComponentTest -public class CurrentServerTest +class CurrentServerTest { @InjectMockComponents private CurrentServer currentServer; diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifierTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifierTest.java index f14994ae..7630f039 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifierTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/data/identifiers/TomcatIdentifierTest.java @@ -43,7 +43,7 @@ * @version $Id$ */ @ComponentTest -public class TomcatIdentifierTest +class TomcatIdentifierTest { @InjectMockComponents private TomcatIdentifier tomcatIdentifier; diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java index 0b391a2b..a90e1d00 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/ImportantFilesManagerTest.java @@ -20,19 +20,18 @@ package com.xwiki.admintools.internal.files; import java.io.IOException; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.zip.ZipOutputStream; -import javax.inject.Provider; +import javax.inject.Named; import javax.script.ScriptContext; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.slf4j.Logger; +import org.xwiki.component.manager.ComponentManager; import org.xwiki.component.util.ReflectionUtils; import org.xwiki.script.ScriptContextManager; import org.xwiki.template.TemplateManager; @@ -49,12 +48,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.AdditionalMatchers.aryEq; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -64,16 +59,15 @@ * @version $Id$ */ @ComponentTest -public class ImportantFilesManagerTest +class ImportantFilesManagerTest { private final String templatePath = "filesSectionTemplate.vm"; + private final Map params = Map.of("input", new String[] { "good_input" }); + @InjectMockComponents private ImportantFilesManager importantFilesManager; - @MockComponent - private Provider> dataResources; - @MockComponent private DataResource archiverDataResource; @@ -92,33 +86,33 @@ public class ImportantFilesManagerTest @MockComponent private ServerIdentifier serverIdentifier; + @MockComponent + @Named("context") + private ComponentManager contextComponentManager; + @Mock private ScriptContext scriptContext; @Mock private Logger logger; - private final Map params = Map.of("input", new String[]{"good_input"}); + @BeforeEach + void setUp() throws Exception + { + when(archiverDataResource.getByteData(params)).thenReturn(new byte[] { 2 }); + when(contextComponentManager.getInstance(DataResource.class, "data_resource_identifier")).thenReturn( + archiverDataResource); + } @Test void getFile() throws Exception { - List dataResourceList = new ArrayList<>(); - dataResourceList.add(archiverDataResource); - when(dataResources.get()).thenReturn(dataResourceList); - when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); - when(archiverDataResource.getByteData(params)).thenReturn(new byte[] { 2 }); - assertArrayEquals(new byte[] { 2 }, importantFilesManager.getFile("data_resource_identifier", params)); } @Test - void getFileResourceNotFound() + void getFileResourceNotFound() throws Exception { - List dataResourceList = new ArrayList<>(); - dataResourceList.add(archiverDataResource); - when(dataResources.get()).thenReturn(dataResourceList); - when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); Exception exception = assertThrows(Exception.class, () -> { importantFilesManager.getFile("data_resource_identifier_invalid", params); }); @@ -129,10 +123,6 @@ void getFileResourceNotFound() @Test void getFileDataResourceError() throws Exception { - List dataResourceList = new ArrayList<>(); - dataResourceList.add(archiverDataResource); - when(dataResources.get()).thenReturn(dataResourceList); - when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); when(archiverDataResource.getByteData(params)).thenThrow(new IOException("IO Error")); Exception exception = assertThrows(Exception.class, () -> { importantFilesManager.getFile("data_resource_identifier", params); @@ -152,13 +142,8 @@ void downloadMultipleFiles() throws Exception filters.put("from", new String[] { "" }); filters.put("to", new String[] { "" }); - List dataResourceList = new ArrayList<>(); - dataResourceList.add(archiverDataResource); - dataResourceList.add(archiverLogsDataResource); - - when(dataResources.get()).thenReturn(dataResourceList); - when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); - when(archiverLogsDataResource.getIdentifier()).thenReturn(LogsDataResource.HINT); + when(contextComponentManager.getInstance(DataResource.class, LogsDataResource.HINT)).thenReturn( + archiverLogsDataResource); importantFilesManager.getFilesArchive(request); verify(archiverDataResource).addZipEntry(any(ZipOutputStream.class), any()); @@ -171,32 +156,22 @@ void downloadMultipleFilesNoArchiverFound() throws Exception String[] files = { "data_resource_identifier_invalid", LogsDataResource.HINT }; Map request = new HashMap<>(); request.put("files", files); - List dataResourceList = new ArrayList<>(); - dataResourceList.add(archiverDataResource); - when(dataResources.get()).thenReturn(dataResourceList); - when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); importantFilesManager.getFilesArchive(request); verify(archiverDataResource, never()).addZipEntry(any(ZipOutputStream.class), any()); } @Test - void downloadMultipleFilesInvalidRequest() + void downloadMultipleFilesInvalidRequest() throws Exception { - String[] files = { "data_resource_identifier", LogsDataResource.HINT }; + String[] files = { "invalid_hint1", "invalid_hint2" }; Map request = new HashMap<>(); request.put("files", files); - List dataResourceList = new ArrayList<>(); - dataResourceList.add(archiverDataResource); - dataResourceList.add(archiverLogsDataResource); - - when(dataResources.get()).thenReturn(dataResourceList); - when(archiverDataResource.getIdentifier()).thenReturn("data_resource_identifier"); - Exception exception = assertThrows(Exception.class, () -> { - importantFilesManager.getFilesArchive(request); - }); - - assertEquals("Error while generating the files archive.", exception.getMessage()); + when(contextComponentManager.getInstance(DataResource.class, LogsDataResource.HINT)).thenReturn( + archiverLogsDataResource); + importantFilesManager.getFilesArchive(request); + verify(archiverDataResource, never()).addZipEntry(any(ZipOutputStream.class), any()); + verify(archiverLogsDataResource, never()).addZipEntry(any(ZipOutputStream.class), any()); } @Test diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java index a5ccd9ea..42965cf0 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/DataProvidersDataResourceTest.java @@ -53,14 +53,14 @@ * @version $Id$ */ @ComponentTest -public class DataProvidersDataResourceTest +class DataProvidersDataResourceTest { - @Mock - ZipOutputStream zipOutputStream; - @InjectMockComponents private DataProvidersDataResource dataProviderResource; + @Mock + private ZipOutputStream zipOutputStream; + @MockComponent private Provider> dataProviders; @@ -104,7 +104,8 @@ void getByteDataThrowError() throws Exception Exception exception = assertThrows(Exception.class, () -> { this.dataProviderResource.getByteData(null); }); - assertEquals("Error while getting JSON data for [data_provider_identifier] DataProvider.", exception.getMessage()); + assertEquals("Error while getting JSON data for [data_provider_identifier] DataProvider.", + exception.getMessage()); } @Test diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java index 7d3baf8d..816bf451 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/LogsDataResourceTest.java @@ -70,16 +70,16 @@ * @version $Id$ */ @ComponentTest -public class LogsDataResourceTest +class LogsDataResourceTest { private final Map params = Map.of("noLines", new String[] { "44" }); - @Mock - ZipOutputStream zipOutputStream; - @InjectMockComponents private LogsDataResource logsDataResource; + @Mock + private ZipOutputStream zipOutputStream; + @Mock private Logger logger; @@ -203,8 +203,7 @@ void getByteDataNullInput() throws IOException readLines(1000); - assertArrayEquals(String.join("\n", logLines).getBytes(), - logsDataResource.getByteData(null)); + assertArrayEquals(String.join("\n", logLines).getBytes(), logsDataResource.getByteData(null)); } @Test @@ -215,8 +214,7 @@ void getByteDataNullNoLines() throws IOException Map params = Map.of("noLines", new String[] { null }); readLines(1000); - assertArrayEquals(String.join("\n", logLines).getBytes(), - logsDataResource.getByteData(params)); + assertArrayEquals(String.join("\n", logLines).getBytes(), logsDataResource.getByteData(params)); } @Test @@ -237,8 +235,8 @@ void addZipEntrySuccessWithFilters() throws IOException when(serverIdentifier.getLogsPattern()).thenReturn(Pattern.compile("\\d{4}-\\d{2}-\\d{2}")); Map filters = new HashMap<>(); - filters.put("from", new String[]{"06-10-2023"}); - filters.put("to", new String[]{"07-10-2023"}); + filters.put("from", new String[] { "06-10-2023" }); + filters.put("to", new String[] { "07-10-2023" }); readLines(400); logsDataResource.addZipEntry(zipOutputStream, filters); byte[] buff = new byte[2048]; @@ -259,8 +257,8 @@ void addZipEntryFilesOutOfFiltersRange() throws IOException when(xWiki.getXWikiPreference("dateformat", "dd-MM-yyyy", wikiContext)).thenReturn("dd yy MM"); Map filters = new HashMap<>(); - filters.put("from", new String[]{"10 23 10"}); - filters.put("to", new String[]{ null }); + filters.put("from", new String[] { "10 23 10" }); + filters.put("to", new String[] { null }); logsDataResource.addZipEntry(zipOutputStream, filters); verify(zipOutputStream, never()).closeEntry(); @@ -276,8 +274,8 @@ void addZipEntryDateParseError() when(serverIdentifier.getLogsFolderPath()).thenReturn(logsDir.getAbsolutePath()); when(serverIdentifier.getLogsPattern()).thenReturn(Pattern.compile("\\bserver\\b")); Map filters = new HashMap<>(); - filters.put("from", new String[]{"2023-10-03"}); - filters.put("to", new String[]{"2023-10-05"}); + filters.put("from", new String[] { "2023-10-03" }); + filters.put("to", new String[] { "2023-10-05" }); logsDataResource.addZipEntry(zipOutputStream, filters); verify(logger).warn("Failed to get logs. Root cause is: [{}]", "DateTimeParseException: Text 'server' could not be parsed at index 0"); @@ -290,8 +288,8 @@ void addZipEntryPatternNotFound() throws IOException when(serverIdentifier.getLogsFolderPath()).thenReturn(logsDir.getAbsolutePath()); when(serverIdentifier.getLogsPattern()).thenReturn(Pattern.compile("\\d{4}_\\d{2}_\\d{2}")); Map filters = new HashMap<>(); - filters.put("from", new String[]{"2023-10-03"}); - filters.put("to", new String[]{"2023-10-05"}); + filters.put("from", new String[] { "2023-10-03" }); + filters.put("to", new String[] { "2023-10-05" }); logsDataResource.addZipEntry(zipOutputStream, filters); verify(zipOutputStream, never()).closeEntry(); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java index 3ae1b1db..920a4833 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiConfigFileDataResourceTest.java @@ -62,7 +62,7 @@ * @version $Id$ */ @ComponentTest -public class XWikiConfigFileDataResourceTest +class XWikiConfigFileDataResourceTest { @InjectMockComponents private XWikiConfigFileDataResource configFileDataResource; @@ -194,8 +194,7 @@ void addZipEntryGetByteFail() throws Exception configFileDataResource.addZipEntry(zipOutputStream, null); verify(zipOutputStream, never()).write(any(), eq(0), anyInt()); verify(logger).warn("Could not add {} to the archive. Root cause is: [{}]", "xwiki.cfg", - "FileNotFoundException: " + cfgDir2.getAbsolutePath() + "/xwiki.cfg (No such file or " - + "directory)"); + "FileNotFoundException: " + cfgDir2.getAbsolutePath() + "/xwiki.cfg (No such file or " + "directory)"); } private byte[] readLines() throws IOException diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java index cf020768..e233a548 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/files/resources/XWikiPropertiesFileDataResourceTest.java @@ -62,7 +62,7 @@ * @version $Id$ */ @ComponentTest -public class XWikiPropertiesFileDataResourceTest +class XWikiPropertiesFileDataResourceTest { @InjectMockComponents private XWikiPropertiesFileDataResource propertiesFileDataResource; diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java index e372c223..066013a3 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java @@ -43,11 +43,14 @@ import static org.mockito.Mockito.when; @ComponentTest -public class MemoryHealthCheckTest +class MemoryHealthCheckTest { @MockComponent private static ContextualLocalizationManager localization; + @InjectMockComponents + private MemoryHealthCheck memoryHealthCheck; + @MockComponent private Provider xcontextProvider; @@ -61,9 +64,6 @@ public class MemoryHealthCheckTest @Mock private XWiki xwiki; - @InjectMockComponents - private MemoryHealthCheck memoryHealthCheck; - @Mock private Logger logger; @@ -74,20 +74,15 @@ static void setUp() throws Exception "Cache status OK"); when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.info")).thenReturn( "Memory status OK"); - when(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.memory.cache.null")).thenReturn( + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.null")).thenReturn( "Store cache capacity is set at 500. Check Cache recommendations in solutions."); - when(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.memory.cache.low")).thenReturn( + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.low")).thenReturn( "Store cache capacity is set at [{}]. Check Cache recommendations in solutions."); - when(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.memory.free.error")).thenReturn( + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.error")).thenReturn( "Your JVM instance has only [{}]MB free memory left! Consult the solution link for support!"); - when(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.memory.free.warn")).thenReturn( + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.warn")).thenReturn( "Your instance memory is running low. Currently only [{}]MB free left."); - when(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.memory.maxcapacity.error")).thenReturn( + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.maxcapacity.error")).thenReturn( "JVM memory is less than 1024MB. Currently: [{}]MB"); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java index 32088fa3..26406476 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java @@ -19,16 +19,16 @@ */ package com.xwiki.admintools.internal.health.checks.configuration; -import java.util.ArrayList; -import java.util.List; import java.util.Map; -import javax.inject.Provider; +import javax.inject.Named; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.slf4j.Logger; +import org.xwiki.component.manager.ComponentLookupException; +import org.xwiki.component.manager.ComponentManager; import org.xwiki.component.util.ReflectionUtils; import org.xwiki.localization.ContextualLocalizationManager; import org.xwiki.test.annotation.BeforeComponent; @@ -45,11 +45,8 @@ import static org.mockito.Mockito.when; @ComponentTest -public class ConfigurationDatabaseHealthCheckTest +class ConfigurationDatabaseHealthCheckTest { - @MockComponent - private static Provider> dataProviders; - @MockComponent private static DataProvider firstDataProvider; @@ -62,34 +59,35 @@ public class ConfigurationDatabaseHealthCheckTest @InjectMockComponents private ConfigurationDatabaseHealthCheck databaseHealthCheck; + @MockComponent + @Named("context") + private ComponentManager contextComponentManager; + @Mock private Logger logger; @BeforeComponent static void setUp() throws Exception { - List dataProviderList = new ArrayList<>(); - dataProviderList.add(firstDataProvider); - dataProviderList.add(secondDataProvider); - when(dataProviders.get()).thenReturn(dataProviderList); Map jsonResponse = Map.of("databaseName", "testDBName"); when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.info")) - .thenReturn("Database status OK"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.warn")) - .thenReturn("Database not found!"); + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.info")).thenReturn( + "Database status OK"); + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.warn")).thenReturn( + "Database not found!"); } @BeforeEach - void beforeEach() + void beforeEach() throws ComponentLookupException { when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(databaseHealthCheck, "logger", this.logger); - when(firstDataProvider.getIdentifier()).thenReturn(ConfigurationDataProvider.HINT); - when(secondDataProvider.getIdentifier()).thenReturn("second"); + when(contextComponentManager.getInstance(DataProvider.class, ConfigurationDataProvider.HINT)).thenReturn( + firstDataProvider); + when(contextComponentManager.getInstance(DataProvider.class, "second")).thenReturn(secondDataProvider); } @Test @@ -100,9 +98,10 @@ void check() } @Test - void checkNullProvider() + void checkNullProvider() throws ComponentLookupException { - when(firstDataProvider.getIdentifier()).thenReturn("first"); + when(contextComponentManager.getInstance(DataProvider.class, ConfigurationDataProvider.HINT)).thenReturn( + null); assertEquals("database_not_detected", databaseHealthCheck.check().getErrorMessage()); verify(logger).warn("Database not found!"); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java index 4c618cd5..628b837d 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java @@ -19,16 +19,16 @@ */ package com.xwiki.admintools.internal.health.checks.configuration; -import java.util.ArrayList; -import java.util.List; import java.util.Map; -import javax.inject.Provider; +import javax.inject.Named; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.slf4j.Logger; +import org.xwiki.component.manager.ComponentLookupException; +import org.xwiki.component.manager.ComponentManager; import org.xwiki.component.util.ReflectionUtils; import org.xwiki.localization.ContextualLocalizationManager; import org.xwiki.test.annotation.BeforeComponent; @@ -45,11 +45,8 @@ import static org.mockito.Mockito.when; @ComponentTest -public class ConfigurationJavaHealthCheckTest +class ConfigurationJavaHealthCheckTest { - @MockComponent - private static Provider> dataProviders; - @MockComponent private static DataProvider firstDataProvider; @@ -62,25 +59,24 @@ public class ConfigurationJavaHealthCheckTest @InjectMockComponents private ConfigurationJavaHealthCheck javaHealthCheck; + @MockComponent + @Named("context") + private ComponentManager contextComponentManager; + @Mock private Logger logger; @BeforeComponent static void setUp() throws Exception { - List dataProviderList = new ArrayList<>(); - dataProviderList.add(firstDataProvider); - dataProviderList.add(secondDataProvider); - when(dataProviders.get()).thenReturn(dataProviderList); - when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.info")) - .thenReturn("Java status OK"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.found")) - .thenReturn("Java version not found!"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.incompatible")) - .thenReturn("Java version is not compatible with the current XWiki installation!"); + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.info")).thenReturn( + "Java status OK"); + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.found")).thenReturn( + "Java version not found!"); + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.incompatible")).thenReturn( + "Java version is not compatible with the current XWiki installation!"); } @BeforeEach @@ -88,12 +84,11 @@ void beforeEach() throws Exception { when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(javaHealthCheck, "logger", this.logger); + when(contextComponentManager.getInstance(DataProvider.class, ConfigurationDataProvider.HINT)).thenReturn( + firstDataProvider); + when(contextComponentManager.getInstance(DataProvider.class, "second")).thenReturn(secondDataProvider); - when(firstDataProvider.getIdentifier()).thenReturn(ConfigurationDataProvider.HINT); - when(secondDataProvider.getIdentifier()).thenReturn("second"); - - Map jsonResponse = Map.of("javaVersion", "11.0.2", - "xwikiVersion", "14.10.2"); + Map jsonResponse = Map.of("javaVersion", "11.0.2", "xwikiVersion", "14.10.2"); when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); } @@ -105,9 +100,10 @@ void check() } @Test - void checkNullProvider() + void checkNullProvider() throws ComponentLookupException { - when(firstDataProvider.getIdentifier()).thenReturn("first"); + when(contextComponentManager.getInstance(DataProvider.class, ConfigurationDataProvider.HINT)).thenReturn( + null); assertEquals("java_version_not_found", javaHealthCheck.check().getErrorMessage()); verify(logger).warn("Java version not found!"); @@ -116,7 +112,7 @@ void checkNullProvider() @Test void checkNullJson() throws Exception { - when(firstDataProvider.getDataAsJSON()).thenThrow(new Exception("error while ggenerating the json")); + when(firstDataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); assertEquals("java_version_not_found", javaHealthCheck.check().getErrorMessage()); verify(logger).warn("Java version not found!"); @@ -125,8 +121,7 @@ void checkNullJson() throws Exception @Test void checkJavaVersionIncompatible() throws Exception { - Map jsonResponse = Map.of("javaVersion", "11.0.2", - "xwikiVersion", "6.10.2"); + Map jsonResponse = Map.of("javaVersion", "11.0.2", "xwikiVersion", "6.10.2"); when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); assertEquals("java_xwiki_not_compatible", javaHealthCheck.check().getErrorMessage()); verify(logger).warn("Java version is not compatible with the current XWiki installation!"); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java index 0cc9d48e..d611bace 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java @@ -19,16 +19,16 @@ */ package com.xwiki.admintools.internal.health.checks.configuration; -import java.util.ArrayList; -import java.util.List; import java.util.Map; -import javax.inject.Provider; +import javax.inject.Named; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.slf4j.Logger; +import org.xwiki.component.manager.ComponentLookupException; +import org.xwiki.component.manager.ComponentManager; import org.xwiki.component.util.ReflectionUtils; import org.xwiki.localization.ContextualLocalizationManager; import org.xwiki.test.annotation.BeforeComponent; @@ -45,11 +45,8 @@ import static org.mockito.Mockito.when; @ComponentTest -public class ConfigurationOsHealthCheckTest +class ConfigurationOsHealthCheckTest { - @MockComponent - private static Provider> dataProviders; - @MockComponent private static DataProvider firstDataProvider; @@ -62,16 +59,16 @@ public class ConfigurationOsHealthCheckTest @InjectMockComponents private ConfigurationOsHealthCheck osHealthCheck; + @MockComponent + @Named("context") + private ComponentManager contextComponentManager; + @Mock private Logger logger; @BeforeComponent static void setUp() throws Exception { - List dataProviderList = new ArrayList<>(); - dataProviderList.add(firstDataProvider); - dataProviderList.add(secondDataProvider); - when(dataProviders.get()).thenReturn(dataProviderList); Map jsonResponse = Map.of("osName", "testDBName", "osVersion", "os_version", "osArch", "os_arch"); when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); @@ -84,13 +81,14 @@ static void setUp() throws Exception } @BeforeEach - void beforeEach() + void beforeEach() throws ComponentLookupException { when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(osHealthCheck, "logger", this.logger); - when(firstDataProvider.getIdentifier()).thenReturn(ConfigurationDataProvider.HINT); - when(secondDataProvider.getIdentifier()).thenReturn("second"); + when(contextComponentManager.getInstance(DataProvider.class, ConfigurationDataProvider.HINT)).thenReturn( + firstDataProvider); + when(contextComponentManager.getInstance(DataProvider.class, "second")).thenReturn(secondDataProvider); } @Test diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheckTest.java similarity index 66% rename from application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheckTest.java rename to application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheckTest.java index 3592f5e4..843465ea 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecuritySystemEncodingHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheckTest.java @@ -23,12 +23,14 @@ import java.util.List; import java.util.Map; +import javax.inject.Named; import javax.inject.Provider; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.slf4j.Logger; +import org.xwiki.component.manager.ComponentManager; import org.xwiki.component.util.ReflectionUtils; import org.xwiki.localization.ContextualLocalizationManager; import org.xwiki.test.annotation.BeforeComponent; @@ -45,7 +47,7 @@ import static org.mockito.Mockito.when; @ComponentTest -public class SecuritySystemEncodingHealthCheckTest +class SecurityEncodingHealthCheckTest { @MockComponent private static Provider> dataProviders; @@ -60,7 +62,11 @@ public class SecuritySystemEncodingHealthCheckTest private static ContextualLocalizationManager localization; @InjectMockComponents - private SecuritySystemEncodingHealthCheck systemEncodingHealthCheck; + private SecurityEncodingHealthCheck systemEncodingHealthCheck; + + @MockComponent + @Named("context") + private ComponentManager contextComponentManager; @Mock private Logger logger; @@ -75,14 +81,20 @@ static void setUp() throws Exception when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); - when(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.security.system.info")).thenReturn("System encoding OK"); - when(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.security.system.lang.warn")).thenReturn( + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.info")).thenReturn( + "System encoding OK"); + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.lang.warn")).thenReturn( "System language encoding is [{}] but should be UTF-8!"); - when(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.security.system.file.warn")).thenReturn( + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.file.warn")).thenReturn( "System file encoding is [{}] but should be UTF-8!"); + when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.xwiki.info")).thenReturn( + "XWiki encoding OK"); + when( + localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.xwiki.active.warn")).thenReturn( + "XWiki active encoding is [{}] but should be UTF-8!"); + when( + localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.xwiki.config.warn")).thenReturn( + "XWiki configuration encoding is [{}] but should be UTF-8!"); } @BeforeEach @@ -93,7 +105,10 @@ void beforeEach() throws Exception when(firstDataProvider.getIdentifier()).thenReturn(SecurityDataProvider.HINT); when(secondDataProvider.getIdentifier()).thenReturn("second"); - Map jsonResponse = Map.of("LANG", "en.UTF8", "fileEncoding", "UTF8"); + Map jsonResponse = + Map.of("LANG", "en.UTF8", "fileEncoding", "UTF8", "activeEncoding", "UTF8", "configurationEncoding", + "UTF8"); + when(contextComponentManager.getInstance(DataProvider.class, "security")).thenReturn(firstDataProvider); when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); } @@ -111,15 +126,21 @@ void checkNullJson() throws Exception assertEquals("xwiki_encoding_err", systemEncodingHealthCheck.check().getErrorMessage()); verify(logger).warn("System language encoding is [{}] but should be UTF-8!", "invalid"); - verify(logger).warn("System file encoding is [{}] but should be UTF-8!", "invalid"); + verify(logger).warn("System file encoding is [{}] but should be UTF-8!", "INVALID"); + verify(logger).warn("XWiki configuration encoding is [{}] but should be UTF-8!", "INVALID"); + verify(logger).warn("XWiki active encoding is [{}] but should be UTF-8!", "INVALID"); } @Test void checkUnsafeEncoding() throws Exception { - Map jsonResponse = Map.of("LANG", "en.UTF8", "fileEncoding", "ISO-8859-1"); + Map jsonResponse = + Map.of("LANG", "en.UTF8", "fileEncoding", "ISO-8859-1", "activeEncoding", "UTF8", "configurationEncoding", + "ISO-8859-1"); when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); assertEquals("xwiki_encoding_err", systemEncodingHealthCheck.check().getErrorMessage()); verify(logger).warn("System file encoding is [{}] but should be UTF-8!", "ISO-8859-1"); + verify(logger).warn("XWiki configuration encoding is [{}] but should be UTF-8!", + "ISO-8859-1"); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheckTest.java deleted file mode 100644 index f9a3e1a7..00000000 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityXWikiEncodingHealthCheckTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools.internal.health.checks.configuration; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.inject.Provider; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.slf4j.Logger; -import org.xwiki.component.util.ReflectionUtils; -import org.xwiki.localization.ContextualLocalizationManager; -import org.xwiki.test.annotation.BeforeComponent; -import org.xwiki.test.junit5.mockito.ComponentTest; -import org.xwiki.test.junit5.mockito.InjectMockComponents; -import org.xwiki.test.junit5.mockito.MockComponent; - -import com.xwiki.admintools.DataProvider; -import com.xwiki.admintools.internal.data.SecurityDataProvider; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ComponentTest -public class SecurityXWikiEncodingHealthCheckTest -{ - @MockComponent - private static Provider> dataProviders; - - @MockComponent - private static DataProvider firstDataProvider; - - @MockComponent - private static DataProvider secondDataProvider; - - @MockComponent - private static ContextualLocalizationManager localization; - - @InjectMockComponents - private SecurityXWikiEncodingHealthCheck xwikiEncodingHealthCheck; - - @Mock - private Logger logger; - - @BeforeComponent - static void setUp() throws Exception - { - List dataProviderList = new ArrayList<>(); - dataProviderList.add(firstDataProvider); - dataProviderList.add(secondDataProvider); - when(dataProviders.get()).thenReturn(dataProviderList); - - when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); - - when(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.security.xwiki.info")).thenReturn("XWiki encoding OK"); - when(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.security.xwiki.active.warn")).thenReturn( - "XWiki active encoding is [{}] but should be UTF-8!"); - when(localization.getTranslationPlain( - "adminTools.dashboard.healthcheck.security.xwiki.config.warn")).thenReturn( - "XWiki configuration encoding is [{}] but should be UTF-8!"); - } - - @BeforeEach - void beforeEach() throws Exception - { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(xwikiEncodingHealthCheck, "logger", this.logger); - - when(firstDataProvider.getIdentifier()).thenReturn(SecurityDataProvider.HINT); - when(secondDataProvider.getIdentifier()).thenReturn("second"); - Map jsonResponse = Map.of("activeEncoding", "UTF8", "configurationEncoding", "UTF8"); - when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); - } - - @Test - void check() - { - assertNull(xwikiEncodingHealthCheck.check().getErrorMessage()); - verify(logger).info("XWiki encoding OK"); - } - - @Test - void checkNullJson() throws Exception - { - when(firstDataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); - - assertEquals("xwiki_encoding_err", xwikiEncodingHealthCheck.check().getErrorMessage()); - verify(logger).warn("XWiki configuration encoding is [{}] but should be UTF-8!", "INVALID"); - verify(logger).warn("XWiki active encoding is [{}] but should be UTF-8!", "INVALID"); - } - - @Test - void checkUnsafeEncoding() throws Exception - { - Map jsonResponse = Map.of("activeEncoding", "UTF8", "configurationEncoding", "ISO-8859-1"); - when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); - assertEquals("xwiki_encoding_err", xwikiEncodingHealthCheck.check().getErrorMessage()); - verify(logger).warn("XWiki configuration encoding is [{}] but should be UTF-8!", "ISO-8859-1"); - } -} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java index 7b197cac..4a4e4bd1 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java @@ -39,7 +39,7 @@ import static org.mockito.Mockito.when; @ComponentTest -public class HealthCheckJobTest +class HealthCheckJobTest { @InjectMockComponents private HealthCheckJob healthCheckJob; diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java index 87ff0e9e..d05f811a 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/rest/DefaultAdminToolsResourceTest.java @@ -57,16 +57,18 @@ * @version $Id$ */ @ComponentTest -public class DefaultAdminToolsResourceTest +class DefaultAdminToolsResourceTest { - XWikiContext xWikiContext; - - @Mock - XWikiRequest xWikiRequest; + private final Map params = Map.of("noLines", new String[] { "1000" }); @InjectMockComponents private DefaultAdminToolsResource defaultAdminToolsResource; + private XWikiContext xWikiContext; + + @Mock + private XWikiRequest xWikiRequest; + @MockComponent private ImportantFilesManager importantFilesManager; @@ -85,8 +87,6 @@ public class DefaultAdminToolsResourceTest @Mock private Logger logger; - private final Map params = Map.of("noLines", new String[]{"1000"}); - @BeforeComponent void beforeComponent() { diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index 4d6a152c..d0f9816a 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -1,4 +1,5 @@ - + + - + + AdminTools.Code AdminToolsJS @@ -130,6 +132,7 @@ }; const runHealthCheckJob = function() { + $('#admin_tools_job_start').prop("disabled", true); var data = []; data.push( {name: 'outputSyntax', value: 'plain'}, @@ -149,19 +152,18 @@ } }; } - }).run(getResourceURL(), data)).catch((reason) => { + }).run(getResourceURL(), data)).catch((reason) => { return Promise.reject(reason); - }).finally(() => { + }).finally(() => { $('#admin_tools_job_start').prop("disabled", false); }); }; const reinitialiseProgressBar = function() { $.get(getResourceURL(), function(data) { + console.log(data) let progressBar = $(data).find('div.ui-progress'); - $('#healthCheck .successmessage').replaceWith(progressBar) - $('#healthCheck .warningmessage').replaceWith(progressBar) - $('#healthCheck .errormessage').replaceWith(progressBar) + $('#healthCheck').find('.successmessage, .warningmessage, .errormessage').replaceWith(progressBar); }); }; @@ -172,7 +174,7 @@ const initialiseJobJS = function() { require.undef('health-check-job'); $.get(getResourceURL(), function(data) { - let jobMinJsURL = $(data).find('input[name="jobMinJsURL"]').val(); + let jobMinJsURL = $(data).find('jobJsURL').attr('data-url'); require.config({ paths: { 'health-check-job': jobMinJsURL @@ -184,11 +186,10 @@ $(document).ready(function() { if ($('#healthCheck').length) { - let jobState = $('input[name="jobState"]').val(); + let jobState = $('jobState').attr('data-state') if (jobState == "RUNNING") { initialiseJobJS(); runHealthCheckJob(); - $('#admin_tools_job_start').prop("disabled", true); $('.job-status').show(); } else if (jobState == "FINISHED") { $('.job-status').show(); @@ -199,7 +200,6 @@ $(document).on('click', '#admin_tools_job_start', function(event) { event.preventDefault(); $(".log").empty(); - $('#admin_tools_job_start').prop("disabled", true); runHealthCheckJob(); reinitialiseProgressBar(); initialiseJobJS(); @@ -254,4 +254,4 @@ onDemand
- \ No newline at end of file + diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Configuration.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Configuration.xml index 2991078d..1bff5635 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Configuration.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Configuration.xml @@ -1,4 +1,4 @@ - + - + + AdminTools.Code Configuration @@ -66,7 +67,7 @@ - +
@@ -292,19 +293,19 @@ - + - + AdminTools.Code.ConfigurationClass - + - + Admin Tools @@ -313,10 +314,10 @@ $services.localization.render('admin.admintools.description') - + - + @@ -328,4 +329,4 @@ - \ No newline at end of file + diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/ConfigurationClass.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/ConfigurationClass.xml index deb2ec4b..6e7a9853 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/ConfigurationClass.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/ConfigurationClass.xml @@ -1,4 +1,4 @@ - + - + + AdminTools.Code ConfigurationClass @@ -128,4 +129,4 @@ XWiki.ClassSheet
- \ No newline at end of file + diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml index 189f133d..4250a297 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml @@ -1,4 +1,5 @@ - + + - + + AdminTools.Code HealthCheckJob @@ -39,22 +41,13 @@ #includeMacros("AdminTools.Code.Macros") #set($jobId = $request.getParameterValues('jobId')) -#set($translationPrefix = $request.getParameter('translationPrefix')) #set($jobStatus = $services.job.getJobStatus($jobId)) #if ($jobStatus) - #outputJobStatusJSON($jobStatus, $translationPrefix) + #outputJobStatusJSON($jobStatus) #else $response.setStatus(404) - - {{html}} - <div class="box errormessage"> - $services.localization.render("${translationPrefix}.notFound") - </div> -{{/html}} - + #error($escapetool.xml($services.localization.render("admintools.job.notFound"))) #end -{{/velocity}} - - - \ No newline at end of file +{{/velocity}} + diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml index b227424d..428d97c3 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml @@ -1,4 +1,5 @@ - + + - + + AdminTools.Code HealthCheckResources @@ -51,13 +53,16 @@ #macro (getHealthCheckResources) #set ($jobMinJsURL = $xwiki.getSkinFile('uicomponents/job/job.min.js')) - #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) - #set ($healthJobStatus = $services.job.getJobStatus($healthCheckJobRequest.id)) + #set ($jobId = ['adminTools', 'healthcheck', $services.wiki.getCurrentWikiId()]) + #set ($healthJobStatus = $services.job.getJobStatus($jobId)) {{html clean=false}} - <div hidden> - <input type="text" id="jobMinJsURL" name="jobMinJsURL" value=$jobMinJsURL></input> + <div hidden> + #data($jobMinJsURL) + <jobJsURL + data-url="${jobMinJsURL}" + </jobJsURL> #displayJobProgressBar($healthJobStatus) - </div> + </div> {{/html}} #end {{/velocity}} @@ -67,9 +72,9 @@ #if ("$!request.action" != '' && !$services.csrf.isTokenValid($request.form_token)) #set ($discard = $response.sendError(401, 'CSRF token verification failed!')) #elseif ($request.action == 'healthCheck') - #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) - #set ($healthCheckJob = $services.admintools.runHealthChecks($healthCheckJobRequest)) - #returnHealthCheckJobStatusJSON($healthCheckJobRequest.id) + #set ($jobId = ['adminTools', 'healthcheck', $services.wiki.getCurrentWikiId()]) + #set ($healthCheckJob = $services.admintools.runHealthChecks($jobId)) + #returnHealthCheckJobStatusJSON($jobId) #elseif ($request.data == 'jobStatus') #set ($healthCheckJobId = $request.jobId.split('/')) #returnHealthCheckJobStatusJSON($healthCheckJobId) @@ -78,4 +83,4 @@ #end #end {{/velocity}} - \ No newline at end of file + diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml index ec75242f..6678b284 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml @@ -1,4 +1,4 @@ - + - + + AdminTools.Code Macros @@ -38,85 +39,85 @@ {{velocity output='false'}} #macro (viewLastNLinesMoldal $id) #set ($modalId = $id + 'ViewLastNLinesModal') - <div class="modal fade" id="${modalId}" tabindex="-1" role="dialog" aria-labelledby="${modalId}Label"> - <div class="modal-dialog modal-sm" role="document"> - <div class="modal-content"> - <div class="logs-modal-content"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal" aria-label="Close"> - <span aria-hidden="true">&times;</span></button> - <h1 class="modal-title"> + <div class="modal fade" id="${modalId}" tabindex="-1" role="dialog" aria-labelledby="${modalId}Label"> + <div class="modal-dialog modal-sm" role="document"> + <div class="modal-content"> + <div class="logs-modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">&times;</span></button> + <h1 class="modal-title"> $escapetool.xml($services.localization.render('adminTools.dashboard.logs.modal.title')) - </h1> - </div> - <div class="modal-body"> - <form class="xform" action="$request.getContextPath()/rest/admintools/files/logs"> - <dl> - <dt> - <label for="noLines">$escapetool.xml($services.localization.render( - 'adminTools.dashboard.logs.modal.nLines.label')) </label> - <span class="xHint">$escapetool.xml($services.localization.render( - 'adminTools.dashboard.logs.modal.nLines.hint'))</span> - </dt> - <dd><input type="number" name="noLines" placeholder="1000"></dd> - </dl> - </form> - </div> - <div class="modal-footer"> - <button type="button" class="btn btn-primary"> - $escapetool.xml($services.localization.render('adminTools.dashboard.logs.modal.submit'))</button> - <button type="button" class="btn btn-default" data-dismiss="modal"> - $escapetool.xml($services.localization.render('cancel'))</button> - </div> - </div> - </div> - </div> - </div> + </h1> + </div> + <div class="modal-body"> + <form class="xform" action="$request.getContextPath()/rest/admintools/files/logs"> + <dl> + <dt> + <label for="noLines">$escapetool.xml($services.localization.render( + 'adminTools.dashboard.logs.modal.nLines.label')) </label> + <span class="xHint">$escapetool.xml($services.localization.render( + 'adminTools.dashboard.logs.modal.nLines.hint'))</span> + </dt> + <dd><input type="number" name="noLines" placeholder="1000"></dd> + </dl> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-primary"> + $escapetool.xml($services.localization.render('adminTools.dashboard.logs.modal.submit'))</button> + <button type="button" class="btn btn-default" data-dismiss="modal"> + $escapetool.xml($services.localization.render('cancel'))</button> + </div> + </div> + </div> + </div> + </div> #end #macro (downloadArchiveModal) <div class="modal fade" id="downloadFilesModal" tabindex="-1" role="dialog" aria-labelledby= - "downloadFilesModalLabel"> - <div class="modal-dialog" role="document"> - <div class="modal-content"> - <div class="modal-header"> - <button type="button" class="close" data-dismiss="modal" aria-label="Close"> - <span aria-hidden="true">&times;</span></button> - <h1 class="modal-title"> + "downloadFilesModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">&times;</span></button> + <h1 class="modal-title"> $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.title')) - </h1> - </div> - <div class="modal-body"> - <form class="xform" action="$request.getContextPath()/rest/admintools/files"> - <div class="download-modal-content"> - <dl> - <dt><label><input type="checkbox" name="files" value="xwikiConfig" checked> + </h1> + </div> + <div class="modal-body"> + <form class="xform" action="$request.getContextPath()/rest/admintools/files"> + <div class="download-modal-content"> + <dl> + <dt><label><input type="checkbox" name="files" value="xwikiConfig" checked> $escapetool.xml($services.localization.render( 'adminTools.dashboard.download.modal.xwikiConfig.title')) - </label> - </dt> - <dt><label><input type="checkbox" name="files" value="xwikiProperties" checked> + </label> + </dt> + <dt><label><input type="checkbox" name="files" value="xwikiProperties" checked> $escapetool.xml($services.localization.render( 'adminTools.dashboard.download.modal.xwikiProperties.title')) - </label> - </dt> - <dt> - <label><input type="checkbox" name="files" value="dataProvider" checked> + </label> + </dt> + <dt> + <label><input type="checkbox" name="files" value="dataProvider" checked> $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.provided')) - </label> - </dt> - <dt> - <label><input type="checkbox" name="files" value="logs" checked> + </label> + </dt> + <dt> + <label><input type="checkbox" name="files" value="logs" checked> $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.logs.title')) - </label> - </dt> - <dt> - <div class="dateFields"> + </label> + </dt> + <dt> + <div class="dateFields"> #set ($defaultDateFormat = 'dd-MM-yyyy') #set ($dateFormat = $xwiki.getXWikiPreference('dateformat', $defaultDateFormat)) - <label for="downloadFilesModalFromDate">$escapetool.xml($services.localization.render( + <label for="downloadFilesModalFromDate">$escapetool.xml($services.localization.render( 'adminTools.dashboard.download.modal.date.from')) - </label> + </label> #set ($dateFromParams = { 'id': "downloadFilesModalFromDate", 'name': 'from', @@ -125,9 +126,9 @@ 'adminTools.dashboard.download.modal.logs.filter.placeholder.from')) }) #dateTimePicker($dateFromParams) - <label for="downloadFilesModalToDate">$escapetool.xml($services.localization.render( + <label for="downloadFilesModalToDate">$escapetool.xml($services.localization.render( 'adminTools.dashboard.download.modal.date.to')) - </label> + </label> #set ($dateToParams = { 'id': "downloadFilesModalToDate", 'name': 'to', @@ -136,30 +137,32 @@ 'adminTools.dashboard.download.modal.logs.filter.placeholder.to')) }) #dateTimePicker($dateToParams) - </div> - </dt> - </dl> - </div> - </form> - </div> - <div class="modal-footer"> - <button type="button" class="btn btn-primary"> - $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.button'))</button> - <button type="button" class="btn btn-default" data-dismiss="modal"> - $escapetool.xml($services.localization.render('cancel'))</button> - </div> - </div> - </div> - </div> + </div> + </dt> + </dl> + </div> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-primary"> + $escapetool.xml($services.localization.render('adminTools.dashboard.download.modal.button'))</button> + <button type="button" class="btn btn-default" data-dismiss="modal"> + $escapetool.xml($services.localization.render('cancel'))</button> + </div> + </div> + </div> + </div> #end #macro (jobFinishedMessage $status $translationPrefix $successKey $errorKey $canceledKey $warningKey) #if ($status.error) - #set($messageKeys = [$errorKey, "${translationPrefix}.finish.error", "job.status.${status.jobType}.error", 'job.status.error']) + #set($messageKeys = [$errorKey, "${translationPrefix}.finish.error", "job.status.${status.jobType}.error", + 'job.status.error']) #set($healthCheckReportMessage = $services.localization.render($messageKeys)) #set($messageClass = 'errormessage') #elseif ($status.canceled) - #set($messageKeys = [$canceledKey, "${translationPrefix}.finish.canceled", "job.status.${status.jobType}.canceled", 'job.status.canceled']) + #set($messageKeys = [$canceledKey, "${translationPrefix}.finish.canceled", "job.status.${status.jobType}.canceled", + 'job.status.canceled']) #set($healthCheckReportMessage = $services.localization.render($messageKeys)) #set($messageClass = 'warningmessage') #elseif ($status.logTail.hasLogLevel('error')) @@ -172,15 +175,14 @@ #set($healthCheckReportMessage = 'No issue found!') #set($messageClass = 'successmessage') #end - <div class="box $messageClass"> + <div class="box $messageClass"> $healthCheckReportMessage - </div> + </div> #end #macro (healthCheckUI) #set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) - #set ($healthCheckJobRequest = $services.admintools.createJobRequest($services.wiki.getCurrentWikiId())) - #set ($jobId = $healthCheckJobRequest.id) + #set ($jobId = ['adminTools', 'healthcheck', $services.wiki.getCurrentWikiId()]) #set ($healthJobStatusURL = $xwiki.getURL('AdminTools.Code.HealthCheckJob', 'get', $escapetool.url({ 'jobId': $jobId, 'outputSyntax': 'plain' @@ -192,39 +194,43 @@ #set ($description = $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.description', [ '__STARTLINK__', '__ENDLINK__' - ])).replace('__STARTLINK__', "<a href='$solutionLink'><strong>").replace('__ENDLINK__', '</strong></a>')) - {{html clean='false'}} - <input type="hidden" name="jobState" value="${healthJobStatus.state}"></input> - <div class="adminToolsDashboardItem" id="healthCheck"> - <h2>$services.icon.renderHTML('bug') - $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.title'))</h2> - <p>$description</p> - <hr/> - <div class="healthCheckWrapper"> - <div class="healthCheckLastCheck"> - Time since the last health check: $services.date.displayTimeAgo($healthJobStatus.getEndDate()) - </div> - <div class="buttonwrapper"> - <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" - value="startHealthCheck">Start health check</button> - </div> - </div> - <div hidden class="xcontent job-status" data-url="${healthJobStatusURL}"> + ])).replace('__STARTLINK__', "<a href='$solutionLink'><strong>").replace('__ENDLINK__', ' + </strong></a>')) + <jobState + data-state="${healthJobStatus.state}" + </jobState> + <input type="hidden" name="jobState" value="${healthJobStatus.state}"></input> + <div class="adminToolsDashboardItem" id="healthCheck"> + <h2>$services.icon.renderHTML('bug') + $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.title'))</h2> + <p>$description</p> + <hr/> + <div class="healthCheckWrapper"> + <div class="healthCheckLastCheck"> + $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.time')): + $services.date.displayTimeAgo($healthJobStatus.getEndDate()) + </div> + <div class="buttonwrapper"> + <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" + value="startHealthCheck">$escapetool.xml($services.localization.render( + 'adminTools.dashboard.healthcheck.start'))</button> + </div> + </div> + <div hidden class="xcontent job-status" data-url="${healthJobStatusURL}"> + #if ($healthJobStatus.state != 'FINISHED') + #displayJobProgressBar($jobStatus) + #else + #jobFinishedMessage($healthJobStatus, $translationPrefix, $successKey, $errorKey, $canceledKey) + #end + #if ($showLogs || $isAdvancedUser || $isSuperAdmin) #if ($healthJobStatus.state != 'FINISHED') - #displayJobProgressBar($jobStatus) + #displayJobStatusLog($jobStatus true) #else - #jobFinishedMessage($healthJobStatus, $translationPrefix, $successKey, $errorKey, $canceledKey) - #end - #if ($showLogs || $isAdvancedUser || $isSuperAdmin) - #if ($healthJobStatus.state != 'FINISHED') - #displayJobStatusLog($jobStatus true) - #else - #displayJobStatusLog($healthJobStatus true) - #end + #displayJobStatusLog($healthJobStatus true) #end - </div> - </div> - {{/html}} + #end + </div> + </div> #end {{/velocity}} - \ No newline at end of file + diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml index 82c607a8..6da7e096 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml @@ -1,4 +1,4 @@ - + - + + AdminTools.Code Translations @@ -94,6 +95,9 @@ adminTools.dashboard.healthcheck.security.xwiki.info=XWiki encoding OK adminTools.dashboard.healthcheck.security.xwiki.active.warn=XWiki active encoding is [{}]. The encoding should be UTF-8! adminTools.dashboard.healthcheck.security.xwiki.config.warn=XWiki configuration encoding is [{}]. The encoding should be UTF-8! adminTools.dashboard.healthcheck.title=Health check +adminTools.dashboard.healthcheck.time=Time since the last health check +adminTools.dashboard.healthcheck.start=Start health check +adminTools.job.notFound=Health check job status not found ## Security adminTools.dashboard.security.activeEncoding=Active encoding @@ -106,6 +110,27 @@ adminTools.dashboard.security.pwd=Working directory adminTools.dashboard.security.title=Security +##Help links +adminTools.helppage.browser.support=Browser support +adminTools.helppage.browser.title=Browser +adminTools.helppage.database.instructions=Specific databases instructions +adminTools.helppage.database.mysql.install=MySQL installation guide +adminTools.helppage.database.mysql.troubleshoot=MySQL troubleshoot +adminTools.helppage.database.supported=Supported databases +adminTools.helppage.database.title=Database issues +adminTools.helppage.java.memory=Java memory +adminTools.helppage.java.support=Java support +adminTools.helppage.java.title=Java +adminTools.helppage.other.title=Other issues +adminTools.helppage.performance.cache=Cache recommendations +adminTools.helppage.performance.hardware=Hardware requirements +adminTools.helppage.performance.memory=Memory recommendations +adminTools.helppage.performance.title=Performance issues +adminTools.helppage.server.supported=Supported servers +adminTools.helppage.server.title=Server issues +adminTools.helppage.server.tomcat=Tomcat recommendations + + ## Modals adminTools.dashboard.download.modal.button=Download adminTools.dashboard.download.modal.date.from=From @@ -147,8 +172,8 @@ adminTools.dashboard.showLogs=View last n lines of log... 1 Scope 0 - - |, + + |, 1 0 GLOBAL|WIKI|USER|ON_DEMAND @@ -159,4 +184,4 @@ adminTools.dashboard.showLogs=View last n lines of log... WIKI
- \ No newline at end of file + diff --git a/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml b/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml index 49074a2c..587c94e9 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml @@ -1,4 +1,5 @@ - + + - + + AdminTools HelpLinks @@ -39,75 +41,52 @@ {{/box}} {{velocity}} += $escapetool.xml($services.localization.render('adminTools.helppage.performance.title')) = -= Performance issues = - -{{html}} - <ul> - <li><a href="https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HSizing" target="_blank"> - Hardware requirements</a></li> - <li><a href="https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HMemory" target="_blank"> - Memory recommendations</a></li> - <li><a href="https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HDocumentCache" - target="_blank">Cache recommendations</a></li> - </ul> -{{/html}} - -= Server issues = +* [[$escapetool.xml($services.localization.render('adminTools.helppage.performance.hardware')) +>>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HSizing||target="_blank"]] +* [[$escapetool.xml($services.localization.render('adminTools.helppage.performance.memory')) +>>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HMemory||target="_blank"]] +* [[$escapetool.xml($services.localization.render('adminTools.helppage.performance.cache')) +>>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HDocumentCache +||target="_blank"]] -{{html}} - <ul> - <li><a href="https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/ServletContainerSupportStrategy/" - target="_blank">Supported servers</a></li> - <li><a - href="https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationTomcat/#HRecommendations" - target="_blank">Tomcat recommendations</a></li> - </ul> -{{/html}} += $escapetool.xml($services.localization.render('adminTools.helppage.server.title')) = -= Database issues = +* [[$escapetool.xml($services.localization.render('adminTools.helppage.server.supported')) +>>https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/ServletContainerSupportStrategy/ +||target="_blank"]] +* [[$escapetool.xml($services.localization.render('adminTools.helppage.server.tomcat')) +>>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationTomcat/#HRecommendations +||target="_blank"]] -{{html}} - <ul> - <li> - <a href="https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/DatabaseSupportStrategy" target="_blank"> - Supported databases</a> - </li> - <li><a href= - "https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/#HSpecificdatabasesinstructions" - target="_blank">Specific databases instructions</a></li> - <li><a href= - "https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationMySQL/#HInstallationSteps" - target="_blank">MySQL installation guide</a></li> - <li><a href= - "https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationMySQL/#HTroubleshooting" - target="_blank">MySQL troubleshoot</a></li> - </ul> -{{/html}} += $escapetool.xml($services.localization.render('adminTools.helppage.database.title')) = -= Other issues = -== Java == +* [[$escapetool.xml($services.localization.render('adminTools.helppage.database.supported')) +>>https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/DatabaseSupportStrategy||target="_blank"]] +* [[$escapetool.xml($services.localization.render('adminTools.helppage.database.instructions')) +>>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/#HSpecificdatabasesinstructions +||target="_blank"]] +* [[$escapetool.xml($services.localization.render('adminTools.helppage.database.mysql.install')) +>>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationMySQL/#HInstallationSteps +||target="_blank"]] +* [[$escapetool.xml($services.localization.render('adminTools.helppage.database.mysql.troubleshoot')) +>>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationMySQL/#HTroubleshooting +||target="_blank"]] -{{html}} - <ul> - <li><a href= - "https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationTomcat/#HGeneralMemorySettings" - target="_blank">Java memory</a></li> - <li><a - href="https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/JavaSupportStrategy/" target="_blank"> - Java support</a></li> - </ul> -{{/html}} += $escapetool.xml($services.localization.render('adminTools.helppage.other.title')) = +== $escapetool.xml($services.localization.render('adminTools.helppage.java.title')) == -== Browser == +* [[$escapetool.xml($services.localization.render('adminTools.helppage.java.memory')) +>>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationTomcat/#HGeneralMemorySettings +||target="_blank"]] +* [[$escapetool.xml($services.localization.render('adminTools.helppage.java.support')) +>>https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/JavaSupportStrategy/||target="_blank"]] -{{html}} - <ul> - <li><a href="https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/BrowserSupportStrategy" target="_blank"> - Browser support</a></li> - </ul> -{{/html}} +== $escapetool.xml($services.localization.render('adminTools.helppage.browser.title')) == +* [[$escapetool.xml($services.localization.render('adminTools.helppage.browser.support')) +>>https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/BrowserSupportStrategy||target="_blank"]] {{/velocity}}
- \ No newline at end of file + diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index 45dfe38b..3d8c28d7 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -1,4 +1,5 @@ - + + - + + AdminTools WebHome @@ -99,7 +101,7 @@ 1, 1
- + </property> </object> <object> @@ -166,14 +168,14 @@ <position>2, 1</position> </property> <property> - <title> + </property> </object> <object> <name>AdminTools.WebHome</name> <number>3</number> <className>XWiki.GadgetClass</className> - <guid>e26584bd-f916-43fd-b57c-4030ba639a9a</guid> + <guid>7ac72ccf-e4d2-474f-b279-ae650ac57a58</guid> <class> <name>XWiki.GadgetClass</name> <customClass/> @@ -227,14 +229,16 @@ {{velocity}} #includeMacros("AdminTools.Code.Macros") - #healthCheckUI() + {{html clean='false'}} + #healthCheckUI() + {{/html}} {{/velocity}}</content> </property> <property> <position>1, 2</position> </property> <property> - <title> + </property> </object> <object> @@ -392,4 +396,4 @@ <use>currentPage</use> </property> </object> -</xwikidoc> \ No newline at end of file +</xwikidoc> From d56a3333c3db27cb1ca4fbfb53fa6331fb673831 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin <sorin.chiuchiu@gmail.com> Date: Thu, 16 Nov 2023 11:10:10 +0200 Subject: [PATCH 67/72] Create a health check dashboard section #13 - backup --- .../health/HealthCheckComponent.java | 45 +++++++++++++++++ .../admintools/health/HealthCheckResult.java | 48 ++++++++++++------- .../admintools/jobs/HealthCheckJobStatus.java | 16 +++++++ .../health/checks/MemoryHealthCheck.java | 8 ++-- .../health/checks/PerformanceHealthCheck.java | 5 +- .../AbstractConfigurationHealthCheck.java | 2 + .../ConfigurationDatabaseHealthCheck.java | 5 +- .../ConfigurationJavaHealthCheck.java | 8 ++-- .../ConfigurationOsHealthCheck.java | 4 +- .../SecurityEncodingHealthCheck.java | 6 ++- .../internal/health/job/HealthCheckJob.java | 4 +- .../health/job/HealthCheckJobTest.java | 4 +- 12 files changed, 119 insertions(+), 36 deletions(-) create mode 100644 application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckComponent.java diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckComponent.java b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckComponent.java new file mode 100644 index 00000000..08331702 --- /dev/null +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckComponent.java @@ -0,0 +1,45 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.health; + +import java.util.List; + +import org.xwiki.component.annotation.Role; +import org.xwiki.stability.Unstable; + +/** + * Check for issues in the current wiki. + * + * @since 1.0 + * @version $Id$ + */ +@Role +@Unstable +public interface HealthCheckComponent +{ + /** + * Execute the health check on the wiki instance. + * + * @return a {@link HealthCheckResult} with {@code null} values if no issue was found, or with initialized values + * otherwise. + */ + List<HealthCheckResult> check(); +} + diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java index 2f2148a7..22f9b969 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java @@ -34,28 +34,35 @@ public class HealthCheckResult private String recommendation; + private String level; + + private String currentValue; + /** * Used for registering an error. * * @param errorMessage Error message representing the summary of the found issue. * @param recommendation Suggestion for fixing the issue. + * @param level Suggestion for fixing the issue. */ - public HealthCheckResult(String errorMessage, String recommendation) + public HealthCheckResult(String errorMessage, String recommendation, String level) { this.errorMessage = errorMessage; this.recommendation = recommendation; + this.level = level; } /** * Used for initializing an empty body result. */ - public HealthCheckResult() + public HealthCheckResult(String errorMessage, String level) { - this(null, null); + this(errorMessage, null, level); } /** * Get the error body. + * * @return a summary of the error. */ public String getErrorMessage() @@ -74,20 +81,29 @@ public String getRecommendation() } /** - * Set the message error. - * @param err summary of the error. - */ - public void setErrorMessage(String err) - { - this.errorMessage = err; - } - - /** - * Set the error recommendation. - * @param recommendation summary of the fix. + * Get the severity level a detected error, where 0 is info, 1 is a warning and 2 is an error. + * + * @return the severity level of an error. */ - public void setRecommendation(String recommendation) + public String getLevel() { - this.recommendation = recommendation; + return level; } +// /** +// * Set the message error. +// * @param err summary of the error. +// */ +// public void setErrorMessage(String err) +// { +// this.errorMessage = err; +// } +// +// /** +// * Set the error recommendation. +// * @param recommendation summary of the fix. +// */ +// public void setRecommendation(String recommendation) +// { +// this.recommendation = recommendation; +// } } diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobStatus.java b/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobStatus.java index fccd9914..1d70b2ba 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobStatus.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobStatus.java @@ -64,4 +64,20 @@ public List<HealthCheckResult> getHealthCheckResults() { return healthCheckResults; } + + /** + * Get the list issues list from the job. + * @param level the logger manager + * + * @return boolean with {@link HealthCheckResult} containing errors. + */ + public boolean hasErrorLevel(String level) + { + for (HealthCheckResult checkResult : healthCheckResults) { + if (checkResult.getLevel().equals(level)) { + return true; + } + } + return false; + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java index 87a7cc12..13609d6c 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java @@ -68,16 +68,16 @@ public HealthCheckResult check() boolean cacheOk = isEnoughCache(); boolean memoryOk = hasEnoughMemory(); if (cacheOk && memoryOk) { - return new HealthCheckResult(); + return new HealthCheckResult("adminTools.dashboard.healthcheck.memory.cache.info", "info"); } - return new HealthCheckResult("There are memory issues!", "dummy memory help link"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.memory.cache.null", "dummy memory help link", + "warn"); } private boolean isEnoughCache() { String storeCacheCapacity = configurationSource.getProperty("xwiki.store.cache.capacity"); if (storeCacheCapacity == null) { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.null")); return false; } @@ -109,7 +109,7 @@ private boolean hasEnoughMemory() } else if (totalFreeMemory < 1024) { logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.warn"), totalFreeMemory); - return true; + return false; } logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.info")); return true; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java index e396976a..80e80150 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java @@ -75,10 +75,11 @@ public HealthCheckResult check() boolean hasMinimumCPURequirements = hasMinimumCPURequirements(); boolean hasMinimumMemoryRequirements = hasMinimumMemoryRequirements(); if (!hasFreeSpace || !hasMinimumCPURequirements || !hasMinimumMemoryRequirements) { - return new HealthCheckResult("performance issues", "minimum sys req link"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.performance.info", "minimum sys req link", + "error"); } logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.info")); - return new HealthCheckResult(); + return new HealthCheckResult("adminTools.dashboard.healthcheck.performance.info", "info"); } private boolean hasFreeSpace() diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java index a977e1fc..fcca4edf 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java @@ -21,6 +21,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; import javax.inject.Inject; import javax.inject.Named; @@ -62,6 +63,7 @@ public abstract class AbstractConfigurationHealthCheck implements HealthCheck protected Map<String, String> getJSON(String hint) { try { + TimeUnit.SECONDS.sleep(1); DataProvider dataProvider = findDataProvider(hint); if (dataProvider == null) { throw new NullPointerException("Could not find a matching DataProvider."); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java index b1850df6..ce9a61f3 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java @@ -47,9 +47,10 @@ public HealthCheckResult check() { if (getJSON(ConfigurationDataProvider.HINT).get("databaseName") == null) { logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.warn")); - return new HealthCheckResult("database_not_detected", "xwiki_db_configuration"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.database.warn", "xwiki_db_configuration", + "warn"); } logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.info")); - return new HealthCheckResult(); + return new HealthCheckResult("adminTools.dashboard.healthcheck.database.info", "info"); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java index 03ddb74f..172b7736 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java @@ -48,17 +48,19 @@ public HealthCheckResult check() String javaVersionString = getJSON(ConfigurationDataProvider.HINT).get("javaVersion"); if (javaVersionString == null) { logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.found")); - return new HealthCheckResult("java_version_not_found", "java_installation_link"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.java.warn.found", "java_installation_link", + "warn"); } String xwikiVersionString = getJSON(ConfigurationDataProvider.HINT).get("xwikiVersion"); float xwikiVersion = parseFloat(xwikiVersionString); float javaVersion = parseFloat(javaVersionString); if (isJavaXWikiCompatible(xwikiVersion, javaVersion)) { logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.incompatible")); - return new HealthCheckResult("java_xwiki_not_compatible", "java_issue_rec"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.java.warn.incompatible", "java_issue_rec", + "warn"); } logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.info")); - return new HealthCheckResult(); + return new HealthCheckResult("adminTools.dashboard.healthcheck.java.info", "info"); } private static float parseFloat(String javaVersionString) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java index 82d18678..d28b9345 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java @@ -50,9 +50,9 @@ public HealthCheckResult check() Map<String, String> dataJSON = getJSON(ConfigurationDataProvider.HINT); if (dataJSON.get("osName") == null || dataJSON.get("osVersion") == null || dataJSON.get("osArch") == null) { logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.os.warn")); - return new HealthCheckResult("os_issue", "os_support"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.os.warn", "os_support", "warn"); } logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.os.info")); - return new HealthCheckResult(); + return new HealthCheckResult("adminTools.dashboard.healthcheck.os.info", "info"); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheck.java index 522c426a..788264d9 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheck.java @@ -67,10 +67,12 @@ public HealthCheckResult check() isSafeEncoding(configEnc, "adminTools.dashboard.healthcheck.security.xwiki.config.warn"); if (!isSafeLangEnc || !isSafeFileEnc || !isActiveEncSafe || !isConfigEncSafe) { - return new HealthCheckResult("xwiki_encoding_err", "xwiki config tutorial link"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.config.warn", "xwiki config" + + " tutorial link", "warn"); } logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.info")); - return new HealthCheckResult(); + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.config.warn", "xwiki config" + + " tutorial link", "warn"); } private boolean isSafeEncoding(String encoding, String message) diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java index c867bcb7..8200d44e 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java @@ -82,9 +82,7 @@ protected void runInternal() HealthCheckResult checkResult = healthCheckIterator.next().check(); // If the check return a result with a null error message then no issue was found, so we do not // add the result to the status HealthCheckResult list. - if (checkResult.getErrorMessage() != null) { - status.getHealthCheckResults().add(checkResult); - } + status.getHealthCheckResults().add(checkResult); progressManager.endStep(this); Thread.yield(); } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java index 4a4e4bd1..512b2561 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java @@ -68,8 +68,8 @@ void runInternal() healthCheckList.add(secondHealthCheck); when(listProvider.get()).thenReturn(healthCheckList); - when(firstHealthCheck.check()).thenReturn(new HealthCheckResult("err", "err_rec")); - when(secondHealthCheck.check()).thenReturn(new HealthCheckResult()); + when(firstHealthCheck.check()).thenReturn(new HealthCheckResult("err", "err_rec", "error")); + when(secondHealthCheck.check()).thenReturn(new HealthCheckResult("safe", "info")); healthCheckJob.initialize(new HealthCheckJobRequest()); healthCheckJob.runInternal(); From aec872e9611a6aab27976c7830fb1e260ba05e53 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin <sorin.chiuchiu@gmail.com> Date: Thu, 16 Nov 2023 18:41:27 +0200 Subject: [PATCH 68/72] Create a health check dashboard section #13 * Modified the test structure * Adpated health checks to the usage of HealthCheckResult * Added tests to be able to return a result for every tested data * Created HealthCheckMacros * Created macro for generating job status info * Created macros for displaying the HealthCheckresults in the UI * Added the posibility to extend a result in the UI to see a more detailed explanation or suggestion * Added coments * Addded and modified translations * Adapted tests and added new tests for the new classes * Other small modification in JS and backend --- .../health/HealthCheckComponent.java | 45 ----- .../admintools/health/HealthCheckResult.java | 74 +++++--- .../internal/AdminToolsManager.java | 3 +- .../data/identifiers/CurrentServer.java | 14 +- .../health/checks/PerformanceHealthCheck.java | 129 ------------- .../AbstractConfigurationHealthCheck.java | 36 +--- .../ConfigurationDatabaseHealthCheck.java | 26 ++- .../ConfigurationJavaHealthCheck.java | 26 +-- .../ConfigurationOsHealthCheck.java | 8 +- .../SecurityEncodingHealthCheck.java | 86 --------- .../checks/memory/CacheMemoryHealthCheck.java | 74 ++++++++ .../{ => memory}/MemoryHealthCheck.java | 68 ++----- .../checks/performance/CPUHealthCheck.java | 71 +++++++ .../PhysicalMemoryHealthCheck.java | 72 +++++++ .../performance/PhysicalSpaceHealthCheck.java | 88 +++++++++ .../security/AbstractSecurityHealthCheck.java | 69 +++++++ .../security/ActiveEncodingHealthCheck.java | 61 ++++++ .../ConfigurationEncodingHealthCheck.java | 63 +++++++ .../security/FileEncodingHealthCheck.java | 61 ++++++ .../security/LangEncodingHealthCheck.java | 61 ++++++ .../main/resources/META-INF/components.txt | 12 +- .../health/checks/MemoryHealthCheckTest.java | 160 ---------------- .../ConfigurationDatabaseHealthCheckTest.java | 53 ++---- .../ConfigurationJavaHealthCheckTest.java | 58 +----- .../ConfigurationOsHealthCheckTest.java | 34 +--- .../SecurityEncodingHealthCheckTest.java | 146 --------------- .../memory/CacheMemoryHealthCheckTest.java | 82 ++++++++ .../checks/memory/MemoryHealthCheckTest.java | 110 +++++++++++ .../ActiveEncodingHealthCheckTest.java | 92 +++++++++ .../ConfigurationEncodingHealthCheckTest.java | 92 +++++++++ .../security/FileEncodingHealthCheckTest.java | 92 +++++++++ .../security/LangEncodingHealthCheckTest.java | 92 +++++++++ .../health/job/HealthCheckJobTest.java | 2 +- .../AdminTools/Code/AdminToolsJS.xml | 5 + .../AdminTools/Code/HealthCheckJob.xml | 4 +- .../AdminTools/Code/HealthCheckMacros.xml | 177 ++++++++++++++++++ .../AdminTools/Code/HealthCheckResources.xml | 2 + .../main/resources/AdminTools/Code/Macros.xml | 80 -------- .../AdminTools/Code/Translations.xml | 98 ++++++---- .../main/resources/AdminTools/HelpLinks.xml | 39 ++-- .../src/main/resources/AdminTools/WebHome.xml | 2 +- 41 files changed, 1604 insertions(+), 963 deletions(-) delete mode 100644 application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckComponent.java delete mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java delete mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheck.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/memory/CacheMemoryHealthCheck.java rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/{ => memory}/MemoryHealthCheck.java (53%) create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/CPUHealthCheck.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalMemoryHealthCheck.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalSpaceHealthCheck.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/AbstractSecurityHealthCheck.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheck.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheck.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheck.java create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheck.java delete mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java delete mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/memory/CacheMemoryHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/memory/MemoryHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheckTest.java create mode 100644 application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheckTest.java create mode 100644 application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckMacros.xml diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckComponent.java b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckComponent.java deleted file mode 100644 index 08331702..00000000 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckComponent.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools.health; - -import java.util.List; - -import org.xwiki.component.annotation.Role; -import org.xwiki.stability.Unstable; - -/** - * Check for issues in the current wiki. - * - * @since 1.0 - * @version $Id$ - */ -@Role -@Unstable -public interface HealthCheckComponent -{ - /** - * Execute the health check on the wiki instance. - * - * @return a {@link HealthCheckResult} with {@code null} values if no issue was found, or with initialized values - * otherwise. - */ - List<HealthCheckResult> check(); -} - diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java index 22f9b969..e41ec85a 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java @@ -22,7 +22,9 @@ import org.xwiki.stability.Unstable; /** - * Result of a health check. Stores the error message and recommendation. + * Result of a health check. May store the error message, severity level, recommendation and the current value of the + * checked resource. The severity level is used as "info", for informative result, "warn" for warnings and "error" + * for critical issues. * * @version $Id$ * @since 1.0 @@ -30,7 +32,7 @@ @Unstable public class HealthCheckResult { - private String errorMessage; + private String message; private String recommendation; @@ -39,25 +41,42 @@ public class HealthCheckResult private String currentValue; /** - * Used for registering an error. + * Used for registering a result. * - * @param errorMessage Error message representing the summary of the found issue. - * @param recommendation Suggestion for fixing the issue. - * @param level Suggestion for fixing the issue. + * @param message Error message representing the summary of the found issue. + * @param recommendation suggestion in context of the message. + * @param level severity level of a result. + * @param currentValue Current value of the checked resource. */ - public HealthCheckResult(String errorMessage, String recommendation, String level) + public HealthCheckResult(String message, String recommendation, String level, String currentValue) { - this.errorMessage = errorMessage; + this.message = message; this.recommendation = recommendation; this.level = level; + this.currentValue = currentValue; } /** - * Used for initializing an empty body result. + * Partial result definition. + * + * @param message Error message representing the summary of the found issue. + * @param recommendation suggestion in context of the message. + * @param level severity level of a result. + */ + public HealthCheckResult(String message, String recommendation, String level) + { + this(message, recommendation, level, null); + } + + /** + * Simple result definition. + * + * @param message Error message representing the summary of the found issue. + * @param level severity level of a result. */ - public HealthCheckResult(String errorMessage, String level) + public HealthCheckResult(String message, String level) { - this(errorMessage, null, level); + this(message, null, level); } /** @@ -65,9 +84,9 @@ public HealthCheckResult(String errorMessage, String level) * * @return a summary of the error. */ - public String getErrorMessage() + public String getMessage() { - return errorMessage; + return message; } /** @@ -81,7 +100,7 @@ public String getRecommendation() } /** - * Get the severity level a detected error, where 0 is info, 1 is a warning and 2 is an error. + * Get the severity level a detected error. * * @return the severity level of an error. */ @@ -89,21 +108,14 @@ public String getLevel() { return level; } -// /** -// * Set the message error. -// * @param err summary of the error. -// */ -// public void setErrorMessage(String err) -// { -// this.errorMessage = err; -// } -// -// /** -// * Set the error recommendation. -// * @param recommendation summary of the fix. -// */ -// public void setRecommendation(String recommendation) -// { -// this.recommendation = recommendation; -// } + + /** + * Get the value of a checked resource. + * + * @return the value of a checked resource. + */ + public String getCurrentValue() + { + return currentValue; + } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index f317c2e4..50822b71 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -19,7 +19,6 @@ */ package com.xwiki.admintools.internal; -import java.util.ArrayList; import java.util.List; import javax.inject.Inject; @@ -108,7 +107,7 @@ public String generateData(String hint) throws ComponentLookupException */ public List<String> getSupportedDBs() { - return new ArrayList<>(this.currentServer.getSupportedDBs().values()); + return this.currentServer.getSupportedDBs(); } /** diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java index 35b7551d..1984b21e 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/data/identifiers/CurrentServer.java @@ -20,9 +20,7 @@ package com.xwiki.admintools.internal.data.identifiers; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import javax.inject.Inject; import javax.inject.Provider; @@ -65,19 +63,13 @@ public ServerIdentifier getCurrentServer() } /** - * Get a {@link Map} with the supported databases. + * Get a {@link List} with the supported databases. * * @return the supported databases. */ - public Map<String, String> getSupportedDBs() + public List<String> getSupportedDBs() { - Map<String, String> supportedDBs = new HashMap<>(); - supportedDBs.put("mysql", "MySQL"); - supportedDBs.put("hsqldb", "HSQLDB"); - supportedDBs.put("mariadb", "MariaDB"); - supportedDBs.put("postgresql", "PostgreSQL"); - supportedDBs.put("oracle", "Oracle"); - return supportedDBs; + return List.of("MySQL", "HSQL", "MariaDB", "PostgreSQL", "Oracle"); } /** diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java deleted file mode 100644 index 80e80150..00000000 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/PerformanceHealthCheck.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools.internal.health.checks; - -import java.io.File; - -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; - -import org.slf4j.Logger; -import org.xwiki.component.annotation.Component; -import org.xwiki.component.phase.Initializable; -import org.xwiki.component.phase.InitializationException; -import org.xwiki.localization.ContextualLocalizationManager; - -import com.xwiki.admintools.health.HealthCheck; -import com.xwiki.admintools.health.HealthCheckResult; - -import oshi.SystemInfo; -import oshi.hardware.CentralProcessor; -import oshi.hardware.HardwareAbstractionLayer; - -/** - * Implementation of {@link HealthCheck} for checking system hardware meets XWiki requirements. - * - * @version $Id$ - */ -@Component -@Named(PerformanceHealthCheck.HINT) -@Singleton -public class PerformanceHealthCheck implements HealthCheck, Initializable -{ - /** - * Component identifier. - */ - public static final String HINT = "PERFORMANCE_HEALTH_CHECK"; - - @Inject - protected ContextualLocalizationManager localization; - - @Inject - private Logger logger; - - private HardwareAbstractionLayer hardware; - - @Override - public void initialize() throws InitializationException - { - SystemInfo systemInfo = new SystemInfo(); - this.hardware = systemInfo.getHardware(); - } - - @Override - public HealthCheckResult check() - { - boolean hasFreeSpace = hasFreeSpace(); - boolean hasMinimumCPURequirements = hasMinimumCPURequirements(); - boolean hasMinimumMemoryRequirements = hasMinimumMemoryRequirements(); - if (!hasFreeSpace || !hasMinimumCPURequirements || !hasMinimumMemoryRequirements) { - return new HealthCheckResult("adminTools.dashboard.healthcheck.performance.info", "minimum sys req link", - "error"); - } - logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.info")); - return new HealthCheckResult("adminTools.dashboard.healthcheck.performance.info", "info"); - } - - private boolean hasFreeSpace() - { - File diskPartition; - if (System.getProperty("os.name").contains("Windows")) { - diskPartition = new File("C:"); - } else { - diskPartition = new File("/"); - } - long freePartitionSpace = diskPartition.getFreeSpace(); - float freeSpace = (float) freePartitionSpace / (1024 * 1024 * 1024); - - if (freeSpace > 2) { - return true; - } else { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.space.warn")); - return false; - } - } - - private boolean hasMinimumMemoryRequirements() - { - float totalMemory = (float) hardware.getMemory().getTotal() / (1024 * 1024 * 1024) + 1; - - if (totalMemory > 2) { - return true; - } else { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.memory.warn")); - return false; - } - } - - private boolean hasMinimumCPURequirements() - { - CentralProcessor processor = hardware.getProcessor(); - int cpuCores = processor.getPhysicalProcessorCount(); - long maxFreq = processor.getMaxFreq() / (1024 * 1024); - - if (cpuCores > 2 && maxFreq > 2048) { - return true; - } else { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.performance.cpu.warn")); - return false; - } - } -} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java index fcca4edf..7a7f6db2 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java @@ -27,55 +27,37 @@ import javax.inject.Named; import org.slf4j.Logger; -import org.xwiki.component.manager.ComponentLookupException; -import org.xwiki.component.manager.ComponentManager; -import org.xwiki.localization.ContextualLocalizationManager; import com.xwiki.admintools.DataProvider; import com.xwiki.admintools.health.HealthCheck; +import com.xwiki.admintools.internal.data.ConfigurationDataProvider; /** - * {@link HealthCheck} implementations to simplify the code. + * {@link HealthCheck} implementations to simplify the code for configuration related health checks. * * @version $Id$ */ public abstract class AbstractConfigurationHealthCheck implements HealthCheck { - /** - * Used to render the translations inside the logger. - */ - @Inject - protected ContextualLocalizationManager localization; - @Inject protected Logger logger; @Inject - @Named("context") - private ComponentManager contextComponentManager; + @Named(ConfigurationDataProvider.HINT) + private DataProvider configurationDataProvider; /** - * Get the JSON needed in the health checks execution. + * Get the JSON needed for the configuration health checks execution. * - * @param hint identifies the {@link DataProvider} for which JSON is required. - * @return a {@link Map} with the {@link DataProvider} info, or an empty {@link Map} in case of an error. + * @return a {@link Map} with the {@link ConfigurationDataProvider} info, or an empty {@link Map} in case of an + * error. */ - protected Map<String, String> getJSON(String hint) + protected Map<String, String> getJSON() { try { - TimeUnit.SECONDS.sleep(1); - DataProvider dataProvider = findDataProvider(hint); - if (dataProvider == null) { - throw new NullPointerException("Could not find a matching DataProvider."); - } - return dataProvider.getDataAsJSON(); + return configurationDataProvider.getDataAsJSON(); } catch (Exception e) { return new HashMap<>(); } } - - private DataProvider findDataProvider(String hint) throws ComponentLookupException - { - return this.contextComponentManager.getInstance(DataProvider.class, hint); - } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java index ce9a61f3..3d878d60 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java @@ -19,13 +19,14 @@ */ package com.xwiki.admintools.internal.health.checks.configuration; +import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import org.xwiki.component.annotation.Component; import com.xwiki.admintools.health.HealthCheckResult; -import com.xwiki.admintools.internal.data.ConfigurationDataProvider; +import com.xwiki.admintools.internal.data.identifiers.CurrentServer; /** * Extension of {@link AbstractConfigurationHealthCheck} for checking the database configuration. @@ -42,15 +43,26 @@ public class ConfigurationDatabaseHealthCheck extends AbstractConfigurationHealt */ public static final String HINT = "CONFIG_DB_HEALTH_CHECK"; + private static final String ERROR_KEY = "error"; + + @Inject + private CurrentServer currentServer; + @Override public HealthCheckResult check() { - if (getJSON(ConfigurationDataProvider.HINT).get("databaseName") == null) { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.warn")); - return new HealthCheckResult("adminTools.dashboard.healthcheck.database.warn", "xwiki_db_configuration", - "warn"); + String usedDatabase = getJSON().get("databaseName"); + if (usedDatabase == null) { + logger.warn("Database not found!"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.database.warn", ERROR_KEY); + } + if (currentServer.getSupportedDBs().stream() + .anyMatch(d -> usedDatabase.toLowerCase().contains(d.toLowerCase()))) + { + return new HealthCheckResult("adminTools.dashboard.healthcheck.database.info", "info"); } - logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.info")); - return new HealthCheckResult("adminTools.dashboard.healthcheck.database.info", "info"); + logger.error("Used database is not supported!"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.database.notSupported", + "adminTools.dashboard.healthcheck.database.recommendation", ERROR_KEY, usedDatabase); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java index 172b7736..1a85ee81 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java @@ -19,13 +19,14 @@ */ package com.xwiki.admintools.internal.health.checks.configuration; +import java.util.Map; + import javax.inject.Named; import javax.inject.Singleton; import org.xwiki.component.annotation.Component; import com.xwiki.admintools.health.HealthCheckResult; -import com.xwiki.admintools.internal.data.ConfigurationDataProvider; /** * Extension of {@link AbstractConfigurationHealthCheck} for checking the Java configuration. @@ -45,21 +46,22 @@ public class ConfigurationJavaHealthCheck extends AbstractConfigurationHealthChe @Override public HealthCheckResult check() { - String javaVersionString = getJSON(ConfigurationDataProvider.HINT).get("javaVersion"); + Map<String, String> configurationJson = getJSON(); + String javaVersionString = configurationJson.get("javaVersion"); if (javaVersionString == null) { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.found")); - return new HealthCheckResult("adminTools.dashboard.healthcheck.java.warn.found", "java_installation_link", - "warn"); + logger.warn("Java version not found!"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.java.warn", + "adminTools.dashboard.healthcheck.java.warn.recommendation", "warn"); } - String xwikiVersionString = getJSON(ConfigurationDataProvider.HINT).get("xwikiVersion"); + String xwikiVersionString = configurationJson.get("xwikiVersion"); float xwikiVersion = parseFloat(xwikiVersionString); float javaVersion = parseFloat(javaVersionString); - if (isJavaXWikiCompatible(xwikiVersion, javaVersion)) { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.incompatible")); - return new HealthCheckResult("adminTools.dashboard.healthcheck.java.warn.incompatible", "java_issue_rec", - "warn"); + if (isNotJavaXWikiCompatible(xwikiVersion, javaVersion)) { + logger.error("Java version is not compatible with the current XWiki installation!"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.java.error", + "adminTools.dashboard.healthcheck.java.error.recommendation", "error", + String.format("Java %s - XWiki %s", javaVersion, xwikiVersion)); } - logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.info")); return new HealthCheckResult("adminTools.dashboard.healthcheck.java.info", "info"); } @@ -69,7 +71,7 @@ private static float parseFloat(String javaVersionString) return Float.parseFloat(parts[0] + "." + parts[1]); } - private boolean isJavaXWikiCompatible(float xwikiVersion, float javaVersion) + private boolean isNotJavaXWikiCompatible(float xwikiVersion, float javaVersion) { boolean isCompatible = false; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java index d28b9345..71164a61 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java @@ -27,7 +27,6 @@ import org.xwiki.component.annotation.Component; import com.xwiki.admintools.health.HealthCheckResult; -import com.xwiki.admintools.internal.data.ConfigurationDataProvider; /** * Extension of {@link AbstractConfigurationHealthCheck} for checking the OS configuration. @@ -47,12 +46,11 @@ public class ConfigurationOsHealthCheck extends AbstractConfigurationHealthCheck @Override public HealthCheckResult check() { - Map<String, String> dataJSON = getJSON(ConfigurationDataProvider.HINT); + Map<String, String> dataJSON = getJSON(); if (dataJSON.get("osName") == null || dataJSON.get("osVersion") == null || dataJSON.get("osArch") == null) { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.os.warn")); - return new HealthCheckResult("adminTools.dashboard.healthcheck.os.warn", "os_support", "warn"); + logger.warn("There has been an error while gathering OS info!"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.os.warn", "warn"); } - logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.os.info")); return new HealthCheckResult("adminTools.dashboard.healthcheck.os.info", "info"); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheck.java deleted file mode 100644 index 788264d9..00000000 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheck.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools.internal.health.checks.configuration; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.inject.Named; -import javax.inject.Singleton; - -import org.xwiki.component.annotation.Component; - -import com.xwiki.admintools.health.HealthCheckResult; -import com.xwiki.admintools.internal.data.SecurityDataProvider; - -/** - * Extension of {@link AbstractConfigurationHealthCheck} for checking system security configuration. - * - * @version $Id$ - */ -@Component -@Named(SecurityEncodingHealthCheck.HINT) -@Singleton -public class SecurityEncodingHealthCheck extends AbstractConfigurationHealthCheck -{ - /** - * Component identifier. - */ - public static final String HINT = "SECURITY_SYSTEM_ENCODING_HEALTH_CHECK"; - - private static final String INVALID = "INVALID"; - - private final List<String> acceptedEncodings = new ArrayList<>(List.of("UTF8", "UTF-8", "utf8", "utf-8")); - - @Override - public HealthCheckResult check() - { - Map<String, String> securityJson = getJSON(SecurityDataProvider.HINT); - String activeEnc = securityJson.getOrDefault("activeEncoding", INVALID); - String configEnc = securityJson.getOrDefault("configurationEncoding", INVALID); - String langEnc = securityJson.getOrDefault("LANG", "invalid.invalid").split("\\.")[1]; - String fileEnc = securityJson.getOrDefault("fileEncoding", INVALID); - - boolean isSafeLangEnc = isSafeEncoding(langEnc, "adminTools.dashboard.healthcheck.security.system.lang.warn"); - boolean isSafeFileEnc = isSafeEncoding(fileEnc, "adminTools.dashboard.healthcheck.security.system.file.warn"); - boolean isActiveEncSafe = - isSafeEncoding(activeEnc, "adminTools.dashboard.healthcheck.security.xwiki.active.warn"); - boolean isConfigEncSafe = - isSafeEncoding(configEnc, "adminTools.dashboard.healthcheck.security.xwiki.config.warn"); - - if (!isSafeLangEnc || !isSafeFileEnc || !isActiveEncSafe || !isConfigEncSafe) { - return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.config.warn", "xwiki config" - + " tutorial link", "warn"); - } - logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.info")); - return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.config.warn", "xwiki config" - + " tutorial link", "warn"); - } - - private boolean isSafeEncoding(String encoding, String message) - { - if (acceptedEncodings.contains(encoding)) { - return true; - } - logger.warn(localization.getTranslationPlain(message), encoding); - return false; - } -} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/memory/CacheMemoryHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/memory/CacheMemoryHealthCheck.java new file mode 100644 index 00000000..0acbcf49 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/memory/CacheMemoryHealthCheck.java @@ -0,0 +1,74 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.memory; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.slf4j.Logger; +import org.xwiki.component.annotation.Component; +import org.xwiki.configuration.ConfigurationSource; + +import com.xwiki.admintools.health.HealthCheck; +import com.xwiki.admintools.health.HealthCheckResult; + +/** + * Implementation of {@link HealthCheck} for checking instance document cache performance. + * + * @version $Id$ + */ +@Component +@Named(CacheMemoryHealthCheck.HINT) +@Singleton +public class CacheMemoryHealthCheck implements HealthCheck +{ + /** + * Component identifier. + */ + public static final String HINT = "CACHE_MEMORY_HEALTH_CHECK"; + + private static final String INFO_LEVEL = "info"; + + @Inject + @Named("xwikicfg") + private ConfigurationSource configurationSource; + + @Inject + private Logger logger; + + @Override + public HealthCheckResult check() + { + String storeCacheCapacity = configurationSource.getProperty("xwiki.store.cache.capacity"); + if (storeCacheCapacity == null) { + logger.warn("Store cache capacity not defined. Set by default at 500."); + return new HealthCheckResult("adminTools.dashboard.healthcheck.memory.cache.null", + "adminTools.dashboard.healthcheck.memory.cache.null.recommendation", INFO_LEVEL); + } + if (Integer.parseInt(storeCacheCapacity) <= 500) { + logger.warn("Store cache capacity is set to [{}].", storeCacheCapacity); + return new HealthCheckResult("adminTools.dashboard.healthcheck.memory.cache.low", null, "warn", + storeCacheCapacity); + } + return new HealthCheckResult("adminTools.dashboard.healthcheck.memory.cache.info", null, INFO_LEVEL, + storeCacheCapacity); + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/memory/MemoryHealthCheck.java similarity index 53% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/memory/MemoryHealthCheck.java index 13609d6c..db3664b6 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/memory/MemoryHealthCheck.java @@ -17,7 +17,9 @@ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ -package com.xwiki.admintools.internal.health.checks; +package com.xwiki.admintools.internal.health.checks.memory; + +import java.text.DecimalFormat; import javax.inject.Inject; import javax.inject.Named; @@ -26,8 +28,6 @@ import org.slf4j.Logger; import org.xwiki.component.annotation.Component; -import org.xwiki.configuration.ConfigurationSource; -import org.xwiki.localization.ContextualLocalizationManager; import com.xpn.xwiki.XWiki; import com.xpn.xwiki.XWikiContext; @@ -49,69 +49,41 @@ public class MemoryHealthCheck implements HealthCheck */ public static final String HINT = "MEMORY_HEALTH_CHECK"; - @Inject - protected ContextualLocalizationManager localization; + private static final String MEMORY_RECOMMENDATION = "adminTools.dashboard.healthcheck.memory.recommendation"; - @Inject - protected Provider<XWikiContext> xcontextProvider; + private static final String MB_UNIT = "MB"; + + private static final String ERROR_LEVEL = "error"; @Inject - @Named("xwikicfg") - private ConfigurationSource configurationSource; + protected Provider<XWikiContext> xcontextProvider; @Inject private Logger logger; @Override public HealthCheckResult check() - { - boolean cacheOk = isEnoughCache(); - boolean memoryOk = hasEnoughMemory(); - if (cacheOk && memoryOk) { - return new HealthCheckResult("adminTools.dashboard.healthcheck.memory.cache.info", "info"); - } - return new HealthCheckResult("adminTools.dashboard.healthcheck.memory.cache.null", "dummy memory help link", - "warn"); - } - - private boolean isEnoughCache() - { - String storeCacheCapacity = configurationSource.getProperty("xwiki.store.cache.capacity"); - if (storeCacheCapacity == null) { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.null")); - return false; - } - if (Integer.parseInt(storeCacheCapacity) <= 500) { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.low"), - storeCacheCapacity); - return false; - } - logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.info")); - return true; - } - - private boolean hasEnoughMemory() { XWiki wiki = xcontextProvider.get().getWiki(); float maxMemory = wiki.maxMemory(); float totalFreeMemory = (maxMemory - (wiki.totalMemory() - wiki.freeMemory())) / (1024.0f * 1024); float maxMemoryGB = maxMemory / (1024.0f * 1024 * 1024); - + DecimalFormat format = new DecimalFormat("0.#"); if (maxMemoryGB < 1) { - logger.error(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.maxcapacity.error"), - maxMemoryGB * 1024); - return false; + logger.error("JVM memory is less than 1024MB. Currently: [{}]", maxMemoryGB * 1024); + return new HealthCheckResult("adminTools.dashboard.healthcheck.memory.maxcapacity.error", + MEMORY_RECOMMENDATION, ERROR_LEVEL, format.format(maxMemoryGB * 1024) + MB_UNIT); } if (totalFreeMemory < 512) { - logger.error(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.error"), - totalFreeMemory); - return false; + logger.error("JVM instance has only [{}]MB free memory left!", totalFreeMemory); + return new HealthCheckResult("adminTools.dashboard.healthcheck.memory.free.error", MEMORY_RECOMMENDATION, + ERROR_LEVEL, format.format(totalFreeMemory) + MB_UNIT); } else if (totalFreeMemory < 1024) { - logger.warn(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.warn"), - totalFreeMemory); - return false; + logger.warn("Instance memory is running low. Currently only [{}]MB free left.", totalFreeMemory); + return new HealthCheckResult("adminTools.dashboard.healthcheck.memory.free.warn", MEMORY_RECOMMENDATION, + "warn", format.format(totalFreeMemory) + MB_UNIT); } - logger.info(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.info")); - return true; + return new HealthCheckResult("adminTools.dashboard.healthcheck.memory.info", null, "info", + String.format(" %s GB", format.format(totalFreeMemory / 1024))); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/CPUHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/CPUHealthCheck.java new file mode 100644 index 00000000..e7eb5096 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/CPUHealthCheck.java @@ -0,0 +1,71 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.performance; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.slf4j.Logger; +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.health.HealthCheck; +import com.xwiki.admintools.health.HealthCheckResult; + +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.HardwareAbstractionLayer; + +/** + * Implementation of {@link HealthCheck} for checking if system CPU meets XWiki requirements. + * + * @version $Id$ + */ +@Component +@Named(CPUHealthCheck.HINT) +@Singleton +public class CPUHealthCheck implements HealthCheck +{ + /** + * Component identifier. + */ + public static final String HINT = "CPU_PERFORMANCE_HEALTH_CHECK"; + + @Inject + private Logger logger; + + @Override + public HealthCheckResult check() + { + SystemInfo systemInfo = new SystemInfo(); + HardwareAbstractionLayer hardware = systemInfo.getHardware(); + CentralProcessor processor = hardware.getProcessor(); + int cpuCores = processor.getPhysicalProcessorCount(); + long maxFreq = processor.getMaxFreq() / (1024 * 1024); + + if (cpuCores > 2 && maxFreq > 2048) { + return new HealthCheckResult("adminTools.dashboard.healthcheck.performance.cpu.info", "info"); + } + String cpuSpecifications = String.format("CPU cores %d - frequency %d", cpuCores, maxFreq); + logger.warn("The CPU does not satisfy the minimum system requirements! [{}]", cpuSpecifications); + return new HealthCheckResult("adminTools.dashboard.healthcheck.performance.cpu.warn", + "adminTools.dashboard.healthcheck.performance.cpu.recommendation", "error", cpuSpecifications); + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalMemoryHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalMemoryHealthCheck.java new file mode 100644 index 00000000..fc26a1c8 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalMemoryHealthCheck.java @@ -0,0 +1,72 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.performance; + +import java.text.DecimalFormat; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.slf4j.Logger; +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.health.HealthCheck; +import com.xwiki.admintools.health.HealthCheckResult; + +import oshi.SystemInfo; +import oshi.hardware.HardwareAbstractionLayer; + +/** + * Implementation of {@link HealthCheck} for checking if system memory meets XWiki requirements. + * + * @version $Id$ + */ +@Component +@Named(PhysicalMemoryHealthCheck.HINT) +@Singleton +public class PhysicalMemoryHealthCheck implements HealthCheck +{ + /** + * Component identifier. + */ + public static final String HINT = "PHYSICAL_MEMORY_HEALTH_CHECK"; + + @Inject + private Logger logger; + + @Override + public HealthCheckResult check() + { + SystemInfo systemInfo = new SystemInfo(); + HardwareAbstractionLayer hardware = systemInfo.getHardware(); + + float totalMemory = (float) hardware.getMemory().getTotal() / (1024 * 1024 * 1024); + DecimalFormat format = new DecimalFormat("0.#"); + String systemCapacityMessage = String.format("%s GB", format.format(totalMemory)); + if (totalMemory > 2) { + return new HealthCheckResult("adminTools.dashboard.healthcheck.performance.memory.info", "info"); + } + logger.warn("There is not enough memory to safely run the XWiki installation! Physical memory detected: [{}]", + systemCapacityMessage); + return new HealthCheckResult("adminTools.dashboard.healthcheck.performance.memory.warn", + "adminTools.dashboard.healthcheck.performance.memory.recommendation", "error", systemCapacityMessage); + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalSpaceHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalSpaceHealthCheck.java new file mode 100644 index 00000000..971233f4 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalSpaceHealthCheck.java @@ -0,0 +1,88 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.performance; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.slf4j.Logger; +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.ServerIdentifier; +import com.xwiki.admintools.health.HealthCheck; +import com.xwiki.admintools.health.HealthCheckResult; +import com.xwiki.admintools.internal.data.identifiers.CurrentServer; + +/** + * Implementation of {@link HealthCheck} for checking if system free space XWiki requirements. + * + * @version $Id$ + */ +@Component +@Named(PhysicalSpaceHealthCheck.HINT) +@Singleton +public class PhysicalSpaceHealthCheck implements HealthCheck +{ + /** + * Component identifier. + */ + public static final String HINT = "PHYSICAL_SPACE_HEALTH_CHECK"; + + @Inject + private CurrentServer currentServer; + + @Inject + private Logger logger; + + @Override + public HealthCheckResult check() + { + File diskPartition; + ServerIdentifier server = currentServer.getCurrentServer(); + if (server == null) { + if (System.getProperty("os.name").toLowerCase().contains("windows")) { + diskPartition = new File("C:"); + } else { + diskPartition = new File("/"); + } + } else { + Path xwikiPath = Paths.get(server.getXwikiCfgFolderPath()); + Path rootDrive = xwikiPath.getRoot(); + diskPartition = new File(String.valueOf(rootDrive)); + } + long freePartitionSpace = diskPartition.getFreeSpace(); + float freeSpace = (float) freePartitionSpace / (1024 * 1024 * 1024); + + String systemFreeSpaceSizeMessage = String.format("%s: %f GB", diskPartition.getAbsolutePath(), freeSpace); + + if (freeSpace > 16) { + return new HealthCheckResult("adminTools.dashboard.healthcheck.performance.space.info", "info"); + } + logger.warn("There is not enough free space for the XWiki installation! Current free space is [{}]", + systemFreeSpaceSizeMessage); + return new HealthCheckResult("adminTools.dashboard.healthcheck.performance.space.warn", + "adminTools.dashboard.healthcheck.performance.space.recommendation", "error", systemFreeSpaceSizeMessage); + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/AbstractSecurityHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/AbstractSecurityHealthCheck.java new file mode 100644 index 00000000..c9289893 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/AbstractSecurityHealthCheck.java @@ -0,0 +1,69 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.security; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.slf4j.Logger; + +import com.xwiki.admintools.DataProvider; +import com.xwiki.admintools.health.HealthCheck; +import com.xwiki.admintools.internal.data.SecurityDataProvider; + +/** + * {@link HealthCheck} implementations to simplify the code for security related health checks. + * + * @version $Id$ + */ +public abstract class AbstractSecurityHealthCheck implements HealthCheck +{ + protected final List<String> acceptedEncodings = new ArrayList<>(List.of("UTF8", "UTF-8", "utf8", "utf-8")); + + @Inject + protected Logger logger; + + @Inject + @Named(SecurityDataProvider.HINT) + private DataProvider securityDataProvider; + + protected boolean isSafeEncoding(String encoding, String type) + { + if (acceptedEncodings.contains(encoding)) { + return true; + } + logger.warn(String.format("%s encoding is [{}], but should be UTF-8!", type), encoding); + return false; + } + + protected Map<String, String> getJSON() + { + try { + return securityDataProvider.getDataAsJSON(); + } catch (Exception e) { + return new HashMap<>(); + } + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheck.java new file mode 100644 index 00000000..97bf0177 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheck.java @@ -0,0 +1,61 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.security; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.health.HealthCheckResult; + +/** + * Extension of {@link AbstractSecurityHealthCheck} for checking XWiki active encoding. + * + * @version $Id$ + */ +@Component +@Named(ActiveEncodingHealthCheck.HINT) +@Singleton +public class ActiveEncodingHealthCheck extends AbstractSecurityHealthCheck +{ + /** + * Component identifier. + */ + public static final String HINT = "ACTIVE_ENCODING_HEALTH_CHECK"; + + private static final String WARN_LEVEL = "warn"; + + @Override + public HealthCheckResult check() + { + String activeEnc = getJSON().get("activeEncoding"); + if (activeEnc == null) { + logger.warn("Active encoding could not be detected!"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.active.notFound", WARN_LEVEL); + } + boolean isActiveEncSafe = isSafeEncoding(activeEnc, "XWiki active"); + if (!isActiveEncSafe) { + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.active.warn", null, + WARN_LEVEL, activeEnc); + } + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.active.info", "info"); + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheck.java new file mode 100644 index 00000000..6ce50c8a --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheck.java @@ -0,0 +1,63 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.security; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.health.HealthCheckResult; + +/** + * Extension of {@link AbstractSecurityHealthCheck} for checking XWiki configuration encoding. + * + * @version $Id$ + */ +@Component +@Named(ConfigurationEncodingHealthCheck.HINT) +@Singleton +public class ConfigurationEncodingHealthCheck extends AbstractSecurityHealthCheck +{ + /** + * Component identifier. + */ + public static final String HINT = "CONFIGURATION_ENCODING_HEALTH_CHECK"; + + private static final String WARN_LEVEL = "warn"; + + @Override + public HealthCheckResult check() + { + String configEnc = getJSON().get("configurationEncoding"); + if (configEnc == null) { + logger.warn("Configuration encoding could not be detected!"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.config.notFound", WARN_LEVEL); + } + boolean isConfigEncSafe = isSafeEncoding(configEnc, "XWiki configuration"); + + if (!isConfigEncSafe) { + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.config.warn", null, + WARN_LEVEL, + configEnc); + } + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.config.info", "info"); + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheck.java new file mode 100644 index 00000000..61beea06 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheck.java @@ -0,0 +1,61 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.security; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.health.HealthCheckResult; + +/** + * Extension of {@link AbstractSecurityHealthCheck} for checking system file encoding. + * + * @version $Id$ + */ +@Component +@Named(FileEncodingHealthCheck.HINT) +@Singleton +public class FileEncodingHealthCheck extends AbstractSecurityHealthCheck +{ + /** + * Component identifier. + */ + public static final String HINT = "FILE_ENCODING_HEALTH_CHECK"; + + private static final String WARN_LEVEL = "warn"; + + @Override + public HealthCheckResult check() + { + String fileEnc = getJSON().get("fileEncoding"); + if (fileEnc == null) { + logger.warn("File encoding could not be detected!"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.system.file.notFound", WARN_LEVEL); + } + boolean isSafeFileEnc = isSafeEncoding(fileEnc, "System file"); + if (!isSafeFileEnc) { + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.system.file.warn", + "adminTools.dashboard.healthcheck.security.system.recommendation", WARN_LEVEL, fileEnc); + } + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.system.file.info", "info"); + } +} diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheck.java new file mode 100644 index 00000000..cad037be --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheck.java @@ -0,0 +1,61 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.security; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.health.HealthCheckResult; + +/** + * Extension of {@link AbstractSecurityHealthCheck} for checking system language configuration. + * + * @version $Id$ + */ +@Component +@Named(LangEncodingHealthCheck.HINT) +@Singleton +public class LangEncodingHealthCheck extends AbstractSecurityHealthCheck +{ + /** + * Component identifier. + */ + public static final String HINT = "LANGUAGE_ENCODING_HEALTH_CHECK"; + + private static final String WARN_LEVEL = "warn"; + + @Override + public HealthCheckResult check() + { + String langEnc = getJSON().get("LANG"); + if (langEnc == null) { + logger.warn("Language encoding could not be detected!"); + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.system.lang.notFound", WARN_LEVEL); + } + boolean isSafeLangEnc = isSafeEncoding(langEnc.split("\\.")[1], "System language"); + if (!isSafeLangEnc) { + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.system.lang.warn", + "adminTools.dashboard.healthcheck.security.system.recommendation", WARN_LEVEL, langEnc); + } + return new HealthCheckResult("adminTools.dashboard.healthcheck.security.system.lang.info", "info"); + } +} diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index c970db2d..a65580bb 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -15,9 +15,15 @@ com.xwiki.admintools.internal.AdminToolsEventListener com.xwiki.admintools.internal.health.checks.configuration.ConfigurationDatabaseHealthCheck com.xwiki.admintools.internal.health.checks.configuration.ConfigurationJavaHealthCheck com.xwiki.admintools.internal.health.checks.configuration.ConfigurationOsHealthCheck -com.xwiki.admintools.internal.health.checks.configuration.SecurityEncodingHealthCheck -com.xwiki.admintools.internal.health.checks.PerformanceHealthCheck -com.xwiki.admintools.internal.health.checks.MemoryHealthCheck +com.xwiki.admintools.internal.health.checks.security.ActiveEncodingHealthCheck +com.xwiki.admintools.internal.health.checks.security.ConfigurationEncodingHealthCheck +com.xwiki.admintools.internal.health.checks.security.FileEncodingHealthCheck +com.xwiki.admintools.internal.health.checks.security.LangEncodingHealthCheck +com.xwiki.admintools.internal.health.checks.performance.CPUHealthCheck +com.xwiki.admintools.internal.health.checks.performance.PhysicalMemoryHealthCheck +com.xwiki.admintools.internal.health.checks.performance.PhysicalSpaceHealthCheck +com.xwiki.admintools.internal.health.checks.memory.CacheMemoryHealthCheck +com.xwiki.admintools.internal.health.checks.memory.MemoryHealthCheck com.xwiki.admintools.internal.health.job.HealthCheckJob com.xwiki.admintools.internal.rest.DefaultAdminToolsResource com.xwiki.admintools.internal.PingProvider diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java deleted file mode 100644 index 066013a3..00000000 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/MemoryHealthCheckTest.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools.internal.health.checks; - -import javax.inject.Named; -import javax.inject.Provider; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.slf4j.Logger; -import org.xwiki.component.util.ReflectionUtils; -import org.xwiki.configuration.ConfigurationSource; -import org.xwiki.localization.ContextualLocalizationManager; -import org.xwiki.test.annotation.BeforeComponent; -import org.xwiki.test.junit5.mockito.ComponentTest; -import org.xwiki.test.junit5.mockito.InjectMockComponents; -import org.xwiki.test.junit5.mockito.MockComponent; - -import com.xpn.xwiki.XWiki; -import com.xpn.xwiki.XWikiContext; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ComponentTest -class MemoryHealthCheckTest -{ - @MockComponent - private static ContextualLocalizationManager localization; - - @InjectMockComponents - private MemoryHealthCheck memoryHealthCheck; - - @MockComponent - private Provider<XWikiContext> xcontextProvider; - - @MockComponent - @Named("xwikicfg") - private ConfigurationSource configurationSource; - - @MockComponent - private XWikiContext context; - - @Mock - private XWiki xwiki; - - @Mock - private Logger logger; - - @BeforeComponent - static void setUp() throws Exception - { - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.info")).thenReturn( - "Cache status OK"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.info")).thenReturn( - "Memory status OK"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.null")).thenReturn( - "Store cache capacity is set at 500. Check Cache recommendations in solutions."); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.cache.low")).thenReturn( - "Store cache capacity is set at [{}]. Check Cache recommendations in solutions."); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.error")).thenReturn( - "Your JVM instance has only [{}]MB free memory left! Consult the solution link for support!"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.free.warn")).thenReturn( - "Your instance memory is running low. Currently only [{}]MB free left."); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.memory.maxcapacity.error")).thenReturn( - "JVM memory is less than 1024MB. Currently: [{}]MB"); - } - - @BeforeEach - void beforeEach() - { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(memoryHealthCheck, "logger", this.logger); - - when(xcontextProvider.get()).thenReturn(context); - when(context.getWiki()).thenReturn(xwiki); - when(configurationSource.getProperty("xwiki.store.cache.capacity")).thenReturn("1000"); - } - - @Test - void check() - { - when(xwiki.maxMemory()).thenReturn((long) (8 * Math.pow(1024, 3))); - when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); - when(xwiki.freeMemory()).thenReturn((long) (0.5 * Math.pow(1024, 3))); - - assertNull(memoryHealthCheck.check().getErrorMessage()); - verify(logger).info("Cache status OK"); - verify(logger).info("Memory status OK"); - } - - @Test - void checkCacheIssues() - { - when(xwiki.maxMemory()).thenReturn((long) (8 * Math.pow(1024, 3))); - when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); - when(xwiki.freeMemory()).thenReturn((long) (0.5 * Math.pow(1024, 3))); - when(configurationSource.getProperty("xwiki.store.cache.capacity")).thenReturn("400"); - assertEquals("There are memory issues!", memoryHealthCheck.check().getErrorMessage()); - verify(logger).warn("Store cache capacity is set at [{}]. Check Cache recommendations in solutions.", "400"); - verify(logger).info("Memory status OK"); - } - - @Test - void checkMaxMemoryIssues() - { - when(xwiki.maxMemory()).thenReturn((long) (0.5 * Math.pow(1024, 3))); - when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); - when(xwiki.freeMemory()).thenReturn((long) (0.5 * Math.pow(1024, 3))); - - assertEquals("There are memory issues!", memoryHealthCheck.check().getErrorMessage()); - verify(logger).info("Cache status OK"); - verify(logger).error("JVM memory is less than 1024MB. Currently: [{}]MB", 512.0f); - } - - @Test - void checkCriticalFreeMemory() - { - when(xwiki.maxMemory()).thenReturn((long) (1.7 * Math.pow(1024, 3))); - when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); - when(xwiki.freeMemory()).thenReturn((long) (0.2 * Math.pow(1024, 3))); - - assertEquals("There are memory issues!", memoryHealthCheck.check().getErrorMessage()); - verify(logger).info("Cache status OK"); - verify(logger).error( - "Your JVM instance has only [{}]MB free memory left! Consult the solution link for support!", 409.6001f); - } - - @Test - void checkLowFreeMemory() - { - when(xwiki.maxMemory()).thenReturn((long) (2 * Math.pow(1024, 3))); - when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); - when(xwiki.freeMemory()).thenReturn((long) (0.2 * Math.pow(1024, 3))); - - assertNull(memoryHealthCheck.check().getErrorMessage()); - verify(logger).info("Cache status OK"); - verify(logger).warn("Your instance memory is running low. Currently only [{}]MB free left.", 716.80005f); - } -} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java index 26406476..259ad94d 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java @@ -19,6 +19,7 @@ */ package com.xwiki.admintools.internal.health.checks.configuration; +import java.util.List; import java.util.Map; import javax.inject.Named; @@ -28,9 +29,7 @@ import org.mockito.Mock; import org.slf4j.Logger; import org.xwiki.component.manager.ComponentLookupException; -import org.xwiki.component.manager.ComponentManager; import org.xwiki.component.util.ReflectionUtils; -import org.xwiki.localization.ContextualLocalizationManager; import org.xwiki.test.annotation.BeforeComponent; import org.xwiki.test.junit5.mockito.ComponentTest; import org.xwiki.test.junit5.mockito.InjectMockComponents; @@ -38,9 +37,9 @@ import com.xwiki.admintools.DataProvider; import com.xwiki.admintools.internal.data.ConfigurationDataProvider; +import com.xwiki.admintools.internal.data.identifiers.CurrentServer; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -48,20 +47,14 @@ class ConfigurationDatabaseHealthCheckTest { @MockComponent - private static DataProvider firstDataProvider; - - @MockComponent - private static DataProvider secondDataProvider; - - @MockComponent - private static ContextualLocalizationManager localization; + @Named(ConfigurationDataProvider.HINT) + private static DataProvider configurationDataProvider; @InjectMockComponents private ConfigurationDatabaseHealthCheck databaseHealthCheck; @MockComponent - @Named("context") - private ComponentManager contextComponentManager; + private CurrentServer currentServer; @Mock private Logger logger; @@ -69,50 +62,42 @@ class ConfigurationDatabaseHealthCheckTest @BeforeComponent static void setUp() throws Exception { - Map<String, String> jsonResponse = Map.of("databaseName", "testDBName"); - when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); - when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); - - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.info")).thenReturn( - "Database status OK"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.database.warn")).thenReturn( - "Database not found!"); + Map<String, String> jsonResponse = Map.of("databaseName", "MYSQL"); + when(configurationDataProvider.getDataAsJSON()).thenReturn(jsonResponse); } @BeforeEach void beforeEach() throws ComponentLookupException { + List<String> supportedDatabases = List.of("MySQL", "HSQL"); + when(currentServer.getSupportedDBs()).thenReturn(supportedDatabases); when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(databaseHealthCheck, "logger", this.logger); - - when(contextComponentManager.getInstance(DataProvider.class, ConfigurationDataProvider.HINT)).thenReturn( - firstDataProvider); - when(contextComponentManager.getInstance(DataProvider.class, "second")).thenReturn(secondDataProvider); } @Test void check() { - assertNull(databaseHealthCheck.check().getErrorMessage()); - verify(logger).info("Database status OK"); + assertEquals("adminTools.dashboard.healthcheck.database.info", databaseHealthCheck.check().getMessage()); } @Test - void checkNullProvider() throws ComponentLookupException + void checkNullJson() throws Exception { - when(contextComponentManager.getInstance(DataProvider.class, ConfigurationDataProvider.HINT)).thenReturn( - null); + when(configurationDataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); - assertEquals("database_not_detected", databaseHealthCheck.check().getErrorMessage()); + assertEquals("adminTools.dashboard.healthcheck.database.warn", databaseHealthCheck.check().getMessage()); verify(logger).warn("Database not found!"); } @Test - void checkNullJson() throws Exception + void checkDatabaseNotCompatible() throws Exception { - when(firstDataProvider.getDataAsJSON()).thenThrow(new Exception("error while ggenerating the json")); + Map<String, String> jsonResponse = Map.of("databaseName", "NOT_COMPATIBLE"); + when(configurationDataProvider.getDataAsJSON()).thenReturn(jsonResponse); - assertEquals("database_not_detected", databaseHealthCheck.check().getErrorMessage()); - verify(logger).warn("Database not found!"); + assertEquals("adminTools.dashboard.healthcheck.database.notSupported", + databaseHealthCheck.check().getMessage()); + verify(logger).error("Used database is not supported!"); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java index 628b837d..4e7152ba 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java @@ -28,10 +28,7 @@ import org.mockito.Mock; import org.slf4j.Logger; import org.xwiki.component.manager.ComponentLookupException; -import org.xwiki.component.manager.ComponentManager; import org.xwiki.component.util.ReflectionUtils; -import org.xwiki.localization.ContextualLocalizationManager; -import org.xwiki.test.annotation.BeforeComponent; import org.xwiki.test.junit5.mockito.ComponentTest; import org.xwiki.test.junit5.mockito.InjectMockComponents; import org.xwiki.test.junit5.mockito.MockComponent; @@ -40,7 +37,6 @@ import com.xwiki.admintools.internal.data.ConfigurationDataProvider; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -48,73 +44,37 @@ class ConfigurationJavaHealthCheckTest { @MockComponent - private static DataProvider firstDataProvider; - - @MockComponent - private static DataProvider secondDataProvider; - - @MockComponent - private static ContextualLocalizationManager localization; + @Named(ConfigurationDataProvider.HINT) + private static DataProvider dataProvider; @InjectMockComponents private ConfigurationJavaHealthCheck javaHealthCheck; - @MockComponent - @Named("context") - private ComponentManager contextComponentManager; - @Mock private Logger logger; - @BeforeComponent - static void setUp() throws Exception - { - when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); - - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.info")).thenReturn( - "Java status OK"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.found")).thenReturn( - "Java version not found!"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.java.warn.incompatible")).thenReturn( - "Java version is not compatible with the current XWiki installation!"); - } - @BeforeEach void beforeEach() throws Exception { when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(javaHealthCheck, "logger", this.logger); - when(contextComponentManager.getInstance(DataProvider.class, ConfigurationDataProvider.HINT)).thenReturn( - firstDataProvider); - when(contextComponentManager.getInstance(DataProvider.class, "second")).thenReturn(secondDataProvider); Map<String, String> jsonResponse = Map.of("javaVersion", "11.0.2", "xwikiVersion", "14.10.2"); - when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); + when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); } @Test void check() { - assertNull(javaHealthCheck.check().getErrorMessage()); - verify(logger).info("Java status OK"); - } - - @Test - void checkNullProvider() throws ComponentLookupException - { - when(contextComponentManager.getInstance(DataProvider.class, ConfigurationDataProvider.HINT)).thenReturn( - null); - - assertEquals("java_version_not_found", javaHealthCheck.check().getErrorMessage()); - verify(logger).warn("Java version not found!"); + assertEquals("adminTools.dashboard.healthcheck.java.info", javaHealthCheck.check().getMessage()); } @Test void checkNullJson() throws Exception { - when(firstDataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); + when(dataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); - assertEquals("java_version_not_found", javaHealthCheck.check().getErrorMessage()); + assertEquals("adminTools.dashboard.healthcheck.java.warn", javaHealthCheck.check().getMessage()); verify(logger).warn("Java version not found!"); } @@ -122,8 +82,8 @@ void checkNullJson() throws Exception void checkJavaVersionIncompatible() throws Exception { Map<String, String> jsonResponse = Map.of("javaVersion", "11.0.2", "xwikiVersion", "6.10.2"); - when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); - assertEquals("java_xwiki_not_compatible", javaHealthCheck.check().getErrorMessage()); - verify(logger).warn("Java version is not compatible with the current XWiki installation!"); + when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); + assertEquals("adminTools.dashboard.healthcheck.java.error", javaHealthCheck.check().getMessage()); + verify(logger).error("Java version is not compatible with the current XWiki installation!"); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java index d611bace..9c8d58a6 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java @@ -28,9 +28,7 @@ import org.mockito.Mock; import org.slf4j.Logger; import org.xwiki.component.manager.ComponentLookupException; -import org.xwiki.component.manager.ComponentManager; import org.xwiki.component.util.ReflectionUtils; -import org.xwiki.localization.ContextualLocalizationManager; import org.xwiki.test.annotation.BeforeComponent; import org.xwiki.test.junit5.mockito.ComponentTest; import org.xwiki.test.junit5.mockito.InjectMockComponents; @@ -48,21 +46,12 @@ class ConfigurationOsHealthCheckTest { @MockComponent - private static DataProvider firstDataProvider; - - @MockComponent - private static DataProvider secondDataProvider; - - @MockComponent - private static ContextualLocalizationManager localization; + @Named(ConfigurationDataProvider.HINT) + private static DataProvider dataProvider; @InjectMockComponents private ConfigurationOsHealthCheck osHealthCheck; - @MockComponent - @Named("context") - private ComponentManager contextComponentManager; - @Mock private Logger logger; @@ -71,13 +60,7 @@ static void setUp() throws Exception { Map<String, String> jsonResponse = Map.of("osName", "testDBName", "osVersion", "os_version", "osArch", "os_arch"); - when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); - when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); - - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.os.info")).thenReturn( - "OS info retrieval OK"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.os.warn")).thenReturn( - "There has been an error while gathering OS info!"); + when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); } @BeforeEach @@ -85,25 +68,20 @@ void beforeEach() throws ComponentLookupException { when(logger.isWarnEnabled()).thenReturn(true); ReflectionUtils.setFieldValue(osHealthCheck, "logger", this.logger); - - when(contextComponentManager.getInstance(DataProvider.class, ConfigurationDataProvider.HINT)).thenReturn( - firstDataProvider); - when(contextComponentManager.getInstance(DataProvider.class, "second")).thenReturn(secondDataProvider); } @Test void check() { - assertNull(osHealthCheck.check().getErrorMessage()); - verify(logger).info("OS info retrieval OK"); + assertEquals("adminTools.dashboard.healthcheck.os.info", osHealthCheck.check().getMessage()); } @Test void checkNullJson() throws Exception { - when(firstDataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); + when(dataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); - assertEquals("os_issue", osHealthCheck.check().getErrorMessage()); + assertEquals("adminTools.dashboard.healthcheck.os.warn", osHealthCheck.check().getMessage()); verify(logger).warn("There has been an error while gathering OS info!"); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheckTest.java deleted file mode 100644 index 843465ea..00000000 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/SecurityEncodingHealthCheckTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package com.xwiki.admintools.internal.health.checks.configuration; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.inject.Named; -import javax.inject.Provider; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.slf4j.Logger; -import org.xwiki.component.manager.ComponentManager; -import org.xwiki.component.util.ReflectionUtils; -import org.xwiki.localization.ContextualLocalizationManager; -import org.xwiki.test.annotation.BeforeComponent; -import org.xwiki.test.junit5.mockito.ComponentTest; -import org.xwiki.test.junit5.mockito.InjectMockComponents; -import org.xwiki.test.junit5.mockito.MockComponent; - -import com.xwiki.admintools.DataProvider; -import com.xwiki.admintools.internal.data.SecurityDataProvider; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ComponentTest -class SecurityEncodingHealthCheckTest -{ - @MockComponent - private static Provider<List<DataProvider>> dataProviders; - - @MockComponent - private static DataProvider firstDataProvider; - - @MockComponent - private static DataProvider secondDataProvider; - - @MockComponent - private static ContextualLocalizationManager localization; - - @InjectMockComponents - private SecurityEncodingHealthCheck systemEncodingHealthCheck; - - @MockComponent - @Named("context") - private ComponentManager contextComponentManager; - - @Mock - private Logger logger; - - @BeforeComponent - static void setUp() throws Exception - { - List<DataProvider> dataProviderList = new ArrayList<>(); - dataProviderList.add(firstDataProvider); - dataProviderList.add(secondDataProvider); - when(dataProviders.get()).thenReturn(dataProviderList); - - when(secondDataProvider.getDataAsJSON()).thenThrow(new Exception("DATA PROVIDE ERROR")); - - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.info")).thenReturn( - "System encoding OK"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.lang.warn")).thenReturn( - "System language encoding is [{}] but should be UTF-8!"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.system.file.warn")).thenReturn( - "System file encoding is [{}] but should be UTF-8!"); - when(localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.xwiki.info")).thenReturn( - "XWiki encoding OK"); - when( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.xwiki.active.warn")).thenReturn( - "XWiki active encoding is [{}] but should be UTF-8!"); - when( - localization.getTranslationPlain("adminTools.dashboard.healthcheck.security.xwiki.config.warn")).thenReturn( - "XWiki configuration encoding is [{}] but should be UTF-8!"); - } - - @BeforeEach - void beforeEach() throws Exception - { - when(logger.isWarnEnabled()).thenReturn(true); - ReflectionUtils.setFieldValue(systemEncodingHealthCheck, "logger", this.logger); - - when(firstDataProvider.getIdentifier()).thenReturn(SecurityDataProvider.HINT); - when(secondDataProvider.getIdentifier()).thenReturn("second"); - Map<String, String> jsonResponse = - Map.of("LANG", "en.UTF8", "fileEncoding", "UTF8", "activeEncoding", "UTF8", "configurationEncoding", - "UTF8"); - when(contextComponentManager.getInstance(DataProvider.class, "security")).thenReturn(firstDataProvider); - when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); - } - - @Test - void check() - { - assertNull(systemEncodingHealthCheck.check().getErrorMessage()); - verify(logger).info("System encoding OK"); - } - - @Test - void checkNullJson() throws Exception - { - when(firstDataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); - - assertEquals("xwiki_encoding_err", systemEncodingHealthCheck.check().getErrorMessage()); - verify(logger).warn("System language encoding is [{}] but should be UTF-8!", "invalid"); - verify(logger).warn("System file encoding is [{}] but should be UTF-8!", "INVALID"); - verify(logger).warn("XWiki configuration encoding is [{}] but should be UTF-8!", "INVALID"); - verify(logger).warn("XWiki active encoding is [{}] but should be UTF-8!", "INVALID"); - } - - @Test - void checkUnsafeEncoding() throws Exception - { - Map<String, String> jsonResponse = - Map.of("LANG", "en.UTF8", "fileEncoding", "ISO-8859-1", "activeEncoding", "UTF8", "configurationEncoding", - "ISO-8859-1"); - when(firstDataProvider.getDataAsJSON()).thenReturn(jsonResponse); - assertEquals("xwiki_encoding_err", systemEncodingHealthCheck.check().getErrorMessage()); - verify(logger).warn("System file encoding is [{}] but should be UTF-8!", "ISO-8859-1"); - verify(logger).warn("XWiki configuration encoding is [{}] but should be UTF-8!", - "ISO-8859-1"); - } -} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/memory/CacheMemoryHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/memory/CacheMemoryHealthCheckTest.java new file mode 100644 index 00000000..f63ff7dd --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/memory/CacheMemoryHealthCheckTest.java @@ -0,0 +1,82 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.memory; + +import javax.inject.Named; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.configuration.ConfigurationSource; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +class CacheMemoryHealthCheckTest +{ + @InjectMockComponents + private CacheMemoryHealthCheck cacheMemoryHealthCheck; + + @MockComponent + @Named("xwikicfg") + private ConfigurationSource configurationSource; + + @Mock + private Logger logger; + + @BeforeEach + void beforeEach() + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(cacheMemoryHealthCheck, "logger", this.logger); + + } + + @Test + void check() + { + when(configurationSource.getProperty("xwiki.store.cache.capacity")).thenReturn("1000"); + assertEquals("adminTools.dashboard.healthcheck.memory.cache.info", cacheMemoryHealthCheck.check().getMessage()); + } + + @Test + void checkCacheLow() + { + when(configurationSource.getProperty("xwiki.store.cache.capacity")).thenReturn("400"); + assertEquals("adminTools.dashboard.healthcheck.memory.cache.low", cacheMemoryHealthCheck.check().getMessage()); + verify(logger).warn("Store cache capacity is set to [{}].", "400"); + } + + + @Test + void checkCacheNotDefined() + { + when(configurationSource.getProperty("xwiki.store.cache.capacity")).thenReturn(null); + assertEquals("adminTools.dashboard.healthcheck.memory.cache.null", cacheMemoryHealthCheck.check().getMessage()); + verify(logger).warn("Store cache capacity not defined. Set by default at 500."); + } +} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/memory/MemoryHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/memory/MemoryHealthCheckTest.java new file mode 100644 index 00000000..e8e3e5ff --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/memory/MemoryHealthCheckTest.java @@ -0,0 +1,110 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.memory; + +import javax.inject.Provider; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xpn.xwiki.XWiki; +import com.xpn.xwiki.XWikiContext; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +class MemoryHealthCheckTest +{ + @InjectMockComponents + private MemoryHealthCheck memoryHealthCheck; + + @MockComponent + private Provider<XWikiContext> xcontextProvider; + + @MockComponent + private XWikiContext context; + + @Mock + private XWiki xwiki; + + @Mock + private Logger logger; + + @BeforeEach + void beforeEach() + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(memoryHealthCheck, "logger", this.logger); + + when(xcontextProvider.get()).thenReturn(context); + when(context.getWiki()).thenReturn(xwiki); + } + + @Test + void check() + { + when(xwiki.maxMemory()).thenReturn((long) (8 * Math.pow(1024, 3))); + when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); + when(xwiki.freeMemory()).thenReturn((long) (0.5 * Math.pow(1024, 3))); + + assertEquals("adminTools.dashboard.healthcheck.memory.info", memoryHealthCheck.check().getMessage()); + } + + @Test + void checkInsufficientMaxMemory() + { + when(xwiki.maxMemory()).thenReturn((long) (0.8 * Math.pow(1024, 3))); + when(xwiki.totalMemory()).thenReturn((long) (0.5 * Math.pow(1024, 3))); + when(xwiki.freeMemory()).thenReturn((long) (0.2 * Math.pow(1024, 3))); + + assertEquals("adminTools.dashboard.healthcheck.memory.maxcapacity.error", + memoryHealthCheck.check().getMessage()); + } + + @Test + void checkCriticalFreeMemory() + { + when(xwiki.maxMemory()).thenReturn((long) (1.7 * Math.pow(1024, 3))); + when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); + when(xwiki.freeMemory()).thenReturn((long) (0.2 * Math.pow(1024, 3))); + + assertEquals("adminTools.dashboard.healthcheck.memory.free.error", memoryHealthCheck.check().getMessage()); + logger.error("JVM instance has only [{}]MB free memory left!", 409.6001f); + } + + @Test + void checkLowFreeMemory() + { + when(xwiki.maxMemory()).thenReturn((long) (2 * Math.pow(1024, 3))); + when(xwiki.totalMemory()).thenReturn((long) (1.5 * Math.pow(1024, 3))); + when(xwiki.freeMemory()).thenReturn((long) (0.2 * Math.pow(1024, 3))); + + assertEquals("adminTools.dashboard.healthcheck.memory.free.warn", memoryHealthCheck.check().getMessage()); + verify(logger).warn("Instance memory is running low. Currently only [{}]MB free left.", 716.80005f); + } +} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheckTest.java new file mode 100644 index 00000000..5282d3b1 --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheckTest.java @@ -0,0 +1,92 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.security; + +import java.util.Map; + +import javax.inject.Named; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xwiki.admintools.DataProvider; +import com.xwiki.admintools.internal.data.SecurityDataProvider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +class ActiveEncodingHealthCheckTest +{ + @InjectMockComponents + private ActiveEncodingHealthCheck activeEncodingHealthCheck; + + @MockComponent + @Named(SecurityDataProvider.HINT) + private DataProvider dataProvider; + + @Mock + private Logger logger; + + @BeforeEach + void beforeEach() throws Exception + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(activeEncodingHealthCheck, "logger", this.logger); + + when(dataProvider.getIdentifier()).thenReturn(SecurityDataProvider.HINT); + Map<String, String> jsonResponse = Map.of("activeEncoding", "UTF8"); + when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); + } + + @Test + void check() + { + assertEquals("adminTools.dashboard.healthcheck.security.xwiki.active.info", + activeEncodingHealthCheck.check().getMessage()); + } + + @Test + void checkNullJson() throws Exception + { + when(dataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); + + assertEquals("adminTools.dashboard.healthcheck.security.xwiki.active.notFound", + activeEncodingHealthCheck.check().getMessage()); + logger.warn("Active encoding could not be detected!"); + } + + @Test + void checkUnsafeEncoding() throws Exception + { + Map<String, String> jsonResponse = Map.of("activeEncoding", "ISO-8859-1"); + when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); + assertEquals("adminTools.dashboard.healthcheck.security.xwiki.active.warn", + activeEncodingHealthCheck.check().getMessage()); + verify(logger).warn("XWiki active encoding is [{}], but should be UTF-8!", "ISO-8859-1"); + } +} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheckTest.java new file mode 100644 index 00000000..2074ad9d --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheckTest.java @@ -0,0 +1,92 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.security; + +import java.util.Map; + +import javax.inject.Named; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xwiki.admintools.DataProvider; +import com.xwiki.admintools.internal.data.SecurityDataProvider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +class ConfigurationEncodingHealthCheckTest +{ + @InjectMockComponents + private ConfigurationEncodingHealthCheck configurationEncodingHealthCheck; + + @MockComponent + @Named(SecurityDataProvider.HINT) + private DataProvider dataProvider; + + @Mock + private Logger logger; + + @BeforeEach + void beforeEach() throws Exception + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(configurationEncodingHealthCheck, "logger", this.logger); + + when(dataProvider.getIdentifier()).thenReturn(SecurityDataProvider.HINT); + Map<String, String> jsonResponse = Map.of("configurationEncoding", "UTF8"); + when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); + } + + @Test + void check() + { + assertEquals("adminTools.dashboard.healthcheck.security.xwiki.config.info", + configurationEncodingHealthCheck.check().getMessage()); + } + + @Test + void checkNullJson() throws Exception + { + when(dataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); + + assertEquals("adminTools.dashboard.healthcheck.security.xwiki.config.notFound", + configurationEncodingHealthCheck.check().getMessage()); + logger.warn("Configuration encoding could not be detected!"); + } + + @Test + void checkUnsafeEncoding() throws Exception + { + Map<String, String> jsonResponse = Map.of("configurationEncoding", "ISO-8859-1"); + when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); + assertEquals("adminTools.dashboard.healthcheck.security.xwiki.config.warn", + configurationEncodingHealthCheck.check().getMessage()); + verify(logger).warn("XWiki configuration encoding is [{}], but should be UTF-8!", "ISO-8859-1"); + } +} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheckTest.java new file mode 100644 index 00000000..b433a486 --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheckTest.java @@ -0,0 +1,92 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.security; + +import java.util.Map; + +import javax.inject.Named; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xwiki.admintools.DataProvider; +import com.xwiki.admintools.internal.data.SecurityDataProvider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +class FileEncodingHealthCheckTest +{ + @InjectMockComponents + private FileEncodingHealthCheck fileEncodingHealthCheck; + + @MockComponent + @Named(SecurityDataProvider.HINT) + private DataProvider dataProvider; + + @Mock + private Logger logger; + + @BeforeEach + void beforeEach() throws Exception + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(fileEncodingHealthCheck, "logger", this.logger); + + when(dataProvider.getIdentifier()).thenReturn(SecurityDataProvider.HINT); + Map<String, String> jsonResponse = Map.of("fileEncoding", "UTF8"); + when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); + } + + @Test + void check() + { + assertEquals("adminTools.dashboard.healthcheck.security.system.file.info", + fileEncodingHealthCheck.check().getMessage()); + } + + @Test + void checkNullJson() throws Exception + { + when(dataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); + + assertEquals("adminTools.dashboard.healthcheck.security.system.file.notFound", + fileEncodingHealthCheck.check().getMessage()); + logger.warn("File encoding could not be detected!"); + } + + @Test + void checkUnsafeEncoding() throws Exception + { + Map<String, String> jsonResponse = Map.of("fileEncoding", "ISO-8859-1"); + when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); + assertEquals("adminTools.dashboard.healthcheck.security.system.file.warn", + fileEncodingHealthCheck.check().getMessage()); + verify(logger).warn("System file encoding is [{}], but should be UTF-8!", "ISO-8859-1"); + } +} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheckTest.java new file mode 100644 index 00000000..448c5b46 --- /dev/null +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheckTest.java @@ -0,0 +1,92 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.security; + +import java.util.Map; + +import javax.inject.Named; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.xwiki.component.util.ReflectionUtils; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; +import org.xwiki.test.junit5.mockito.MockComponent; + +import com.xwiki.admintools.DataProvider; +import com.xwiki.admintools.internal.data.SecurityDataProvider; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ComponentTest +class LangEncodingHealthCheckTest +{ + @InjectMockComponents + private LangEncodingHealthCheck langEncodingHealthCheck; + + @MockComponent + @Named(SecurityDataProvider.HINT) + private DataProvider dataProvider; + + @Mock + private Logger logger; + + @BeforeEach + void beforeEach() throws Exception + { + when(logger.isWarnEnabled()).thenReturn(true); + ReflectionUtils.setFieldValue(langEncodingHealthCheck, "logger", this.logger); + + when(dataProvider.getIdentifier()).thenReturn(SecurityDataProvider.HINT); + Map<String, String> jsonResponse = Map.of("LANG", "en.UTF8"); + when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); + } + + @Test + void check() + { + assertEquals("adminTools.dashboard.healthcheck.security.system.lang.info", + langEncodingHealthCheck.check().getMessage()); + } + + @Test + void checkNullJson() throws Exception + { + when(dataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); + + assertEquals("adminTools.dashboard.healthcheck.security.system.lang.notFound", + langEncodingHealthCheck.check().getMessage()); + logger.warn("Language encoding could not be detected!"); + } + + @Test + void checkUnsafeEncoding() throws Exception + { + Map<String, String> jsonResponse = Map.of("LANG", "en.ISO-8859-1"); + when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); + assertEquals("adminTools.dashboard.healthcheck.security.system.lang.warn", + langEncodingHealthCheck.check().getMessage()); + verify(logger).warn("System language encoding is [{}], but should be UTF-8!", "ISO-8859-1"); + } +} diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java index 512b2561..8635b67d 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java @@ -74,6 +74,6 @@ void runInternal() healthCheckJob.initialize(new HealthCheckJobRequest()); healthCheckJob.runInternal(); HealthCheckJobStatus healthCheckJobStatus = healthCheckJob.getStatus(); - assertEquals(1, healthCheckJobStatus.getHealthCheckResults().size()); + assertEquals(2, healthCheckJobStatus.getHealthCheckResults().size()); } } diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index 6c739260..74a57ae6 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -197,6 +197,10 @@ } }); + $(document).on('click', '.log-item-warn', function(event) { + $(this).children(".recommendation").toggle(); + }); + $(document).on('click', '#admin_tools_job_start', function(event) { event.preventDefault(); $(".log").empty(); @@ -214,6 +218,7 @@ const link = document.createElement('a'); link.href = downloadForm.attr('action') + '?' + downloadForm.serialize(); link.click(); + $(event.currentTarget).closest('.modal').modal('toggle'); }); $(document).on('click', '#filesViewLastNLinesModal .btn-primary, #configurationViewLastNLinesModal .btn-primary', diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml index 4250a297..b4f8cd17 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml @@ -38,13 +38,13 @@ <hidden>true</hidden> <content>{{velocity}} #template('job_macros.vm') -#includeMacros("AdminTools.Code.Macros") +#includeMacros("AdminTools.Code.HealthCheckMacros") #set($jobId = $request.getParameterValues('jobId')) #set($jobStatus = $services.job.getJobStatus($jobId)) #if ($jobStatus) - #outputJobStatusJSON($jobStatus) + #healthCheckOutputJobStatus($jobStatus) #else $response.setStatus(404) #error($escapetool.xml($services.localization.render("admintools.job.notFound"))) diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckMacros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckMacros.xml new file mode 100644 index 00000000..e37a342f --- /dev/null +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckMacros.xml @@ -0,0 +1,177 @@ +<?xml version="1.1" encoding="UTF-8"?> + +<!-- + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. +--> + +<xwikidoc version="1.5" reference="AdminTools.Code.HealthCheckMacros" locale=""> + <web>AdminTools.Code</web> + <name>HealthCheckMacros</name> + <language/> + <defaultLanguage/> + <translation>0</translation> + <creator>xwiki:XWiki.Admin</creator> + <parent>AdminTools.WebHome</parent> + <author>xwiki:XWiki.Admin</author> + <contentAuthor>xwiki:XWiki.Admin</contentAuthor> + <version>1.1</version> + <title>HealthCheckMacros + + false + xwiki/2.1 + true + {{velocity output='false'}} +#macro (getHealthCheckJobStatusJSON $status $json) + #set ($results = []) + #foreach ($logEvent in $status.getHealthCheckResults()) + #set ($discard = $results.add({ + 'level': $logEvent.getLevel(), + 'renderedMessage': "#printResult($logEvent)" + })) + #end + #set ($json = $NULL) + #setVariable("$json" { + 'id': $status.request.id, + 'state': $status.state, + 'progress': { + 'offset': $status.progress.offset + }, + 'log': { + 'offset': 0, + 'items': $results + } + }) +#end + +#macro (healthCheckOutputJobStatus $jobStatus) + #getHealthCheckJobStatusJSON($jobStatus, $json, $translationPrefix) + #set ($json.message = "#healthCheckJobFinishedMessage($jobStatus)") + $response.setContentType('application/json') + $jsontool.serialize($json) +#end + +#macro (healthCheckJobFinishedMessage $status) + #if ($status.error) + #set($messageKeys = ["job.status.${status.jobType}.error", 'job.status.error']) + #set($healthCheckReportMessage = $services.localization.render($messageKeys)) + #set($messageClass = 'errormessage') + #elseif ($status.hasErrorLevel('error')) + #set($healthCheckReportMessage = 'Critical issues were found, please consult the log!') + #set($messageClass = 'errormessage') + #elseif ($status.hasErrorLevel('warn')) + #set($healthCheckReportMessage = 'Some issues have been found, for more details please see the log.') + #set($messageClass = 'warningmessage') + #else + #set($healthCheckReportMessage = 'No issue found!') + #set($messageClass = 'successmessage') + #end + <div class="box $messageClass"> + $healthCheckReportMessage + </div> +#end + +#macro (printResult $healthCheckResult) + <div style="cursor: pointer;">$escapetool.xml($services.localization.render($healthCheckResult.getErrorMessage())) + #if ($healthCheckResult.getCurrentValue()) $escapetool.xml($services.localization.render( + 'adminTools.dashboard.healthcheck.currentValue')) $healthCheckResult.getCurrentValue()#end</div> + #if($healthCheckResult.getRecommendation()) + <div class="recommendation" style="cursor: pointer;"> + $escapetool.xml($services.localization.render($healthCheckResult.getRecommendation()))</div> + #end +#end + +#macro (printHealthCheckResults $status) + #if ($status.state != 'FINISHED') + #set($loading = true) + #end + #set($healthCheckResults = $status.getHealthCheckResults()) + <ul class="log"> + #foreach ($healthCheckResult in $healthCheckResults) + #set ($resultLevel = $healthCheckResult.getLevel()) + ## Display the last log item as loading if the associated task is not finished. + <li class="log-item log-item-${resultLevel}#if ($loading && !$foreach.hasNext) log-item-loading#end"> + #printResult($healthCheckResult) + </li> + #end + </ul> +#end + +#macro (displayHealthCheckResults $status $collapsed) + <dl class="xform"> + ## Collapse the job log if the job is waiting for user input (leave more space for the job question). + <dt> + <label class="collapse-toggle#if ($collapsed || $status.state == 'WAITING') collapsed#end" + data-target-xpath="parent::*/following-sibling::*"> + <span class="icon-closed">$services.icon.renderHTML('caret-right')</span> + <span class="icon-opened">$services.icon.renderHTML('caret-down')</span> + Health Check Results + </label> + </dt> + <dd>#printHealthCheckResults($status)</dd> + </dl> +#end + +#macro (healthCheckUI) + #set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) + #set ($jobId = ['adminTools', 'healthcheck', $services.wiki.getCurrentWikiId()]) + #set ($healthJobStatusURL = $xwiki.getURL('AdminTools.Code.HealthCheckJob', 'get', $escapetool.url({ + 'jobId': $jobId, + 'outputSyntax': 'plain' + }))) + #set ($healthJobStatus = $services.job.getJobStatus($jobId)) + #set ($solutionLink = $xwiki.getURL('AdminTools.HelpLinks')) + #set ($description = $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.description', [ + '__STARTLINK__', + '__ENDLINK__' + ])).replace('__STARTLINK__', "<a href='$solutionLink'><strong>").replace('__ENDLINK__', ' + </strong></a>')) + <jobState + data-state="${healthJobStatus.state}" + </jobState> + <input type="hidden" name="jobState" value="${healthJobStatus.state}"></input> + <div class="adminToolsDashboardItem" id="healthCheck"> + <h2>$services.icon.renderHTML('bug') + $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.title'))</h2> + <p>$description</p> + <hr/> + <div class="healthCheckWrapper"> + <div class="healthCheckLastCheck"> + $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.time')): + $services.date.displayTimeAgo($healthJobStatus.getEndDate()) + </div> + <div class="buttonwrapper"> + <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" + value="startHealthCheck">$escapetool.xml($services.localization.render( + 'adminTools.dashboard.healthcheck.start'))</button> + </div> + </div> + <div hidden class="xcontent job-status" data-url="${healthJobStatusURL}"> + #if ($healthJobStatus.state != 'FINISHED') + #displayJobProgressBar($healthJobStatus) + #else + #healthCheckJobFinishedMessage($healthJobStatus, $translationPrefix, $successKey, $errorKey, $canceledKey) + #end + #if ($showLogs || $isAdvancedUser || $isSuperAdmin || $isAdmin) + #displayHealthCheckResults($healthJobStatus true) + #end + </div> + </div> +#end +{{/velocity}} + diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml index 428d97c3..fe38c4c9 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml @@ -61,6 +61,7 @@ <jobJsURL data-url="${jobMinJsURL}" </jobJsURL> + ## MOVE TO MACRO #displayJobProgressBar($healthJobStatus) </div> {{/html}} @@ -78,6 +79,7 @@ #elseif ($request.data == 'jobStatus') #set ($healthCheckJobId = $request.jobId.split('/')) #returnHealthCheckJobStatusJSON($healthCheckJobId) + ## TO BE REMOVED #else #getHealthCheckResources() #end diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml index 6678b284..0be60386 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Macros.xml @@ -74,7 +74,6 @@ </div> </div> #end - #macro (downloadArchiveModal) <div class="modal fade" id="downloadFilesModal" tabindex="-1" role="dialog" aria-labelledby= "downloadFilesModalLabel"> @@ -153,84 +152,5 @@ </div> </div> #end - -#macro (jobFinishedMessage $status $translationPrefix $successKey $errorKey $canceledKey $warningKey) - #if ($status.error) - #set($messageKeys = [$errorKey, "${translationPrefix}.finish.error", "job.status.${status.jobType}.error", - 'job.status.error']) - #set($healthCheckReportMessage = $services.localization.render($messageKeys)) - #set($messageClass = 'errormessage') - #elseif ($status.canceled) - #set($messageKeys = [$canceledKey, "${translationPrefix}.finish.canceled", "job.status.${status.jobType}.canceled", - 'job.status.canceled']) - #set($healthCheckReportMessage = $services.localization.render($messageKeys)) - #set($messageClass = 'warningmessage') - #elseif ($status.logTail.hasLogLevel('error')) - #set($healthCheckReportMessage = 'Critical issues were found, please consult the log!') - #set($messageClass = 'errormessage') - #elseif ($status.logTail.hasLogLevel('warn')) - #set($healthCheckReportMessage = 'Some issues have been found, for more details please see the log.') - #set($messageClass = 'warningmessage') - #else - #set($healthCheckReportMessage = 'No issue found!') - #set($messageClass = 'successmessage') - #end - <div class="box $messageClass"> - $healthCheckReportMessage - </div> -#end - -#macro (healthCheckUI) - #set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) - #set ($jobId = ['adminTools', 'healthcheck', $services.wiki.getCurrentWikiId()]) - #set ($healthJobStatusURL = $xwiki.getURL('AdminTools.Code.HealthCheckJob', 'get', $escapetool.url({ - 'jobId': $jobId, - 'outputSyntax': 'plain' - }))) - #if ($jobId) - #set ($healthJobStatus = $services.job.getJobStatus($jobId)) - #end - #set($solutionLink = $xwiki.getURL('AdminTools.HelpLinks')) - #set ($description = $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.description', [ - '__STARTLINK__', - '__ENDLINK__' - ])).replace('__STARTLINK__', "<a href='$solutionLink'><strong>").replace('__ENDLINK__', ' - </strong></a>')) - <jobState - data-state="${healthJobStatus.state}" - </jobState> - <input type="hidden" name="jobState" value="${healthJobStatus.state}"></input> - <div class="adminToolsDashboardItem" id="healthCheck"> - <h2>$services.icon.renderHTML('bug') - $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.title'))</h2> - <p>$description</p> - <hr/> - <div class="healthCheckWrapper"> - <div class="healthCheckLastCheck"> - $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.time')): - $services.date.displayTimeAgo($healthJobStatus.getEndDate()) - </div> - <div class="buttonwrapper"> - <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" - value="startHealthCheck">$escapetool.xml($services.localization.render( - 'adminTools.dashboard.healthcheck.start'))</button> - </div> - </div> - <div hidden class="xcontent job-status" data-url="${healthJobStatusURL}"> - #if ($healthJobStatus.state != 'FINISHED') - #displayJobProgressBar($jobStatus) - #else - #jobFinishedMessage($healthJobStatus, $translationPrefix, $successKey, $errorKey, $canceledKey) - #end - #if ($showLogs || $isAdvancedUser || $isSuperAdmin) - #if ($healthJobStatus.state != 'FINISHED') - #displayJobStatusLog($jobStatus true) - #else - #displayJobStatusLog($healthJobStatus true) - #end - #end - </div> - </div> -#end {{/velocity}} diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml index 6c3a29d7..cd187a2a 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml @@ -70,34 +70,55 @@ adminTools.dashboard.download.view.properties=XWiki properties file adminTools.dashboard.download.warning=Before downloading and sending the files, please make sure you introduced the lines that may contain sensitive info in Admin Tools configuration page! ## Health check -adminTools.dashboard.healthcheck.database.info=Database status OK +adminTools.dashboard.healthcheck.database.info=Database status OK. adminTools.dashboard.healthcheck.database.warn=Database not found! -adminTools.dashboard.healthcheck.description=Check if your instance is configured correctly and is properly running. For any issues, check out this {0}solutions{1}. -adminTools.dashboard.healthcheck.java.info=Java status OK -adminTools.dashboard.healthcheck.java.warn.found=Java version not found! -adminTools.dashboard.healthcheck.java.warn.incompatible=Java version is not compatible with the current XWiki installation! -adminTools.dashboard.healthcheck.memory.cache.info=Cache status OK -adminTools.dashboard.healthcheck.memory.cache.null=Store cache capacity is set at 500. See cache recommendations in solutions. -adminTools.dashboard.healthcheck.memory.cache.low=Store cache capacity is set at [{}]. See cache recommendations in solutions. -adminTools.dashboard.healthcheck.memory.free.error=Your JVM instance has only [{}]MB free memory left! Consult the solution link for support! -adminTools.dashboard.healthcheck.memory.free.warn=Your instance memory is running low. Currently only [{}]MB free left. -adminTools.dashboard.healthcheck.memory.info=Memory status OK -adminTools.dashboard.healthcheck.memory.maxcapacity.error=JVM memory is less than 1024MB. Currently: [{}]MB -adminTools.dashboard.healthcheck.os.info=OS info retrieval OK +adminTools.dashboard.healthcheck.database.notSupported=Used database is not supported! +adminTools.dashboard.healthcheck.database.recommendation=The used database is currently not supported by XWiki. Check the help links to find the database compatibility requirements. +adminTools.dashboard.healthcheck.description=Check if your instance is configured correctly and is properly running. For any issues, check out this {0}help links{1}. +adminTools.dashboard.healthcheck.java.info=Java status OK. +adminTools.dashboard.healthcheck.java.warn=Java version not found! +adminTools.dashboard.healthcheck.java.warn.recommendation=Java version could not be found! Please make sure you correctly installed and configured the paths for your Java installation. For further help, consult the help links. +adminTools.dashboard.healthcheck.java.error=Java version is not compatible with the current XWiki installation! +adminTools.dashboard.healthcheck.java.error.recommendation=The current version of Java that you are using it is not compatible with the XWiki installation version. Please check the help links to view the compatibility. +adminTools.dashboard.healthcheck.memory.cache.info=Document cache status OK. +adminTools.dashboard.healthcheck.memory.cache.null=Document cache capacity currently set at 500. +adminTools.dashboard.healthcheck.memory.cache.null.recommendation=Document store cache capacity was not confiugred and is set by default to 500. See cache recommendations in help links above. +adminTools.dashboard.healthcheck.memory.cache.low=Document cache capacity is set to a low value. See cache recommendations in the help links page. +adminTools.dashboard.healthcheck.memory.free.error=Your JVM instance has less than 512MB of free memory left. +adminTools.dashboard.healthcheck.memory.free.warn=Your instance memory is running low. +adminTools.dashboard.healthcheck.memory.info=Memory status OK. +adminTools.dashboard.healthcheck.memory.maxcapacity.error=JVM memory is less than 1024MB. +adminTools.dashboard.healthcheck.memory.recommendation=Allocate more resources to you JVM! Check the help links for further help. +adminTools.dashboard.healthcheck.os.info=OS info retrieval OK. adminTools.dashboard.healthcheck.os.warn=There has been an error while gathering OS info! adminTools.dashboard.healthcheck.performance.cpu.warn=The CPU does not satisfy the minimum system requirements! -adminTools.dashboard.healthcheck.performance.info=System performance OK +adminTools.dashboard.healthcheck.performance.cpu.recommendation=The CPU should have a minimum of 2 Cores, 2800MHz frequency and 2048KB cache size. View the help page for more details. +adminTools.dashboard.healthcheck.performance.cpu.info=CPU performance OK. +adminTools.dashboard.healthcheck.performance.info=System performance OK. adminTools.dashboard.healthcheck.performance.memory.warn=There is not enough memory to safely run the XWiki installation! +adminTools.dashboard.healthcheck.performance.memory.info=System memory capacity OK. +adminTools.dashboard.healthcheck.performance.memory.recommendation=It is recommended to have at least 2GB of RAM to run XWiki. adminTools.dashboard.healthcheck.performance.space.warn=There is not enough free space for the XWiki installation! -adminTools.dashboard.healthcheck.security.system.info=System encoding OK -adminTools.dashboard.healthcheck.security.system.file.warn=System file encoding is [{}] but should be UTF-8! -adminTools.dashboard.healthcheck.security.system.lang.warn=System language encoding is [{}] but should be UTF-8! -adminTools.dashboard.healthcheck.security.xwiki.info=XWiki encoding OK -adminTools.dashboard.healthcheck.security.xwiki.active.warn=XWiki active encoding is [{}]. The encoding should be UTF-8! -adminTools.dashboard.healthcheck.security.xwiki.config.warn=XWiki configuration encoding is [{}]. The encoding should be UTF-8! +adminTools.dashboard.healthcheck.performance.space.recommendation=There should be at least 16GB of free system space. +adminTools.dashboard.healthcheck.security.system.info=System encoding OK. +adminTools.dashboard.healthcheck.security.system.file.warn=System file encoding is NOT UTF-8! +adminTools.dashboard.healthcheck.security.system.file.info=System file encoding is set to UTF-8. +adminTools.dashboard.healthcheck.security.system.file.notFound=File encoding could not be detected! +adminTools.dashboard.healthcheck.security.system.lang.warn=System language encoding is NOT UTF-8! +adminTools.dashboard.healthcheck.security.system.lang.info=System language encoding is set to UTF-8. +adminTools.dashboard.healthcheck.security.system.lang.notFound=Language encoding could not be detected! +adminTools.dashboard.healthcheck.security.system.recommendation=System encoding should be set to UTF-8! Please consult the help links page to get further instructions of how to configure the system encoding. +adminTools.dashboard.healthcheck.security.xwiki.info=XWiki encoding OK. +adminTools.dashboard.healthcheck.security.xwiki.active.warn=XWiki active encoding is NOT UTF-8! +adminTools.dashboard.healthcheck.security.xwiki.active.info=XWiki active encoding is set to UTF-8. +adminTools.dashboard.healthcheck.security.xwiki.active.notFound=Active encoding could not be detected! +adminTools.dashboard.healthcheck.security.xwiki.config.warn=XWiki configuration encoding is NOT UTF-8! +adminTools.dashboard.healthcheck.security.xwiki.config.info=XWiki configuration encoding is set to UTF-8! +adminTools.dashboard.healthcheck.security.xwiki.config.notFound=Configuration encoding could not be detected! adminTools.dashboard.healthcheck.title=Health check adminTools.dashboard.healthcheck.time=Time since the last health check adminTools.dashboard.healthcheck.start=Start health check +adminTools.dashboard.healthcheck.currentValue=Current value: adminTools.job.notFound=Health check job status not found ## Security @@ -112,24 +133,25 @@ adminTools.dashboard.security.title=Security ##Help links -adminTools.helppage.browser.support=Browser support -adminTools.helppage.browser.title=Browser -adminTools.helppage.database.instructions=Specific databases instructions -adminTools.helppage.database.mysql.install=MySQL installation guide -adminTools.helppage.database.mysql.troubleshoot=MySQL troubleshoot -adminTools.helppage.database.supported=Supported databases -adminTools.helppage.database.title=Database issues -adminTools.helppage.java.memory=Java memory -adminTools.helppage.java.support=Java support -adminTools.helppage.java.title=Java -adminTools.helppage.other.title=Other issues -adminTools.helppage.performance.cache=Cache recommendations -adminTools.helppage.performance.hardware=Hardware requirements -adminTools.helppage.performance.memory=Memory recommendations -adminTools.helppage.performance.title=Performance issues -adminTools.helppage.server.supported=Supported servers -adminTools.helppage.server.title=Server issues -adminTools.helppage.server.tomcat=Tomcat recommendations +adminTools.helpPage.browser.support=Browser support +adminTools.helpPage.browser.title=Browser +adminTools.helpPage.database.instructions=Specific databases instructions +adminTools.helpPage.database.mysql.install=MySQL installation guide +adminTools.helpPage.database.mysql.troubleshoot=MySQL troubleshoot +adminTools.helpPage.database.supported=Supported databases +adminTools.helpPage.database.title=Database issues +adminTools.helpPage.java.memory=Java memory +adminTools.helpPage.java.support=Java support +adminTools.helpPage.java.title=Java +adminTools.helpPage.other.title=Other issues +adminTools.helpPage.performance.cache=Cache recommendations +adminTools.helpPage.performance.hardware=Hardware requirements +adminTools.helpPage.performance.memory=Memory recommendations +adminTools.helpPage.performance.title=Performance issues +adminTools.helpPage.server.security=Security configuration +adminTools.helpPage.server.supported=Supported servers +adminTools.helpPage.server.title=Server issues +adminTools.helpPage.server.tomcat=Tomcat recommendations ## Modals diff --git a/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml b/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml index 587c94e9..a549125e 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml @@ -41,51 +41,54 @@ {{/box}} {{velocity}} -= $escapetool.xml($services.localization.render('adminTools.helppage.performance.title')) = += $escapetool.xml($services.localization.render('adminTools.helpPage.performance.title')) = -* [[$escapetool.xml($services.localization.render('adminTools.helppage.performance.hardware')) +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.performance.hardware')) >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HSizing||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helppage.performance.memory')) +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.performance.memory')) >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HMemory||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helppage.performance.cache')) +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.performance.cache')) >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HDocumentCache ||target="_blank"]] -= $escapetool.xml($services.localization.render('adminTools.helppage.server.title')) = += $escapetool.xml($services.localization.render('adminTools.helpPage.server.title')) = -* [[$escapetool.xml($services.localization.render('adminTools.helppage.server.supported')) +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.server.security')) +>>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Configuration/Encoding/ +||target="_blank"]] +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.server.supported')) >>https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/ServletContainerSupportStrategy/ ||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helppage.server.tomcat')) +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.server.tomcat')) >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationTomcat/#HRecommendations ||target="_blank"]] -= $escapetool.xml($services.localization.render('adminTools.helppage.database.title')) = += $escapetool.xml($services.localization.render('adminTools.helpPage.database.title')) = -* [[$escapetool.xml($services.localization.render('adminTools.helppage.database.supported')) +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.database.supported')) >>https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/DatabaseSupportStrategy||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helppage.database.instructions')) +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.database.instructions')) >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/#HSpecificdatabasesinstructions ||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helppage.database.mysql.install')) +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.database.mysql.install')) >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationMySQL/#HInstallationSteps ||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helppage.database.mysql.troubleshoot')) +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.database.mysql.troubleshoot')) >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationMySQL/#HTroubleshooting ||target="_blank"]] -= $escapetool.xml($services.localization.render('adminTools.helppage.other.title')) = -== $escapetool.xml($services.localization.render('adminTools.helppage.java.title')) == += $escapetool.xml($services.localization.render('adminTools.helpPage.other.title')) = +== $escapetool.xml($services.localization.render('adminTools.helpPage.java.title')) == -* [[$escapetool.xml($services.localization.render('adminTools.helppage.java.memory')) +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.java.memory')) >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationTomcat/#HGeneralMemorySettings ||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helppage.java.support')) +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.java.support')) >>https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/JavaSupportStrategy/||target="_blank"]] -== $escapetool.xml($services.localization.render('adminTools.helppage.browser.title')) == +== $escapetool.xml($services.localization.render('adminTools.helpPage.browser.title')) == -* [[$escapetool.xml($services.localization.render('adminTools.helppage.browser.support')) +* [[$escapetool.xml($services.localization.render('adminTools.helpPage.browser.support')) >>https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/BrowserSupportStrategy||target="_blank"]] {{/velocity}} diff --git a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml index d4c461ca..b33f02e8 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/WebHome.xml @@ -239,7 +239,7 @@ {{template name="job_macros.vm"/}} {{velocity}} - #includeMacros("AdminTools.Code.Macros") + #includeMacros("AdminTools.Code.HealthCheckMacros") {{html clean='false'}} #healthCheckUI() {{/html}} From 0cb50933c5c2aee168bc721be5c07accc0b7014c Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Fri, 17 Nov 2023 14:31:27 +0200 Subject: [PATCH 69/72] Create a health check dashboard section #13 * Adapted the request for job.js in AdminToolsJs to be initialized only once * Added grouping for the job * Created function to generate the job id inside the script service * Refactored the help links * Refactored the HealthCheckMacros and HealthCheckResources --- .../jobs/HealthCheckJobRequest.java | 5 +-- .../internal/AdminToolsManager.java | 13 +++--- .../AbstractConfigurationHealthCheck.java | 1 - .../internal/health/job/HealthCheckJob.java | 16 ++++++- .../script/AdminToolsScriptService.java | 21 ++++++++- .../health/job/HealthCheckJobTest.java | 15 +++++++ .../AdminTools/Code/AdminToolsJS.xml | 45 ++++++++++--------- .../AdminTools/Code/Configuration.xml | 23 +++++++++- .../AdminTools/Code/HealthCheckMacros.xml | 26 +++++------ .../AdminTools/Code/HealthCheckResources.xml | 29 ++++++------ .../AdminTools/Code/Translations.xml | 11 +++-- .../main/resources/AdminTools/HelpLinks.xml | 38 ++++++++-------- 12 files changed, 156 insertions(+), 87 deletions(-) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java b/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java index 9b048946..0ad1d0a6 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/jobs/HealthCheckJobRequest.java @@ -19,7 +19,6 @@ */ package com.xwiki.admintools.jobs; -import java.util.ArrayList; import java.util.List; import org.xwiki.job.AbstractRequest; @@ -54,9 +53,7 @@ public HealthCheckJobRequest(List requestId) private void setDefaultId() { - List id = new ArrayList<>(); - id.add("adminTools"); - id.add("healthCheck"); + List id = List.of("adminTools", "healthCheck"); setId(id); } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index 50822b71..eb024b78 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -26,6 +26,7 @@ import javax.inject.Provider; import javax.inject.Singleton; +import org.apache.commons.lang.exception.ExceptionUtils; import org.slf4j.Logger; import org.xwiki.component.annotation.Component; import org.xwiki.component.manager.ComponentLookupException; @@ -92,12 +93,14 @@ public String generateData() */ public String generateData(String hint) throws ComponentLookupException { - DataProvider dataProvider = contextComponentManager.getInstance(DataProvider.class, hint); - if (dataProvider == null) { - logger.error(GET_DATA_PROVIDER_ERROR_MESSAGE); - throw new NullPointerException(GET_DATA_PROVIDER_ERROR_MESSAGE); + try { + DataProvider dataProvider = contextComponentManager.getInstance(DataProvider.class, hint); + return dataProvider.getRenderedData(); + } catch (ComponentLookupException e) { + logger.error("Could not find the requested Data Provider. Root cause: [{}]", + ExceptionUtils.getRootCauseMessage(e)); + throw e; } - return dataProvider.getRenderedData(); } /** diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java index 7a7f6db2..4cf6d81f 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java @@ -21,7 +21,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.concurrent.TimeUnit; import javax.inject.Inject; import javax.inject.Named; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java index 8200d44e..21803fa7 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/job/HealthCheckJob.java @@ -28,7 +28,10 @@ import org.xwiki.component.annotation.Component; import org.xwiki.job.AbstractJob; +import org.xwiki.job.GroupedJob; +import org.xwiki.job.JobGroupPath; +import com.xpn.xwiki.XWikiContext; import com.xwiki.admintools.health.HealthCheck; import com.xwiki.admintools.health.HealthCheckResult; import com.xwiki.admintools.jobs.HealthCheckJobRequest; @@ -41,7 +44,7 @@ */ @Component @Named(HealthCheckJob.JOB_TYPE) -public class HealthCheckJob extends AbstractJob +public class HealthCheckJob extends AbstractJob implements GroupedJob { /** * Admin Tools health check job type. @@ -51,12 +54,23 @@ public class HealthCheckJob extends AbstractJob> healthChecks; + @Inject + private Provider wikiContextProvider; + @Override public String getType() { return JOB_TYPE; } + @Override + public JobGroupPath getGroupPath() + { + XWikiContext wikiContext = wikiContextProvider.get(); + String wikiId = wikiContext.getWikiId(); + return new JobGroupPath(List.of("adminTools", "healthCheck", wikiId)); + } + @Override protected HealthCheckJobStatus createNewStatus(HealthCheckJobRequest request) { diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index c2f16ab9..fc8a2ad6 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -23,6 +23,7 @@ import javax.inject.Inject; import javax.inject.Named; +import javax.inject.Provider; import javax.inject.Singleton; import org.xwiki.component.annotation.Component; @@ -32,6 +33,7 @@ import org.xwiki.script.service.ScriptService; import org.xwiki.stability.Unstable; +import com.xpn.xwiki.XWikiContext; import com.xwiki.admintools.internal.AdminToolsManager; import com.xwiki.admintools.internal.health.job.HealthCheckJob; import com.xwiki.admintools.jobs.HealthCheckJobRequest; @@ -54,6 +56,9 @@ public class AdminToolsScriptService implements ScriptService @Inject private JobExecutor jobExecutor; + @Inject + private Provider wikiContextProvider; + /** * Retrieve all the configuration information in a format given by the associated templates generated by the data * providers. @@ -110,12 +115,12 @@ public String getFilesSection() * Check if an Admin Tools Health Check job for the wiki from where the request was made exists. If it does, return * the job instance, else create a new Admin Tools health check request for the given wiki and start the execution. * - * @param requestId the ID to be used for the request. * @return the asynchronous background job that will execute the request. */ - public Job runHealthChecks(List requestId) + public Job runHealthChecks() { try { + List requestId = this.getHealthCheckJobId(); Job job = this.jobExecutor.getJob(requestId); if (job == null) { HealthCheckJobRequest healthCheckJobRequest = new HealthCheckJobRequest(requestId); @@ -127,4 +132,16 @@ public Job runHealthChecks(List requestId) return null; } } + + /** + * Get the Health Check job id for the current wiki. + * + * @return Health check job id. + */ + public List getHealthCheckJobId() + { + XWikiContext wikiContext = wikiContextProvider.get(); + String wikiID = wikiContext.getWikiId(); + return List.of("adminTools", "healthCheck", wikiID); + } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java index 8635b67d..278db631 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/job/HealthCheckJobTest.java @@ -30,6 +30,7 @@ import org.xwiki.test.junit5.mockito.InjectMockComponents; import org.xwiki.test.junit5.mockito.MockComponent; +import com.xpn.xwiki.XWikiContext; import com.xwiki.admintools.health.HealthCheck; import com.xwiki.admintools.health.HealthCheckResult; import com.xwiki.admintools.jobs.HealthCheckJobRequest; @@ -47,6 +48,12 @@ class HealthCheckJobTest @MockComponent private Provider> listProvider; + @MockComponent + private Provider wikiContextProvider; + + @MockComponent + private XWikiContext wikiContext; + @Mock private HealthCheck firstHealthCheck; @@ -76,4 +83,12 @@ void runInternal() HealthCheckJobStatus healthCheckJobStatus = healthCheckJob.getStatus(); assertEquals(2, healthCheckJobStatus.getHealthCheckResults().size()); } + + @Test + void getGroupPath() + { + when(wikiContextProvider.get()).thenReturn(wikiContext); + when(wikiContext.getWikiId()).thenReturn("xwiki"); + assertEquals(List.of("adminTools", "healthCheck", "xwiki"), healthCheckJob.getGroupPath().getPath()); + } } diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index 74a57ae6..4c1bc9ef 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -126,7 +126,7 @@ require(['jquery', 'xwiki-meta', 'xwiki-job-runner'], function($, xwikiMeta, JobRunner) { - const getResourceURL = function() { + const getHealthCheckActionPageURL = function() { let documentReference = XWiki.Model.resolve('AdminTools.Code.HealthCheckResources', XWiki.EntityType.DOCUMENT); return new XWiki.Document(documentReference).getURL('get'); }; @@ -143,7 +143,7 @@ return Promise.resolve(new JobRunner({ createStatusRequest: function(jobId) { return { - url: getResourceURL(), + url: getHealthCheckActionPageURL(), data: { outputSyntax: 'plain', sheet: 'AdminTools.Code.HealthCheckResources', @@ -152,43 +152,47 @@ } }; } - }).run(getResourceURL(), data)).catch((reason) => { + }).run(getHealthCheckActionPageURL(), data)).catch((reason) => { return Promise.reject(reason); }).finally(() => { $('#admin_tools_job_start').prop("disabled", false); }); }; - const reinitialiseProgressBar = function() { - $.get(getResourceURL(), function(data) { - console.log(data) - let progressBar = $(data).find('div.ui-progress'); - $('#healthCheck').find('.successmessage, .warningmessage, .errormessage').replaceWith(progressBar); - }); - }; - // Need to call job.min.js only after the job has started its execution and the result message has been changed for // the progress bar. Otherwise, job.js won't see .ui-progress and will not initialize and run a new JobRunner // with the requested configuration. To make sure the job .ui-progress is seen, we need to undefine and request the // resource again. const initialiseJobJS = function() { - require.undef('health-check-job'); - $.get(getResourceURL(), function(data) { - let jobMinJsURL = $(data).find('jobJsURL').attr('data-url'); + $.get(getHealthCheckActionPageURL(), function(data) { + let jobJsURL = $(data).find('#jobJsURL').attr('data-jobJsURL'); require.config({ paths: { - 'health-check-job': jobMinJsURL + 'health-check-job': jobJsURL } }); require(['health-check-job'], function(){}); }); }; + const recallJobJs = function() { + require.undef('health-check-job'); + require(['health-check-job'], function(){}); + } + + const reinitialiseHealthCheckResources = function() { + $.get(getHealthCheckActionPageURL(), function(data) { + let progressBar = $(data).find('div.ui-progress'); + $('#healthCheck').find('.successmessage, .warningmessage, .errormessage').replaceWith(progressBar); + recallJobJs() + }); + }; + $(document).ready(function() { if ($('#healthCheck').length) { - let jobState = $('jobState').attr('data-state') + initialiseJobJS(); + let jobState = $('#healthCheckJobState').attr('data-jobState'); if (jobState == "RUNNING") { - initialiseJobJS(); runHealthCheckJob(); $('.job-status').show(); } else if (jobState == "FINISHED") { @@ -197,7 +201,7 @@ } }); - $(document).on('click', '.log-item-warn', function(event) { + $(document).on('click', '.log-item-warn, log-item-error', function(event) { $(this).children(".recommendation").toggle(); }); @@ -205,8 +209,7 @@ event.preventDefault(); $(".log").empty(); runHealthCheckJob(); - reinitialiseProgressBar(); - initialiseJobJS(); + reinitialiseHealthCheckResources(); $('.job-status').show(); }); @@ -222,7 +225,7 @@ }); $(document).on('click', '#filesViewLastNLinesModal .btn-primary, #configurationViewLastNLinesModal .btn-primary', - function(event) { + function(event) { event.preventDefault(); const modal = $(event.currentTarget).closest('.modal'); const downloadForm = modal.find('form'); diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Configuration.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Configuration.xml index 1bff5635..650d3a60 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Configuration.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Configuration.xml @@ -51,6 +51,24 @@ + + PureText + + 0 + PureText + + excludedLines + 2 + 1 + excludedLines + 0 + 5 + 40 + 0 + + + com.xpn.xwiki.objects.classes.TextAreaClass + 0 @@ -58,7 +76,7 @@ serverLocation 1 1 - Server location + serverLocation 30 0 @@ -66,6 +84,9 @@ com.xpn.xwiki.objects.classes.StringClass + + + diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckMacros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckMacros.xml index e37a342f..c4a509b1 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckMacros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckMacros.xml @@ -39,10 +39,10 @@ {{velocity output='false'}} #macro (getHealthCheckJobStatusJSON $status $json) #set ($results = []) - #foreach ($logEvent in $status.getHealthCheckResults()) + #foreach ($result in $status.getHealthCheckResults()) #set ($discard = $results.add({ - 'level': $logEvent.getLevel(), - 'renderedMessage': "#printResult($logEvent)" + 'level': $result.getLevel(), + 'renderedMessage': "#printResult($result)" })) #end #set ($json = $NULL) @@ -72,13 +72,13 @@ #set($healthCheckReportMessage = $services.localization.render($messageKeys)) #set($messageClass = 'errormessage') #elseif ($status.hasErrorLevel('error')) - #set($healthCheckReportMessage = 'Critical issues were found, please consult the log!') + #set($healthCheckReportMessage = $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.message.error'))) #set($messageClass = 'errormessage') #elseif ($status.hasErrorLevel('warn')) - #set($healthCheckReportMessage = 'Some issues have been found, for more details please see the log.') + #set($healthCheckReportMessage = $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.message.warning'))) #set($messageClass = 'warningmessage') #else - #set($healthCheckReportMessage = 'No issue found!') + #set($healthCheckReportMessage = $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.message.success'))) #set($messageClass = 'successmessage') #end <div class="box $messageClass"> @@ -87,7 +87,7 @@ #end #macro (printResult $healthCheckResult) - <div style="cursor: pointer;">$escapetool.xml($services.localization.render($healthCheckResult.getErrorMessage())) + <div style="cursor: pointer;">$escapetool.xml($services.localization.render($healthCheckResult.getMessage())) #if ($healthCheckResult.getCurrentValue()) $escapetool.xml($services.localization.render( 'adminTools.dashboard.healthcheck.currentValue')) $healthCheckResult.getCurrentValue()#end</div> #if($healthCheckResult.getRecommendation()) @@ -104,7 +104,7 @@ <ul class="log"> #foreach ($healthCheckResult in $healthCheckResults) #set ($resultLevel = $healthCheckResult.getLevel()) - ## Display the last log item as loading if the associated task is not finished. + ## Display the last result item as loading if the associated task is not finished. <li class="log-item log-item-${resultLevel}#if ($loading && !$foreach.hasNext) log-item-loading#end"> #printResult($healthCheckResult) </li> @@ -114,7 +114,6 @@ #macro (displayHealthCheckResults $status $collapsed) <dl class="xform"> - ## Collapse the job log if the job is waiting for user input (leave more space for the job question). <dt> <label class="collapse-toggle#if ($collapsed || $status.state == 'WAITING') collapsed#end" data-target-xpath="parent::*/following-sibling::*"> @@ -129,7 +128,7 @@ #macro (healthCheckUI) #set ($discard = $xwiki.jsx.use('AdminTools.Code.AdminToolsJS')) - #set ($jobId = ['adminTools', 'healthcheck', $services.wiki.getCurrentWikiId()]) + #set ($jobId = $services.admintools.getHealthCheckJobId()) #set ($healthJobStatusURL = $xwiki.getURL('AdminTools.Code.HealthCheckJob', 'get', $escapetool.url({ 'jobId': $jobId, 'outputSyntax': 'plain' @@ -141,10 +140,9 @@ '__ENDLINK__' ])).replace('__STARTLINK__', "<a href='$solutionLink'><strong>").replace('__ENDLINK__', ' </strong></a>')) - <jobState - data-state="${healthJobStatus.state}" - </jobState> - <input type="hidden" name="jobState" value="${healthJobStatus.state}"></input> + <span id="healthCheckJobState" + data-jobState="${healthJobStatus.state}"> + </span> <div class="adminToolsDashboardItem" id="healthCheck"> <h2>$services.icon.renderHTML('bug') $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.title'))</h2> diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml index fe38c4c9..9661c9b6 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml @@ -39,7 +39,8 @@ {{template name="job_macros.vm"/}} {{velocity output="false"}} -#macro (returnHealthCheckJobStatusJSON $healthCheckJobId) +#macro (returnHealthCheckJobStatusJSON) + #set ($healthCheckJobId = $services.admintools.getHealthCheckJobId()) #set ($healthCheckJobStatus = $services.job.getJobStatus($healthCheckJobId)) #set ($healthCheckJobStatusJSON = { 'id': $healthCheckJobStatus.request.id, @@ -51,18 +52,16 @@ #jsonResponse($healthCheckJobStatusJSON) #end -#macro (getHealthCheckResources) - #set ($jobMinJsURL = $xwiki.getSkinFile('uicomponents/job/job.min.js')) - #set ($jobId = ['adminTools', 'healthcheck', $services.wiki.getCurrentWikiId()]) +#macro (getHealthCheckJobResources) + #set ($jobJsURL = $xwiki.getSkinFile('uicomponents/job/job.js')) + #set ($jobId = $services.admintools.getHealthCheckJobId()) #set ($healthJobStatus = $services.job.getJobStatus($jobId)) {{html clean=false}} - <div hidden> - #data($jobMinJsURL) - <jobJsURL - data-url="${jobMinJsURL}" - </jobJsURL> - ## MOVE TO MACRO - #displayJobProgressBar($healthJobStatus) + <div> + <span id="jobJsURL" + data-jobJsURL="${jobJsURL}"> + </span> + #displayJobProgressBar($healthJobStatus) </div> {{/html}} #end @@ -73,15 +72,13 @@ #if ("$!request.action" != '' && !$services.csrf.isTokenValid($request.form_token)) #set ($discard = $response.sendError(401, 'CSRF token verification failed!')) #elseif ($request.action == 'healthCheck') - #set ($jobId = ['adminTools', 'healthcheck', $services.wiki.getCurrentWikiId()]) - #set ($healthCheckJob = $services.admintools.runHealthChecks($jobId)) - #returnHealthCheckJobStatusJSON($jobId) + #set ($healthCheckJob = $services.admintools.runHealthChecks()) + #returnHealthCheckJobStatusJSON() #elseif ($request.data == 'jobStatus') #set ($healthCheckJobId = $request.jobId.split('/')) #returnHealthCheckJobStatusJSON($healthCheckJobId) - ## TO BE REMOVED #else - #getHealthCheckResources() + #getHealthCheckJobResources() #end #end {{/velocity}} diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml index cd187a2a..3d185440 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml @@ -100,6 +100,7 @@ adminTools.dashboard.healthcheck.performance.memory.info=System memory capacity adminTools.dashboard.healthcheck.performance.memory.recommendation=It is recommended to have at least 2GB of RAM to run XWiki. adminTools.dashboard.healthcheck.performance.space.warn=There is not enough free space for the XWiki installation! adminTools.dashboard.healthcheck.performance.space.recommendation=There should be at least 16GB of free system space. +adminTools.dashboard.healthcheck.performance.space.info=The system has enough free space for the XWiki installation. adminTools.dashboard.healthcheck.security.system.info=System encoding OK. adminTools.dashboard.healthcheck.security.system.file.warn=System file encoding is NOT UTF-8! adminTools.dashboard.healthcheck.security.system.file.info=System file encoding is set to UTF-8. @@ -113,13 +114,17 @@ adminTools.dashboard.healthcheck.security.xwiki.active.warn=XWiki active encodin adminTools.dashboard.healthcheck.security.xwiki.active.info=XWiki active encoding is set to UTF-8. adminTools.dashboard.healthcheck.security.xwiki.active.notFound=Active encoding could not be detected! adminTools.dashboard.healthcheck.security.xwiki.config.warn=XWiki configuration encoding is NOT UTF-8! -adminTools.dashboard.healthcheck.security.xwiki.config.info=XWiki configuration encoding is set to UTF-8! +adminTools.dashboard.healthcheck.security.xwiki.config.info=XWiki configuration encoding is set to UTF-8. adminTools.dashboard.healthcheck.security.xwiki.config.notFound=Configuration encoding could not be detected! adminTools.dashboard.healthcheck.title=Health check adminTools.dashboard.healthcheck.time=Time since the last health check adminTools.dashboard.healthcheck.start=Start health check adminTools.dashboard.healthcheck.currentValue=Current value: adminTools.job.notFound=Health check job status not found +adminTools.dashboard.healthcheck.message.success=No issue found! +adminTools.dashboard.healthcheck.message.warning=Some issues have been found, for more details please see the results below. +adminTools.dashboard.healthcheck.message.error=Critical issues were found, please consult the results below! + ## Security adminTools.dashboard.security.activeEncoding=Active encoding @@ -195,8 +200,8 @@ adminTools.dashboard.showLogs=View last n lines of log... 1 Scope 0 - - |, + + |, 1 0 GLOBAL|WIKI|USER|ON_DEMAND diff --git a/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml b/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml index a549125e..d6a80179 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/HelpLinks.xml @@ -41,54 +41,54 @@ {{/box}} {{velocity}} -= $escapetool.xml($services.localization.render('adminTools.helpPage.performance.title')) = += {{translation key="adminTools.helpPage.performance.title" /}} = -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.performance.hardware')) +* [[{{translation key="adminTools.helpPage.performance.hardware" /}} >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HSizing||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.performance.memory')) +* [[{{translation key="adminTools.helpPage.performance.memory" /}} >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HMemory||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.performance.cache')) +* [[{{translation key="adminTools.helpPage.performance.cache" /}} >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Performances/#HDocumentCache ||target="_blank"]] -= $escapetool.xml($services.localization.render('adminTools.helpPage.server.title')) = += {{translation key="adminTools.helpPage.server.title" /}} = -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.server.security')) +* [[{{translation key="adminTools.helpPage.server.security" /}} >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Configuration/Encoding/ ||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.server.supported')) +* [[{{translation key="adminTools.helpPage.server.supported" /}} >>https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/ServletContainerSupportStrategy/ ||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.server.tomcat')) +* [[{{translation key="adminTools.helpPage.server.tomcat" /}} >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationTomcat/#HRecommendations ||target="_blank"]] -= $escapetool.xml($services.localization.render('adminTools.helpPage.database.title')) = += {{translation key="adminTools.helpPage.database.title" /}} = -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.database.supported')) +* [[{{translation key="adminTools.helpPage.database.supported" /}} >>https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/DatabaseSupportStrategy||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.database.instructions')) +* [[{{translation key="adminTools.helpPage.database.instructions" /}} >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/#HSpecificdatabasesinstructions ||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.database.mysql.install')) +* [[{{translation key="adminTools.helpPage.database.mysql.install" /}} >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationMySQL/#HInstallationSteps ||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.database.mysql.troubleshoot')) +* [[{{translation key="adminTools.helpPage.database.mysql.troubleshoot" /}} >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationMySQL/#HTroubleshooting ||target="_blank"]] -= $escapetool.xml($services.localization.render('adminTools.helpPage.other.title')) = -== $escapetool.xml($services.localization.render('adminTools.helpPage.java.title')) == += {{translation key="adminTools.helpPage.other.title" /}} = +== {{translation key="adminTools.helpPage.java.title" /}} == -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.java.memory')) +* [[{{translation key="adminTools.helpPage.java.memory" /}} >>https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Installation/InstallationWAR/InstallationTomcat/#HGeneralMemorySettings ||target="_blank"]] -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.java.support')) +* [[{{translation key="adminTools.helpPage.java.support" /}} >>https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/JavaSupportStrategy/||target="_blank"]] -== $escapetool.xml($services.localization.render('adminTools.helpPage.browser.title')) == +== {{translation key="adminTools.helpPage.browser.title" /}} == -* [[$escapetool.xml($services.localization.render('adminTools.helpPage.browser.support')) +* [[{{translation key="adminTools.helpPage.browser.support" /}} >>https://dev.xwiki.org/xwiki/bin/view/Community/SupportStrategy/BrowserSupportStrategy||target="_blank"]] {{/velocity}} From 18d6765de8c37fcdbfa93449f18419c6d1cf4e86 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Fri, 17 Nov 2023 14:42:11 +0200 Subject: [PATCH 70/72] Create a health check dashboard section #13 * Fixed missing CSS class selector --- .../src/main/resources/AdminTools/Code/AdminToolsJS.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index 4c1bc9ef..c95223fa 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -201,7 +201,7 @@ } }); - $(document).on('click', '.log-item-warn, log-item-error', function(event) { + $(document).on('click', '.log-item-warn, .log-item-error', function(event) { $(this).children(".recommendation").toggle(); }); From 1d53e87998f56732560eb990e64a804e23016eb7 Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Fri, 24 Nov 2023 10:37:28 +0200 Subject: [PATCH 71/72] Create a health check dashboard section #13 * Code refactoring --- .../admintools/health/HealthCheckResult.java | 6 ++-- application-admintools-default/pom.xml | 14 ++++---- .../internal/AdminToolsManager.java | 9 ------ .../AbstractConfigurationHealthCheck.java | 5 +-- .../ConfigurationDatabaseHealthCheck.java | 4 +-- .../ConfigurationJavaHealthCheck.java | 4 +-- ...k.java => ConfigurationOSHealthCheck.java} | 8 ++--- .../checks/performance/CPUHealthCheck.java | 2 +- .../PhysicalMemoryHealthCheck.java | 2 +- .../performance/PhysicalSpaceHealthCheck.java | 2 +- .../security/AbstractSecurityHealthCheck.java | 4 +-- .../security/ActiveEncodingHealthCheck.java | 4 +-- .../ConfigurationEncodingHealthCheck.java | 7 ++-- .../security/FileEncodingHealthCheck.java | 4 +-- .../security/LangEncodingHealthCheck.java | 4 +-- .../script/AdminToolsScriptService.java | 13 +++++++- .../main/resources/META-INF/components.txt | 2 +- .../ConfigurationDatabaseHealthCheckTest.java | 2 +- .../ConfigurationJavaHealthCheckTest.java | 2 +- ...va => ConfigurationOSHealthCheckTest.java} | 6 ++-- .../ActiveEncodingHealthCheckTest.java | 4 +-- .../ConfigurationEncodingHealthCheckTest.java | 4 +-- .../security/FileEncodingHealthCheckTest.java | 4 +-- .../security/LangEncodingHealthCheckTest.java | 4 +-- .../AdminTools/Code/AdminToolsJS.xml | 32 +++++++++---------- .../AdminTools/Code/HealthCheckJob.xml | 2 -- .../AdminTools/Code/HealthCheckMacros.xml | 6 ++-- .../AdminTools/Code/HealthCheckResources.xml | 6 ++-- .../AdminTools/Code/Translations.xml | 2 +- 29 files changed, 84 insertions(+), 84 deletions(-) rename application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/{ConfigurationOsHealthCheck.java => ConfigurationOSHealthCheck.java} (88%) rename application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/{ConfigurationOsHealthCheckTest.java => ConfigurationOSHealthCheckTest.java} (95%) diff --git a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java index e41ec85a..96d974f4 100644 --- a/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java +++ b/application-admintools-api/src/main/java/com/xwiki/admintools/health/HealthCheckResult.java @@ -43,7 +43,7 @@ public class HealthCheckResult /** * Used for registering a result. * - * @param message Error message representing the summary of the found issue. + * @param message error message representing the summary of the found issue. * @param recommendation suggestion in context of the message. * @param level severity level of a result. * @param currentValue Current value of the checked resource. @@ -59,7 +59,7 @@ public HealthCheckResult(String message, String recommendation, String level, St /** * Partial result definition. * - * @param message Error message representing the summary of the found issue. + * @param message error message representing the summary of the found issue. * @param recommendation suggestion in context of the message. * @param level severity level of a result. */ @@ -71,7 +71,7 @@ public HealthCheckResult(String message, String recommendation, String level) /** * Simple result definition. * - * @param message Error message representing the summary of the found issue. + * @param message error message representing the summary of the found issue. * @param level severity level of a result. */ public HealthCheckResult(String message, String level) diff --git a/application-admintools-default/pom.xml b/application-admintools-default/pom.xml index e165cdf0..5f6b55f8 100644 --- a/application-admintools-default/pom.xml +++ b/application-admintools-default/pom.xml @@ -41,6 +41,12 @@ xwiki-platform-oldcore ${platform.version} + + + com.github.oshi + oshi-core + 5.8.0 + javax.servlet javax.servlet-api @@ -71,14 +77,8 @@ xwiki-commons-cache-api ${commons.version} - - - com.github.oshi - oshi-core - 5.8.0 - - 0.77 + 0.76 \ No newline at end of file diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java index eb024b78..af546c4d 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/AdminToolsManager.java @@ -26,8 +26,6 @@ import javax.inject.Provider; import javax.inject.Singleton; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.slf4j.Logger; import org.xwiki.component.annotation.Component; import org.xwiki.component.manager.ComponentLookupException; import org.xwiki.component.manager.ComponentManager; @@ -45,11 +43,6 @@ @Singleton public class AdminToolsManager { - private static final String GET_DATA_PROVIDER_ERROR_MESSAGE = "Could not find the requested Data Provider!"; - - @Inject - private Logger logger; - /** * A list of all the data providers for Admin Tools. */ @@ -97,8 +90,6 @@ public String generateData(String hint) throws ComponentLookupException DataProvider dataProvider = contextComponentManager.getInstance(DataProvider.class, hint); return dataProvider.getRenderedData(); } catch (ComponentLookupException e) { - logger.error("Could not find the requested Data Provider. Root cause: [{}]", - ExceptionUtils.getRootCauseMessage(e)); throw e; } } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java index 4cf6d81f..dbc378d1 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/AbstractConfigurationHealthCheck.java @@ -46,12 +46,13 @@ public abstract class AbstractConfigurationHealthCheck implements HealthCheck private DataProvider configurationDataProvider; /** - * Get the JSON needed for the configuration health checks execution. + * Retrieve a JSON containing the necessary instance configuration information required for executing the + * configuration health checks. * * @return a {@link Map} with the {@link ConfigurationDataProvider} info, or an empty {@link Map} in case of an * error. */ - protected Map getJSON() + protected Map getConfigurationProviderJSON() { try { return configurationDataProvider.getDataAsJSON(); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java index 3d878d60..3f4d3f00 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheck.java @@ -41,7 +41,7 @@ public class ConfigurationDatabaseHealthCheck extends AbstractConfigurationHealt /** * Component identifier. */ - public static final String HINT = "CONFIG_DB_HEALTH_CHECK"; + public static final String HINT = "configurationDatabase"; private static final String ERROR_KEY = "error"; @@ -51,7 +51,7 @@ public class ConfigurationDatabaseHealthCheck extends AbstractConfigurationHealt @Override public HealthCheckResult check() { - String usedDatabase = getJSON().get("databaseName"); + String usedDatabase = getConfigurationProviderJSON().get("databaseName"); if (usedDatabase == null) { logger.warn("Database not found!"); return new HealthCheckResult("adminTools.dashboard.healthcheck.database.warn", ERROR_KEY); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java index 1a85ee81..e3596c50 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheck.java @@ -41,12 +41,12 @@ public class ConfigurationJavaHealthCheck extends AbstractConfigurationHealthChe /** * Component identifier. */ - public static final String HINT = "CONFIG_JAVA_HEALTH_CHECK"; + public static final String HINT = "configurationJava"; @Override public HealthCheckResult check() { - Map configurationJson = getJSON(); + Map configurationJson = getConfigurationProviderJSON(); String javaVersionString = configurationJson.get("javaVersion"); if (javaVersionString == null) { logger.warn("Java version not found!"); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOSHealthCheck.java similarity index 88% rename from application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java rename to application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOSHealthCheck.java index 71164a61..14858eb5 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOSHealthCheck.java @@ -34,19 +34,19 @@ * @version $Id$ */ @Component -@Named(ConfigurationOsHealthCheck.HINT) +@Named(ConfigurationOSHealthCheck.HINT) @Singleton -public class ConfigurationOsHealthCheck extends AbstractConfigurationHealthCheck +public class ConfigurationOSHealthCheck extends AbstractConfigurationHealthCheck { /** * Component identifier. */ - public static final String HINT = "CONFIG_OS_HEALTH_CHECK"; + public static final String HINT = "configurationOS"; @Override public HealthCheckResult check() { - Map dataJSON = getJSON(); + Map dataJSON = getConfigurationProviderJSON(); if (dataJSON.get("osName") == null || dataJSON.get("osVersion") == null || dataJSON.get("osArch") == null) { logger.warn("There has been an error while gathering OS info!"); return new HealthCheckResult("adminTools.dashboard.healthcheck.os.warn", "warn"); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/CPUHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/CPUHealthCheck.java index e7eb5096..2a86b707 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/CPUHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/CPUHealthCheck.java @@ -46,7 +46,7 @@ public class CPUHealthCheck implements HealthCheck /** * Component identifier. */ - public static final String HINT = "CPU_PERFORMANCE_HEALTH_CHECK"; + public static final String HINT = "cpuPerformance"; @Inject private Logger logger; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalMemoryHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalMemoryHealthCheck.java index fc26a1c8..3eeb9462 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalMemoryHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalMemoryHealthCheck.java @@ -47,7 +47,7 @@ public class PhysicalMemoryHealthCheck implements HealthCheck /** * Component identifier. */ - public static final String HINT = "PHYSICAL_MEMORY_HEALTH_CHECK"; + public static final String HINT = "physicalMemory"; @Inject private Logger logger; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalSpaceHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalSpaceHealthCheck.java index 971233f4..70f77550 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalSpaceHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/PhysicalSpaceHealthCheck.java @@ -48,7 +48,7 @@ public class PhysicalSpaceHealthCheck implements HealthCheck /** * Component identifier. */ - public static final String HINT = "PHYSICAL_SPACE_HEALTH_CHECK"; + public static final String HINT = "physicalSpace"; @Inject private CurrentServer currentServer; diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/AbstractSecurityHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/AbstractSecurityHealthCheck.java index c9289893..d724a2ec 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/AbstractSecurityHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/AbstractSecurityHealthCheck.java @@ -54,11 +54,11 @@ protected boolean isSafeEncoding(String encoding, String type) if (acceptedEncodings.contains(encoding)) { return true; } - logger.warn(String.format("%s encoding is [{}], but should be UTF-8!", type), encoding); + logger.warn("[{}] encoding is [{}], but should be UTF-8!", type, encoding); return false; } - protected Map getJSON() + protected Map getSecurityProviderJSON() { try { return securityDataProvider.getDataAsJSON(); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheck.java index 97bf0177..65ffdf05 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheck.java @@ -39,14 +39,14 @@ public class ActiveEncodingHealthCheck extends AbstractSecurityHealthCheck /** * Component identifier. */ - public static final String HINT = "ACTIVE_ENCODING_HEALTH_CHECK"; + public static final String HINT = "activeEncoding"; private static final String WARN_LEVEL = "warn"; @Override public HealthCheckResult check() { - String activeEnc = getJSON().get("activeEncoding"); + String activeEnc = getSecurityProviderJSON().get(HINT); if (activeEnc == null) { logger.warn("Active encoding could not be detected!"); return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.active.notFound", WARN_LEVEL); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheck.java index 6ce50c8a..1060fdc5 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheck.java @@ -39,14 +39,14 @@ public class ConfigurationEncodingHealthCheck extends AbstractSecurityHealthChec /** * Component identifier. */ - public static final String HINT = "CONFIGURATION_ENCODING_HEALTH_CHECK"; + public static final String HINT = "configurationEncoding"; private static final String WARN_LEVEL = "warn"; @Override public HealthCheckResult check() { - String configEnc = getJSON().get("configurationEncoding"); + String configEnc = getSecurityProviderJSON().get(HINT); if (configEnc == null) { logger.warn("Configuration encoding could not be detected!"); return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.config.notFound", WARN_LEVEL); @@ -55,8 +55,7 @@ public HealthCheckResult check() if (!isConfigEncSafe) { return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.config.warn", null, - WARN_LEVEL, - configEnc); + WARN_LEVEL, configEnc); } return new HealthCheckResult("adminTools.dashboard.healthcheck.security.xwiki.config.info", "info"); } diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheck.java index 61beea06..fb81aefa 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheck.java @@ -39,14 +39,14 @@ public class FileEncodingHealthCheck extends AbstractSecurityHealthCheck /** * Component identifier. */ - public static final String HINT = "FILE_ENCODING_HEALTH_CHECK"; + public static final String HINT = "fileEncoding"; private static final String WARN_LEVEL = "warn"; @Override public HealthCheckResult check() { - String fileEnc = getJSON().get("fileEncoding"); + String fileEnc = getSecurityProviderJSON().get(HINT); if (fileEnc == null) { logger.warn("File encoding could not be detected!"); return new HealthCheckResult("adminTools.dashboard.healthcheck.security.system.file.notFound", WARN_LEVEL); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheck.java index cad037be..6568b23b 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheck.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheck.java @@ -39,14 +39,14 @@ public class LangEncodingHealthCheck extends AbstractSecurityHealthCheck /** * Component identifier. */ - public static final String HINT = "LANGUAGE_ENCODING_HEALTH_CHECK"; + public static final String HINT = "languageEncoding"; private static final String WARN_LEVEL = "warn"; @Override public HealthCheckResult check() { - String langEnc = getJSON().get("LANG"); + String langEnc = getSecurityProviderJSON().get("LANG"); if (langEnc == null) { logger.warn("Language encoding could not be detected!"); return new HealthCheckResult("adminTools.dashboard.healthcheck.security.system.lang.notFound", WARN_LEVEL); diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java index fc8a2ad6..7cb773fb 100644 --- a/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/script/AdminToolsScriptService.java @@ -26,6 +26,8 @@ import javax.inject.Provider; import javax.inject.Singleton; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.slf4j.Logger; import org.xwiki.component.annotation.Component; import org.xwiki.component.manager.ComponentLookupException; import org.xwiki.job.Job; @@ -50,6 +52,9 @@ @Unstable public class AdminToolsScriptService implements ScriptService { + @Inject + private Logger logger; + @Inject private AdminToolsManager adminToolsManager; @@ -78,7 +83,13 @@ public String getConfigurationData() */ public String getConfigurationData(String hint) throws ComponentLookupException { - return this.adminToolsManager.generateData(hint); + try { + return this.adminToolsManager.generateData(hint); + } catch (ComponentLookupException e) { + logger.error("Could not retrieve data for the given hint [{}]. Root cause is: [{}]", hint, + ExceptionUtils.getRootCauseMessage(e)); + throw e; + } } /** diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index a65580bb..deb7fa2e 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -14,7 +14,7 @@ com.xwiki.admintools.internal.configuration.DefaultAdminToolsConfiguration com.xwiki.admintools.internal.AdminToolsEventListener com.xwiki.admintools.internal.health.checks.configuration.ConfigurationDatabaseHealthCheck com.xwiki.admintools.internal.health.checks.configuration.ConfigurationJavaHealthCheck -com.xwiki.admintools.internal.health.checks.configuration.ConfigurationOsHealthCheck +com.xwiki.admintools.internal.health.checks.configuration.ConfigurationOSHealthCheck com.xwiki.admintools.internal.health.checks.security.ActiveEncodingHealthCheck com.xwiki.admintools.internal.health.checks.security.ConfigurationEncodingHealthCheck com.xwiki.admintools.internal.health.checks.security.FileEncodingHealthCheck diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java index 259ad94d..2624b548 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationDatabaseHealthCheckTest.java @@ -82,7 +82,7 @@ void check() } @Test - void checkNullJson() throws Exception + void checkNullJSON() throws Exception { when(configurationDataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java index 4e7152ba..82ed504d 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationJavaHealthCheckTest.java @@ -70,7 +70,7 @@ void check() } @Test - void checkNullJson() throws Exception + void checkNullJSON() throws Exception { when(dataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOSHealthCheckTest.java similarity index 95% rename from application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java rename to application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOSHealthCheckTest.java index 9c8d58a6..8c7071cd 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOsHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/configuration/ConfigurationOSHealthCheckTest.java @@ -43,14 +43,14 @@ import static org.mockito.Mockito.when; @ComponentTest -class ConfigurationOsHealthCheckTest +class ConfigurationOSHealthCheckTest { @MockComponent @Named(ConfigurationDataProvider.HINT) private static DataProvider dataProvider; @InjectMockComponents - private ConfigurationOsHealthCheck osHealthCheck; + private ConfigurationOSHealthCheck osHealthCheck; @Mock private Logger logger; @@ -77,7 +77,7 @@ void check() } @Test - void checkNullJson() throws Exception + void checkNullJSON() throws Exception { when(dataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheckTest.java index 5282d3b1..80519212 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ActiveEncodingHealthCheckTest.java @@ -71,7 +71,7 @@ void check() } @Test - void checkNullJson() throws Exception + void checkNullJSON() throws Exception { when(dataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); @@ -87,6 +87,6 @@ void checkUnsafeEncoding() throws Exception when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); assertEquals("adminTools.dashboard.healthcheck.security.xwiki.active.warn", activeEncodingHealthCheck.check().getMessage()); - verify(logger).warn("XWiki active encoding is [{}], but should be UTF-8!", "ISO-8859-1"); + verify(logger).warn("[{}] encoding is [{}], but should be UTF-8!", "XWiki active", "ISO-8859-1"); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheckTest.java index 2074ad9d..72e12ccd 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/ConfigurationEncodingHealthCheckTest.java @@ -71,7 +71,7 @@ void check() } @Test - void checkNullJson() throws Exception + void checkNullJSON() throws Exception { when(dataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); @@ -87,6 +87,6 @@ void checkUnsafeEncoding() throws Exception when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); assertEquals("adminTools.dashboard.healthcheck.security.xwiki.config.warn", configurationEncodingHealthCheck.check().getMessage()); - verify(logger).warn("XWiki configuration encoding is [{}], but should be UTF-8!", "ISO-8859-1"); + verify(logger).warn("[{}] encoding is [{}], but should be UTF-8!", "XWiki configuration", "ISO-8859-1"); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheckTest.java index b433a486..c99808a4 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/FileEncodingHealthCheckTest.java @@ -71,7 +71,7 @@ void check() } @Test - void checkNullJson() throws Exception + void checkNullJSON() throws Exception { when(dataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); @@ -87,6 +87,6 @@ void checkUnsafeEncoding() throws Exception when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); assertEquals("adminTools.dashboard.healthcheck.security.system.file.warn", fileEncodingHealthCheck.check().getMessage()); - verify(logger).warn("System file encoding is [{}], but should be UTF-8!", "ISO-8859-1"); + verify(logger).warn("[{}] encoding is [{}], but should be UTF-8!", "System file", "ISO-8859-1"); } } diff --git a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheckTest.java b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheckTest.java index 448c5b46..c4b59c90 100644 --- a/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheckTest.java +++ b/application-admintools-default/src/test/java/com/xwiki/admintools/internal/health/checks/security/LangEncodingHealthCheckTest.java @@ -71,7 +71,7 @@ void check() } @Test - void checkNullJson() throws Exception + void checkNullJSON() throws Exception { when(dataProvider.getDataAsJSON()).thenThrow(new Exception("error while generating the json")); @@ -87,6 +87,6 @@ void checkUnsafeEncoding() throws Exception when(dataProvider.getDataAsJSON()).thenReturn(jsonResponse); assertEquals("adminTools.dashboard.healthcheck.security.system.lang.warn", langEncodingHealthCheck.check().getMessage()); - verify(logger).warn("System language encoding is [{}], but should be UTF-8!", "ISO-8859-1"); + verify(logger).warn("[{}] encoding is [{}], but should be UTF-8!", "System language", "ISO-8859-1"); } } diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml index c95223fa..0b15bdf2 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/AdminToolsJS.xml @@ -132,7 +132,7 @@ }; const runHealthCheckJob = function() { - $('#admin_tools_job_start').prop("disabled", true); + $('#healthCheckJobStart').prop('disabled', true); var data = []; data.push( {name: 'outputSyntax', value: 'plain'}, @@ -155,7 +155,7 @@ }).run(getHealthCheckActionPageURL(), data)).catch((reason) => { return Promise.reject(reason); }).finally(() => { - $('#admin_tools_job_start').prop("disabled", false); + $('#healthCheckJobStart').prop('disabled', false); }); }; @@ -165,17 +165,17 @@ // resource again. const initialiseJobJS = function() { $.get(getHealthCheckActionPageURL(), function(data) { - let jobJsURL = $(data).find('#jobJsURL').attr('data-jobJsURL'); + let jobJSURL = $(data).find('.jobJSURL').attr('data-jobJSURL'); require.config({ paths: { - 'health-check-job': jobJsURL + 'health-check-job': jobJSURL } }); require(['health-check-job'], function(){}); }); }; - const recallJobJs = function() { + const reinitializeJobJS = function() { require.undef('health-check-job'); require(['health-check-job'], function(){}); } @@ -184,33 +184,33 @@ $.get(getHealthCheckActionPageURL(), function(data) { let progressBar = $(data).find('div.ui-progress'); $('#healthCheck').find('.successmessage, .warningmessage, .errormessage').replaceWith(progressBar); - recallJobJs() + reinitializeJobJS() }); }; $(document).ready(function() { if ($('#healthCheck').length) { initialiseJobJS(); - let jobState = $('#healthCheckJobState').attr('data-jobState'); - if (jobState == "RUNNING") { + let jobState = $('.healthCheckJobState').attr('data-jobState'); + if (jobState == 'RUNNING') { runHealthCheckJob(); - $('.job-status').show(); - } else if (jobState == "FINISHED") { - $('.job-status').show(); + $('#healthCheck .job-status').show(); + } else if (jobState == 'FINISHED') { + $('#healthCheck .job-status').show(); } } }); - $(document).on('click', '.log-item-warn, .log-item-error', function(event) { - $(this).children(".recommendation").toggle(); + $(document).on('click', '#healthCheck .log-item-warn, #healthCheck .log-item-error', function(event) { + $(this).children('.recommendation').toggle(); }); - $(document).on('click', '#admin_tools_job_start', function(event) { + $(document).on('click', '#healthCheckJobStart', function(event) { event.preventDefault(); - $(".log").empty(); + $('#healthCheck .log').empty(); runHealthCheckJob(); reinitialiseHealthCheckResources(); - $('.job-status').show(); + $('#healthCheck .job-status').show(); }); $(document).on('click', '#downloadFilesModal .btn-primary', function(event) { diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml index b4f8cd17..db45950f 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckJob.xml @@ -39,10 +39,8 @@ {{velocity}} #template('job_macros.vm') #includeMacros("AdminTools.Code.HealthCheckMacros") - #set($jobId = $request.getParameterValues('jobId')) #set($jobStatus = $services.job.getJobStatus($jobId)) - #if ($jobStatus) #healthCheckOutputJobStatus($jobStatus) #else diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckMacros.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckMacros.xml index c4a509b1..8c587421 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckMacros.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckMacros.xml @@ -119,7 +119,7 @@ data-target-xpath="parent::*/following-sibling::*"> <span class="icon-closed">$services.icon.renderHTML('caret-right')</span> <span class="icon-opened">$services.icon.renderHTML('caret-down')</span> - Health Check Results + $escapetool.xml($services.localization.render('adminTools.dashboard.healthcheck.result')) </label> </dt> <dd>#printHealthCheckResults($status)</dd> @@ -140,7 +140,7 @@ '__ENDLINK__' ])).replace('__STARTLINK__', "<a href='$solutionLink'><strong>").replace('__ENDLINK__', ' </strong></a>')) - <span id="healthCheckJobState" + <span class="healthCheckJobState" data-jobState="${healthJobStatus.state}"> </span> <div class="adminToolsDashboardItem" id="healthCheck"> @@ -154,7 +154,7 @@ $services.date.displayTimeAgo($healthJobStatus.getEndDate()) </div> <div class="buttonwrapper"> - <button id="admin_tools_job_start" type="submit" class="btn btn-primary" name="startHealthCheck" + <button id="healthCheckJobStart" type="submit" class="btn btn-primary" name="startHealthCheck" value="startHealthCheck">$escapetool.xml($services.localization.render( 'adminTools.dashboard.healthcheck.start'))</button> </div> diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml index 9661c9b6..f534d5e4 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/HealthCheckResources.xml @@ -53,13 +53,13 @@ #end #macro (getHealthCheckJobResources) - #set ($jobJsURL = $xwiki.getSkinFile('uicomponents/job/job.js')) + #set ($jobJSURL = $xwiki.getSkinFile('uicomponents/job/job.js')) #set ($jobId = $services.admintools.getHealthCheckJobId()) #set ($healthJobStatus = $services.job.getJobStatus($jobId)) {{html clean=false}} <div> - <span id="jobJsURL" - data-jobJsURL="${jobJsURL}"> + <span class="jobJSURL" + data-jobJSURL="${jobJSURL}"> </span> #displayJobProgressBar($healthJobStatus) </div> diff --git a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml index 3d185440..b0137b19 100644 --- a/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml +++ b/application-admintools-ui/src/main/resources/AdminTools/Code/Translations.xml @@ -124,7 +124,7 @@ adminTools.job.notFound=Health check job status not found adminTools.dashboard.healthcheck.message.success=No issue found! adminTools.dashboard.healthcheck.message.warning=Some issues have been found, for more details please see the results below. adminTools.dashboard.healthcheck.message.error=Critical issues were found, please consult the results below! - +adminTools.dashboard.healthcheck.result=Health check results ## Security adminTools.dashboard.security.activeEncoding=Active encoding From c8b8a8e7bc8e9378d86e11e61bc343c3e1ae46fe Mon Sep 17 00:00:00 2001 From: ChiuchiuSorin Date: Thu, 7 Dec 2023 12:31:39 +0200 Subject: [PATCH 72/72] Create health check for size of the log files #35 - draft * Created a check for verifying the size of the logs folder --- .../checks/performance/LogsSizeCheck.java | 87 +++++++++++++++++++ .../main/resources/META-INF/components.txt | 1 + 2 files changed, 88 insertions(+) create mode 100644 application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/LogsSizeCheck.java diff --git a/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/LogsSizeCheck.java b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/LogsSizeCheck.java new file mode 100644 index 00000000..243b0870 --- /dev/null +++ b/application-admintools-default/src/main/java/com/xwiki/admintools/internal/health/checks/performance/LogsSizeCheck.java @@ -0,0 +1,87 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package com.xwiki.admintools.internal.health.checks.performance; + +import java.io.File; +import java.text.DecimalFormat; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.xwiki.component.annotation.Component; + +import com.xwiki.admintools.ServerIdentifier; +import com.xwiki.admintools.health.HealthCheck; +import com.xwiki.admintools.health.HealthCheckResult; +import com.xwiki.admintools.internal.data.identifiers.CurrentServer; + +@Component +@Named(LogsSizeCheck.HINT) +@Singleton +public class LogsSizeCheck implements HealthCheck +{ + /** + * Component identifier. + */ + public static final String HINT = "logSize"; + + @Inject + private CurrentServer currentServer; + + @Override + public HealthCheckResult check() + { + ServerIdentifier server = currentServer.getCurrentServer(); + + long logsSize = getFolderSize(server.getLogsFolderPath()); + + String[] units = new String[] { "B", "KB", "MB", "GB" }; + int unitIndex = (int) (Math.log10(logsSize) / 3); + double unitValue = 1 << (unitIndex * 10); + + String readableSize = new DecimalFormat("#,##0.#").format(logsSize / unitValue) + " " + units[unitIndex]; + + // NEED TO SET SOME METRICS. WHAT LOG SIZE IS TOO BIG? + if (logsSize / (1024 * 1024) > 500) { + return new HealthCheckResult("adminTools.dashboard.healthcheck.performance.cpu.info", "info"); + } else { + return new HealthCheckResult("adminTools.dashboard.healthcheck.performance.cpu.warn", + "adminTools.dashboard.healthcheck.performance.cpu.recommendation", "error", "cpuSpecifications"); + } + } + + public static long getFolderSize(String folderPath) + { + File folder = new File(folderPath); + long length = 0; + File[] files = folder.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isFile()) { + length += file.length(); + } else { + length += getFolderSize(file.getAbsolutePath()); + } + } + } + return length; + } +} diff --git a/application-admintools-default/src/main/resources/META-INF/components.txt b/application-admintools-default/src/main/resources/META-INF/components.txt index deb7fa2e..a3f0e4c1 100644 --- a/application-admintools-default/src/main/resources/META-INF/components.txt +++ b/application-admintools-default/src/main/resources/META-INF/components.txt @@ -20,6 +20,7 @@ com.xwiki.admintools.internal.health.checks.security.ConfigurationEncodingHealth com.xwiki.admintools.internal.health.checks.security.FileEncodingHealthCheck com.xwiki.admintools.internal.health.checks.security.LangEncodingHealthCheck com.xwiki.admintools.internal.health.checks.performance.CPUHealthCheck +com.xwiki.admintools.internal.health.checks.performance.LogsSizeCheck com.xwiki.admintools.internal.health.checks.performance.PhysicalMemoryHealthCheck com.xwiki.admintools.internal.health.checks.performance.PhysicalSpaceHealthCheck com.xwiki.admintools.internal.health.checks.memory.CacheMemoryHealthCheck