/** * Copyright (C) 2010 Asterios Raptis * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * 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.alpharogroup.wicket.base.util.application; import java.io.IOException; import org.apache.wicket.Application; import org.apache.wicket.RuntimeConfigurationType; import org.apache.wicket.core.util.file.WebApplicationPath; import org.apache.wicket.javascript.DefaultJavaScriptCompressor; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.head.filter.JavaScriptFilteredIntoFooterHeaderResponse; import org.apache.wicket.markup.html.IHeaderResponseDecorator; import org.apache.wicket.markup.html.IPackageResourceGuard; import org.apache.wicket.markup.html.SecurePackageResourceGuard; import org.apache.wicket.protocol.http.IRequestLogger; import org.apache.wicket.protocol.http.RequestLogger; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.protocol.https.HttpsConfig; import org.apache.wicket.protocol.https.HttpsMapper; import org.apache.wicket.protocol.https.Scheme; import org.apache.wicket.request.IRequestMapper; import org.apache.wicket.request.Url; import org.apache.wicket.request.component.IRequestablePage; import org.apache.wicket.request.cycle.AbstractRequestCycleListener; import org.apache.wicket.request.resource.ResourceReference; import org.apache.wicket.request.resource.UrlResourceReference; import org.apache.wicket.settings.ExceptionSettings; import org.apache.wicket.spring.injection.annot.SpringComponentInjector; import org.apache.wicket.util.file.File; import org.apache.wicket.util.file.Files; import org.apache.wicket.util.resource.IResourceStream; import org.apache.wicket.util.time.Duration; import de.alpharogroup.wicket.base.util.resource.ByteArrayResourceStreamWriter; /** * The Class ApplicationExtensions. */ public final class ApplicationExtensions { /** The Constant DEFAULT_PACKAGE_RESOURCE_GUARD_PATTERNS. */ public static final String[] DEFAULT_PACKAGE_RESOURCE_GUARD_PATTERNS = { "UTF-8", "+*.css", "+*.png", "+*.woff2", "+*.js.map" }; /** * Adds the given file patterns to package resource guard from the given application. * * @param application * the application * @param patterns * the patterns */ public static void addFilePatternsToPackageResourceGuard(final Application application, final String... patterns) { final IPackageResourceGuard packageResourceGuard = application.getResourceSettings() .getPackageResourceGuard(); if (packageResourceGuard instanceof SecurePackageResourceGuard) { final SecurePackageResourceGuard guard = (SecurePackageResourceGuard)packageResourceGuard; for (final String pattern : patterns) { guard.addPattern(pattern); } } } /** * Adds the given resourcePath to the resource finder from the given application. * * @param application * the application * @param resourcePath * the resource path * @see org.apache.wicket.settings.ResourceSettings#getResourceFinders() */ public static void addResourceFinder(final WebApplication application, final String resourcePath) { application.getResourceSettings().getResourceFinders() .add(new WebApplicationPath(application.getServletContext(), resourcePath)); } /** * Gets the context path from the given WebApplication. * * @param application * the WebApplication * @return the context path */ public static String getContextPath(final WebApplication application) { final String contextPath = application.getServletContext().getContextPath(); if ((null != contextPath) && !contextPath.isEmpty()) { return contextPath; } return ""; } /** * Gets the default jquery reference from the current application. * * @return the default jquery reference */ public static ResourceReference getJQueryReference() { return getJQueryReference(Application.get()); } /** * Gets the default jquery reference from the given application. * * @param application * the application * @return the default jquery reference */ public static ResourceReference getJQueryReference(final Application application) { return application.getJavaScriptLibrarySettings().getJQueryReference(); } /** * Gets the real path corresponding to the given virtual path from the given WebApplication. * This method gets decorated the method of the * {@link javax.servlet.ServletContext#getRealPath(String)}. * * @param application * the wicket application * @param path * the virtual path to be translated to a real path * @return the real path, or null if the translation cannot be performed */ public static String getRealPath(final WebApplication application, final String path) { final String realPath = application.getServletContext().getRealPath(path); if ((null != realPath) && !realPath.isEmpty()) { return realPath; } return ""; } /** * Gets the request logger of the current WebApplication. * * @return the request logger */ public static IRequestLogger getRequestLogger() { return getRequestLogger(null); } /** * Gets the request logger from the given WebApplication. * * @param webApplication * the web application * @return the request logger */ public static IRequestLogger getRequestLogger(WebApplication webApplication) { if (webApplication == null) { webApplication = (WebApplication)Application.get(); } IRequestLogger requestLogger = webApplication.getRequestLogger(); if (requestLogger == null) { requestLogger = new RequestLogger(); } return requestLogger; } /** * Gets the resource stream from the given parameters. * * @param file * the file * @param contentType * the content type * @return the resource stream * @throws IOException * Signals that an I/O exception has occurred. */ public static IResourceStream getResourceStream(final java.io.File file, final String contentType) throws IOException { return new ByteArrayResourceStreamWriter() { private static final long serialVersionUID = 1L; @Override public String getContentType() { return contentType; } @Override protected byte[] load() throws IOException { final byte[] data = Files.readBytes(file); return data; } }; } /** * Gets the resource stream from the given parameters. * * @param application * the application * @param path * the path * @param contentType * the content type * @return the resource stream * @throws IOException * Signals that an I/O exception has occurred. */ public static IResourceStream getResourceStream(final WebApplication application, final String path, final String contentType) throws IOException { return new ByteArrayResourceStreamWriter() { private static final long serialVersionUID = 1L; @Override public String getContentType() { return contentType; } @Override protected byte[] load() throws IOException { final String realPath = ApplicationExtensions.getRealPath(application, path); final File file = new File(realPath); final byte[] data = Files.readBytes(file); return data; } }; } /** * Initializes the given WebApplication with the Spring framework. * * @param application * the WebApplication */ public static void initializeSpring(final WebApplication application) { application.getComponentInstantiationListeners() .add(new SpringComponentInjector(application)); } /** * Replace the default jquery resource reference from the given application with the given cdn * url. * * @param application * the WebApplication * @param cdnjsUrl * the given cdn url. */ public static void replaceJQueryReference(final WebApplication application, final String cdnjsUrl) { application.getJavaScriptLibrarySettings() .setJQueryReference(new UrlResourceReference(Url.parse(cdnjsUrl))); } /** * Sets the debug settings for deployment mode for the given application. * * @param application * the new debug settings for development * @deprecated use instead * {@link ApplicationExtensions#setDeploymentModeConfiguration(Application)} */ @Deprecated public static void setDebugSettingsForDeployment(final Application application) { setDeploymentModeConfiguration(application); } /** * Sets the debug settings for development mode for the given application. * * @param application * the new debug settings for development */ public static void setDebugSettingsForDevelopment(final Application application) { application.getDebugSettings().setComponentUseCheck(true); application.getDebugSettings().setOutputMarkupContainerClassName(true); application.getDebugSettings().setLinePreciseReportingOnAddComponentEnabled(true); application.getDebugSettings().setLinePreciseReportingOnNewComponentEnabled(true); application.getDebugSettings().setAjaxDebugModeEnabled(true); application.getDebugSettings().setDevelopmentUtilitiesEnabled(true); } /** * Sets a set of default development settings for development mode for the given application. * * @param application * the new debug settings for development */ public static void setDefaultDebugSettingsForDevelopment(final WebApplication application) { ApplicationExtensions.setHtmlHotDeploy(application); ApplicationExtensions.setDebugSettingsForDevelopment(application); ApplicationExtensions.setExceptionSettingsForDevelopment(application); // set the behavior if an missing resource is found... application.getResourceSettings().setThrowExceptionOnMissingResource(true); } /** * Sets a set of default deployment settings for deployment mode for the given application. * * @param application * the application to set the settings * @param applicationRequestCycleListener * the {@link AbstractRequestCycleListener} to set. */ public static void setDefaultDeploymentModeConfiguration(final Application application, final AbstractRequestCycleListener applicationRequestCycleListener) { if (applicationRequestCycleListener != null) { ApplicationExtensions.setExceptionSettingsForDeployment(application, applicationRequestCycleListener); } ApplicationExtensions.setDeploymentModeConfiguration(application); } /** * Sets the deployment settings for deployment mode for the given application. * * @param application * the application to set the settings */ public static void setDeploymentModeConfiguration(final Application application) { application.getMarkupSettings().setStripComments(true); // The resources are never polled. This are properties, html, // css, js files. application.getResourceSettings().setResourcePollFrequency(null); application.getResourceSettings() .setJavaScriptCompressor(new DefaultJavaScriptCompressor()); // set the behavior if an missing resource is found... application.getResourceSettings().setThrowExceptionOnMissingResource(false); // debug settings... application.getDebugSettings().setComponentUseCheck(false); application.getDebugSettings().setAjaxDebugModeEnabled(false); application.getDebugSettings().setDevelopmentUtilitiesEnabled(false); application.getDebugSettings().setOutputMarkupContainerClassName(false); application.getDebugSettings().setLinePreciseReportingOnAddComponentEnabled(false); application.getDebugSettings().setLinePreciseReportingOnNewComponentEnabled(false); } /** * Sets the deployment exception settings for the given application. * * @param application * the application * @param applicationRequestCycleListener * the application request cycle listener */ public static void setExceptionSettingsForDeployment(final Application application, final AbstractRequestCycleListener applicationRequestCycleListener) { // show the exception page from us... application.getExceptionSettings() .setUnexpectedExceptionDisplay(ExceptionSettings.SHOW_INTERNAL_ERROR_PAGE); // In case of unhandled exception redirect it to a custom page application.getRequestCycleListeners().add(applicationRequestCycleListener); } /** * Sets the exception settings for development mode for the given application. * * @param application * the new exception settings for development */ public static void setExceptionSettingsForDevelopment(final Application application) { // show the exception page from wicket... application.getExceptionSettings() .setUnexpectedExceptionDisplay(ExceptionSettings.SHOW_EXCEPTION_PAGE); } /** * Sets the footer header response for the given application from the given footerFilterName. * * @param application * the application * @param footerFilterName * the name of the filter that you will use for your footer container * @deprecated use instead * {@link ApplicationExtensions#setHeaderResponseDecorator(Application, String)} */ @Deprecated public static void setFooterHeaderResponse(final Application application, final String footerFilterName) { setHeaderResponseDecorator(application, footerFilterName); } /** * Can be used to set the global settings for development and deployment mode for the given * application. * * @param application * the application * @param httpPort * the http port * @param httpsPort * the https port * @param footerFilterName * the footer filter name * @param encoding * the encoding * @param patterns * the patterns */ public static void setGlobalSettings(final WebApplication application, final int httpPort, final int httpsPort, final String footerFilterName, final String encoding, final String... patterns) { // Standard-Encoding for Markup-Files application.getMarkupSettings().setDefaultMarkupEncoding(encoding); // Sets the Response-Header to Character encoding // this means Content-Type text/html;charset=<encoding> application.getRequestCycleSettings().setResponseRequestEncoding(encoding); // set footer scripts... ApplicationExtensions.setHeaderResponseDecorator(application, footerFilterName); // set up ports for http and https... ApplicationExtensions.setRootRequestMapper(application, httpPort, httpsPort); // add file patterns to the resource guard... ApplicationExtensions.addFilePatternsToPackageResourceGuard(application, patterns); // Removes(strips) all wicket tags like <wicket:panel>, <wicket:extend> and <wicket:child>. // This is very important to set to true if you use the library wicket-jquery-ui application.getMarkupSettings().setStripWicketTags(true); } /** * Sets an {@link IHeaderResponseDecorator} for the given application to use to decorate header * responses. * * @param application * the application * @param footerFilterName * the footer filter name */ public static void setHeaderResponseDecorator(final Application application, final String footerFilterName) { application.setHeaderResponseDecorator(new IHeaderResponseDecorator() { @Override public IHeaderResponse decorate(final IHeaderResponse response) { return new JavaScriptFilteredIntoFooterHeaderResponse(response, footerFilterName); } }); } /** * Use this method to enable hot deploy of your html templates on development. Works only with * jetty. Only for * * @param application * the new html hot deploy */ public static void setHtmlHotDeploy(final WebApplication application) { application.getResourceSettings().setResourcePollFrequency(Duration.ONE_SECOND); final String slash = "/"; String realPath = application.getServletContext().getRealPath(slash); if ((realPath != null) && !realPath.endsWith(slash)) { realPath += slash; } final String javaSourcePath = realPath + "../java"; final String resourcesPath = realPath + "../resources"; addResourceFinder(application, javaSourcePath); addResourceFinder(application, resourcesPath); } /** * Sets the root request mapper for the given application from the given httpPort and httpsPort. * * @param application * the application * @param httpPort * the http port * @param httpsPort * the https port * @return the i request mapper */ public static IRequestMapper setRootRequestMapper(final Application application, final int httpPort, final int httpsPort) { final IRequestMapper httpsMapper = new HttpsMapper(application.getRootRequestMapper(), new HttpsConfig(httpPort, httpsPort)); application.setRootRequestMapper(httpsMapper); return httpsMapper; } /** * Sets the RootRequestMapper for the given application from the given httpPort and httpsPort. * Note: if the configuration type is RuntimeConfigurationType.DEVELOPMENT then only HTTP scheme * will be returned. * * @param application * the application * @param httpPort * the http port * @param httpsPort * the https port */ public static void setRootRequestMapperForDevelopment(final Application application, final int httpPort, final int httpsPort) { application.setRootRequestMapper(new HttpsMapper(application.getRootRequestMapper(), new HttpsConfig(httpPort, httpsPort)) { @Override protected Scheme getDesiredSchemeFor(final Class<? extends IRequestablePage> pageClass) { if (application.getConfigurationType().equals(RuntimeConfigurationType.DEVELOPMENT)) { // is in development mode, returning Scheme.HTTP... return Scheme.HTTP; } else { // not in development mode, letting the mapper decide return super.getDesiredSchemeFor(pageClass); } } }); } /** * Sets the settings for deployment mode for the given application. * * @param application * the new settings for deployment * @deprecated use instead * {@link ApplicationExtensions#setDeploymentModeConfiguration(Application)} */ @Deprecated public static void setSettingsForDeployment(final Application application) { setDeploymentModeConfiguration(application); } /** * private constructor. */ private ApplicationExtensions() { } }