From 8da1e3ee4ea1d3e2f57a67061b47792a7d216b08 Mon Sep 17 00:00:00 2001 From: Andre Date: Sat, 7 Apr 2018 15:46:37 +0200 Subject: [PATCH 1/7] Use official JavaMelody AutoStarter --- admin-tools-demo-core/pom.xml | 8 +- .../main/java/de/chandre/admintool/Beans.java | 17 +++ .../admintool/JavaMelodyConfiguration.java | 117 ----------------- .../src/main/resources/application.properties | 3 +- .../src/main/resources/application.properties | 119 +++++++++--------- 5 files changed, 84 insertions(+), 180 deletions(-) delete mode 100644 admin-tools-demo-core/src/main/java/de/chandre/admintool/JavaMelodyConfiguration.java diff --git a/admin-tools-demo-core/pom.xml b/admin-tools-demo-core/pom.xml index b06496d..8fcfc80 100644 --- a/admin-tools-demo-core/pom.xml +++ b/admin-tools-demo-core/pom.xml @@ -86,7 +86,7 @@ de.chandre.quartz spring-boot-starter-quartz - 1.0.1 + 1.0.4 @@ -109,6 +109,12 @@ + + net.bull.javamelody + javamelody-spring-boot-starter + 1.71.0 + + org.springframework.boot spring-boot-starter-log4j2 diff --git a/admin-tools-demo-core/src/main/java/de/chandre/admintool/Beans.java b/admin-tools-demo-core/src/main/java/de/chandre/admintool/Beans.java index 707627e..83d0462 100644 --- a/admin-tools-demo-core/src/main/java/de/chandre/admintool/Beans.java +++ b/admin-tools-demo-core/src/main/java/de/chandre/admintool/Beans.java @@ -123,6 +123,23 @@ public Appender datasourceAppender(DataSource dataSource, AdminToolLog4j2Util lo final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); final Configuration config = ctx.getConfiguration(); +// ColumnConfig[] cc = { +// ColumnConfig.newBuilder().setConfiguration(config).setName("DATE").setEventTimestamp(true).build(), +// ColumnConfig.newBuilder().setConfiguration(config).setName("LEVEL").setPattern("%level").build(), +// ColumnConfig.newBuilder().setConfiguration(config).setName("LOGGER").setPattern("%logger").build(), +// ColumnConfig.newBuilder().setConfiguration(config).setName("MESSAGE").setPattern("%message").setClob(true).build(), +// ColumnConfig.newBuilder().setConfiguration(config).setName("EXCEPTION").setPattern("%ex{full}").setClob(true).build() +// }; +// +// Appender appender = JdbcAppender.newBuilder() +// .setBufferSize(0) +// .setColumnConfigs(cc) +// .setConnectionSource(new Connect(dataSource)) +// .setTableName("LOGGING") +// .withName("databaseAppender") +// .withIgnoreExceptions(false) +// .build(); + ColumnConfig[] cc = { ColumnConfig.createColumnConfig(config, "DATE", null, null, "true", null, null), ColumnConfig.createColumnConfig(config, "LEVEL", "%level", null, null, null, null), diff --git a/admin-tools-demo-core/src/main/java/de/chandre/admintool/JavaMelodyConfiguration.java b/admin-tools-demo-core/src/main/java/de/chandre/admintool/JavaMelodyConfiguration.java deleted file mode 100644 index bfef11f..0000000 --- a/admin-tools-demo-core/src/main/java/de/chandre/admintool/JavaMelodyConfiguration.java +++ /dev/null @@ -1,117 +0,0 @@ -package de.chandre.admintool; - -import javax.servlet.DispatcherType; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; -import org.springframework.aop.support.annotation.AnnotationMatchingPointcut; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.embedded.FilterRegistrationBean; -import org.springframework.boot.context.embedded.ServletContextInitializer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Controller; -import org.springframework.stereotype.Service; -import org.springframework.web.bind.annotation.RestController; - -import net.bull.javamelody.MonitoredWithAnnotationPointcut; -import net.bull.javamelody.MonitoringFilter; -import net.bull.javamelody.MonitoringSpringAdvisor; -import net.bull.javamelody.Parameter; -import net.bull.javamelody.SessionListener; -import net.bull.javamelody.SpringDataSourceBeanPostProcessor; - -/** - * - * @see https://github.com/javamelody/javamelody/wiki/UserGuideAdvanced#spring-boot-app - * @author speralta, evernat - */ -@Configuration -@ImportResource("classpath:net/bull/javamelody/monitoring-spring.xml") -@SuppressWarnings("javadoc") -public class JavaMelodyConfiguration implements ServletContextInitializer -{ - private static final Logger LOGGER = LogManager.getFormatterLogger(JavaMelodyConfiguration.class); - - @Override - public void onStartup(ServletContext servletContext) throws ServletException { - servletContext.addListener(new SessionListener()); - } - - @Bean - public FilterRegistrationBean javaMelody(Environment environment) { - FilterRegistrationBean javaMelody = new FilterRegistrationBean(); - javaMelody.setFilter(new MonitoringFilter()); - javaMelody.setAsyncSupported(true); - javaMelody.setName("javamelody"); - javaMelody.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC); - - // see the list of parameters: - // https://github.com/javamelody/javamelody/wiki/UserGuide#6-optional-parameters - //javaMelody.addInitParameter(Parameter.LOG.getCode(), Boolean.toString(true)); - // to add basic auth: - // javaMelody.addInitParameter(Parameter.AUTHORIZED_USERS.getCode(), "admin:pwd"); - // to change the default storage directory: - - if (null != environment.getProperty("javamelody.storage-directory")) { - javaMelody.addInitParameter(Parameter.STORAGE_DIRECTORY.getCode(), - environment.getProperty("javamelody.storage-directory")); - } - - javaMelody.addUrlPatterns("/*"); - return javaMelody; - } - - // Note: if you have auto-proxy issues, you can add the following dependency in your pom.xml: - // - // org.aspectj - // aspectjweaver - // - @Bean - public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() { - return new DefaultAdvisorAutoProxyCreator(); - } - - // monitoring of jdbc datasources: - @Bean - public SpringDataSourceBeanPostProcessor monitoringDataSourceBeanPostProcessor() { - final SpringDataSourceBeanPostProcessor processor = new SpringDataSourceBeanPostProcessor(); - processor.setExcludedDatasources(null); - return processor; - } - - // monitoring of beans or methods having @MonitoredWithSpring: - @Bean - public MonitoringSpringAdvisor monitoringAdvisor() { - final MonitoringSpringAdvisor interceptor = new MonitoringSpringAdvisor(); - interceptor.setPointcut(new MonitoredWithAnnotationPointcut()); - return interceptor; - } - - // monitoring of all services and controllers (even without having @MonitoredWithSpring): - @Bean - public MonitoringSpringAdvisor springServiceMonitoringAdvisor() { - final MonitoringSpringAdvisor interceptor = new MonitoringSpringAdvisor(); - interceptor.setPointcut(new AnnotationMatchingPointcut(Service.class)); - return interceptor; - } - - @Bean - public MonitoringSpringAdvisor springControllerMonitoringAdvisor() { - final MonitoringSpringAdvisor interceptor = new MonitoringSpringAdvisor(); - interceptor.setPointcut(new AnnotationMatchingPointcut(Controller.class)); - return interceptor; - } - - @Bean - public MonitoringSpringAdvisor springRestControllerMonitoringAdvisor() { - final MonitoringSpringAdvisor interceptor = new MonitoringSpringAdvisor(); - interceptor.setPointcut(new AnnotationMatchingPointcut(RestController.class)); - return interceptor; - } -} diff --git a/admin-tools-demo-jar/src/main/resources/application.properties b/admin-tools-demo-jar/src/main/resources/application.properties index eb2eaa2..9130cb5 100644 --- a/admin-tools-demo-jar/src/main/resources/application.properties +++ b/admin-tools-demo-jar/src/main/resources/application.properties @@ -5,8 +5,7 @@ server.port=8090 spring.application.name=AdminTool-Demo -#seperate by ";" -jminix.urlMappings=/jmx;/jmx/* +javamelody.enabled=true spring.thymeleaf.enabled=true spring.thymeleaf.encoding=UTF-8 diff --git a/admin-tools-demo-war/src/main/resources/application.properties b/admin-tools-demo-war/src/main/resources/application.properties index 14ee948..ecc9f92 100644 --- a/admin-tools-demo-war/src/main/resources/application.properties +++ b/admin-tools-demo-war/src/main/resources/application.properties @@ -1,61 +1,60 @@ -## The Spring application configuration file -## see: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties - -server.port=8090 - -spring.application.name=AdminTool-Demo - -#seperate by ";" -jminix.urlMappings=/jmx;/jmx/* - -spring.thymeleaf.enabled=true -spring.thymeleaf.encoding=UTF-8 - -flyway.enabled=false -flyway.locations=classpath:db/migration/h2 -flyway.baseline-on-migrate=true -flyway.table=SCHEMA_VERSION - -# disabling velocity resolver for controllers (Jminix Dependency) -spring.velocity.enabled=false - -spring.datasource.url=jdbc:h2:mem:datajpa -spring.datasource.username=sa -spring.datasource.password= -spring.datasource.driver-class-name=org.h2.Driver - -spring.datasource.tomcat.max-wait=100 -spring.datasource.tomcat.max-active=30 -spring.datasource.tomcat.min-idle=5 -spring.datasource.tomcat.test-on-borrow=true -spring.datasource.tomcat.validation-query=SELECT 1 - -spring.jpa.hibernate.ddl-auto=create-drop -spring.jpa.database-platform=org.hibernate.dialect.H2Dialect - -admintool.core.useCDN=true -admintool.core.fontAwsome.cdn.useBower=true - -admintool.dbbrowser.clobEncodings=UTF-8;UTF-16;ISO-8859-1 - -admintool.filebrowser.forbiddenDrives=c:\\;o:\\ -admintool.filebrowser.zipUseTempFile=false -admintool.filebrowser.restrictedBrowsing=true -admintool.filebrowser.restrictedBrowsingIsWhitelist=false -admintool.filebrowser.restrictedPaths=E:\\Programme\\cygwin\\ - -admintool.fileviewer.readOnly=false - -admintool.dbbrowser.hideMenuItem=false - -admintool.properties.componentPosition=1 -admintool.quartz.componentPosition=2 - -admintool.filebrowser.securityRoles=ROLE_ANONYMOUS;ROLE_ADMIN -admintool.log4j2.securityRoles=ROLE_ADMIN -admintool.jmx.securityRoles=ROLE_OPERATOR;ROLE_ADMIN -admintool.melody.securityRoles=ROLE_OPERATOR;ROLE_ADMIN -admintool.quartz.securityRoles.config=ROLE_ADMIN -admintool.quartz.securityRoles.jobs=ROLE_OPERATOR;ROLE_ADMIN -admintool.properties.securityRoles=ROLE_ANONYMOUS;ROLE_ADMIN +## The Spring application configuration file +## see: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties + +server.port=8090 + +spring.application.name=AdminTool-Demo + +javamelody.enabled=true + +spring.thymeleaf.enabled=true +spring.thymeleaf.encoding=UTF-8 + +flyway.enabled=false +flyway.locations=classpath:db/migration/h2 +flyway.baseline-on-migrate=true +flyway.table=SCHEMA_VERSION + +# disabling velocity resolver for controllers (Jminix Dependency) +spring.velocity.enabled=false + +spring.datasource.url=jdbc:h2:mem:datajpa +spring.datasource.username=sa +spring.datasource.password= +spring.datasource.driver-class-name=org.h2.Driver + +spring.datasource.tomcat.max-wait=100 +spring.datasource.tomcat.max-active=30 +spring.datasource.tomcat.min-idle=5 +spring.datasource.tomcat.test-on-borrow=true +spring.datasource.tomcat.validation-query=SELECT 1 + +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect + +admintool.core.useCDN=true +admintool.core.fontAwsome.cdn.useBower=true + +admintool.dbbrowser.clobEncodings=UTF-8;UTF-16;ISO-8859-1 + +admintool.filebrowser.forbiddenDrives=c:\\;o:\\ +admintool.filebrowser.zipUseTempFile=false +admintool.filebrowser.restrictedBrowsing=true +admintool.filebrowser.restrictedBrowsingIsWhitelist=false +admintool.filebrowser.restrictedPaths=E:\\Programme\\cygwin\\ + +admintool.fileviewer.readOnly=false + +admintool.dbbrowser.hideMenuItem=false + +admintool.properties.componentPosition=1 +admintool.quartz.componentPosition=2 + +admintool.filebrowser.securityRoles=ROLE_ANONYMOUS;ROLE_ADMIN +admintool.log4j2.securityRoles=ROLE_ADMIN +admintool.jmx.securityRoles=ROLE_OPERATOR;ROLE_ADMIN +admintool.melody.securityRoles=ROLE_OPERATOR;ROLE_ADMIN +admintool.quartz.securityRoles.config=ROLE_ADMIN +admintool.quartz.securityRoles.jobs=ROLE_OPERATOR;ROLE_ADMIN +admintool.properties.securityRoles=ROLE_ANONYMOUS;ROLE_ADMIN admintool.dbbrowser.securityRoles=ROLE_ADMIN \ No newline at end of file From e67ea27bda9530d1a233eb03f335d5da0993a350 Mon Sep 17 00:00:00 2001 From: Andre Date: Sat, 7 Apr 2018 15:47:38 +0200 Subject: [PATCH 2/7] Clean up --- .../core/security/TemplateUserService.java | 8 ++++ .../security/TemplateUserServiceImpl.java | 44 +++++++------------ .../i18n/admintool/core-messages.properties | 23 +++++----- 3 files changed, 35 insertions(+), 40 deletions(-) diff --git a/admin-tools-core-security/src/main/java/de/chandre/admintool/core/security/TemplateUserService.java b/admin-tools-core-security/src/main/java/de/chandre/admintool/core/security/TemplateUserService.java index 4403e9b..9da3a18 100644 --- a/admin-tools-core-security/src/main/java/de/chandre/admintool/core/security/TemplateUserService.java +++ b/admin-tools-core-security/src/main/java/de/chandre/admintool/core/security/TemplateUserService.java @@ -1,11 +1,19 @@ package de.chandre.admintool.core.security; +import org.springframework.security.core.Authentication; + /** * service used in templates to get some user information * @author Andre * @since 1.0.1 */ public interface TemplateUserService { + + /** + * returns the authentication object + * @return + */ + Authentication getAuthentication(); /** * should return the user name diff --git a/admin-tools-core-security/src/main/java/de/chandre/admintool/core/security/TemplateUserServiceImpl.java b/admin-tools-core-security/src/main/java/de/chandre/admintool/core/security/TemplateUserServiceImpl.java index fbfeca0..9e6f745 100644 --- a/admin-tools-core-security/src/main/java/de/chandre/admintool/core/security/TemplateUserServiceImpl.java +++ b/admin-tools-core-security/src/main/java/de/chandre/admintool/core/security/TemplateUserServiceImpl.java @@ -15,9 +15,10 @@ public class TemplateUserServiceImpl implements TemplateUserService { protected static final String ROLE_ANONYMOUS = "ROLE_ANONYMOUS"; - + @Override - public String getUserName() { + public Authentication getAuthentication() { + SecurityContext securityContext = SecurityContextHolder.getContext(); if (securityContext == null) return null; @@ -25,25 +26,24 @@ public String getUserName() { Authentication authentication = securityContext.getAuthentication(); if (authentication == null) return null; + return authentication; + } + @Override + public String getUserName() { + + Authentication authentication = getAuthentication(); if (authentication.getAuthorities().size() == 1 && authentication.getAuthorities().iterator().next().getAuthority().equals(ROLE_ANONYMOUS)) { return "Login"; } - return authentication.getName(); } @Override public boolean isAnonymous() { - SecurityContext securityContext = SecurityContextHolder.getContext(); - if (securityContext == null) - return true; - - Authentication authentication = securityContext.getAuthentication(); - if (authentication == null) - return true; - + + Authentication authentication = getAuthentication(); if (authentication instanceof AnonymousAuthenticationToken) { return true; } @@ -52,37 +52,23 @@ public boolean isAnonymous() { @Override public Object getUserDetails() { - SecurityContext securityContext = SecurityContextHolder.getContext(); - if (securityContext == null) - return null; - - Authentication authentication = securityContext.getAuthentication(); - if (authentication == null) - return null; - + + Authentication authentication = getAuthentication(); if (authentication.getAuthorities().size() == 1 && authentication.getAuthorities().iterator().next().getAuthority().equals(ROLE_ANONYMOUS)) { return null; } - return authentication.getDetails(); } @Override public Object getUserPrincipal() { - SecurityContext securityContext = SecurityContextHolder.getContext(); - if (securityContext == null) - return null; - - Authentication authentication = securityContext.getAuthentication(); - if (authentication == null) - return null; - + + Authentication authentication = getAuthentication(); if (authentication.getAuthorities().size() == 1 && authentication.getAuthorities().iterator().next().getAuthority().equals(ROLE_ANONYMOUS)) { return null; } - return authentication.getPrincipal(); } } diff --git a/admin-tools-core/src/main/resources/i18n/admintool/core-messages.properties b/admin-tools-core/src/main/resources/i18n/admintool/core-messages.properties index 89085fb..d9f91f6 100644 --- a/admin-tools-core/src/main/resources/i18n/admintool/core-messages.properties +++ b/admin-tools-core/src/main/resources/i18n/admintool/core-messages.properties @@ -1,12 +1,13 @@ -ui.admintool.core.menu.headline=MAINMENU - -ui.admintool.core.modal.error.title=Error -ui.admintool.core.modal.error.text=An Error has been occurred - -ui.admintool.core.modal.confirm.title=Confirm -ui.admintool.core.modal.confirm.text=Do you confirm? - -ui.admintool.core.modal.btn.save=Save -ui.admintool.core.modal.btn.delete=Delete -ui.admintool.core.modal.btn.close=Close +ui.admintool.core.menu.headline=MAINMENU + +ui.admintool.core.modal.error.title=Error +ui.admintool.core.modal.error.text=An Error has been occurred + +ui.admintool.core.modal.confirm.title=Confirm +ui.admintool.core.modal.confirm.text=Do you confirm? + +ui.admintool.core.modal.btn.save=Save +ui.admintool.core.modal.btn.add=Add +ui.admintool.core.modal.btn.delete=Delete +ui.admintool.core.modal.btn.close=Close ui.admintool.core.modal.btn.confirm=Confirm \ No newline at end of file From a45134509979a8fc9aea3320c687db88df166283 Mon Sep 17 00:00:00 2001 From: Andre Date: Sat, 7 Apr 2018 15:50:51 +0200 Subject: [PATCH 3/7] Fix #35 - sorting of root paths and file list should be initially by name in natural order --- .../AdminToolFilebrowserController.java | 10 +- .../AdminToolFilebrowserService.java | 458 ++++----- .../AdminToolFilebrowserServiceImpl.java | 29 +- .../filebrowser/content/filebrowser.html | 882 +++++++++--------- 4 files changed, 707 insertions(+), 672 deletions(-) diff --git a/admin-tools-filebrowser/src/main/java/de/chandre/admintool/filebrowser/AdminToolFilebrowserController.java b/admin-tools-filebrowser/src/main/java/de/chandre/admintool/filebrowser/AdminToolFilebrowserController.java index e6b05c5..2f56059 100644 --- a/admin-tools-filebrowser/src/main/java/de/chandre/admintool/filebrowser/AdminToolFilebrowserController.java +++ b/admin-tools-filebrowser/src/main/java/de/chandre/admintool/filebrowser/AdminToolFilebrowserController.java @@ -16,6 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; @@ -108,7 +109,7 @@ public void download(@RequestParam("file") String filePath, ModelMap model, Http } @RequestMapping(value = {"/zip"}, method={RequestMethod.GET, RequestMethod.POST}) - public void downloadAsZip(@RequestParam("selectedFile") List filePaths, ModelMap model, HttpServletRequest request, + public void downloadAsZip(@RequestParam(name="selectedFile", required=false) List filePaths, ModelMap model, HttpServletRequest request, HttpServletResponse response) throws IOException, DownloadNotAllowedException, GenericFilebrowserException { if (!filebrowserConfig.isEnabled()) { return; @@ -126,9 +127,10 @@ public void downloadAsZip(@RequestParam("selectedFile") List filePaths, } }); } - - if(LOGGER.isTraceEnabled()) LOGGER.trace("downloadAsZip file: " + decodedPaths.size()); - filebrowserService.downloadFilesAsZip(decodedPaths, response); + if (!CollectionUtils.isEmpty(decodedPaths)) { + if(LOGGER.isTraceEnabled()) LOGGER.trace("downloadAsZip file: " + decodedPaths.size()); + filebrowserService.downloadFilesAsZip(decodedPaths, response); + } } @RequestMapping(value = {"/upload"}, method={RequestMethod.POST}) diff --git a/admin-tools-filebrowser/src/main/java/de/chandre/admintool/filebrowser/AdminToolFilebrowserService.java b/admin-tools-filebrowser/src/main/java/de/chandre/admintool/filebrowser/AdminToolFilebrowserService.java index f6b109b..2abade2 100644 --- a/admin-tools-filebrowser/src/main/java/de/chandre/admintool/filebrowser/AdminToolFilebrowserService.java +++ b/admin-tools-filebrowser/src/main/java/de/chandre/admintool/filebrowser/AdminToolFilebrowserService.java @@ -1,229 +1,229 @@ -package de.chandre.admintool.filebrowser; - -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.io.FileUtils; -import org.springframework.web.multipart.MultipartFile; - -/** - * interface for file browser service - * @author Andre - * - */ -public interface AdminToolFilebrowserService { - - /** - * checks if file is allowed to access - * - * @param path - * @param write - * @param configReadOnly - * @return - * @throws IOException - */ - public boolean isAllowed(File path, boolean write, boolean configReadOnly) throws IOException; - - /** - * to url-encode a string - * - * @param path - * @return - * @throws UnsupportedEncodingException - */ - String encodeURL(String path) throws UnsupportedEncodingException; - - /** - * returns all root directories - * @return - */ - Set getRootDirs(); - - /** - * returns if the currentDir starts with rootDir - * @param rootDir - * @param currentDir - * @return - */ - boolean isRootActive(String rootDir, String currentDir); - - /** - * returns the parent of directory - * @param dir - * @return - * @throws IOException - */ - String getParent(String dir) throws IOException; - - /** - * lists all directories within the directory - * @param currentDir - * @param sortCol - * @param sortAsc - * @return - * @throws IOException - */ - List getDirectories(String currentDir, SortColumn sortCol, Boolean sortAsc, String filter) throws IOException; - - /** - * lists all files within the directory - * @param currentDir - * @param sortCol - * @param sortAsc - * @return - * @throws IOException - */ - List getFiles(String currentDir, SortColumn sortCol, Boolean sortAsc, String filter) throws IOException; - - /** - * @param currentDir - * @return - */ - String getDirOrRootName(File currentDir); - - /** - * return a ordered list of files of directories - * @param currentDir - * @return - */ - List getBreadcrumb(String currentDir); - - /** - * @see #downloadFile(String, HttpServletResponse, String) - * @param filePath - * @param response - * @param if content-disposition: attachment should be set to header - * @throws DownloadNotAllowedException - * @throws GenericFilebrowserException - */ - void downloadFile(String filePath, HttpServletResponse response, boolean asAttachment) - throws DownloadNotAllowedException, GenericFilebrowserException; - - /** - * put's the file to servlet output stream - * @param filePath - * @param response - * @param alternativeFileName - * @param if content-disposition: attachment should be set to header - * @throws DownloadNotAllowedException - * @throws GenericFilebrowserException - */ - - void downloadFile(String filePath, HttpServletResponse response, String alternativeFileName, boolean asAttachment) - throws DownloadNotAllowedException, GenericFilebrowserException; - - /** - * creates a zip of given files and put's it to servlet output stream - * - * @param filePaths - * @param response - * @throws GenericFilebrowserException - */ - void downloadFilesAsZip(List filePaths, HttpServletResponse response) throws GenericFilebrowserException; - - /** - * returns the sum of file size of all files within the directory - * @param dir - * @return - * @throws IOException - */ - String getFileSizeSum(String dir, String filter) throws IOException; - - /** - * returns the last change date - * @param file - * @return - * @throws IOException - */ - Date getLastChange(File file) throws IOException; - - /** - * return the fileType ("DIR" or file extension) - * @param file - * @return - */ - String getFileType(File file); - - /** - * returns the file size - * @param file - * @return - */ - String getFileSize(File file); - - /** - * return "up", "down" or empty string - * @param current - * @param sortCol - * @param sortAsc - * @return - */ - String getSortDirection(int current, SortColumn sortCol, Boolean sortAsc); - - /** - * - * @param file - * @return - */ - String accessibleCSS(File file); - - /** - * - * @param path - * @throws IOException - * @throws GenericFilebrowserException - */ - String createFolder(String path, String folderName) throws IOException, GenericFilebrowserException; - - /** - * deletes a file or folder - * - * @param path - * @return - * @throws IOException - * @throws GenericFilebrowserException - */ - String deleteResource(String path) throws IOException, GenericFilebrowserException; - - /** - * returns a map with gathered file information - * @param path - * @return - * @throws IOException - */ - Map getFileInfo(String path) throws IOException; - - /** - * calculates the file size with configured parameters, except that it's scaled additionally - * - * @param fileLength - * @return - */ - String getFileSize(long fileLength); - - /** - * calculates the file size like {@link FileUtils}, except that it's scaled additionally - * - * @param fileLength - * @return - */ - String getNormalFileSize(long fileLength); - - /** - * - * @param decodedPath - * @param upload - * @return - * @throws IOException - * @throws GenericFilebrowserException - * @since 1.1.6 - */ - boolean saveFile(String decodedPath, MultipartFile upload) throws IOException, GenericFilebrowserException; -} +package de.chandre.admintool.filebrowser; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.FileUtils; +import org.springframework.web.multipart.MultipartFile; + +/** + * interface for file browser service + * @author Andre + * + */ +public interface AdminToolFilebrowserService { + + /** + * checks if file is allowed to access + * + * @param path + * @param write + * @param configReadOnly + * @return + * @throws IOException + */ + public boolean isAllowed(File path, boolean write, boolean configReadOnly) throws IOException; + + /** + * to url-encode a string + * + * @param path + * @return + * @throws UnsupportedEncodingException + */ + String encodeURL(String path) throws UnsupportedEncodingException; + + /** + * returns all root directories + * @return + */ + Collection getRootDirs(); + + /** + * returns if the currentDir starts with rootDir + * @param rootDir + * @param currentDir + * @return + */ + boolean isRootActive(String rootDir, String currentDir); + + /** + * returns the parent of directory + * @param dir + * @return + * @throws IOException + */ + String getParent(String dir) throws IOException; + + /** + * lists all directories within the directory + * @param currentDir + * @param sortCol + * @param sortAsc + * @return + * @throws IOException + */ + List getDirectories(String currentDir, SortColumn sortCol, Boolean sortAsc, String filter) throws IOException; + + /** + * lists all files within the directory + * @param currentDir + * @param sortCol + * @param sortAsc + * @return + * @throws IOException + */ + List getFiles(String currentDir, SortColumn sortCol, Boolean sortAsc, String filter) throws IOException; + + /** + * @param currentDir + * @return + */ + String getDirOrRootName(File currentDir); + + /** + * return a ordered list of files of directories + * @param currentDir + * @return + */ + List getBreadcrumb(String currentDir); + + /** + * @see #downloadFile(String, HttpServletResponse, String) + * @param filePath + * @param response + * @param if content-disposition: attachment should be set to header + * @throws DownloadNotAllowedException + * @throws GenericFilebrowserException + */ + void downloadFile(String filePath, HttpServletResponse response, boolean asAttachment) + throws DownloadNotAllowedException, GenericFilebrowserException; + + /** + * put's the file to servlet output stream + * @param filePath + * @param response + * @param alternativeFileName + * @param if content-disposition: attachment should be set to header + * @throws DownloadNotAllowedException + * @throws GenericFilebrowserException + */ + + void downloadFile(String filePath, HttpServletResponse response, String alternativeFileName, boolean asAttachment) + throws DownloadNotAllowedException, GenericFilebrowserException; + + /** + * creates a zip of given files and put's it to servlet output stream + * + * @param filePaths + * @param response + * @throws GenericFilebrowserException + */ + void downloadFilesAsZip(List filePaths, HttpServletResponse response) throws GenericFilebrowserException; + + /** + * returns the sum of file size of all files within the directory + * @param dir + * @return + * @throws IOException + */ + String getFileSizeSum(String dir, String filter) throws IOException; + + /** + * returns the last change date + * @param file + * @return + * @throws IOException + */ + Date getLastChange(File file) throws IOException; + + /** + * return the fileType ("DIR" or file extension) + * @param file + * @return + */ + String getFileType(File file); + + /** + * returns the file size + * @param file + * @return + */ + String getFileSize(File file); + + /** + * return "up", "down" or empty string + * @param current + * @param sortCol + * @param sortAsc + * @return + */ + String getSortDirection(int current, SortColumn sortCol, Boolean sortAsc); + + /** + * + * @param file + * @return + */ + String accessibleCSS(File file); + + /** + * + * @param path + * @throws IOException + * @throws GenericFilebrowserException + */ + String createFolder(String path, String folderName) throws IOException, GenericFilebrowserException; + + /** + * deletes a file or folder + * + * @param path + * @return + * @throws IOException + * @throws GenericFilebrowserException + */ + String deleteResource(String path) throws IOException, GenericFilebrowserException; + + /** + * returns a map with gathered file information + * @param path + * @return + * @throws IOException + */ + Map getFileInfo(String path) throws IOException; + + /** + * calculates the file size with configured parameters, except that it's scaled additionally + * + * @param fileLength + * @return + */ + String getFileSize(long fileLength); + + /** + * calculates the file size like {@link FileUtils}, except that it's scaled additionally + * + * @param fileLength + * @return + */ + String getNormalFileSize(long fileLength); + + /** + * + * @param decodedPath + * @param upload + * @return + * @throws IOException + * @throws GenericFilebrowserException + * @since 1.1.6 + */ + boolean saveFile(String decodedPath, MultipartFile upload) throws IOException, GenericFilebrowserException; +} diff --git a/admin-tools-filebrowser/src/main/java/de/chandre/admintool/filebrowser/AdminToolFilebrowserServiceImpl.java b/admin-tools-filebrowser/src/main/java/de/chandre/admintool/filebrowser/AdminToolFilebrowserServiceImpl.java index af37451..06d3d62 100644 --- a/admin-tools-filebrowser/src/main/java/de/chandre/admintool/filebrowser/AdminToolFilebrowserServiceImpl.java +++ b/admin-tools-filebrowser/src/main/java/de/chandre/admintool/filebrowser/AdminToolFilebrowserServiceImpl.java @@ -22,6 +22,7 @@ import java.nio.file.attribute.PosixFilePermissions; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; @@ -30,7 +31,6 @@ import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; -import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.zip.ZipEntry; @@ -79,19 +79,22 @@ public class AdminToolFilebrowserServiceImpl extends AbstractFileBrowserService @Autowired private Environment env; - private Set rootDirsCache = Collections.newSetFromMap(new ConcurrentHashMap<>()); + private List rootDirsCache = new ArrayList<>(); @Override - public Set getRootDirs() { + public Collection getRootDirs() { File[] roots = File.listRoots(); if (this.rootDirsCache.isEmpty()) { - for (File file : roots) { - if(!config.getForbiddenDrives().contains(file.getAbsolutePath().toLowerCase())) { - // if not forbidden add it to result - this.rootDirsCache.add(file.getAbsolutePath()); + synchronized (this.rootDirsCache) { + for (File file : roots) { + if(!config.getForbiddenDrives().contains(file.getAbsolutePath().toLowerCase())) { + // if not forbidden add it to result + this.rootDirsCache.add(file.getAbsolutePath()); + } } + Collections.sort(this.rootDirsCache); } } return this.rootDirsCache; @@ -114,10 +117,13 @@ public String getParent(String dir) throws IOException { return ""; } - protected List sort(File[] fileAr, final SortColumn sortCol, Boolean sortAsc) { + protected List sort(File[] fileAr, SortColumn sortCol, Boolean sortAsc) { List files = Arrays.asList(fileAr); + final SortColumn sortColToUse; if (null == sortCol) { - return files; + sortColToUse = SortColumn.NAME; + } else { + sortColToUse = sortCol; } if (null == sortAsc) { sortAsc = Boolean.TRUE; @@ -128,7 +134,7 @@ protected List sort(File[] fileAr, final SortColumn sortCol, Boolean sortA @Override public int compare(File o1, File o2) { try { - switch (sortCol) { + switch (sortColToUse) { case DATE: return getLastChange(o1).compareTo(getLastChange(o2)) * direction; case SIZE: @@ -150,6 +156,9 @@ public int compare(File o1, File o2) { @Override public String getSortDirection(int current, SortColumn sortCol, Boolean sortAsc) { + if(null == sortCol) { + return "up"; + } if (current == sortCol.getIndex() && sortAsc != null) { return sortAsc ? "up" : "down"; } diff --git a/admin-tools-filebrowser/src/main/resources/templates/admintool/filebrowser/content/filebrowser.html b/admin-tools-filebrowser/src/main/resources/templates/admintool/filebrowser/content/filebrowser.html index db0aab3..02850dd 100644 --- a/admin-tools-filebrowser/src/main/resources/templates/admintool/filebrowser/content/filebrowser.html +++ b/admin-tools-filebrowser/src/main/resources/templates/admintool/filebrowser/content/filebrowser.html @@ -1,429 +1,453 @@ - - - -
-
-

