diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/GlobalProperties.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/GlobalProperties.java deleted file mode 100644 index d1faa6ea8..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/GlobalProperties.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.owasp.webgoat.plugins; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.List; -import java.util.Objects; - -public final class GlobalProperties { - - private final Path pluginDirectory; - - public GlobalProperties(Path pluginDirectory) { - this.pluginDirectory = Objects.requireNonNull(pluginDirectory, "pluginDirectory cannot be null"); - } - - public void loadProperties(Path globalPropertiesPath) { - try { - PluginFileUtils.createDirsIfNotExists(pluginDirectory); - List filesInDirectory = PluginFileUtils.getFilesInDirectory(globalPropertiesPath); - new Plugin(pluginDirectory).loadFiles(filesInDirectory, true); - } catch (IOException e) { - throw new IllegalStateException("Unable to load global properties, check your installation for the directory i18n: " + globalPropertiesPath.toString(), e); - } - } - -} diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java index 0a22fd066..a9b2121c1 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/Plugin.java @@ -5,8 +5,8 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import org.owasp.webgoat.classloader.PluginClassLoader; import org.owasp.webgoat.lessons.AbstractLesson; +import org.owasp.webgoat.util.LabelProvider; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -90,16 +90,11 @@ public class Plugin { private void copyProperties(boolean reload, Path file) { try { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - Files.copy(file, bos); + byte[] lines = Files.readAllBytes(file); Path propertiesPath = createPropertiesDirectory(); - ResourceBundleClassLoader.setPropertiesPath(propertiesPath); + LabelProvider.updatePluginResources(propertiesPath); PluginFileUtils.createDirsIfNotExists(file.getParent()); - if (reload) { - Files.write(propertiesPath.resolve(file.getFileName()), bos.toByteArray(), CREATE, APPEND); - } else { - Files.write(propertiesPath.resolve(file.getFileName()), bos.toByteArray(), CREATE, TRUNCATE_EXISTING); - } + Files.write(propertiesPath.resolve(file.getFileName()), lines, CREATE, (reload ? APPEND : TRUNCATE_EXISTING)); } catch (IOException io) { throw new PluginLoadingFailure("Property file detected, but unable to copy the properties", io); } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java index b2d727fb0..cdea39ee2 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/PluginsLoader.java @@ -3,6 +3,7 @@ package org.owasp.webgoat.plugins; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import org.owasp.webgoat.classloader.PluginClassLoader; +import org.owasp.webgoat.util.LabelProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -78,6 +79,7 @@ public class PluginsLoader implements Runnable { plugins.add(plugin); } } + LabelProvider.refresh(); return plugins; } diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/ResourceBundleClassLoader.java b/webgoat-container/src/main/java/org/owasp/webgoat/plugins/ResourceBundleClassLoader.java deleted file mode 100644 index dcd27266a..000000000 --- a/webgoat-container/src/main/java/org/owasp/webgoat/plugins/ResourceBundleClassLoader.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.owasp.webgoat.plugins; - -import java.io.IOException; -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; - -public class ResourceBundleClassLoader { - - private final static ResourceBundleClassLoader classLoader = new ResourceBundleClassLoader(); - private Path propertiesPath; - - private ResourceBundleClassLoader() { - } - - public static void setPropertiesPath(Path path) { - classLoader.propertiesPath = path; - } - - public static ClassLoader createPropertyFilesClassLoader() { - final List urls = new ArrayList<>(); - - try { - urls.add(classLoader.propertiesPath.toUri().toURL()); - } catch (IOException e) { - throw new PluginLoadingFailure("Unable to load the properties for the classloader", e); - } - return new URLClassLoader(urls.toArray(new URL[urls.size()]), Thread.currentThread().getContextClassLoader()); - } - -} \ No newline at end of file diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/session/Course.java b/webgoat-container/src/main/java/org/owasp/webgoat/session/Course.java index a69774d93..b381ba71c 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/session/Course.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/session/Course.java @@ -3,7 +3,6 @@ package org.owasp.webgoat.session; import org.owasp.webgoat.HammerHead; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Category; -import org.owasp.webgoat.plugins.GlobalProperties; import org.owasp.webgoat.plugins.Plugin; import org.owasp.webgoat.plugins.PluginsLoader; import org.slf4j.Logger; @@ -24,7 +23,6 @@ import javax.servlet.ServletContext; import org.owasp.webgoat.HammerHead; import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Category; -import org.owasp.webgoat.plugins.GlobalProperties; import org.owasp.webgoat.plugins.LegacyLoader; import org.owasp.webgoat.plugins.Plugin; import org.owasp.webgoat.plugins.PluginsLoader; @@ -299,7 +297,6 @@ public class Course { logger.error("Plugins directory {} not found", pluginPath); return; } - new GlobalProperties(Paths.get(targetPath)).loadProperties(Paths.get(context.getRealPath("container//i18n"))); List plugins = new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).loadPlugins(true); for (Plugin plugin : plugins) { diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManagerImpl.java b/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManagerImpl.java index 5427a11a9..2c6b59661 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManagerImpl.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelManagerImpl.java @@ -1,11 +1,9 @@ package org.owasp.webgoat.util; -import org.springframework.context.annotation.Scope; -import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.annotation.Resource; import java.io.Serializable; import java.util.Locale; @@ -38,10 +36,11 @@ import java.util.Locale; * For details, please see http://webgoat.github.io */ @Component("labelManager") -@Scope(value="session", proxyMode=ScopedProxyMode.INTERFACES) public class LabelManagerImpl implements LabelManager, Serializable { - @Resource + private static final long serialVersionUID = 1L; + + @Autowired private transient LabelProvider labelProvider; /** Locale mapped with current session. */ diff --git a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelProvider.java b/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelProvider.java index 370f6434c..5aa3a85c8 100644 --- a/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelProvider.java +++ b/webgoat-container/src/main/java/org/owasp/webgoat/util/LabelProvider.java @@ -1,70 +1,91 @@ package org.owasp.webgoat.util; -import org.owasp.webgoat.plugins.ResourceBundleClassLoader; +import org.springframework.context.support.ReloadableResourceBundleMessageSource; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Component; -import java.util.HashMap; +import javax.inject.Singleton; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; import java.util.Locale; -import java.util.ResourceBundle; -/*************************************************************************************************** - * - * +/** + * ************************************************************************************************ + *

+ *

* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * please see http://www.owasp.org/ - * + *

* Copyright (c) 2002 - 20014 Bruce Mayhew - * + *

* This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. - * + *

* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * + *

* You should have received a copy of the GNU General Public License along with this program; if * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. - * + *

* Getting Source ============== - * + *

* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for * free software projects. - * + *

* For details, please see http://webgoat.github.io */ @Component -public class LabelProvider -{ - public final static String DEFAULT_LANGUAGE = Locale.ENGLISH.getLanguage(); +@Singleton +public class LabelProvider { + public final static String DEFAULT_LANGUAGE = Locale.ENGLISH.getLanguage(); - private final HashMap labels = new HashMap(); - private final WebGoatResourceBundleController localeController = new WebGoatResourceBundleController(); + private static final List SUPPORTED = Arrays.asList(Locale.GERMAN, Locale.FRENCH, Locale.ENGLISH, + Locale.forLanguageTag("ru")); + private final ReloadableResourceBundleMessageSource labels = new ReloadableResourceBundleMessageSource(); + private static final ReloadableResourceBundleMessageSource pluginLabels = new ReloadableResourceBundleMessageSource(); - public String get(Locale locale, String strName) - { - if (!labels.containsKey(locale)) - { - ClassLoader classLoader = ResourceBundleClassLoader.createPropertyFilesClassLoader(); - ResourceBundle resBundle = ResourceBundle.getBundle("WebGoatLabels", locale, classLoader, localeController); - labels.put(locale, resBundle); - } - return labels.get(locale).getString(strName); - } + public LabelProvider() { + labels.setBasename("classpath:/i18n/WebGoatLabels"); + labels.setFallbackToSystemLocale(false); + labels.setUseCodeAsDefaultMessage(true); + pluginLabels.setParentMessageSource(labels); + } - private class WebGoatResourceBundleController extends ResourceBundle.Control - { - private final Locale fallbackLocale = new Locale(DEFAULT_LANGUAGE); + public static void updatePluginResources(final Path propertyFile) { + pluginLabels.setBasename("WebGoatLabels"); + pluginLabels.setFallbackToSystemLocale(false); + pluginLabels.setUseCodeAsDefaultMessage(true); + pluginLabels.setResourceLoader(new ResourceLoader() { + @Override + public Resource getResource(String location) { + return new FileSystemResource(propertyFile.toFile()); + } - @Override - public Locale getFallbackLocale(String baseName, Locale locale) - { - if (!fallbackLocale.equals(locale)) { return fallbackLocale; } - return Locale.ROOT; - } - } + @Override + public ClassLoader getClassLoader() { + return Thread.currentThread().getContextClassLoader(); + } + }); + } + + public static void refresh() { + pluginLabels.clearCache(); + } + + public String get(Locale locale, String strName) { + return pluginLabels.getMessage(strName, null, useLocaleOrFallbackToEnglish(locale)); + } + + private Locale useLocaleOrFallbackToEnglish(Locale locale) { + return SUPPORTED.contains(locale) ? Locale.ENGLISH : locale; + } } diff --git a/webgoat-container/src/main/webapp/container/i18n/WebGoatLabels.properties b/webgoat-container/src/main/resources/i18n/WebGoatLabels.properties similarity index 100% rename from webgoat-container/src/main/webapp/container/i18n/WebGoatLabels.properties rename to webgoat-container/src/main/resources/i18n/WebGoatLabels.properties diff --git a/webgoat-container/src/main/webapp/container/i18n/WebGoatLabels_de.properties b/webgoat-container/src/main/resources/i18n/WebGoatLabels_de.properties similarity index 100% rename from webgoat-container/src/main/webapp/container/i18n/WebGoatLabels_de.properties rename to webgoat-container/src/main/resources/i18n/WebGoatLabels_de.properties diff --git a/webgoat-container/src/main/webapp/container/i18n/WebGoatLabels_fr.properties b/webgoat-container/src/main/resources/i18n/WebGoatLabels_fr.properties similarity index 100% rename from webgoat-container/src/main/webapp/container/i18n/WebGoatLabels_fr.properties rename to webgoat-container/src/main/resources/i18n/WebGoatLabels_fr.properties diff --git a/webgoat-container/src/main/webapp/container/i18n/WebGoatLabels_ru.properties b/webgoat-container/src/main/resources/i18n/WebGoatLabels_ru.properties similarity index 100% rename from webgoat-container/src/main/webapp/container/i18n/WebGoatLabels_ru.properties rename to webgoat-container/src/main/resources/i18n/WebGoatLabels_ru.properties diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/plugins/GlobalPropertiesTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/plugins/GlobalPropertiesTest.java deleted file mode 100644 index 109d35d26..000000000 --- a/webgoat-container/src/test/java/org/owasp/webgoat/plugins/GlobalPropertiesTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.owasp.webgoat.plugins; - -import org.junit.Test; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; - -import static org.junit.Assert.assertNotNull; - -public class GlobalPropertiesTest { - - @Test - public void propertyFilesShouldBeLoaded() throws IOException { - Path tempDirectory = PluginTestHelper.createTmpDir(); - Path pluginDirectory = Files.createDirectory(Paths.get(tempDirectory.toString(), "plugins")); - Path directory = Files.createDirectory(Paths.get(tempDirectory.toString(), "i18n")); - Path globalProperties = Files.createFile(Paths.get(directory.toString(), "global.properties")); - Files.write(globalProperties, Arrays.asList("test=label for test"), StandardCharsets.UTF_8); - new GlobalProperties(pluginDirectory).loadProperties(directory); - - ClassLoader propertyFilesClassLoader = - ResourceBundleClassLoader.createPropertyFilesClassLoader(); - assertNotNull(propertyFilesClassLoader.getResourceAsStream("global.properties")); - } - - @Test(expected = IllegalStateException.class) - public void propertyFilesDirectoryNotFoundShouldRaiseError() throws IOException { - Path tempDirectory = PluginTestHelper.createTmpDir(); - Path pluginDirectory = Files.createDirectory(Paths.get(tempDirectory.toString(), "plugins")); - Path directory = Files.createDirectory(Paths.get(tempDirectory.toString(), "i18n")); - Files.delete(directory); - - new GlobalProperties(pluginDirectory).loadProperties(directory); - } - -} \ No newline at end of file diff --git a/webgoat-container/src/test/java/org/owasp/webgoat/util/LabelProviderTest.java b/webgoat-container/src/test/java/org/owasp/webgoat/util/LabelProviderTest.java new file mode 100644 index 000000000..5d27873db --- /dev/null +++ b/webgoat-container/src/test/java/org/owasp/webgoat/util/LabelProviderTest.java @@ -0,0 +1,33 @@ +package org.owasp.webgoat.util; + +import org.hamcrest.CoreMatchers; +import org.junit.Test; +import org.springframework.core.io.ClassPathResource; + +import java.io.IOException; +import java.util.Locale; + +import static org.junit.Assert.assertThat; + +public class LabelProviderTest { + + @Test + public void defaultLabelsShouldBePresent() { + LabelProvider labelProvider = new LabelProvider(); + assertThat(labelProvider.get(Locale.ENGLISH, "LessonCompleted"), CoreMatchers.equalTo( + "Congratulations. You have successfully completed this lesson.")); + } + + @Test + public void loadingPluginLabels() throws IOException { + LabelProvider labelProvider = new LabelProvider(); + labelProvider.updatePluginResources(new ClassPathResource("log4j.properties").getFile().toPath()); + LabelProvider.refresh(); + assertThat(labelProvider.get(Locale.ENGLISH, "LessonCompleted"), CoreMatchers.equalTo( + "Congratulations. You have successfully completed this lesson.")); + assertThat(labelProvider.get(Locale.ENGLISH, "log4j.appender.CONSOLE.Target"), CoreMatchers.equalTo( + "System.out")); + } + + +} \ No newline at end of file