From 336f9a7a1ccd0757ee968e91ac7850e134d01554 Mon Sep 17 00:00:00 2001 From: Richard Eckart de Castilho Date: Mon, 29 May 2023 13:06:07 +0200 Subject: [PATCH] #4032 - Allow using externalized strings from backend code - Add getStrings() mechanism that could be used from backend code - Bit of cleaning up - Remove support for `.vue` files which are no longer used by INCEpTION --- ...tSensitivePackageStringResourceLoader.java | 46 +++++++++++++++++++ .../support/wicket/resource/Strings.java | 27 +++++++++++ .../ui/core/WicketApplicationBase.java | 45 +++++++----------- 3 files changed, 90 insertions(+), 28 deletions(-) create mode 100644 inception/inception-support/src/main/java/de/tudarmstadt/ukp/clarin/webanno/support/wicket/resource/ContextSensitivePackageStringResourceLoader.java create mode 100644 inception/inception-support/src/main/java/de/tudarmstadt/ukp/clarin/webanno/support/wicket/resource/Strings.java diff --git a/inception/inception-support/src/main/java/de/tudarmstadt/ukp/clarin/webanno/support/wicket/resource/ContextSensitivePackageStringResourceLoader.java b/inception/inception-support/src/main/java/de/tudarmstadt/ukp/clarin/webanno/support/wicket/resource/ContextSensitivePackageStringResourceLoader.java new file mode 100644 index 00000000000..ebc89f83928 --- /dev/null +++ b/inception/inception-support/src/main/java/de/tudarmstadt/ukp/clarin/webanno/support/wicket/resource/ContextSensitivePackageStringResourceLoader.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Technische Universität Darmstadt under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The Technische Universität Darmstadt + * licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.tudarmstadt.ukp.clarin.webanno.support.wicket.resource; + +import java.lang.StackWalker.Option; +import java.util.Locale; +import java.util.Set; + +import org.apache.wicket.Localizer; +import org.apache.wicket.resource.loader.PackageStringResourceLoader; + +public class ContextSensitivePackageStringResourceLoader + extends PackageStringResourceLoader +{ + private static final Set IGNORED_PREFIXES = Set.of( + ContextSensitivePackageStringResourceLoader.class.getPackageName() + ".", + Localizer.class.getPackageName() + "."); + + @Override + public String loadStringResource(Class aClazz, String aKey, Locale aLocale, String aStyle, + String aVariation) + { + var context = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE) + .walk(s -> s.dropWhile( + f -> IGNORED_PREFIXES.stream().anyMatch(f.getClassName()::startsWith)) + .findFirst()); + + return context.map(v -> super.loadStringResource(v.getDeclaringClass(), aKey, aLocale, + aStyle, aVariation)).orElse(null); + } +} diff --git a/inception/inception-support/src/main/java/de/tudarmstadt/ukp/clarin/webanno/support/wicket/resource/Strings.java b/inception/inception-support/src/main/java/de/tudarmstadt/ukp/clarin/webanno/support/wicket/resource/Strings.java new file mode 100644 index 00000000000..162e7c3657d --- /dev/null +++ b/inception/inception-support/src/main/java/de/tudarmstadt/ukp/clarin/webanno/support/wicket/resource/Strings.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Technische Universität Darmstadt under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The Technische Universität Darmstadt + * licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.tudarmstadt.ukp.clarin.webanno.support.wicket.resource; + +public class Strings +{ + public static String getString(String aKey, String aDefaultValue) + { + return org.apache.wicket.Application.get().getResourceSettings().getLocalizer() + .getString(aKey, null, aDefaultValue); + } +} diff --git a/inception/inception-ui-core/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/core/WicketApplicationBase.java b/inception/inception-ui-core/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/core/WicketApplicationBase.java index 3ea79bf1dfa..bf33ad0ca7b 100644 --- a/inception/inception-ui-core/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/core/WicketApplicationBase.java +++ b/inception/inception-ui-core/src/main/java/de/tudarmstadt/ukp/clarin/webanno/ui/core/WicketApplicationBase.java @@ -42,6 +42,7 @@ import static org.apache.wicket.settings.ExceptionSettings.SHOW_INTERNAL_ERROR_PAGE; import java.io.File; +import java.lang.invoke.MethodHandles; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -55,8 +56,6 @@ import org.apache.wicket.csp.CSPRenderable; import org.apache.wicket.csp.FixedCSPValue; import org.apache.wicket.devutils.stateless.StatelessChecker; -import org.apache.wicket.markup.html.IPackageResourceGuard; -import org.apache.wicket.markup.html.SecurePackageResourceGuard; import org.apache.wicket.protocol.http.ResourceIsolationRequestCycleListener; import org.apache.wicket.request.Response; import org.apache.wicket.request.cycle.IRequestCycleListener; @@ -85,6 +84,7 @@ import de.tudarmstadt.ukp.clarin.webanno.support.SettingsUtil; import de.tudarmstadt.ukp.clarin.webanno.support.wicket.PatternMatchingCrossOriginEmbedderPolicyRequestCycleListener; import de.tudarmstadt.ukp.clarin.webanno.support.wicket.kendo.KendoFixDisabledInputComponentStylingBehavior; +import de.tudarmstadt.ukp.clarin.webanno.support.wicket.resource.ContextSensitivePackageStringResourceLoader; import de.tudarmstadt.ukp.clarin.webanno.ui.config.FontAwesomeResourceBehavior; import de.tudarmstadt.ukp.clarin.webanno.ui.config.JQueryJavascriptBehavior; import de.tudarmstadt.ukp.clarin.webanno.ui.config.JQueryUIResourceBehavior; @@ -106,7 +106,7 @@ public abstract class WicketApplicationBase extends WicketBootSecuredWebApplication { - private final Logger log = LoggerFactory.getLogger(getClass()); + private final static Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private @Autowired CspProperties cspProperties; @@ -197,6 +197,8 @@ private void installPatternMatchingCrossOriginEmbedderPolicyRequestCycleListener protected void initOnce() { + initContextSensitivePackageStringResourceLoader(); + // Allow nested string resource resolving using "#(key)" initNestedStringResourceLoader(); @@ -209,8 +211,6 @@ protected void initOnce() initNonCachingInDevEnvironment(); - initAccessToVueComponents(); - initErrorPage(); } @@ -218,13 +218,15 @@ private void initNonCachingInDevEnvironment() { if (DEVELOPMENT.equals(getConfigurationType())) { // Do not cache pages in development mode - allows us to make changes to the HMTL - // without - // having to reload the application + // without having to reload the application getMarkupSettings().getMarkupFactory().getMarkupCache().clear(); getResourceSettings().setCachingStrategy(NoOpResourceCachingStrategy.INSTANCE); // Same for resources getResourceSettings().setDefaultCacheDuration(Duration.ZERO); + + // Same for properties + getResourceSettings().getLocalizer().setEnableCache(false); } } @@ -265,7 +267,7 @@ protected void initBootstrap() File customBootstrap = new File(getApplicationHome(), "bootstrap.css"); if (customBootstrap.exists()) { - log.info("Using custom bootstrap at [{}]", customBootstrap); + LOG.info("Using custom bootstrap at [{}]", customBootstrap); settings.setCssResourceReference(new FileSystemResourceReference( "inception-bootstrap.css", customBootstrap.toPath())); } @@ -281,7 +283,7 @@ protected void addCustomCssToAllPages() File customCss = new File(getApplicationHome(), "theme.css"); if (customCss.exists()) { - log.info("Using custom CSS at [{}]", customCss); + LOG.info("Using custom CSS at [{}]", customCss); getComponentInstantiationListeners().add(component -> { if (component instanceof ApplicationPageBase) { component.add(new CustomThemeCssResourceBehavior()); @@ -352,6 +354,12 @@ protected void initJQueryResourceReference() getJavaScriptLibrarySettings().setJQueryReference(JQueryResourceReference.getV3()); } + protected void initContextSensitivePackageStringResourceLoader() + { + getResourceSettings().getStringResourceLoaders() + .add(new ContextSensitivePackageStringResourceLoader()); + } + protected void initNestedStringResourceLoader() { List loaders = new ArrayList<>( @@ -410,23 +418,4 @@ private void initErrorPage() mountPage("/whoops/test", ErrorTestPage.class); } } - - private void initAccessToVueComponents() - { - IPackageResourceGuard resourceGuard = getResourceSettings().getPackageResourceGuard(); - if (resourceGuard instanceof SecurePackageResourceGuard) { - SecurePackageResourceGuard securePackageResourceGuard = (SecurePackageResourceGuard) resourceGuard; - securePackageResourceGuard.addPattern("+*.vue"); - } - } - - @Override - public String getMimeType(String aFileName) - { - if (aFileName.endsWith(".vue")) { - return "text/javascript"; - } - - return super.getMimeType(aFileName); - } }