- Filebrowser -

- -
- -
- -
- -
- -

- - -

- -
- -
-

- - - / - -

-
- -
-
- - -
-
- -
-
-
- -
-
- - -
-
-
-
- - - - - - -
-
-
-
-
- -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - Actions -
- - - -
- - - -
- - - - - - - -
- -
- - - - - - - - - - - - - - - - - - - - - -
-
-
- -
- -
- - - - - - - - - - -
- - -
- - - - + + + +
+
+

+ Filebrowser +

+ +
+ +
+ +
+ +
+ +

+ + +

+ +
+ +
+

+ + + / + +

+
+ +
+
+ + +
+
+ +
+
+
+ +
+
+ + +
+
+
+
+ + + + + + +
+
+
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + Actions +
+ + + +
+ + + +
+ + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+ + + + + + + + + + +
+ + +
+ + + + From 2ce26814db132765a19213e6dcacfaddb996477d Mon Sep 17 00:00:00 2001 From: Andre Date: Sat, 7 Apr 2018 15:53:42 +0200 Subject: [PATCH 4/7] Close #36 - view of java.util.Date as readable date --- .../de/chandre/admintool/ExampleMXBean.java | 43 +++++++++++++ .../resources/static/admintool/jmx/js/jmx.js | 62 +++++++++++-------- 2 files changed, 80 insertions(+), 25 deletions(-) create mode 100644 admin-tools-demo-core/src/main/java/de/chandre/admintool/ExampleMXBean.java diff --git a/admin-tools-demo-core/src/main/java/de/chandre/admintool/ExampleMXBean.java b/admin-tools-demo-core/src/main/java/de/chandre/admintool/ExampleMXBean.java new file mode 100644 index 0000000..80130ea --- /dev/null +++ b/admin-tools-demo-core/src/main/java/de/chandre/admintool/ExampleMXBean.java @@ -0,0 +1,43 @@ +package de.chandre.admintool; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Date; + +import org.springframework.stereotype.Component; + +import de.chandre.admintool.core.AdminToolConfig; + +@Component +public class ExampleMXBean implements AdminToolConfig { + + public Date getDate() { + return new Date(); + } + + public LocalDate getLocalDate() { + return LocalDate.now(); + } + + public LocalDateTime getLocalDateTime() { + return LocalDateTime.now(); + } + + public Double getDouble() { + return Double.valueOf(123.456d); + } + + public double getPrimitiveDouble() { + return 654.321d; + } + + @Override + public void printConfig() { + + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/admin-tools-jminix/src/main/resources/static/admintool/jmx/js/jmx.js b/admin-tools-jminix/src/main/resources/static/admintool/jmx/js/jmx.js index 54a6f87..359f4bd 100644 --- a/admin-tools-jminix/src/main/resources/static/admintool/jmx/js/jmx.js +++ b/admin-tools-jminix/src/main/resources/static/admintool/jmx/js/jmx.js @@ -11,6 +11,7 @@ $.extend(AdminTool.Jmx.prototype, { name : 'adminToolJmx', postInit: function() { + this.debug=false; this.initJsTree() }, @@ -60,9 +61,11 @@ $.extend(AdminTool.Jmx.prototype, { var selectedNode = data.instance.get_node(data.selected[0]); if (selectedNode.type == 'attributes') { - console.log('The selected node is: ' + selectedNode.text); - console.log('The selected parent is: ' + selectedNode.parent); - console.log('The selected parents parent is: ' + data.instance.get_node(selectedNode.parent).parent); + if (console && this.debug) { + console.log('The selected node is: ' + selectedNode.text); + console.log('The selected parent is: ' + selectedNode.parent); + console.log('The selected parents parent is: ' + data.instance.get_node(selectedNode.parent).parent); + } var domain = this.getParent(data, selectedNode.parent); var queryData = { @@ -71,17 +74,11 @@ $.extend(AdminTool.Jmx.prototype, { 'server' : this.getParent(data, domain) }; - console.log(queryData); - - this.sendRequest({ - url: "/admintool/jmx/attributes", - requestType:'POST', - dataType: "json", - data: JSON.stringify(queryData), - my: this - }, - $.proxy(this.viewAttributeList, this)); - + if (console && this.debug) { + console.log(queryData); + } + this.loadAttribute("attributes", queryData); + } else if (selectedNode.type == 'attribute' || selectedNode.type == 'operation') { console.log('The selected node is: ' + selectedNode.text); @@ -99,10 +96,11 @@ $.extend(AdminTool.Jmx.prototype, { 'domain' : domain, 'server' : server }; - console.log(queryData); - + if (console && this.debug) { + console.log(queryData); + } if(isAttribute) { - this.loadAttribute(queryData); + this.loadAttribute("attribute", queryData); } else { this.sendRequest({ url: "/admintool/jmx/operation", @@ -115,7 +113,9 @@ $.extend(AdminTool.Jmx.prototype, { } } catch (e) { - console.log(e) + if (console) { + console.log(e) + } } } } @@ -132,15 +132,17 @@ $.extend(AdminTool.Jmx.prototype, { return data.instance.get_node(currentNode).parent; }, - loadAttribute: function(queryData) { + loadAttribute: function(urlSuffix, queryData) { + this.sendRequest({ - url: "/admintool/jmx/attribute", + url: "/admintool/jmx/" + urlSuffix, requestType:'POST', dataType: "json", data: JSON.stringify(queryData), showModalOnError: true, showXHRErrorInModal: true, my: this, + urlSuffix: urlSuffix }, $.proxy(this.viewAttributeList, this)); }, @@ -156,6 +158,8 @@ $.extend(AdminTool.Jmx.prototype, { } else if (Array.isArray(method.value) || typeof method.value === 'object') { data.methods[i].value = JSON.stringify(method.value, null, "\t"); + } else if (method.type == "java.util.Date" || method.type == "java.sql.Date") { + data.methods[i].value = new Date(method.value) + " (TS: "+method.value+")" } } @@ -167,11 +171,18 @@ $.extend(AdminTool.Jmx.prototype, { } } $('#jmxView').html(result); - $('#jmxView').find('#refreshView').on('click', $.proxy(this.loadAttribute, this, orgData)); + $('#jmxView').find('#refreshView').on('click', $.proxy(this.loadAttribute, this, query.urlSuffix, orgData)); + + clearTimeout(this.loadTimout); + this.loadTimout = window.setTimeout(function() { + $('.fa-refresh').removeClass("fa-spin") + }, 800); }, viewOperation: function(data, query) { - console.log(data) + if (console && this.debug) { + console.log(data); + } var result = ""; if (data && data.methods && data.methods.length > 0) { @@ -203,7 +214,8 @@ $.extend(AdminTool.Jmx.prototype, { var msg = $('#jmxView').find('#save_success'); if (msg && msg.length > 0) { - window.setTimeout(function() { + clearTimeout(this.saveTimout); + this.saveTimout = window.setTimeout(function() { $("#save_success").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); }); @@ -245,7 +257,7 @@ $.pluginMaker(AdminTool.Jmx); var attributeListTpl = '
'+ '

{{headline}}

'+ - '
'+ + '
'+ '
'+ '
'+ '' + @@ -261,7 +273,7 @@ Mustache.parse(attributeListTpl); var attributeTpl = '
'+ '

{{name}}

'+ - '
'+ + '
'+ '
'+ '
' + '' + From ba0f89947226c9e34de178342a78936a0938c060 Mon Sep 17 00:00:00 2001 From: Andre Date: Sat, 7 Apr 2018 15:56:29 +0200 Subject: [PATCH 5/7] #37 - option to create custom loggers --- .../log4j2/AdminLog4j2Controller.java | 380 ++++--- .../admintool/log4j2/AdminToolLog4j2Util.java | 1007 ++++++++++------- .../log4j2/Log4j2ManageLoggerTO.java | 101 ++ .../resources/static/admintool/css/log4j2.css | 123 +- .../resources/static/admintool/js/log4j2.js | 768 +++++++------ .../templates/admintool/content/log4j2.html | 340 ++++-- 6 files changed, 1605 insertions(+), 1114 deletions(-) create mode 100644 admin-tools-log4j2/src/main/java/de/chandre/admintool/log4j2/Log4j2ManageLoggerTO.java diff --git a/admin-tools-log4j2/src/main/java/de/chandre/admintool/log4j2/AdminLog4j2Controller.java b/admin-tools-log4j2/src/main/java/de/chandre/admintool/log4j2/AdminLog4j2Controller.java index 4c50ad7..2005ce0 100644 --- a/admin-tools-log4j2/src/main/java/de/chandre/admintool/log4j2/AdminLog4j2Controller.java +++ b/admin-tools-log4j2/src/main/java/de/chandre/admintool/log4j2/AdminLog4j2Controller.java @@ -1,169 +1,211 @@ -package de.chandre.admintool.log4j2; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.logging.log4j.Level; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; - -import de.chandre.admintool.core.AdminTool; - -@Controller -@RequestMapping(AdminTool.ROOTCONTEXT + "/log4j2") -public class AdminLog4j2Controller -{ - private static final Log LOGGER = LogFactory.getLog(AdminLog4j2Controller.class); - - @Autowired - private AdminToolLog4j2Config config; - - @Autowired - private AdminToolLog4j2Util log4jUtil; - - @RequestMapping(value = "/changeLevel/{loggerName}/{level}", method = {RequestMethod.POST, RequestMethod.GET}) - @ResponseBody - public String changeLevel(@PathVariable("loggerName") String loggerName, @PathVariable("level") String level, - HttpServletRequest request) - { - if (!config.isEnabled()) { - return null; - } - return changeLevelParent(loggerName, level, false, request); - } - - @RequestMapping(value = "/changeLevel/{loggerName}/{level}/parent/{parent}", method = {RequestMethod.POST, RequestMethod.GET}) - @ResponseBody - public String changeLevelParent(@PathVariable("loggerName") String loggerName, @PathVariable("level") String level, - @PathVariable("parent") boolean parent, HttpServletRequest request) - { - if (!config.isEnabled()) { - return null; - } - LOGGER.info(String.format("change %s to %s (parent: %s)", loggerName, level, parent)); - try { - log4jUtil.changeLogger(loggerName, level, parent); - } catch (Exception e) { - return "false"; - } - if (loggerName.equals("ROOT") || parent) { - return "reload"; - } - return "true"; - } - - @RequestMapping(value = "/removeCustomLoggers", method = {RequestMethod.POST, RequestMethod.GET}) - @ResponseBody - public String removeCustomLoggers() { - if (!config.isEnabled()) { - return null; - } - LOGGER.info(String.format("removing custom loggers")); - log4jUtil.removeCustomLoggers(); - return "reload"; - } - - @RequestMapping(value = "/getLevels", method = RequestMethod.GET) - @ResponseBody - public Collection getLevels(HttpServletRequest request) - { - List res = new ArrayList<>(); - for (Level level : log4jUtil.getLevels()) { - res.add(level.name()); - } - return res; - } - - @RequestMapping(value = "/getLevelCss/{prefix}", method = RequestMethod.GET) - @ResponseBody - public Map getLevelCssClass(@PathVariable("prefix") String prefix, HttpServletRequest request) - { - Map css = new HashMap<>(); - for (Level level : log4jUtil.getLevels()) { - css.put(level.name(), log4jUtil.getLoggerLevelCss(prefix, level)); - } - return css; - } - - @RequestMapping(value = "/initConsole", method = RequestMethod.POST) - @ResponseBody - public String initConsole(@RequestBody Log4j2ConsoleTO consoleTO, HttpServletRequest request) - { - if (!config.isEnabled()) { - return null; - } - try { - HttpSession session = request.getSession(true); - - if (session.getAttribute(AdminToolLog4j2Util.SESSION_APPENDER_NAME) != null) { - // there is already a output stream which should be closed first - log4jUtil.closeOutputStreamAppender(String.class.cast(session.getAttribute(AdminToolLog4j2Util.SESSION_APPENDER_NAME))); - } - - String name = log4jUtil.createOutputStreamAppender(consoleTO.getName(), consoleTO.getPattern(), consoleTO.getEncoding(), - consoleTO.getLoggerNames(), consoleTO.getLevel(), consoleTO.isRecursive(), consoleTO.isOverrideLogLevel()); - session.setAttribute(AdminToolLog4j2Util.SESSION_APPENDER_NAME, name); - LOGGER.debug(String.format("log4j console initialized: %s, %s", consoleTO.getLevel(), consoleTO.getEncoding())); - } catch (Exception e) { - LOGGER.error(e.getMessage(), e); - return "false"; - } - return "true"; - } - - @RequestMapping(value = "/stopConsole", method = {RequestMethod.GET, RequestMethod.POST}) - @ResponseBody - public String stopConsole(HttpServletRequest request) - { - if (!config.isEnabled()) { - return null; - } - try { - HttpSession session = request.getSession(false); - log4jUtil.closeOutputStreamAppender(String.class.cast(session.getAttribute(AdminToolLog4j2Util.SESSION_APPENDER_NAME))); - } catch (Exception e) { - LOGGER.error(e.getMessage(), e); - return "false"; - } - return "true"; - } - - @RequestMapping(value = {"/getConsoleContent", "/getConsoleContent/"}, method = {RequestMethod.GET, RequestMethod.POST}) - @ResponseBody - public String getConsoleContent(HttpServletRequest request) - { - if (!config.isEnabled()) { - return null; - } - return getConsoleContent(null, request); - } - - @RequestMapping(value = "/getConsoleContent/{encoding}", method = {RequestMethod.GET, RequestMethod.POST}) - @ResponseBody - public String getConsoleContent(@PathVariable("encoding") String encoding, HttpServletRequest request) - { - if (!config.isEnabled()) { - return null; - } - try { - HttpSession session = request.getSession(false); - return log4jUtil.getStringOutput(String.class.cast(session.getAttribute(AdminToolLog4j2Util.SESSION_APPENDER_NAME)), encoding); - } catch (Exception e) { - LOGGER.error(e.getMessage(), e); - return e.getMessage(); - } - } -} +package de.chandre.admintool.log4j2; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.logging.log4j.Level; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import de.chandre.admintool.core.AdminTool; + +@Controller +@RequestMapping(AdminTool.ROOTCONTEXT + "/log4j2") +public class AdminLog4j2Controller +{ + private static final Log LOGGER = LogFactory.getLog(AdminLog4j2Controller.class); + + private static final String RESULT_ACTION_RELOAD = "reload"; + private static final String RESULT_TRUE = Boolean.TRUE.toString(); + private static final String RESULT_FALSE = Boolean.FALSE.toString(); + + @Autowired + private AdminToolLog4j2Config config; + + @Autowired + private AdminToolLog4j2Util log4jUtil; + + @RequestMapping(value = "/changeLevel/{loggerName}/{level}", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String changeLevel(@PathVariable("loggerName") String loggerName, @PathVariable("level") String level, + HttpServletRequest request) + { + if (!config.isEnabled()) { + return null; + } + return changeLevelParent(loggerName, level, false, request); + } + + @RequestMapping(value = "/changeLevel/{loggerName}/{level}/parent/{parent}", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String changeLevelParent(@PathVariable("loggerName") String loggerName, @PathVariable("level") String level, + @PathVariable("parent") boolean parent, HttpServletRequest request) + { + if (!config.isEnabled()) { + return null; + } + LOGGER.info(String.format("change %s to %s (parent: %s)", loggerName, level, parent)); + try { + log4jUtil.changeLogger(loggerName, level, parent); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + return RESULT_FALSE; + } + if (loggerName.equals("ROOT") || parent) { + return RESULT_ACTION_RELOAD; + } + return RESULT_TRUE; + } + + /** + * + * @param manageTO + * @param request + * @return + * @since 1.1.6.4 + */ + @RequestMapping(value = "/manageLogger", method = RequestMethod.POST) + @ResponseBody + public String manageLogger(@RequestBody Log4j2ManageLoggerTO manageTO, HttpServletRequest request) + { + if (!config.isEnabled()) { + return RESULT_FALSE; + } + LOGGER.info(String.format("manage logger %s", manageTO)); + try { + log4jUtil.addCustomParentLogger(manageTO.isAdditivity(), manageTO.getLevel(), manageTO.getLoggerName(), manageTO.getAppenderNames()); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + return RESULT_FALSE; + } + return RESULT_ACTION_RELOAD; + } + + @RequestMapping(value = "/removeCustomLoggers", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String removeCustomLoggers() { + if (!config.isEnabled()) { + return null; + } + LOGGER.info(String.format("removing custom loggers")); + log4jUtil.removeCustomLoggers(); + return RESULT_ACTION_RELOAD; + } + + @RequestMapping(value = "/removeCustomParentLogger", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String removeCustomParentLogger() { + if (!config.isEnabled()) { + return null; + } + LOGGER.info(String.format("removing custom loggers")); + log4jUtil.removeCustomParentLoggers(); + return RESULT_ACTION_RELOAD; + } + + + + @RequestMapping(value = "/getLevels", method = RequestMethod.GET) + @ResponseBody + public Collection getLevels(HttpServletRequest request) + { + List res = new ArrayList<>(); + for (Level level : log4jUtil.getLevels()) { + res.add(level.name()); + } + return res; + } + + @RequestMapping(value = "/getLevelCss/{prefix}", method = RequestMethod.GET) + @ResponseBody + public Map getLevelCssClass(@PathVariable("prefix") String prefix, HttpServletRequest request) + { + Map css = new HashMap<>(); + for (Level level : log4jUtil.getLevels()) { + css.put(level.name(), log4jUtil.getLoggerLevelCss(prefix, level)); + } + return css; + } + + @RequestMapping(value = "/initConsole", method = RequestMethod.POST) + @ResponseBody + public String initConsole(@RequestBody Log4j2ConsoleTO consoleTO, HttpServletRequest request) + { + if (!config.isEnabled()) { + return null; + } + try { + HttpSession session = request.getSession(true); + + if (session.getAttribute(AdminToolLog4j2Util.SESSION_APPENDER_NAME) != null) { + // there is already a output stream which should be closed first + log4jUtil.closeOutputStreamAppender(String.class.cast(session.getAttribute(AdminToolLog4j2Util.SESSION_APPENDER_NAME))); + } + + String name = log4jUtil.createOutputStreamAppender(consoleTO.getName(), consoleTO.getPattern(), consoleTO.getEncoding(), + consoleTO.getLoggerNames(), consoleTO.getLevel(), consoleTO.isRecursive(), consoleTO.isOverrideLogLevel()); + session.setAttribute(AdminToolLog4j2Util.SESSION_APPENDER_NAME, name); + LOGGER.debug(String.format("log4j console initialized: %s, %s", consoleTO.getLevel(), consoleTO.getEncoding())); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + return RESULT_FALSE; + } + return RESULT_TRUE; + } + + @RequestMapping(value = "/stopConsole", method = {RequestMethod.GET, RequestMethod.POST}) + @ResponseBody + public String stopConsole(HttpServletRequest request) + { + if (!config.isEnabled()) { + return null; + } + try { + HttpSession session = request.getSession(false); + log4jUtil.closeOutputStreamAppender(String.class.cast(session.getAttribute(AdminToolLog4j2Util.SESSION_APPENDER_NAME))); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + return RESULT_FALSE; + } + return RESULT_TRUE; + } + + @RequestMapping(value = {"/getConsoleContent", "/getConsoleContent/"}, method = {RequestMethod.GET, RequestMethod.POST}) + @ResponseBody + public String getConsoleContent(HttpServletRequest request) + { + if (!config.isEnabled()) { + return null; + } + return getConsoleContent(null, request); + } + + @RequestMapping(value = "/getConsoleContent/{encoding}", method = {RequestMethod.GET, RequestMethod.POST}) + @ResponseBody + public String getConsoleContent(@PathVariable("encoding") String encoding, HttpServletRequest request) + { + if (!config.isEnabled()) { + return null; + } + try { + HttpSession session = request.getSession(false); + return log4jUtil.getStringOutput(String.class.cast(session.getAttribute(AdminToolLog4j2Util.SESSION_APPENDER_NAME)), encoding); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + return e.getMessage(); + } + } +} diff --git a/admin-tools-log4j2/src/main/java/de/chandre/admintool/log4j2/AdminToolLog4j2Util.java b/admin-tools-log4j2/src/main/java/de/chandre/admintool/log4j2/AdminToolLog4j2Util.java index 0bc7a94..b1459c9 100644 --- a/admin-tools-log4j2/src/main/java/de/chandre/admintool/log4j2/AdminToolLog4j2Util.java +++ b/admin-tools-log4j2/src/main/java/de/chandre/admintool/log4j2/AdminToolLog4j2Util.java @@ -1,435 +1,572 @@ -package de.chandre.admintool.log4j2; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeSet; -import java.util.UUID; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.core.Appender; -import org.apache.logging.log4j.core.Logger; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.appender.OutputStreamAppender; -import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.LoggerConfig; -import org.apache.logging.log4j.core.layout.PatternLayout; -import org.apache.logging.log4j.spi.StandardLevel; -import org.springframework.stereotype.Service; -import org.springframework.util.ConcurrentReferenceHashMap; -import org.springframework.util.StringUtils; - -/** - * service for log4j2 manipulation - * @author Andre - * @since 1.0.0 - */ -@Service("adminToolLog4j2Util") -public class AdminToolLog4j2Util -{ - private static List LEVELS = new ArrayList<>(7); - static { - LEVELS.add(Level.OFF); - LEVELS.add(Level.TRACE); - LEVELS.add(Level.DEBUG); - LEVELS.add(Level.INFO); - LEVELS.add(Level.WARN); - LEVELS.add(Level.ERROR); - LEVELS.add(Level.FATAL); - } - - private static final Comparator LOGGER_COMP = new Comparator() { - @Override - public int compare(Logger o1, Logger o2) { - return o1.getName().compareTo(o2.getName()); - } - }; - - private static final String DEFAULT_PATTERN = "%d{dd.MM.yyyy HH:mm:ss.SSS} %X{sessionId} [%t] %-5level %logger{36} : %msg%n"; - - public static final String SESSION_APPENDER_NAME = "log4j2AppenderName"; - - private Map customLoggers = new ConcurrentReferenceHashMap<>(); - private Map customParentLoggers = new ConcurrentReferenceHashMap<>(); - - private Map outputStreams = new ConcurrentReferenceHashMap<>(); - - public int getCustomLoggerSize() { - return customLoggers.size(); - } - - public int getCustomParentLoggerSize() { - return customParentLoggers.size(); - } - - /** - * returns all parent loggers - * @return - */ - public Collection getParentLoggers() { - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - List loggers = new ArrayList<>(ctx.getLoggers()); - Map parentMap = new HashMap<>(); - try { - for (Logger logger : loggers) { - if (null != logger.getParent() && parentMap.get(logger.getParent().getName()) == null) { - parentMap.put(logger.getParent().getName(), logger.getParent()); - } - } - List parents = new ArrayList<>(parentMap.values()); - Collections.sort(parents, LOGGER_COMP); - return parents; - } finally { - loggers.clear(); - parentMap.clear(); - } - } - - public Collection getParentLoggerNames() { - List loggerNames = new ArrayList<>(); - for (Logger logger : getParentLoggers()) { - loggerNames.add(logger.getName()); - } - return loggerNames; - } - - /** - * returns all loggers - * @return - */ - public Collection getLoggers() { - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - List loggers = new ArrayList<>(ctx.getLoggers()); - Collections.sort(loggers, LOGGER_COMP); - return loggers; - } - - /** - * returns all logger names including custom loggers - * - * @since 1.1.1 - * @return - */ - public Collection getAllLoggerNames() { - Set loggerNames = new TreeSet<>(); - for (Logger logger : getParentLoggers()) { - loggerNames.add(logger.getName()); - } - for (Logger logger : getLoggers()) { - loggerNames.add(logger.getName()); - } - if (!customLoggers.isEmpty()) { - for (Entry entry : customLoggers.entrySet()) { - loggerNames.add(entry.getKey().getName()); - } - } - if (!customParentLoggers.isEmpty()) { - for (Entry entry : customParentLoggers.entrySet()) { - loggerNames.add(entry.getKey().getName()); - } - } - return loggerNames; - } - - /** - * returns the a css class with optional prefix for the particular log level.
- * if prefix is set result will be <prefix>-<css-class> - * - * @param prefix (optional) a prefic - * @param level the log level - * @return - */ - public String getLoggerLevelCss(String prefix, Level level) { - if (null == prefix) { - prefix = ""; - } else { - prefix += "-"; - } - if (level.intLevel() == StandardLevel.TRACE.intLevel()) { - return prefix + "info"; - } - if (level.intLevel() == StandardLevel.DEBUG.intLevel()) { - return prefix + "primary"; - } - if (level.intLevel() == StandardLevel.INFO.intLevel()) { - return prefix + "success"; - } - if (level.intLevel() == StandardLevel.WARN.intLevel()) { - return prefix + "warning"; - } - if (level.intLevel() == StandardLevel.ERROR.intLevel()) { - return prefix + "danger"; - } - if (level.intLevel() == StandardLevel.FATAL.intLevel()) { - return prefix + "muted"; - } - if (level.intLevel() == StandardLevel.OFF.intLevel()) { - return prefix + "muted"; - } - return ""; - } - - /** - * returns fix amount of logger levels - * @return - */ - public Collection getLevels() { - return LEVELS; - } - - private Level getLevel(final String levelStr) { - Level level = Level.getLevel(levelStr); - if (null == level || !LEVELS.contains(level)) { - throw new IllegalArgumentException("wrong logger level: " + String.valueOf(levelStr)); - } - return level; - } - - /** - * changes the level of an logger - * - * @param name logger name - * @param levelStr level as string - * @param parent if the logger is a parent logger - * @throws IllegalArgumentException - */ - public void changeLogger(final String name, final String levelStr, boolean parent) throws IllegalArgumentException - { - Level level = getLevel(levelStr); - changeLogger(name, level, parent); - } - - /** - * - * @param name - * @param level - * @param parent - * @throws IllegalArgumentException - * @see {@link #changeLogger(String, String, boolean)} - */ - public void changeLogger(final String name, final Level level, boolean parent) throws IllegalArgumentException - { - if (null == name) { - throw new IllegalArgumentException("logger name must not null"); - } - String loggerName = name; - if (name.equals("ROOT")) { - loggerName = LogManager.ROOT_LOGGER_NAME; - } - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - Configuration config = ctx.getConfiguration(); - LoggerConfig loggerConfig = config.getLoggerConfig(loggerName); - if (null == loggerConfig) { - throw new IllegalArgumentException("no logger config found for: " + String.valueOf(loggerName)); - } - if (customLoggers.containsValue(loggerName)) { - setLevelOnExistingCustomLogger(this.customLoggers, loggerName, level); - } - else if (customParentLoggers.containsValue(loggerName)) { - setLevelOnExistingCustomLogger(this.customParentLoggers, loggerName, level); - } - else if (!loggerConfig.getName().equals(loggerName)) { - LoggerConfig loggerConfigNew = new LoggerConfig(); - loggerConfigNew.setLevel(level); - config.addLogger(loggerName, loggerConfigNew); - if (parent) { - customParentLoggers.put(loggerConfigNew, loggerName); - } else { - customLoggers.put(loggerConfigNew, loggerName); - } - } - else { - loggerConfig.setLevel(level); - } - ctx.updateLoggers(); - } - - private void setLevelOnExistingCustomLogger(Map customLoggers, String loggerName, Level level) { - for (Entry entry : customLoggers.entrySet()) { - if (entry.getValue().equals(loggerName)) { - entry.getKey().setLevel(level); - } - } - } - - /** - * removes all custom loggers - * - * @throws IllegalArgumentException - */ - public void removeCustomLoggers() throws IllegalArgumentException - { - if (customLoggers.isEmpty()) { - return; - } - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - Configuration config = ctx.getConfiguration(); - for (Entry entry : customLoggers.entrySet()) { - config.removeLogger(entry.getValue()); - } - ctx.updateLoggers(); - customLoggers.clear(); - } - - /** - * returns the default log message pattern (used in template) - * @return - * @since 1.1.1 - */ - public String getDefaultPattern() { - return DEFAULT_PATTERN; - } - - /** - * creates the custom output steam appender and returns the name - * - * @param name - * @param pattern - * @param encoding - * @param loggerNames - * @param levelStr - * @return - * @since 1.1.1 - */ - public String createOutputStreamAppender(String name, String pattern, String encoding, Collection loggerNames, - String levelStr, boolean recursive, boolean overrideLogLevel) { - Level level = getLevel(levelStr); - String encodingToUse = StringUtils.isEmpty(encoding) ? "UTF-8" : encoding; - PatternLayout layout = PatternLayout.newBuilder() - .withPattern(StringUtils.isEmpty(pattern) ? DEFAULT_PATTERN : pattern) - .withCharset(Charset.forName(encodingToUse)) - .build(); - - String appenderName = StringUtils.isEmpty(name) ? UUID.randomUUID().toString() : name; - - AdminToolLog4j2OutputStream baos = new AdminToolLog4j2OutputStream(4096, encodingToUse); - outputStreams.put(appenderName, baos); - - OutputStreamAppender appender = OutputStreamAppender.newBuilder() - .setName(appenderName) - .setTarget(baos) - .setLayout(layout) - .setFollow(false) - .build(); - - appender.start(); - - final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - final Configuration config = ctx.getConfiguration(); - config.addAppender(appender); - - Collection parentLoggerNames = getParentLoggerNames(); - - for (String configuredLoggerName : getAllLoggerNames()) { - for (String loggerNameToApply : loggerNames) { - - boolean apply = (recursive && configuredLoggerName.startsWith(loggerNameToApply)) - || (!recursive && configuredLoggerName.equalsIgnoreCase(loggerNameToApply)); - - if (apply) { - LoggerConfig loggerConfig = config.getLoggerConfig(configuredLoggerName); - loggerConfig.addAppender(appender, level, null); - if (overrideLogLevel) { - baos.addOriginalLevel(configuredLoggerName, loggerConfig.getLevel()); - changeLogger(configuredLoggerName, level, parentLoggerNames.contains(configuredLoggerName)); - } - } - } - - } - ctx.updateLoggers(); - return appenderName; - } - - /** - * returns the log messages from custom appenders output stream - * - * @param appenderName - * @param encoding - * @return - * @throws UnsupportedEncodingException - * @since 1.1.1 - */ - public String getStringOutput(String appenderName, String encoding) throws UnsupportedEncodingException { - AdminToolLog4j2OutputStream baos = outputStreams.get(appenderName); - String output = ""; - if (null != baos) { - output = baos.getAndReset(encoding); - } - return output.trim().isEmpty() ? null : output; - - } - - /** - * closes output stream and removes appender from loggers - * @param appenderName - * @throws IOException - * @since 1.1.1 - */ - public void closeOutputStreamAppender(String appenderName) throws IOException { - if (null == appenderName) { - return; - } - final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - final Configuration config = ctx.getConfiguration(); - AdminToolLog4j2OutputStream baos = outputStreams.get(appenderName); - - if (null != config && null != config.getAppenders()) { - OutputStreamAppender appender = config.getAppender(appenderName); - if (null != appender) { - appender.stop(); - - Collection parentLoggerNames = getParentLoggerNames(); - - for (String configuredLoggerName : getAllLoggerNames()) { - LoggerConfig loggerConfig = config.getLoggerConfig(configuredLoggerName); - loggerConfig.removeAppender(appender.getName()); - if (null != baos.getOriginalLevel(configuredLoggerName)) { - changeLogger(configuredLoggerName, baos.getOriginalLevel(configuredLoggerName), - parentLoggerNames.contains(configuredLoggerName)); - } - } - //unsure about, if removing the appender from logger config if it gets also removed from logger instance too... - removeAppender(appender, getParentLoggers()); - removeAppender(appender, getLoggers()); - appender.getManager().getByteBuffer().clear(); - - ctx.updateLoggers(); - } - } - - if (null != baos) { - try { - baos.close(); - baos.clearOriginalLevels(); - } catch (Exception ignore) { - } finally { - outputStreams.remove(appenderName); - } - } - } - - private void removeAppender(Appender appender, Collection appenders) { - for (Logger logger : appenders) { - logger.removeAppender(appender); - } - } - - public Map getAppenders() { - final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - final Configuration config = ctx.getConfiguration(); - - return config.getAppenders(); - } - -} +package de.chandre.admintool.log4j2; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeSet; +import java.util.UUID; +import java.util.stream.Collectors; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Appender; +import org.apache.logging.log4j.core.Logger; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.appender.OutputStreamAppender; +import org.apache.logging.log4j.core.config.AppenderRef; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.LoggerConfig; +import org.apache.logging.log4j.core.layout.PatternLayout; +import org.apache.logging.log4j.spi.StandardLevel; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import org.springframework.util.ConcurrentReferenceHashMap; +import org.springframework.util.StringUtils; + +/** + * service for log4j2 manipulation + * @author Andre + * @since 1.0.0 + */ +@Service("adminToolLog4j2Util") +public class AdminToolLog4j2Util +{ + private static List LEVELS = new ArrayList<>(7); + static { + LEVELS.add(Level.OFF); + LEVELS.add(Level.TRACE); + LEVELS.add(Level.DEBUG); + LEVELS.add(Level.INFO); + LEVELS.add(Level.WARN); + LEVELS.add(Level.ERROR); + LEVELS.add(Level.FATAL); + } + + private static final Comparator LOGGER_COMP = new Comparator() { + @Override + public int compare(Logger o1, Logger o2) { + return o1.getName().compareTo(o2.getName()); + } + }; + + private static final String DEFAULT_PATTERN = "%d{dd.MM.yyyy HH:mm:ss.SSS} %X{sessionId} [%t] %-5level %logger{36} : %msg%n"; + + public static final String SESSION_APPENDER_NAME = "log4j2AppenderName"; + + private Map customLoggers = new ConcurrentReferenceHashMap<>(); + private Map customParentLoggers = new ConcurrentReferenceHashMap<>(); + + private Map outputStreams = new ConcurrentReferenceHashMap<>(); + + public int getCustomLoggerSize() { + return customLoggers.size(); + } + + public int getCustomParentLoggerSize() { + return customParentLoggers.size(); + } + + public boolean isCustom(String name) { + return customLoggers.containsValue(name) || customParentLoggers.containsValue(name); + } + + /** + * returns all parent loggers + * @return + */ + public Collection getParentLoggers() { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + List loggers = new ArrayList<>(ctx.getLoggers()); + Map parentMap = new HashMap<>(); + try { + for (Logger logger : loggers) { + if (null != logger.getParent() && parentMap.get(logger.getParent().getName()) == null) { + parentMap.put(logger.getParent().getName(), logger.getParent()); + } + } + List parents = new ArrayList<>(parentMap.values()); + Collections.sort(parents, LOGGER_COMP); + return parents; + } finally { + loggers.clear(); + parentMap.clear(); + } + } + + public Collection getParentLoggerNames() { + List loggerNames = new ArrayList<>(); + for (Logger logger : getParentLoggers()) { + loggerNames.add(logger.getName()); + } + return loggerNames; + } + + /** + * returns all loggers + * @return + */ + public Collection getLoggers() { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + List loggers = new ArrayList<>(ctx.getLoggers()); + Collections.sort(loggers, LOGGER_COMP); + return loggers; + } + + /** + * returns all logger names including custom loggers + * + * @since 1.1.1 + * @return + */ + public Collection getAllLoggerNames() { + Set loggerNames = new TreeSet<>(); + for (Logger logger : getParentLoggers()) { + loggerNames.add(logger.getName()); + } + for (Logger logger : getLoggers()) { + loggerNames.add(logger.getName()); + } + if (!customLoggers.isEmpty()) { + for (Entry entry : customLoggers.entrySet()) { + loggerNames.add(entry.getKey().getName()); + } + } + if (!customParentLoggers.isEmpty()) { + for (Entry entry : customParentLoggers.entrySet()) { + loggerNames.add(entry.getKey().getName()); + } + } + return loggerNames; + } + + /** + * returns the a css class with optional prefix for the particular log level.
+ * if prefix is set result will be <prefix>-<css-class> + * + * @param prefix (optional) a prefic + * @param level the log level + * @return + */ + public String getLoggerLevelCss(String prefix, Level level) { + if (null == prefix) { + prefix = ""; + } else { + prefix += "-"; + } + if (level.intLevel() == StandardLevel.TRACE.intLevel()) { + return prefix + "info"; + } + if (level.intLevel() == StandardLevel.DEBUG.intLevel()) { + return prefix + "primary"; + } + if (level.intLevel() == StandardLevel.INFO.intLevel()) { + return prefix + "success"; + } + if (level.intLevel() == StandardLevel.WARN.intLevel()) { + return prefix + "warning"; + } + if (level.intLevel() == StandardLevel.ERROR.intLevel()) { + return prefix + "danger"; + } + if (level.intLevel() == StandardLevel.FATAL.intLevel()) { + return prefix + "muted"; + } + if (level.intLevel() == StandardLevel.OFF.intLevel()) { + return prefix + "muted"; + } + return ""; + } + + /** + * returns fix amount of logger levels + * @return + */ + public Collection getLevels() { + return LEVELS; + } + + private Level getLevel(final String levelStr) { + Level level = Level.getLevel(levelStr); + if (null == level || !LEVELS.contains(level)) { + throw new IllegalArgumentException("wrong logger level: " + String.valueOf(levelStr)); + } + return level; + } + + /** + * changes the level of an logger + * + * @param name logger name + * @param levelStr level as string + * @param parent if the logger is a parent logger + * @throws IllegalArgumentException + */ + public void changeLogger(final String name, final String levelStr, boolean parent) throws IllegalArgumentException + { + Level level = getLevel(levelStr); + changeLogger(name, level, parent); + } + + /** + * + * @param name + * @param level + * @param parent + * @throws IllegalArgumentException + * @see {@link #changeLogger(String, String, boolean)} + */ + public void changeLogger(final String name, final Level level, boolean parent) throws IllegalArgumentException + { + if (null == name) { + throw new IllegalArgumentException("logger name must not null"); + } + String loggerName = name; + if (name.equals("ROOT")) { + loggerName = LogManager.ROOT_LOGGER_NAME; + } + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + LoggerConfig loggerConfig = config.getLoggerConfig(loggerName); + if (null == loggerConfig) { + throw new IllegalArgumentException("no logger config found for: " + String.valueOf(loggerName)); + } + if (customLoggers.containsValue(loggerName)) { + setLevelOnExistingCustomLogger(this.customLoggers, loggerName, level); + } + else if (customParentLoggers.containsValue(loggerName)) { + setLevelOnExistingCustomLogger(this.customParentLoggers, loggerName, level); + } + else if (!loggerConfig.getName().equals(loggerName)) { +// LoggerConfig loggerConfigNew = new LoggerConfig(); +// loggerConfigNew.setLevel(level); +// config.addLogger(loggerName, loggerConfigNew); +// if (parent) { +// customParentLoggers.put(loggerConfigNew, loggerName); +// } else { +// customLoggers.put(loggerConfigNew, loggerName); +// } + addCustomParentLogger(false, level, loggerName, Arrays.asList("Console")); + } + else { + loggerConfig.setLevel(level); + } + ctx.updateLoggers(); + } + + private void setLevelOnExistingCustomLogger(Map customLoggers, String loggerName, Level level) { + for (Entry entry : customLoggers.entrySet()) { + if (entry.getValue().equals(loggerName)) { + entry.getKey().setLevel(level); + } + } + } + + public Collection getAppenderNames() { + final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + final Configuration config = ctx.getConfiguration(); + return config.getAppenders().keySet(); + } + + public String getAppendersForLogger(String loggerName) { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + LoggerConfig loggerConfig = config.getLoggerConfig(loggerName); + List appenderRefs = loggerConfig.getAppenderRefs(); + return StringUtils.collectionToCommaDelimitedString(appenderRefs.parallelStream().map(ar -> ar.getRef()).collect(Collectors.toSet())); + } + + /** + * + * @param additivity + * @param level + * @param loggerName + * @param appenderNames + * @param recursive + * + * @since 1.1.6.4 + */ + public void addCustomParentLogger(boolean additivity, String levelStr, String loggerName, Collection appenderNames) { + Level level = getLevel(levelStr); + addCustomParentLogger(additivity, level, loggerName, appenderNames); + } + + /** + * + * @param additivity + * @param level + * @param loggerName + * @param appenderNames + * @param recursive + * + * @since 1.1.6.4 + */ + public void addCustomParentLogger(boolean additivity, Level level, String loggerName, Collection appenderNames) { + if (StringUtils.isEmpty(loggerName)) { + throw new IllegalArgumentException("loggerName should not be null"); + } + if (null == level) { + throw new IllegalArgumentException("level should not be null"); + } + + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + + if (null == appenderNames) { + appenderNames = Collections.emptyList(); + } + List appenderRefs = appenderNames.stream() + .map(name -> AppenderRef.createAppenderRef(name, null, null)) + .collect(Collectors.toList()); + + LoggerConfig loggerConfigForTest = config.getLoggerConfig(loggerName); + List appenderRefsToAdd = new ArrayList<>(appenderNames); + final LoggerConfig loggerConfig; + if (null == loggerConfigForTest || StringUtils.isEmpty(loggerConfigForTest.getName()) || !loggerConfigForTest.getName().equals(loggerName)) { + //create a new Logger + loggerConfig = LoggerConfig.createLogger(additivity, level, loggerName, "true", appenderRefs.toArray(new AppenderRef[]{}), null, config, null); + customParentLoggers.put(loggerConfig, loggerName); + } + else { + //manage a existing logger + loggerConfig = config.getLoggerConfig(loggerName); + //remove appenderRef which are not selected anymore + List currentRefs = loggerConfig.getAppenderRefs(); + Iterator refIter = currentRefs.iterator(); + while (refIter.hasNext()) { + AppenderRef ref = (AppenderRef) refIter.next(); + if (!appenderNames.contains(ref.getRef())) { + refIter.remove(); + loggerConfig.removeAppender(ref.getRef()); + } else { + appenderRefsToAdd.remove(ref.getRef()); + } + + } + //add appendersRefs + if (!CollectionUtils.isEmpty(appenderRefsToAdd)) { + appenderRefsToAdd.forEach(appenderRefName -> { + loggerConfig.getAppenderRefs().add(AppenderRef.createAppenderRef(appenderRefName, null, null)); + }); + } + } + + config.getAppenders().entrySet().stream() + .filter(entry -> appenderRefsToAdd.contains(entry.getKey())) + .forEach(appenderEntry -> loggerConfig.addAppender(appenderEntry.getValue(), null, null)); + + config.addLogger(loggerName, loggerConfig); + ctx.updateLoggers(); + } + + /** + * removes all custom loggers (without parents) + * + * @throws IllegalArgumentException + */ + public void removeCustomLoggers() throws IllegalArgumentException + { + removeCustomLoggers(customLoggers); + } + + /** + * removes all custom parent loggers + * @throws IllegalArgumentException + */ + public void removeCustomParentLoggers() throws IllegalArgumentException + { + removeCustomLoggers(customParentLoggers); + } + + public void removeCustomLoggers(Map customMap) throws IllegalArgumentException + { + if (customMap.isEmpty()) { + return; + } + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + for (Entry entry : customMap.entrySet()) { + config.removeLogger(entry.getValue()); + } + ctx.updateLoggers(); + customMap.clear(); + } + + + /** + * returns the default log message pattern (used in template) + * @return + * @since 1.1.1 + */ + public String getDefaultPattern() { + return DEFAULT_PATTERN; + } + + /** + * creates the custom output steam appender and returns the name + * + * @param name + * @param pattern + * @param encoding + * @param loggerNames + * @param levelStr + * @return + * @since 1.1.1 + */ + public String createOutputStreamAppender(String name, String pattern, String encoding, Collection loggerNames, + String levelStr, boolean recursive, boolean overrideLogLevel) { + Level level = getLevel(levelStr); + String encodingToUse = StringUtils.isEmpty(encoding) ? "UTF-8" : encoding; + PatternLayout layout = PatternLayout.newBuilder() + .withPattern(StringUtils.isEmpty(pattern) ? DEFAULT_PATTERN : pattern) + .withCharset(Charset.forName(encodingToUse)) + .build(); + + String appenderName = StringUtils.isEmpty(name) ? UUID.randomUUID().toString() : name; + + AdminToolLog4j2OutputStream baos = new AdminToolLog4j2OutputStream(4096, encodingToUse); + outputStreams.put(appenderName, baos); + + OutputStreamAppender appender = OutputStreamAppender.newBuilder() + .setName(appenderName) + .setTarget(baos) + .setLayout(layout) + .setFollow(false) + .build(); + + appender.start(); + + final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + final Configuration config = ctx.getConfiguration(); + config.addAppender(appender); + + Collection parentLoggerNames = getParentLoggerNames(); + + Map configs = getRecursiveLoggerConfigs(loggerNames, recursive, config); + configs.entrySet().forEach(configEntry ->{ + configEntry.getValue().addAppender(appender, level, null); + if (overrideLogLevel) { + baos.addOriginalLevel(configEntry.getKey(), configEntry.getValue().getLevel()); + changeLogger(configEntry.getKey(), level, parentLoggerNames.contains(configEntry.getKey())); + } + }); + + ctx.updateLoggers(); + return appenderName; + } + + /** + * + * @param loggerNames + * @param recursive + * @param config + * @return + */ + private Map getRecursiveLoggerConfigs(Collection loggerNames, boolean recursive, + final Configuration config) { + Map configs = new HashMap<>(); + for (String configuredLoggerName : getAllLoggerNames()) { + for (String loggerNameToApply : loggerNames) { + + boolean apply = (recursive && configuredLoggerName.startsWith(loggerNameToApply)) + || (!recursive && configuredLoggerName.equalsIgnoreCase(loggerNameToApply)); + if (apply) { + configs.put(configuredLoggerName, config.getLoggerConfig(configuredLoggerName)); + } + } + } + return configs; + } + + /** + * returns the log messages from custom appenders output stream + * + * @param appenderName + * @param encoding + * @return + * @throws UnsupportedEncodingException + * @since 1.1.1 + */ + public String getStringOutput(String appenderName, String encoding) throws UnsupportedEncodingException { + AdminToolLog4j2OutputStream baos = outputStreams.get(appenderName); + String output = ""; + if (null != baos) { + output = baos.getAndReset(encoding); + } + return output.trim().isEmpty() ? null : output; + + } + + /** + * closes output stream and removes appender from loggers + * @param appenderName + * @throws IOException + * @since 1.1.1 + */ + public void closeOutputStreamAppender(String appenderName) throws IOException { + if (null == appenderName) { + return; + } + final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + final Configuration config = ctx.getConfiguration(); + AdminToolLog4j2OutputStream baos = outputStreams.get(appenderName); + + if (null != config && null != config.getAppenders()) { + OutputStreamAppender appender = config.getAppender(appenderName); + if (null != appender) { + appender.stop(); + + Collection parentLoggerNames = getParentLoggerNames(); + + for (String configuredLoggerName : getAllLoggerNames()) { + LoggerConfig loggerConfig = config.getLoggerConfig(configuredLoggerName); + loggerConfig.removeAppender(appender.getName()); + if (null != baos.getOriginalLevel(configuredLoggerName)) { + changeLogger(configuredLoggerName, baos.getOriginalLevel(configuredLoggerName), + parentLoggerNames.contains(configuredLoggerName)); + } + } + //unsure about, if removing the appender from logger config if it gets also removed from logger instance too... + removeAppender(appender, getParentLoggers()); + removeAppender(appender, getLoggers()); + appender.getManager().getByteBuffer().clear(); + + ctx.updateLoggers(); + } + } + + if (null != baos) { + try { + baos.close(); + baos.clearOriginalLevels(); + } catch (Exception ignore) { + } finally { + outputStreams.remove(appenderName); + } + } + } + + private void removeAppender(Appender appender, Collection appenders) { + for (Logger logger : appenders) { + logger.removeAppender(appender); + } + } + + public Map getAppenders() { + final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + final Configuration config = ctx.getConfiguration(); + + return config.getAppenders(); + } + +} diff --git a/admin-tools-log4j2/src/main/java/de/chandre/admintool/log4j2/Log4j2ManageLoggerTO.java b/admin-tools-log4j2/src/main/java/de/chandre/admintool/log4j2/Log4j2ManageLoggerTO.java new file mode 100644 index 0000000..fee158b --- /dev/null +++ b/admin-tools-log4j2/src/main/java/de/chandre/admintool/log4j2/Log4j2ManageLoggerTO.java @@ -0,0 +1,101 @@ +package de.chandre.admintool.log4j2; + +import java.io.Serializable; +import java.util.List; + +/** + * + * @author Chandre + * @since 1.1.6.4 + */ +public class Log4j2ManageLoggerTO implements Serializable { + private static final long serialVersionUID = 991894759701275970L; + + private String loggerName; + + private List appenderNames; + + private String level; + + private boolean additivity; + + public String getLoggerName() { + return loggerName; + } + + public void setLoggerName(String loggerName) { + this.loggerName = loggerName; + } + + public List getAppenderNames() { + return appenderNames; + } + + public void setAppenderNames(List appenderNames) { + this.appenderNames = appenderNames; + } + + public String getLevel() { + return level; + } + + public void setLevel(String level) { + this.level = level; + } + + public boolean isAdditivity() { + return additivity; + } + + public void setAdditivity(boolean additivity) { + this.additivity = additivity; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Log4j2ManageLoggerTO [loggerName=").append(loggerName).append(", appenderNames=").append(appenderNames) + .append(", level=").append(level).append(", additivity=").append(additivity).append("]"); + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (additivity ? 1231 : 1237); + result = prime * result + ((appenderNames == null) ? 0 : appenderNames.hashCode()); + result = prime * result + ((level == null) ? 0 : level.hashCode()); + result = prime * result + ((loggerName == null) ? 0 : loggerName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Log4j2ManageLoggerTO other = (Log4j2ManageLoggerTO) obj; + if (additivity != other.additivity) + return false; + if (appenderNames == null) { + if (other.appenderNames != null) + return false; + } else if (!appenderNames.equals(other.appenderNames)) + return false; + if (level == null) { + if (other.level != null) + return false; + } else if (!level.equals(other.level)) + return false; + if (loggerName == null) { + if (other.loggerName != null) + return false; + } else if (!loggerName.equals(other.loggerName)) + return false; + return true; + } +} diff --git a/admin-tools-log4j2/src/main/resources/static/admintool/css/log4j2.css b/admin-tools-log4j2/src/main/resources/static/admintool/css/log4j2.css index 2ebfc64..0731232 100644 --- a/admin-tools-log4j2/src/main/resources/static/admintool/css/log4j2.css +++ b/admin-tools-log4j2/src/main/resources/static/admintool/css/log4j2.css @@ -1,60 +1,63 @@ - -.label { - margin: 0 2px 0 0; -} - -.label-muted { - background-color:#777 !important; -} - -.changeLogger { - color: #fff; - cursor: pointer; - cursor: hand; -} - -.logname { - white-space: normal; - overflow-wrap: break-word; - word-wrap: break-word; - /*word-break: break-word;*/ - word-break: break-all; - -ms-hyphens: auto; - -moz-hyphens: auto; - -webkit-hyphens: auto; - hyphens: auto; -} -td.loglevel { - width: 58px; - min-width: 58px; -} -td.logaction { - width: 330px; - min-width: 330px; -} -span.logline { - display: block; - white-space: nowrap; - width: 100%; -} - -div#lineNumbers { - width: 3%; - float: left; - text-align: right; -} -div#consoleContent { - overflow-x: scroll; - height: 100%; - width: 96%; - float: right; -} - -@media (max-width: 991px) { - div#lineNumbers { - width: 6%; - } - div#consoleContent { - width: 93%; - } -} +.topButton { + margin: 0 0 0 2px; +} + +.label { + margin: 0 2px 0 0; +} + +.label-muted { + background-color:#777 !important; +} + +.changeLogger { + color: #fff; + cursor: pointer; + cursor: hand; +} + +.logname { + white-space: normal; + overflow-wrap: break-word; + word-wrap: break-word; + /*word-break: break-word;*/ + word-break: break-all; + -ms-hyphens: auto; + -moz-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} +td.loglevel { + width: 58px; + min-width: 58px; +} +td.logaction { + width: 340px; + min-width: 340px; +} +span.logline { + display: block; + white-space: nowrap; + width: 100%; +} + +div#lineNumbers { + width: 3%; + float: left; + text-align: right; +} +div#consoleContent { + overflow-x: scroll; + height: 100%; + width: 96%; + float: right; +} + +@media (max-width: 991px) { + div#lineNumbers { + width: 6%; + } + div#consoleContent { + width: 93%; + } +} diff --git a/admin-tools-log4j2/src/main/resources/static/admintool/js/log4j2.js b/admin-tools-log4j2/src/main/resources/static/admintool/js/log4j2.js index 2828297..69c3cc3 100644 --- a/admin-tools-log4j2/src/main/resources/static/admintool/js/log4j2.js +++ b/admin-tools-log4j2/src/main/resources/static/admintool/js/log4j2.js @@ -1,333 +1,437 @@ -var leveCss = null; -var prefix = 'bg'; - -AdminTool.Log4j = {} - -AdminTool.Log4j.Loggers = function(el, options) { - if (el) { - this.init(el, options) - } -} -AdminTool.Log4j.Loggers.prototype = new AdminTool.Core(); - -$.extend(AdminTool.Log4j.Loggers.prototype, { - - name : 'adminToolLog4jLoggers', - - postInit: function() { - this.sendRequest( - {url: "/admintool/log4j2/getLevelCss/" + prefix, dataType: "json", my: this}, - function(data, query) { - query.my.setLevelCss(data); - } - ); - this.bind(); - }, - - bind : function() { - if($('#parentLoggers').length > 0) { - $('#parentLoggers').on('init.dt', $.proxy(this.initEvents, this)).dataTable(); - $('#parentLoggers').on('page.dt', $.proxy(this.initEvents, this)); - } - var eventsInitialized = false; - if($('#loggers').length > 0) { - $('#loggers').on('init.dt', $.proxy(this.initEvents, this)).dataTable(); - $('#loggers').on('page.dt', $.proxy(this.initEvents, this)); - eventsInitialized = true; - } - - if($('.removeCustomLogger').length > 0) { - $('.removeCustomLogger').click(function(){ - sendRequest("/admintool/log4j2/removeCustomLoggers", "POST", "text", function(data) { - location.reload(); - }); - }); - } - }, - - initEvents : function() { - $('.changeLogger').each(function() { - var $el = $(this); - $el.unbind('click'); - $el.on({'click': function(){ - getByID('log4jContent').adminToolLog4jLoggers('changeLogLevel', $el)} - }); - }); - }, - - unbind : function() { - $('.removeCustomLogger').unbind(); - $('.changeLogger').unbind(); - }, - - - setLevelCss : function (levels) { - this.levelCss = levels; - }, - - getCurrentLevel: function($link) { - return $link.html(); - }, - - getCurrentRow: function($link) { - return $($link.parent().parent()); - }, - - changeLogLevel : function(link) { - var $link = $(link); - var level = this.getCurrentLevel($link); - var $tr = this.getCurrentRow($link); - var name = $tr.find('.logname').text(); - var serviceUrl = "/admintool/log4j2/changeLevel/" + name + "/" + level; - if ($tr.hasClass('parent')) { - serviceUrl += "/parent/true"; - } - - this.sendRequest( - {url: serviceUrl, requestType: "POST", dataType: "text", my: this, link: $link}, - function(data, query) { - query.my.changeLogLevelDone(data, query.link); - } - ); - }, - - changeLogLevelDone: function(data, $link) { - if (data == 'true') { - var $levelTd = this.getCurrentRow($link).children('.loglevel'); - var oldlevel = $levelTd.text(); - var level = this.getCurrentLevel($link); - - $levelTd.removeAddClass(this.levelCss[oldlevel], this.levelCss[level]); - $levelTd.text(level); - } else if (data == 'reload') { - location.reload(); - } else { - $('#admintoolError').modal(); - } - } - -}); -$.pluginMaker(AdminTool.Log4j.Loggers); - - -AdminTool.Log4j.Console = function(el, options) { - if (el) { - this.init(el, options) - } -} -AdminTool.Log4j.Console.prototype = new AdminTool.Core(); - -$.extend(AdminTool.Log4j.Console.prototype, { - - name : 'adminToolLog4jConsole', - - postInit: function() { - this.bind(); - this.requestCount = 0; - this.lineCount = 0; - this.maxListLength = 100; - this.initCheckboxes(); - }, - - bind : function() { - this.loggerNames = getByID('loggerNames').select2({ - placeholder: 'Root Logger' - }); - - getByID('startConsole').on({'click': $.proxy(this.startConsole, this)}); - getByClazz('stopConsole').hide(); - getByID('clearConsole').on({'click': $.proxy(this.clearConsole, this)}); - - }, - - unbind : function() { - getByID('loggerNames').unbind(); - getByID('startConsole').unbind(); - getByID('clearConsole').unbind(); - }, - - initCheckboxes: function() { - getByID('recursive').iCheck('destroy'); - getByID('recursive').iCheck({ - checkboxClass: 'icheckbox_minimal', - radioClass: 'iradio_minimal' -// increaseArea: '20%' // optional - }); - getByID('overrideLogLevel').iCheck('destroy'); - getByID('overrideLogLevel').iCheck({ - checkboxClass: 'icheckbox_minimal', - radioClass: 'iradio_minimal' -// increaseArea: '20%' // optional - }); - }, - - startConsole : function() { - - var data = { -// name:getByID('name').val(), - pattern: getByID('pattern').val(), - encoding: getByID('encoding').val(), - recursive: getByID('recursive').prop("checked"), - overrideLogLevel: getByID('overrideLogLevel').prop("checked"), - level: getByID('level').val(), - loggerNames: this.loggerNames.val() - }; - - this.sendRequest( - { - url: "/admintool/log4j2/initConsole", - requestType: "POST", - dataType: "text", - data: JSON.stringify(data), - showModalOnError: true, - my: this - }, - function(data, query) { - query.my.consoleStarted(data); - } - ); - }, - - consoleStarted : function(data) { - var stopButtons = getByClazz('stopConsole'); - stopButtons.on({'click': $.proxy(this.stopConsole, this)}); - stopButtons.show(); - this.startUpdateConsole(); - $.AdminLTE.boxWidget.collapse(getByID('log4jTailConfigCollapse')); - getByID('startConsole').prop('disabled', true); - }, - - startUpdateConsole : function() { - this.intervalId = setInterval(function() { - getByID('log4jTail').adminToolLog4jConsole('updateConsole'); - }, 5000); - }, - - stopUpdateConsole : function() { - clearInterval(this.intervalId); - this.intervalId = null; - getByID('startConsole').prop('disabled', false); - }, - - updateConsole: function() { - this.sendRequest( - {url: "/admintool/log4j2/getConsoleContent", dataType: "text", my: this}, - function(data, query) { - if (null != data && data.trim() != "" && data.trim() != "null") { - var lines = data.trim().split("\n"); - if (lines.length > 0) { - var existingLines = $('#consoleContent span'); - var existingNumbers = $('#lineNumbers span'); - var hasContent = existingLines.length > 0; - var clazz; - for (var i=-1, l=lines.length; ++i < l;) { - var line = lines[i]; - if (line == null || line == undefined || line.trim() == "") { - continue; - } - clazz = query.my.getSpanClass(line) || clazz; - - if (!hasContent) { - getByID('consoleContent').html(query.my.getText(line, clazz)); - getByID('lineNumbers').html(query.my.getText("1", "text-muted")); - query.my.lineCount = 1; - } else { - $('#consoleContent span:last-child').after(query.my.getText(line, clazz)); - query.my.lineCount++ - $('#lineNumbers span:last-child').after(query.my.getText(query.my.lineCount.toString(), "text-muted")); - } - } - - var oversize = lines.length + existingLines.length - query.my.getMaxListLength(); - if (oversize > 0) { - for (var i=-1; ++i < oversize;) { - $(existingLines[i]).remove(); - $(existingNumbers[i]).remove(); - } - } - - if (getByID('scrollToBottom').prop( "checked" )) { - $('html, body').scrollTop(getByID('consoleContent')[0].scrollHeight); - } - } - } - query.my.requestCount++; - getByID('requestCount').text(query.my.requestCount); - } - ); - }, - - getMaxListLength() { - var userMaxLength = parseInt(getByID('maxListLength').val()); - if (isNaN(userMaxLength) || userMaxLength == Infinity) { - return this.maxListLength; - } - return userMaxLength; - }, - - getText: function(line, clazz) { - line = line.replace(//g, '>'); - if (undefined !== clazz) { - return '' + line + ''; - } - return '' + line + ''; - }, - - getSpanClass: function(line) { - var lowerLine = line.toLowerCase(); - if (lowerLine.indexOf(' error ') != -1 || lowerLine.indexOf(' fatal ') != -1) { - return "text-danger"; - } - else if (lowerLine.indexOf(' warn ') != -1) { - return "text-warning"; - } - else if (lowerLine.indexOf(' info ') != -1 || lowerLine.indexOf(' debug ') != -1 || lowerLine.indexOf(' trace ') != -1) { - return "text-info"; - } - else if (lowerLine.indexOf(' off ') != -1) { - return "text-muted"; - } - return undefined; - }, - - stopConsole : function() { - this.stopUpdateConsole(); - this.sendRequest( - { - url: "/admintool/log4j2/stopConsole", - dataType: "text", - showModalOnError: true, - my: this - }, - function(data, query) { - query.my.consoleStopped(data); - } - ); - }, - - consoleStopped : function(data) { - var stopButtons = getByClazz('stopConsole'); - stopButtons.unbind(); - stopButtons.hide(); - }, - - clearConsole : function() { - this.requestCount = 0; - this.lineCount = 0; - getByID('requestCount').text(this.requestCount); - getByID('consoleContent').text(""); - getByID('lineNumbers').text(""); - } - -}); -$.pluginMaker(AdminTool.Log4j.Console); - - -$( document ).ready(function() { - if (getByID('log4jContent').length > 0) { - getByID('log4jContent').adminToolLog4jLoggers(); - } - if (getByID('log4jTail').length > 0) { - getByID('log4jTail').adminToolLog4jConsole(); - } +var leveCss = null; +var prefix = 'bg'; + +AdminTool.Log4j = {} + +AdminTool.Log4j.Loggers = function(el, options) { + if (el) { + this.init(el, options) + } +} +AdminTool.Log4j.Loggers.prototype = new AdminTool.Core(); + +$.extend(AdminTool.Log4j.Loggers.prototype, { + + name : 'adminToolLog4jLoggers', + + postInit: function() { + this.sendRequest( + {url: "/admintool/log4j2/getLevelCss/" + prefix, dataType: "json", my: this}, + function(data, query) { + query.my.setLevelCss(data); + } + ); + this.bind(); + }, + + bind : function() { + if($('#parentLoggers').length > 0) { + $('#parentLoggers').on('init.dt', $.proxy(this.initEvents, this)).dataTable(); + $('#parentLoggers').on('page.dt', $.proxy(this.initEvents, this)); + } + var eventsInitialized = false; + if($('#loggers').length > 0) { + $('#loggers').on('init.dt', $.proxy(this.initEvents, this)).dataTable(); + $('#loggers').on('page.dt', $.proxy(this.initEvents, this)); + eventsInitialized = true; + } + + if($('.removeCustomLogger').length > 0) { + $('.removeCustomLogger').click(function(){ + sendRequest("/admintool/log4j2/removeCustomLoggers", "POST", "text", function(data) { + location.reload(); + }); + }); + } + + if($('.removeCustomParentLogger').length > 0) { + $('.removeCustomParentLogger').click(function(){ + sendRequest("/admintool/log4j2/removeCustomParentLogger", "POST", "text", function(data) { + location.reload(); + }); + }); + } + }, + + initEvents : function() { + $('.changeLogger').each(function() { + var $el = $(this); + $el.unbind('click'); + $el.on({'click': function(){ + getByID('log4jContent').adminToolLog4jLoggers('changeLogLevel', $el)} + }); + }); + $('.manageLogger').each(function() { + var $el = $(this); + $el.unbind('click'); + $el.on({'click': function(){ + getByID('log4jContent').adminToolLog4jLoggers('manageLogger', $el)} + }); + }); + getByID('addCustomLogger').on({'click': function(){ + getByID('log4jContent').adminToolLog4jLoggers('manageLogger', null)} + }); + + this.initModalInputs(); + }, + + initModalInputs: function() { + getByID('appenderNames').select2({ + placeholder: 'Appenders', + width: '100%' + }); + + getByID('additivity').iCheck('destroy'); + getByID('additivity').iCheck({ + checkboxClass: 'icheckbox_minimal', + radioClass: 'iradio_minimal' + }); + }, + + unbind : function() { + $('.removeCustomLogger').unbind(); + $('.removeCustomParentLogger').unbind(); + $('.changeLogger').unbind(); + getByID('addCustomLogger').unbind(); + getByID('manageLogger_submit').unbind(); + getByID('appenderNames').select2('destroy'); + getByID('additivity').iCheck('destroy'); + }, + + setLevelCss : function (levels) { + this.levelCss = levels; + }, + + getCurrentLevel: function($link) { + return $link.html(); + }, + + getCurrentRow: function($link) { + return $($link.parent().parent()); + }, + + changeLogLevel : function(link) { + var $link = $(link); + var level = this.getCurrentLevel($link); + var $tr = this.getCurrentRow($link); + var name = $tr.find('.logname').text(); + var serviceUrl = "/admintool/log4j2/changeLevel/" + name + "/" + level; + if ($tr.hasClass('parent')) { + serviceUrl += "/parent/true"; + } + + this.sendRequest( + {url: serviceUrl, requestType: "POST", dataType: "text", my: this, link: $link}, + function(data, query) { + query.my.changeLogLevelDone(data, query.link); + } + ); + }, + + changeLogLevelDone: function(data, $link) { + if (data == 'true') { + var $levelTd = this.getCurrentRow($link).children('.loglevel'); + var oldlevel = $levelTd.text(); + var level = this.getCurrentLevel($link); + + $levelTd.removeAddClass(this.levelCss[oldlevel], this.levelCss[level]); + $levelTd.text(level); + } else if (data == 'reload') { + location.reload(); + } else { + $('#admintoolError').modal(); + } + }, + + manageLogger: function(link) { + var $lni = getByID('loggerName'); + $lni.val("") + $lni.on({'keyup': $.proxy(this.checkActivation, this)}); + $lni.on({'blur': $.proxy(this.checkActivation, this)}); + + getByID('appenderNames').val(null).trigger("change"); + var $btn = getByID('manageLogger_submit'); + $btn.unbind(); + if(null != link) { + var $link = $(link); + var $tr = this.getCurrentRow($link); + var $td = $tr.find('.logname'); + + $lni.attr('disabled','disabled'); + $lni.val($td.text()); + + getByID('appenderNames').val($td.data('appenders').split(',')).trigger("change"); + + $btn.removeAttr('disabled'); + } else { + $lni.removeAttr('disabled'); + $btn.attr('disabled','disabled'); + } + + $btn.on({'click': $.proxy(this.saveLogger, this)}); + + getByID("manageLoggerModal").modal(); + }, + + checkActivation: function() { + var $lni = getByID('loggerName'); + var $btn = getByID('manageLogger_submit'); + + if ($lni.val().length > 0) { + $btn.removeAttr('disabled'); + } else { + $btn.attr('disabled','disabled'); + } + }, + + saveLogger: function() { + + var data = { + loggerName: getByID('loggerName').val(), + encoding: getByID('encoding').val(), + //recursive: getByID('recursive').prop("checked"), + additivity: getByID('additivity').prop("checked"), + level: getByID('level').val(), + appenderNames: getByID('appenderNames').val() + }; + + this.sendRequest({ + url: "/admintool/log4j2/manageLogger", + requestType: "POST", + dataType: "text", + data: JSON.stringify(data), + showModalOnError: true, + my: this + }, + function(data, query) { + if (data == 'reload') { + location.reload(); + } else { + $('#admintoolError').modal(); + } + }); + } + +}); +$.pluginMaker(AdminTool.Log4j.Loggers); + +/* + * Log4j.Console live html appender + */ +AdminTool.Log4j.Console = function(el, options) { + if (el) { + this.init(el, options) + } +} +AdminTool.Log4j.Console.prototype = new AdminTool.Core(); + +$.extend(AdminTool.Log4j.Console.prototype, { + + name : 'adminToolLog4jConsole', + + postInit: function() { + this.bind(); + this.requestCount = 0; + this.lineCount = 0; + this.maxListLength = 100; + this.initCheckboxes(); + }, + + bind : function() { + this.loggerNames = getByID('loggerNames').select2({ + placeholder: 'Root Logger' + }); + + getByID('startConsole').on({'click': $.proxy(this.startConsole, this)}); + getByClazz('stopConsole').hide(); + getByID('clearConsole').on({'click': $.proxy(this.clearConsole, this)}); + + }, + + unbind : function() { + getByID('loggerNames').unbind(); + getByID('startConsole').unbind(); + getByID('clearConsole').unbind(); + }, + + initCheckboxes: function() { + getByID('recursive').iCheck('destroy'); + getByID('recursive').iCheck({ + checkboxClass: 'icheckbox_minimal', + radioClass: 'iradio_minimal' +// increaseArea: '20%' // optional + }); + getByID('overrideLogLevel').iCheck('destroy'); + getByID('overrideLogLevel').iCheck({ + checkboxClass: 'icheckbox_minimal', + radioClass: 'iradio_minimal' +// increaseArea: '20%' // optional + }); + }, + + startConsole : function() { + + var data = { +// name:getByID('name').val(), + pattern: getByID('pattern').val(), + encoding: getByID('encoding').val(), + recursive: getByID('recursive').prop("checked"), + overrideLogLevel: getByID('overrideLogLevel').prop("checked"), + level: getByID('level').val(), + loggerNames: this.loggerNames.val() + }; + + this.sendRequest({ + url: "/admintool/log4j2/initConsole", + requestType: "POST", + dataType: "text", + data: JSON.stringify(data), + showModalOnError: true, + my: this + }, + function(data, query) { + query.my.consoleStarted(data); + }); + }, + + consoleStarted : function(data) { + var stopButtons = getByClazz('stopConsole'); + stopButtons.on({'click': $.proxy(this.stopConsole, this)}); + stopButtons.show(); + this.startUpdateConsole(); + $.AdminLTE.boxWidget.collapse(getByID('log4jTailConfigCollapse')); + getByID('startConsole').prop('disabled', true); + }, + + startUpdateConsole : function() { + this.intervalId = setInterval(function() { + getByID('log4jTail').adminToolLog4jConsole('updateConsole'); + }, 5000); + }, + + stopUpdateConsole : function() { + clearInterval(this.intervalId); + this.intervalId = null; + getByID('startConsole').prop('disabled', false); + }, + + updateConsole: function() { + this.sendRequest( + {url: "/admintool/log4j2/getConsoleContent", dataType: "text", my: this}, + function(data, query) { + if (null != data && data.trim() != "" && data.trim() != "null") { + var lines = data.trim().split("\n"); + if (lines.length > 0) { + var existingLines = $('#consoleContent span'); + var existingNumbers = $('#lineNumbers span'); + var hasContent = existingLines.length > 0; + var clazz; + for (var i=-1, l=lines.length; ++i < l;) { + var line = lines[i]; + if (line == null || line == undefined || line.trim() == "") { + continue; + } + clazz = query.my.getSpanClass(line) || clazz; + + if (!hasContent) { + getByID('consoleContent').html(query.my.getText(line, clazz)); + getByID('lineNumbers').html(query.my.getText("1", "text-muted")); + query.my.lineCount = 1; + } else { + $('#consoleContent span:last-child').after(query.my.getText(line, clazz)); + query.my.lineCount++ + $('#lineNumbers span:last-child').after(query.my.getText(query.my.lineCount.toString(), "text-muted")); + } + } + + var oversize = lines.length + existingLines.length - query.my.getMaxListLength(); + if (oversize > 0) { + for (var i=-1; ++i < oversize;) { + $(existingLines[i]).remove(); + $(existingNumbers[i]).remove(); + } + } + + if (getByID('scrollToBottom').prop( "checked" )) { + $('html, body').scrollTop(getByID('consoleContent')[0].scrollHeight); + } + } + } + query.my.requestCount++; + getByID('requestCount').text(query.my.requestCount); + } + ); + }, + + getMaxListLength() { + var userMaxLength = parseInt(getByID('maxListLength').val()); + if (isNaN(userMaxLength) || userMaxLength == Infinity) { + return this.maxListLength; + } + return userMaxLength; + }, + + getText: function(line, clazz) { + line = line.replace(//g, '>'); + if (undefined !== clazz) { + return '' + line + ''; + } + return '' + line + ''; + }, + + getSpanClass: function(line) { + var lowerLine = line.toLowerCase(); + if (lowerLine.indexOf(' error ') != -1 || lowerLine.indexOf(' fatal ') != -1) { + return "text-danger"; + } + else if (lowerLine.indexOf(' warn ') != -1) { + return "text-warning"; + } + else if (lowerLine.indexOf(' info ') != -1 || lowerLine.indexOf(' debug ') != -1 || lowerLine.indexOf(' trace ') != -1) { + return "text-info"; + } + else if (lowerLine.indexOf(' off ') != -1) { + return "text-muted"; + } + return undefined; + }, + + stopConsole : function() { + this.stopUpdateConsole(); + this.sendRequest({ + url: "/admintool/log4j2/stopConsole", + dataType: "text", + showModalOnError: true, + my: this + }, + function(data, query) { + query.my.consoleStopped(data); + }); + }, + + consoleStopped : function(data) { + var stopButtons = getByClazz('stopConsole'); + stopButtons.unbind(); + stopButtons.hide(); + }, + + clearConsole : function() { + this.requestCount = 0; + this.lineCount = 0; + getByID('requestCount').text(this.requestCount); + getByID('consoleContent').text(""); + getByID('lineNumbers').text(""); + } + +}); +$.pluginMaker(AdminTool.Log4j.Console); + + +$( document ).ready(function() { + if (getByID('log4jContent').length > 0) { + getByID('log4jContent').adminToolLog4jLoggers(); + } + if (getByID('log4jTail').length > 0) { + getByID('log4jTail').adminToolLog4jConsole(); + } }); \ No newline at end of file diff --git a/admin-tools-log4j2/src/main/resources/templates/admintool/content/log4j2.html b/admin-tools-log4j2/src/main/resources/templates/admintool/content/log4j2.html index 8d36502..7dbe0b2 100644 --- a/admin-tools-log4j2/src/main/resources/templates/admintool/content/log4j2.html +++ b/admin-tools-log4j2/src/main/resources/templates/admintool/content/log4j2.html @@ -1,118 +1,222 @@ - - - -
-
-

- Log4j Console Configuration -

- -
- - -
- -
- -
-

- - - -

- -
-
- -
-
- - - - - - - - - - - - - - -
- -
-
- - - - - -
- -
-

- - - -

- -
-
- -
- - - - - - - - - - - - - - - -
-
-
- -
-
-
- - -
- - - - - - - + + + +
+
+

+ Log4j Console Configuration +

+ +
+ + +
+ +
+ +
+

+ + + +

+ + +
+
+ +
+ + + + + + + + + + + + + + + +
+ + +
+
+
+ + +
+ +
+ +
+

+ + + +

+ +
+
+ +
+ + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ + +
+ + + +
+
+ + + + From 223fc2abaa9d68c2eb0b635fc84a2bf3a6e873da Mon Sep 17 00:00:00 2001 From: Andre Date: Sun, 8 Apr 2018 17:53:13 +0200 Subject: [PATCH 6/7] #37 - fix overriding log4j version + mark custom loggers in view --- admin-tools-demo-core/pom.xml | 13 ++++- .../main/java/de/chandre/admintool/Beans.java | 53 ++++++++++--------- admin-tools-demo-jar/pom.xml | 23 +++++++- admin-tools-demo-war/pom.xml | 23 +++++++- admin-tools-log4j2/pom.xml | 5 -- .../templates/admintool/content/log4j2.html | 4 +- pom.xml | 4 +- 7 files changed, 89 insertions(+), 36 deletions(-) diff --git a/admin-tools-demo-core/pom.xml b/admin-tools-demo-core/pom.xml index 8fcfc80..bd4c722 100644 --- a/admin-tools-demo-core/pom.xml +++ b/admin-tools-demo-core/pom.xml @@ -18,7 +18,7 @@ jar - 2.9.1 + 2.11.0 2.3.0 @@ -134,6 +134,17 @@ log4j-web ${log4j2.version}
+ + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j2.version} + + + + org.slf4j + log4j-over-slf4j + + org.springframework.boot spring-boot-configuration-processor diff --git a/admin-tools-demo-core/src/main/java/de/chandre/admintool/Beans.java b/admin-tools-demo-core/src/main/java/de/chandre/admintool/Beans.java index 83d0462..22d3fbb 100644 --- a/admin-tools-demo-core/src/main/java/de/chandre/admintool/Beans.java +++ b/admin-tools-demo-core/src/main/java/de/chandre/admintool/Beans.java @@ -15,8 +15,9 @@ import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.appender.db.ColumnMapping; +import org.apache.logging.log4j.core.appender.db.jdbc.AbstractConnectionSource; import org.apache.logging.log4j.core.appender.db.jdbc.ColumnConfig; -import org.apache.logging.log4j.core.appender.db.jdbc.ConnectionSource; import org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.LoggerConfig; @@ -123,32 +124,33 @@ public Appender datasourceAppender(DataSource dataSource, AdminToolLog4j2Util lo final LoggerContext ctx = (LoggerContext) LogManager.getContext(false); final Configuration config = ctx.getConfiguration(); -// ColumnConfig[] cc = { -// ColumnConfig.newBuilder().setConfiguration(config).setName("DATE").setEventTimestamp(true).build(), -// ColumnConfig.newBuilder().setConfiguration(config).setName("LEVEL").setPattern("%level").build(), -// ColumnConfig.newBuilder().setConfiguration(config).setName("LOGGER").setPattern("%logger").build(), -// ColumnConfig.newBuilder().setConfiguration(config).setName("MESSAGE").setPattern("%message").setClob(true).build(), -// ColumnConfig.newBuilder().setConfiguration(config).setName("EXCEPTION").setPattern("%ex{full}").setClob(true).build() -// }; -// -// Appender appender = JdbcAppender.newBuilder() -// .setBufferSize(0) -// .setColumnConfigs(cc) -// .setConnectionSource(new Connect(dataSource)) -// .setTableName("LOGGING") -// .withName("databaseAppender") -// .withIgnoreExceptions(false) -// .build(); - ColumnConfig[] cc = { - ColumnConfig.createColumnConfig(config, "DATE", null, null, "true", null, null), - ColumnConfig.createColumnConfig(config, "LEVEL", "%level", null, null, null, null), - ColumnConfig.createColumnConfig(config, "LOGGER", "%logger", null, null, null, null), - ColumnConfig.createColumnConfig(config, "MESSAGE", "%message", null, null, null, "true"), - ColumnConfig.createColumnConfig(config, "EXCEPTION", "%ex{full}", null, null, null, "true"), + ColumnConfig.newBuilder().setConfiguration(config).setName("DATE").setEventTimestamp(true).build(), + ColumnConfig.newBuilder().setConfiguration(config).setName("LEVEL").setPattern("%level").build(), + ColumnConfig.newBuilder().setConfiguration(config).setName("LOGGER").setPattern("%logger").build(), + ColumnConfig.newBuilder().setConfiguration(config).setName("MESSAGE").setPattern("%message").setClob(true).build(), + ColumnConfig.newBuilder().setConfiguration(config).setName("EXCEPTION").setPattern("%ex{full}").setClob(true).build() }; - Appender appender = JdbcAppender.createAppender("databaseAppender", "false", null, new Connect(dataSource), "0", "LOGGING", cc); + Appender appender = JdbcAppender.newBuilder() + .setBufferSize(0) + .setColumnConfigs(cc) + .setColumnMappings(new ColumnMapping[]{}) + .setConnectionSource(new Connect(dataSource)) + .setTableName("LOGGING") + .withName("databaseAppender") + .withIgnoreExceptions(false) + .build(); + +// ColumnConfig[] cc = { +// ColumnConfig.createColumnConfig(config, "DATE", null, null, "true", null, null), +// ColumnConfig.createColumnConfig(config, "LEVEL", "%level", null, null, null, null), +// ColumnConfig.createColumnConfig(config, "LOGGER", "%logger", null, null, null, null), +// ColumnConfig.createColumnConfig(config, "MESSAGE", "%message", null, null, null, "true"), +// ColumnConfig.createColumnConfig(config, "EXCEPTION", "%ex{full}", null, null, null, "true"), +// }; +// Appender appender = JdbcAppender.createAppender("databaseAppender", "false", null, new Connect(dataSource), "0", "LOGGING", cc); + appender.start(); config.addAppender(appender); LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME); @@ -170,11 +172,12 @@ public Appender datasourceAppender(DataSource dataSource, AdminToolLog4j2Util lo } // inner class - class Connect implements ConnectionSource { + class Connect extends AbstractConnectionSource { private DataSource dsource; public Connect(DataSource dsource) { this.dsource = dsource; + setState(State.STARTED); } @Override diff --git a/admin-tools-demo-jar/pom.xml b/admin-tools-demo-jar/pom.xml index 51240c6..9805f74 100644 --- a/admin-tools-demo-jar/pom.xml +++ b/admin-tools-demo-jar/pom.xml @@ -19,7 +19,7 @@ 1.2.0 - 2.6.2 + 2.11.0 @@ -42,6 +42,27 @@ flyway-core 4.1.0 + + + org.apache.logging.log4j + log4j-api + ${log4j2.version} + + + org.apache.logging.log4j + log4j-core + ${log4j2.version} + + + org.apache.logging.log4j + log4j-web + ${log4j2.version} + + + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j2.version} + diff --git a/admin-tools-demo-war/pom.xml b/admin-tools-demo-war/pom.xml index 2300c57..04ac8c9 100644 --- a/admin-tools-demo-war/pom.xml +++ b/admin-tools-demo-war/pom.xml @@ -19,7 +19,7 @@ 1.2.0 - 2.6.2 + 2.11.0 @@ -43,6 +43,27 @@ flyway-core 4.1.0 + + + org.apache.logging.log4j + log4j-api + ${log4j2.version} + + + org.apache.logging.log4j + log4j-core + ${log4j2.version} + + + org.apache.logging.log4j + log4j-web + ${log4j2.version} + + + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j2.version} + diff --git a/admin-tools-log4j2/pom.xml b/admin-tools-log4j2/pom.xml index a8445f7..cff5484 100644 --- a/admin-tools-log4j2/pom.xml +++ b/admin-tools-log4j2/pom.xml @@ -46,11 +46,6 @@ ${log4j.version} true - - org.apache.logging.log4j - log4j-slf4j-impl - true - diff --git a/admin-tools-log4j2/src/main/resources/templates/admintool/content/log4j2.html b/admin-tools-log4j2/src/main/resources/templates/admintool/content/log4j2.html index 7dbe0b2..a9f782e 100644 --- a/admin-tools-log4j2/src/main/resources/templates/admintool/content/log4j2.html +++ b/admin-tools-log4j2/src/main/resources/templates/admintool/content/log4j2.html @@ -48,7 +48,9 @@

+ th:inline="text">[[${#strings.defaultString(logger.getName(),'ROOT')}]] + + diff --git a/pom.xml b/pom.xml index 05e29c0..1a84f96 100644 --- a/pom.xml +++ b/pom.xml @@ -200,9 +200,9 @@ false 0.7.9 - 3.6 + 3.7 4.1 - 2.5 + 2.6 1.2 20151123 From 44b20fa32f53541a6bad69a76138ec66d931ed44 Mon Sep 17 00:00:00 2001 From: Andre Date: Sun, 8 Apr 2018 17:54:40 +0200 Subject: [PATCH 7/7] release 1.1.6.4 --- README.md | 10 +++++++--- admin-tools-core-security/README.md | 4 ++-- admin-tools-core-security/pom.xml | 2 +- admin-tools-core/README.md | 2 +- admin-tools-core/pom.xml | 2 +- admin-tools-dbbrowser/README.md | 4 ++-- admin-tools-dbbrowser/pom.xml | 2 +- admin-tools-demo-core/pom.xml | 2 +- admin-tools-demo-jar/pom.xml | 2 +- admin-tools-demo-war/pom.xml | 2 +- admin-tools-filebrowser/README.md | 4 ++-- admin-tools-filebrowser/pom.xml | 2 +- admin-tools-jminix/README.md | 4 ++-- admin-tools-jminix/pom.xml | 2 +- admin-tools-log4j2/README.md | 6 ++++-- admin-tools-log4j2/pom.xml | 2 +- admin-tools-melody/README.md | 4 ++-- admin-tools-melody/pom.xml | 2 +- admin-tools-properties/README.md | 4 ++-- admin-tools-properties/pom.xml | 2 +- admin-tools-quartz/README.md | 4 ++-- admin-tools-quartz/pom.xml | 2 +- pom.xml | 2 +- 23 files changed, 39 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index e39150b..cc94ecf 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,12 @@ This is just a spare-time project. The usage of this tool (especially in production systems) is at your own risk. Prev Release: 1.1.6.1 - 18.01.2018 + Prev Release: 1.1.6.2 - 20.03.2018 -Last Release: 1.1.6.3 - 03.04.2018 + +Prev Release: 1.1.6.3 - 03.04.2018 + +Last Release: 1.1.6.4 - 08.04.2018 [![Maven Central](https://img.shields.io/maven-central/v/de.chandre.admin-tools/admin-tools-core.svg)](https://mvnrepository.com/artifact/de.chandre.admin-tools) [![GitHub issues](https://img.shields.io/github/issues/andrehertwig/admintool.svg)](https://github.com/andrehertwig/admintool/issues) @@ -60,7 +64,7 @@ Last Release: 1.1.6.3 - 03.04.2018 ## Based on * [Spring Boot 1.3.*](http://projects.spring.io/spring-boot/) - * Since 1.1.2 also Spring Boot 1.4.* is supported + * Since 1.1.2 also Spring Boot 1.4.*+ is supported * [Admin LTE](https://almsaeedstudio.com/preview) * [Thymeleaf](http://www.thymeleaf.org/) @@ -81,7 +85,7 @@ Include the dependencies in your dependency management. You can find it in [Mave de.chandre.admin-tools admin-tools-core - 1.1.6.3 + 1.1.6.4 ... ``` diff --git a/admin-tools-core-security/README.md b/admin-tools-core-security/README.md index 1bc8b6e..6ae0673 100644 --- a/admin-tools-core-security/README.md +++ b/admin-tools-core-security/README.md @@ -19,12 +19,12 @@ de.chandre.admin-tools admin-tools-core - 1.1.6.3 + 1.1.6.4 de.chandre.admin-tools admin-tools-core-security - 1.1.6.3 + 1.1.6.4 ``` diff --git a/admin-tools-core-security/pom.xml b/admin-tools-core-security/pom.xml index c49d71f..7138c26 100644 --- a/admin-tools-core-security/pom.xml +++ b/admin-tools-core-security/pom.xml @@ -6,7 +6,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 ../ diff --git a/admin-tools-core/README.md b/admin-tools-core/README.md index f3f392f..6701416 100644 --- a/admin-tools-core/README.md +++ b/admin-tools-core/README.md @@ -20,7 +20,7 @@ de.chandre.admin-tools admin-tools-core - 1.1.6.3 + 1.1.6.4 ``` diff --git a/admin-tools-core/pom.xml b/admin-tools-core/pom.xml index be79821..1b27db2 100644 --- a/admin-tools-core/pom.xml +++ b/admin-tools-core/pom.xml @@ -7,7 +7,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 ../ diff --git a/admin-tools-dbbrowser/README.md b/admin-tools-dbbrowser/README.md index 200aeff..b42a0c0 100644 --- a/admin-tools-dbbrowser/README.md +++ b/admin-tools-dbbrowser/README.md @@ -32,12 +32,12 @@ Result will be displayed via jquery.datatables de.chandre.admin-tools admin-tools-core - 1.1.6.3 + 1.1.6.4 de.chandre.admin-tools admin-tools-dbbrowser - 1.1.6.3 + 1.1.6.4 ``` diff --git a/admin-tools-dbbrowser/pom.xml b/admin-tools-dbbrowser/pom.xml index d5262d2..fa6f91f 100644 --- a/admin-tools-dbbrowser/pom.xml +++ b/admin-tools-dbbrowser/pom.xml @@ -6,7 +6,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 ../ diff --git a/admin-tools-demo-core/pom.xml b/admin-tools-demo-core/pom.xml index bd4c722..be72f30 100644 --- a/admin-tools-demo-core/pom.xml +++ b/admin-tools-demo-core/pom.xml @@ -6,7 +6,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 ../ diff --git a/admin-tools-demo-jar/pom.xml b/admin-tools-demo-jar/pom.xml index 9805f74..317ee13 100644 --- a/admin-tools-demo-jar/pom.xml +++ b/admin-tools-demo-jar/pom.xml @@ -6,7 +6,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 ../ diff --git a/admin-tools-demo-war/pom.xml b/admin-tools-demo-war/pom.xml index 04ac8c9..fb0a186 100644 --- a/admin-tools-demo-war/pom.xml +++ b/admin-tools-demo-war/pom.xml @@ -6,7 +6,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 ../ diff --git a/admin-tools-filebrowser/README.md b/admin-tools-filebrowser/README.md index 95e587e..f63b00f 100644 --- a/admin-tools-filebrowser/README.md +++ b/admin-tools-filebrowser/README.md @@ -34,12 +34,12 @@ de.chandre.admin-tools admin-tools-core - 1.1.6.3 + 1.1.6.4 de.chandre.admin-tools admin-tools-filebrowser - 1.1.6.3 + 1.1.6.4 ``` diff --git a/admin-tools-filebrowser/pom.xml b/admin-tools-filebrowser/pom.xml index 7d90054..8d44b31 100644 --- a/admin-tools-filebrowser/pom.xml +++ b/admin-tools-filebrowser/pom.xml @@ -6,7 +6,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 ../ diff --git a/admin-tools-jminix/README.md b/admin-tools-jminix/README.md index 1d1a2f1..1eab1c1 100644 --- a/admin-tools-jminix/README.md +++ b/admin-tools-jminix/README.md @@ -12,12 +12,12 @@ de.chandre.admin-tools admin-tools-core - 1.1.6.3 + 1.1.6.4 de.chandre.admin-tools admin-tools-jminix - 1.1.6.3 + 1.1.6.4 ``` diff --git a/admin-tools-jminix/pom.xml b/admin-tools-jminix/pom.xml index 816df9d..e45d1ae 100644 --- a/admin-tools-jminix/pom.xml +++ b/admin-tools-jminix/pom.xml @@ -6,7 +6,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 ../ diff --git a/admin-tools-log4j2/README.md b/admin-tools-log4j2/README.md index c4d5bbc..01e0d5f 100644 --- a/admin-tools-log4j2/README.md +++ b/admin-tools-log4j2/README.md @@ -1,6 +1,8 @@ # The Log4j2 Management Plugin > Shows all loggers with possibility to change the level +Since 1.1.6.4 it's possible to add new Logger with available appenders + ![Preview image](doc/screen_log4j_org.png?raw=true "AdminTool Log4jLoggers UI") Since 1.1.1 a web console is available @@ -15,12 +17,12 @@ de.chandre.admin-tools admin-tools-core - 1.1.6.3 + 1.1.6.4 de.chandre.admin-tools admin-tools-log4j2 - 1.1.6.3 + 1.1.6.4 ``` diff --git a/admin-tools-log4j2/pom.xml b/admin-tools-log4j2/pom.xml index cff5484..58f4335 100644 --- a/admin-tools-log4j2/pom.xml +++ b/admin-tools-log4j2/pom.xml @@ -6,7 +6,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 ../ diff --git a/admin-tools-melody/README.md b/admin-tools-melody/README.md index f1b0902..9a8fed2 100644 --- a/admin-tools-melody/README.md +++ b/admin-tools-melody/README.md @@ -22,12 +22,12 @@ http de.chandre.admin-tools admin-tools-core - 1.1.6.3 + 1.1.6.4 de.chandre.admin-tools admin-tools-melody - 1.1.6.3 + 1.1.6.4 ``` diff --git a/admin-tools-melody/pom.xml b/admin-tools-melody/pom.xml index 163d7d9..e76262e 100644 --- a/admin-tools-melody/pom.xml +++ b/admin-tools-melody/pom.xml @@ -6,7 +6,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 ../ diff --git a/admin-tools-properties/README.md b/admin-tools-properties/README.md index 351ddee..1742103 100644 --- a/admin-tools-properties/README.md +++ b/admin-tools-properties/README.md @@ -12,12 +12,12 @@ de.chandre.admin-tools admin-tools-core - 1.1.6.3 + 1.1.6.4 de.chandre.admin-tools admin-tools-properties - 1.1.6.3 + 1.1.6.4 ``` diff --git a/admin-tools-properties/pom.xml b/admin-tools-properties/pom.xml index 2ae0842..f16daf9 100644 --- a/admin-tools-properties/pom.xml +++ b/admin-tools-properties/pom.xml @@ -6,7 +6,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 ../ diff --git a/admin-tools-quartz/README.md b/admin-tools-quartz/README.md index 66fc774..7254453 100644 --- a/admin-tools-quartz/README.md +++ b/admin-tools-quartz/README.md @@ -22,12 +22,12 @@ de.chandre.admin-tools admin-tools-core - 1.1.6.3 + 1.1.6.4 de.chandre.admin-tools admin-tools-quartz - 1.1.6.3 + 1.1.6.4 ``` diff --git a/admin-tools-quartz/pom.xml b/admin-tools-quartz/pom.xml index f980052..169311d 100644 --- a/admin-tools-quartz/pom.xml +++ b/admin-tools-quartz/pom.xml @@ -6,7 +6,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 ../ diff --git a/pom.xml b/pom.xml index 1a84f96..63e2e79 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ de.chandre.admin-tools admin-tools - 1.1.6.3 + 1.1.6.4 pom Admin tools