|
@@ -20,12 +20,14 @@
|
|
|
|
|
|
package password.pwm.http.servlet.resource;
|
|
|
|
|
|
+import lombok.Value;
|
|
|
import org.webjars.WebJarAssetLocator;
|
|
|
import password.pwm.config.DomainConfig;
|
|
|
import password.pwm.config.PwmSetting;
|
|
|
import password.pwm.error.ErrorInformation;
|
|
|
import password.pwm.error.PwmError;
|
|
|
import password.pwm.error.PwmUnrecoverableException;
|
|
|
+import password.pwm.http.HttpContentType;
|
|
|
import password.pwm.http.HttpHeader;
|
|
|
import password.pwm.http.PwmHttpRequestWrapper;
|
|
|
import password.pwm.util.java.StringUtil;
|
|
@@ -34,13 +36,15 @@ import password.pwm.util.logging.PwmLogger;
|
|
|
import javax.servlet.ServletContext;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
import java.io.File;
|
|
|
-import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
+import java.time.Instant;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Collection;
|
|
|
import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+import java.util.Optional;
|
|
|
import java.util.regex.Matcher;
|
|
|
import java.util.zip.ZipEntry;
|
|
|
import java.util.zip.ZipFile;
|
|
@@ -58,17 +62,22 @@ class ResourceFileRequest
|
|
|
private final DomainConfig domainConfig;
|
|
|
private final ResourceServletConfiguration resourceServletConfiguration;
|
|
|
|
|
|
- private FileResource fileResource;
|
|
|
+ private final Optional<FileResource> fileResource;
|
|
|
|
|
|
ResourceFileRequest(
|
|
|
final DomainConfig domainConfig,
|
|
|
final ResourceServletConfiguration resourceServletConfiguration,
|
|
|
final HttpServletRequest httpServletRequest
|
|
|
)
|
|
|
+ throws PwmUnrecoverableException
|
|
|
{
|
|
|
this.domainConfig = domainConfig;
|
|
|
this.resourceServletConfiguration = resourceServletConfiguration;
|
|
|
this.httpServletRequest = httpServletRequest;
|
|
|
+
|
|
|
+ final String resourcePathUri = this.getRequestURI();
|
|
|
+ final ServletContext servletContext = this.getHttpServletRequest().getServletContext();
|
|
|
+ fileResource = resolveRequestedResource( domainConfig, servletContext, resourcePathUri, resourceServletConfiguration );
|
|
|
}
|
|
|
|
|
|
HttpServletRequest getHttpServletRequest()
|
|
@@ -94,35 +103,36 @@ class ResourceFileRequest
|
|
|
return acceptsCompression ? rawContentType : rawContentType + ";charset=UTF-8";
|
|
|
}
|
|
|
|
|
|
- FileResource getRequestedFileResource()
|
|
|
+ Optional<FileResource> getRequestedFileResource()
|
|
|
throws PwmUnrecoverableException
|
|
|
{
|
|
|
- if ( fileResource == null )
|
|
|
- {
|
|
|
- final String resourcePathUri = this.getRequestURI();
|
|
|
- final ServletContext servletContext = this.getHttpServletRequest().getServletContext();
|
|
|
- fileResource = resolveRequestedResource( domainConfig, servletContext, resourcePathUri, resourceServletConfiguration );
|
|
|
- }
|
|
|
return fileResource;
|
|
|
}
|
|
|
|
|
|
private String getRawMimeType()
|
|
|
throws PwmUnrecoverableException
|
|
|
{
|
|
|
- final String filename = getRequestedFileResource().getName();
|
|
|
- final String contentType = this.httpServletRequest.getServletContext().getMimeType( filename );
|
|
|
- if ( contentType == null )
|
|
|
+ if ( fileResource.isPresent() )
|
|
|
{
|
|
|
- if ( filename.endsWith( ".woff2" ) )
|
|
|
+ final String filename = fileResource.get().getName();
|
|
|
+ final String contentType = this.httpServletRequest.getServletContext().getMimeType( filename );
|
|
|
+ if ( contentType == null )
|
|
|
{
|
|
|
- return "font/woff2";
|
|
|
+ if ( filename.endsWith( ".woff2" ) )
|
|
|
+ {
|
|
|
+ return "font/woff2";
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ // If content type is unknown, then set the default value.
|
|
|
+ // For all content types, see: http://www.w3schools.com/media/media_mimeref.asp
|
|
|
+ // To add new content types, add new mime-mapping entry in web.xml.
|
|
|
+ return contentType == null
|
|
|
+ ? HttpContentType.octetstream.getMimeType()
|
|
|
+ : contentType;
|
|
|
}
|
|
|
|
|
|
- // If content type is unknown, then set the default value.
|
|
|
- // For all content types, see: http://www.w3schools.com/media/media_mimeref.asp
|
|
|
- // To add new content types, add new mime-mapping entry in web.xml.
|
|
|
- return contentType == null ? "application/octet-stream" : contentType;
|
|
|
+ return HttpContentType.octetstream.getMimeType();
|
|
|
}
|
|
|
|
|
|
boolean allowsCompression()
|
|
@@ -168,15 +178,11 @@ class ResourceFileRequest
|
|
|
return requestURI.substring( httpServletRequest.getContextPath().length() );
|
|
|
}
|
|
|
|
|
|
- static FileResource resolveRequestedResource(
|
|
|
+ static String deriveEffectiveURI(
|
|
|
final DomainConfig domainConfig,
|
|
|
- final ServletContext servletContext,
|
|
|
- final String inputResourcePathUri,
|
|
|
- final ResourceServletConfiguration resourceServletConfiguration
|
|
|
+ final String inputResourcePathUri
|
|
|
)
|
|
|
- throws PwmUnrecoverableException
|
|
|
{
|
|
|
-
|
|
|
// URL-decode the file name (might contain spaces and on) and prepare file object.
|
|
|
String effectiveUri = StringUtil.urlDecode( inputResourcePathUri );
|
|
|
|
|
@@ -195,14 +201,69 @@ class ResourceFileRequest
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ return effectiveUri;
|
|
|
+ }
|
|
|
+
|
|
|
+ static Optional<FileResource> resolveRequestedResource(
|
|
|
+ final DomainConfig domainConfig,
|
|
|
+ final ServletContext servletContext,
|
|
|
+ final String inputResourcePathUri,
|
|
|
+ final ResourceServletConfiguration resourceServletConfiguration
|
|
|
+ )
|
|
|
+ throws PwmUnrecoverableException
|
|
|
+ {
|
|
|
+ final String effectiveUri = deriveEffectiveURI( domainConfig, inputResourcePathUri );
|
|
|
+
|
|
|
if ( !effectiveUri.startsWith( ResourceFileServlet.RESOURCE_PATH ) )
|
|
|
{
|
|
|
- final String filenameFinal = effectiveUri;
|
|
|
- LOGGER.warn( () -> "illegal url request to " + filenameFinal );
|
|
|
+ LOGGER.warn( () -> "illegal url request to " + effectiveUri );
|
|
|
throw new PwmUnrecoverableException( new ErrorInformation( PwmError.ERROR_SERVICE_NOT_AVAILABLE, "illegal url request" ) );
|
|
|
}
|
|
|
|
|
|
+ final ResourceRequestContext context = new ResourceRequestContext( effectiveUri, domainConfig, resourceServletConfiguration, servletContext );
|
|
|
+ for ( final ResourceUriResolver resourceUriResolver : RESOLVERS )
|
|
|
+ {
|
|
|
+ final Optional<FileResource> resource = resourceUriResolver.resolveUri( context );
|
|
|
+ if ( resource.isPresent() )
|
|
|
+ {
|
|
|
+ return resource;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return Optional.empty();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Value
|
|
|
+ private static class ResourceRequestContext
|
|
|
+ {
|
|
|
+ private final String uri;
|
|
|
+ private final DomainConfig domainConfig;
|
|
|
+ private final ResourceServletConfiguration resourceServletConfiguration;
|
|
|
+ private final ServletContext servletContext;
|
|
|
+ }
|
|
|
+
|
|
|
+ private interface ResourceUriResolver
|
|
|
+ {
|
|
|
+ Optional<FileResource> resolveUri( ResourceRequestContext resourceRequestContext )
|
|
|
+ throws PwmUnrecoverableException;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static final List<ResourceUriResolver> RESOLVERS = List.of(
|
|
|
+ new ThemeUriResolver(),
|
|
|
+ new BuiltInZipFileUriResolver(),
|
|
|
+ new WebJarUriResolver(),
|
|
|
+ new RealFileUriResolver(),
|
|
|
+ new CustomZipFileUriResolver()
|
|
|
+ );
|
|
|
+
|
|
|
+ private static class ThemeUriResolver implements ResourceUriResolver
|
|
|
+ {
|
|
|
+ @Override
|
|
|
+ public Optional<FileResource> resolveUri( final ResourceRequestContext resourceRequestContext )
|
|
|
{
|
|
|
+ final String effectiveUri = resourceRequestContext.getUri();
|
|
|
+ final DomainConfig domainConfig = resourceRequestContext.getDomainConfig();
|
|
|
+
|
|
|
final String embedThemeUrl = ResourceFileServlet.RESOURCE_PATH
|
|
|
+ ResourceFileServlet.THEME_CSS_PATH.replace( ResourceFileServlet.TOKEN_THEME, ResourceFileServlet.EMBED_THEME );
|
|
|
final String embedThemeMobileUrl = ResourceFileServlet.RESOURCE_PATH
|
|
@@ -210,24 +271,26 @@ class ResourceFileRequest
|
|
|
|
|
|
if ( effectiveUri.equalsIgnoreCase( embedThemeUrl ) )
|
|
|
{
|
|
|
- return new ConfigSettingFileResource( PwmSetting.DISPLAY_CSS_EMBED, domainConfig, effectiveUri );
|
|
|
+ return Optional.of( new ConfigSettingFileResource( PwmSetting.DISPLAY_CSS_EMBED, domainConfig, effectiveUri ) );
|
|
|
}
|
|
|
else if ( effectiveUri.equalsIgnoreCase( embedThemeMobileUrl ) )
|
|
|
{
|
|
|
- return new ConfigSettingFileResource( PwmSetting.DISPLAY_CSS_MOBILE_EMBED, domainConfig, effectiveUri );
|
|
|
+ return Optional.of( new ConfigSettingFileResource( PwmSetting.DISPLAY_CSS_MOBILE_EMBED, domainConfig, effectiveUri ) );
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
-
|
|
|
- {
|
|
|
- final FileResource resource = handleWebjarURIs( servletContext, effectiveUri );
|
|
|
- if ( resource != null )
|
|
|
- {
|
|
|
- return resource;
|
|
|
- }
|
|
|
+ return Optional.empty();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
+ private static class BuiltInZipFileUriResolver implements ResourceUriResolver
|
|
|
+ {
|
|
|
+ @Override
|
|
|
+ public Optional<FileResource> resolveUri( final ResourceRequestContext resourceRequestContext )
|
|
|
+ throws PwmUnrecoverableException
|
|
|
{
|
|
|
+ final String effectiveUri = resourceRequestContext.getUri();
|
|
|
+ final ResourceServletConfiguration resourceServletConfiguration = resourceRequestContext.getResourceServletConfiguration();
|
|
|
+
|
|
|
// check files system zip files.
|
|
|
final Map<String, ZipFile> zipResources = resourceServletConfiguration.getZipResources();
|
|
|
for ( final Map.Entry<String, ZipFile> entry : zipResources.entrySet() )
|
|
@@ -240,160 +303,174 @@ class ResourceFileRequest
|
|
|
final ZipEntry zipEntry = zipFile.getEntry( zipSubPath );
|
|
|
if ( zipEntry != null )
|
|
|
{
|
|
|
- return new ZipFileResource( zipFile, zipEntry );
|
|
|
+ return Optional.of( new ZipFileResource( zipFile, zipEntry ) );
|
|
|
}
|
|
|
}
|
|
|
if ( effectiveUri.startsWith( zipResources.get( path ).getName() ) )
|
|
|
{
|
|
|
- final String filenameFinal = effectiveUri;
|
|
|
- LOGGER.warn( () -> "illegal url request to " + filenameFinal + " zip resource" );
|
|
|
+ LOGGER.warn( () -> "illegal url request to " + effectiveUri + " zip resource" );
|
|
|
throw new PwmUnrecoverableException( new ErrorInformation( PwmError.ERROR_SERVICE_NOT_AVAILABLE, "illegal url request" ) );
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- // convert to file.
|
|
|
- final String filePath = servletContext.getRealPath( effectiveUri );
|
|
|
- final File file = new File( filePath );
|
|
|
|
|
|
- // figure top-most path allowed by request
|
|
|
- final String parentDirectoryPath = servletContext.getRealPath( ResourceFileServlet.RESOURCE_PATH );
|
|
|
- final File parentDirectory = new File( parentDirectoryPath );
|
|
|
-
|
|
|
- FileResource fileSystemResource = null;
|
|
|
- {
|
|
|
- //verify the requested page is a child of the servlet resource path.
|
|
|
- int recursions = 0;
|
|
|
- File recurseFile = file.getParentFile();
|
|
|
- while ( recurseFile != null && recursions < 100 )
|
|
|
- {
|
|
|
- if ( parentDirectory.equals( recurseFile ) )
|
|
|
- {
|
|
|
- fileSystemResource = new RealFileResource( file );
|
|
|
- break;
|
|
|
- }
|
|
|
- recurseFile = recurseFile.getParentFile();
|
|
|
- recursions++;
|
|
|
- }
|
|
|
+ return Optional.empty();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- if ( fileSystemResource == null )
|
|
|
+ private static class WebJarUriResolver implements ResourceUriResolver
|
|
|
+ {
|
|
|
+ @Override
|
|
|
+ public Optional<FileResource> resolveUri( final ResourceRequestContext resourceRequestContext )
|
|
|
{
|
|
|
- LOGGER.warn( () -> "attempt to access file outside of servlet path " + file.getAbsolutePath() );
|
|
|
- throw new PwmUnrecoverableException( new ErrorInformation( PwmError.ERROR_SERVICE_NOT_AVAILABLE, "illegal file path request" ) );
|
|
|
- }
|
|
|
+ final String effectiveUri = resourceRequestContext.getUri();
|
|
|
+ final ServletContext servletContext = resourceRequestContext.getServletContext();
|
|
|
|
|
|
- if ( !fileSystemResource.exists() )
|
|
|
- {
|
|
|
- // check custom (configuration defined) zip file bundles
|
|
|
- final Map<String, FileResource> customResources = resourceServletConfiguration.getCustomFileBundle();
|
|
|
- for ( final Map.Entry<String, FileResource> entry : customResources.entrySet() )
|
|
|
+ if ( effectiveUri.startsWith( ResourceFileServlet.WEBJAR_BASE_URL_PATH ) )
|
|
|
{
|
|
|
- final String customFileName = entry.getKey();
|
|
|
- final String testName = ResourceFileServlet.RESOURCE_PATH + "/" + customFileName;
|
|
|
- if ( testName.equals( effectiveUri ) )
|
|
|
+ // This allows us to override a webjar file, if needed. Mostly helpful during development.
|
|
|
+ final File file = new File( servletContext.getRealPath( effectiveUri ) );
|
|
|
+ if ( file.exists() )
|
|
|
{
|
|
|
- return entry.getValue();
|
|
|
+ return Optional.of( new RealFileResource( file ) );
|
|
|
}
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return fileSystemResource;
|
|
|
- }
|
|
|
-
|
|
|
- private static FileResource handleWebjarURIs(
|
|
|
- final ServletContext servletContext,
|
|
|
- final String resourcePathUri
|
|
|
- )
|
|
|
- throws PwmUnrecoverableException
|
|
|
- {
|
|
|
- if ( resourcePathUri.startsWith( ResourceFileServlet.WEBJAR_BASE_URL_PATH ) )
|
|
|
- {
|
|
|
- // This allows us to override a webjar file, if needed. Mostly helpful during development.
|
|
|
- final File file = new File( servletContext.getRealPath( resourcePathUri ) );
|
|
|
- if ( file.exists() )
|
|
|
- {
|
|
|
- return new RealFileResource( file );
|
|
|
- }
|
|
|
|
|
|
- final String remainingPath = resourcePathUri.substring( ResourceFileServlet.WEBJAR_BASE_URL_PATH.length() );
|
|
|
+ final String remainingPath = effectiveUri.substring( ResourceFileServlet.WEBJAR_BASE_URL_PATH.length() );
|
|
|
|
|
|
- final String webJarName;
|
|
|
- final String webJarPath;
|
|
|
- {
|
|
|
- final int slashIndex = remainingPath.indexOf( "/" );
|
|
|
- if ( slashIndex < 0 )
|
|
|
+ final String webJarName;
|
|
|
+ final String webJarPath;
|
|
|
{
|
|
|
- return null;
|
|
|
+ final int slashIndex = remainingPath.indexOf( "/" );
|
|
|
+ if ( slashIndex < 0 )
|
|
|
+ {
|
|
|
+ return Optional.empty();
|
|
|
+ }
|
|
|
+ webJarName = remainingPath.substring( 0, slashIndex );
|
|
|
+ webJarPath = remainingPath.substring( slashIndex + 1 );
|
|
|
}
|
|
|
- webJarName = remainingPath.substring( 0, slashIndex );
|
|
|
- webJarPath = remainingPath.substring( slashIndex + 1 );
|
|
|
- }
|
|
|
-
|
|
|
- final String versionString = WEB_JAR_VERSION_MAP.get( webJarName );
|
|
|
- if ( versionString == null )
|
|
|
- {
|
|
|
- return null;
|
|
|
- }
|
|
|
|
|
|
- final String fullPath = ResourceFileServlet.WEBJAR_BASE_FILE_PATH + "/" + webJarName + "/" + versionString + "/" + webJarPath;
|
|
|
- if ( WEB_JAR_ASSET_LIST.contains( fullPath ) )
|
|
|
- {
|
|
|
- final ClassLoader classLoader = servletContext.getClassLoader();
|
|
|
- final InputStream inputStream = classLoader.getResourceAsStream( fullPath );
|
|
|
+ final String versionString = WEB_JAR_VERSION_MAP.get( webJarName );
|
|
|
+ if ( versionString == null )
|
|
|
+ {
|
|
|
+ return Optional.empty();
|
|
|
+ }
|
|
|
|
|
|
- if ( inputStream != null )
|
|
|
+ final String fullPath = ResourceFileServlet.WEBJAR_BASE_FILE_PATH + "/" + webJarName + "/" + versionString + "/" + webJarPath;
|
|
|
+ if ( WEB_JAR_ASSET_LIST.contains( fullPath ) )
|
|
|
{
|
|
|
- return new InputStreamFileResource( inputStream, fullPath );
|
|
|
+ final ClassLoader classLoader = servletContext.getClassLoader();
|
|
|
+ final InputStream inputStream = classLoader.getResourceAsStream( fullPath );
|
|
|
+
|
|
|
+ if ( inputStream != null )
|
|
|
+ {
|
|
|
+ return Optional.of( new InputStreamFileResource( inputStream, fullPath ) );
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- return null;
|
|
|
+ return Optional.empty();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ @Value
|
|
|
private static class InputStreamFileResource implements FileResource
|
|
|
{
|
|
|
private final InputStream inputStream;
|
|
|
- private final String fullPath;
|
|
|
-
|
|
|
- InputStreamFileResource( final InputStream inputStream, final String fullPath )
|
|
|
- {
|
|
|
- this.inputStream = inputStream;
|
|
|
- this.fullPath = fullPath;
|
|
|
- }
|
|
|
+ private final String name;
|
|
|
|
|
|
@Override
|
|
|
- public InputStream getInputStream( ) throws IOException
|
|
|
+ public long length( )
|
|
|
{
|
|
|
- return inputStream;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public long length( )
|
|
|
+ public Instant lastModified( )
|
|
|
{
|
|
|
- return 0;
|
|
|
+ return Instant.EPOCH;
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
+ private static class RealFileUriResolver implements ResourceUriResolver
|
|
|
+ {
|
|
|
@Override
|
|
|
- public long lastModified( )
|
|
|
+ public Optional<FileResource> resolveUri( final ResourceRequestContext resourceRequestContext )
|
|
|
+ throws PwmUnrecoverableException
|
|
|
{
|
|
|
- return 0;
|
|
|
+ final String effectiveUri = resourceRequestContext.getUri();
|
|
|
+ final ServletContext servletContext = resourceRequestContext.getServletContext();
|
|
|
+
|
|
|
+ // convert to file.
|
|
|
+ final String filePath = servletContext.getRealPath( effectiveUri );
|
|
|
+ final File file = new File( filePath );
|
|
|
+
|
|
|
+ if ( file.exists() )
|
|
|
+ {
|
|
|
+ verifyPath( file, servletContext );
|
|
|
+
|
|
|
+ return Optional.of( new RealFileResource( file ) );
|
|
|
+ }
|
|
|
+
|
|
|
+ return Optional.empty();
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public boolean exists( )
|
|
|
+ private void verifyPath(
|
|
|
+ final File file,
|
|
|
+ final ServletContext servletContext
|
|
|
+ )
|
|
|
+ throws PwmUnrecoverableException
|
|
|
{
|
|
|
- return true;
|
|
|
+ // figure top-most path allowed by request
|
|
|
+ final String parentDirectoryPath = servletContext.getRealPath( ResourceFileServlet.RESOURCE_PATH );
|
|
|
+ final File parentDirectory = new File( parentDirectoryPath );
|
|
|
+
|
|
|
+ {
|
|
|
+ //verify the requested page is a child of the servlet resource path.
|
|
|
+ int recursions = 0;
|
|
|
+ File recurseFile = file.getParentFile();
|
|
|
+ while ( recurseFile != null && recursions < 100 )
|
|
|
+ {
|
|
|
+ if ( parentDirectory.equals( recurseFile ) )
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ recurseFile = recurseFile.getParentFile();
|
|
|
+ recursions++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ LOGGER.warn( () -> "attempt to access file outside of servlet path " + file.getAbsolutePath() );
|
|
|
+ throw new PwmUnrecoverableException( new ErrorInformation( PwmError.ERROR_SERVICE_NOT_AVAILABLE, "illegal file path request" ) );
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
+ private static class CustomZipFileUriResolver implements ResourceUriResolver
|
|
|
+ {
|
|
|
@Override
|
|
|
- public String getName( )
|
|
|
+ public Optional<FileResource> resolveUri( final ResourceRequestContext resourceRequestContext )
|
|
|
+ throws PwmUnrecoverableException
|
|
|
{
|
|
|
- return fullPath;
|
|
|
+ final String effectiveUri = resourceRequestContext.getUri();
|
|
|
+ final ResourceServletConfiguration resourceServletConfiguration = resourceRequestContext.getResourceServletConfiguration();
|
|
|
+
|
|
|
+ // check custom (configuration defined) zip file bundles
|
|
|
+ final Map<String, FileResource> customResources = resourceServletConfiguration.getCustomFileBundle();
|
|
|
+ for ( final Map.Entry<String, FileResource> entry : customResources.entrySet() )
|
|
|
+ {
|
|
|
+ final String customFileName = entry.getKey();
|
|
|
+ final String testName = ResourceFileServlet.RESOURCE_PATH + "/" + customFileName;
|
|
|
+ if ( testName.equals( effectiveUri ) )
|
|
|
+ {
|
|
|
+ return Optional.of( entry.getValue() );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return Optional.empty();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* Returns true if the given accept header accepts the given value.
|
|
|
*
|