All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sap.cloud.yaas.servicesdk.springboot.ramlrewriter.RamlResourcesAutoConfiguration Maven / Gradle / Ivy

There is a newer version: 4.17.1
Show newest version
/*
 * © 2017 SAP SE or an SAP affiliate company.
 * All rights reserved.
 * Please see http://www.sap.com/corporate-en/legal/copyright/index.epx for additional trademark information and
 * notices.
 */
package com.sap.cloud.yaas.servicesdk.springboot.ramlrewriter;

import javax.servlet.http.HttpServletRequest;

import com.github.ulisesbocchio.jar.resources.JarResourceLoader;
import com.sap.cloud.yaas.servicesdk.ramlrewriter.filter.RequestBasedRamlRewriter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.MimeMappings;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.resource.ResourceTransformer;
import org.springframework.web.servlet.resource.ResourceTransformerChain;
import org.springframework.web.servlet.resource.TransformedResource;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;


/**
 * Auto Configuration class that auto-registers the functionality of raml-rewriter library of the YaaS Service SDK.
 * 

* It registers a RAML rewriting {@link ResourceTransformer} that uses {@link RequestBasedRamlRewriter} internally. */ @Configuration @ConditionalOnClass({ WebMvcConfigurerAdapter.class, RequestBasedRamlRewriter.class }) @ConditionalOnWebApplication public class RamlResourcesAutoConfiguration { private static final Logger LOG = LoggerFactory.getLogger(RamlResourcesAutoConfiguration.class); private static final String PUBLIC_PATH = "/public/"; private static final String METADATA_PATH = PUBLIC_PATH + "meta-data/"; /** * Registers an instance of {@link RequestBasedRamlRewriter}. * * @return an instance of {@link RequestBasedRamlRewriter} * @throws IOException in case of problems retrieving the raml resources root path */ @Bean @Lazy @ConditionalOnClass(RequestBasedRamlRewriter.class) @ConditionalOnMissingBean(RequestBasedRamlRewriter.class) public RequestBasedRamlRewriter ramlRewriter() throws IOException { return new RequestBasedRamlRewriter(); } /** * Registers an instance of {@link ResourceTransformer}. * * @return an instance of {@link ResourceTransformer} */ @Bean @Lazy @ConditionalOnBean(RequestBasedRamlRewriter.class) public ResourceTransformer ramlRewritingTransformer() { return new RamlRewritingTransformer(); } /** * Registers a {@link WebMvcConfigurerAdapter} that adds resource handlers for static RAML serving and rewriting. * * @return serving static RAML configuration * @throws IOException in case of streaming problems during transformation */ @Bean public WebMvcConfigurerAdapter ramlResourcesConfiguration() throws IOException { return new RamlResourcesConfiguration(); } private class RamlRewritingTransformer implements ResourceTransformer { @Override public Resource transform(final HttpServletRequest request, final Resource resource, final ResourceTransformerChain transformerChain) throws IOException { try (InputStream input = resource.getInputStream()) { final byte[] rawContent = StreamUtils.copyToByteArray(input); final byte[] rewrittenContent = ramlRewriter().rewrite(rawContent, request); final Resource rewrittenResource = new TransformedResource(resource, rewrittenContent); return transformerChain.transform(request, rewrittenResource); } } } private class RamlResourcesConfiguration extends WebMvcConfigurerAdapter { private static final String BASE_PATH = "/meta-data/**"; @Override @SuppressWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE") public void addResourceHandlers(final ResourceHandlerRegistry registry) { final Resource resourceLocation = new ClassPathResource(METADATA_PATH); if (resourceLocation.exists()) { LOG.info("Serving RAML resources from classpath at : '" + METADATA_PATH + "'."); final String location; try { location = resourceLocation.getURL().toString(); } catch (final IOException e) { LOG.warn("The path '" + METADATA_PATH + "' for RAML resources does not seem to be valid." + " Will ignore this, and not attempt to serve static resources for RAML.", e); return; } final ResourceHandlerRegistration registration = registry.addResourceHandler(BASE_PATH); registration.addResourceLocations(location); LOG.info("Activating RAML rewriting for all RAML resources being served."); registration.resourceChain(false).addTransformer(ramlRewritingTransformer()); } else { LOG.warn("The path '" + METADATA_PATH + "' does not exist on the classpath." + " Will ignore this, and not attempt to serve static resources for RAML."); } } } /** * Adds the Content-type mapping for *.raml extension, so that it is served as text/plain MIME type * instead of application/octet-stream. Additionally, provide a proper document root to serve * resources from the ServletContext to allow for RAML expansion and add a * servlet mapping for /meta-data/* */ @Component public static class ServletContainerCustomizer implements EmbeddedServletContainerCustomizer { private static final String DOC_ROOT_PREFIX = "tempDocRoot"; @Override public void customize(final ConfigurableEmbeddedServletContainer container) { customizeMimeMappings(container); customizeDocumentRoot(container); } private void customizeMimeMappings(final ConfigurableEmbeddedServletContainer container) { final MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT); mappings.add("raml", "text/plain"); container.setMimeMappings(mappings); } private void customizeDocumentRoot(final ConfigurableEmbeddedServletContainer container) { // we wrap the actual resource in a JarResource. If contained in a JAR file, the resource will be unpacked // to a temp directory. This allows us to get a File object to set the document root directory. try { final String docRootDir = Files.createTempDirectory(DOC_ROOT_PREFIX).toAbsolutePath().toString(); final Resource unpackedDocumentRootResource = new JarResourceLoader(docRootDir).getResource(PUBLIC_PATH); if (unpackedDocumentRootResource.exists()) { final File documentRoot = unpackedDocumentRootResource.getFile(); container.setDocumentRoot(documentRoot); LOG.info("Using custom document root for our servlet context: " + documentRoot); } } catch (final IOException e) { LOG.warn("Failed to set document root to " + PUBLIC_PATH + ", falling back to default.", e); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy