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

com.sap.cds.adapter.ServletUrlResourcePaths Maven / Gradle / Ivy

The newest version!
/**************************************************************************
 * (C) 2019-2024 SAP SE or an SAP affiliate company. All rights reserved. *
 **************************************************************************/
package com.sap.cds.adapter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

import com.sap.cds.services.runtime.CdsRuntime;
import com.sap.cds.services.runtime.ExtendedServiceLoader;

/**
 * A utility to iterate the public {@link UrlResourcePath}s of Servlets created by {@link ServletAdapterFactory}
 * according to the passed {@link CdsRuntime}.
 * 

* Define an instance of {@link UrlResourcePathVisitor} to take further action on public endpoints. */ public class ServletUrlResourcePaths { private List servletPaths = new ArrayList<>(); /** * Create an instance based on the underlying {@link CdsRuntime}. * * @param runtime the {@link CdsRuntime}. */ public ServletUrlResourcePaths(CdsRuntime runtime) { Objects.requireNonNull(runtime, "runtime must not be null"); // we need to touch the endpoints of all servlet-based adapters Iterator factoryIterator = ExtendedServiceLoader.loadAll(AdapterFactory.class, runtime); factoryIterator.forEachRemaining(factory -> { if (factory instanceof ServletAdapterFactory servletFactory && servletFactory.isEnabled()) { UrlResourcePath servletPath = servletFactory.getServletPath(); servletPaths.add(servletPath); } }); Collections.sort(servletPaths, (p1, p2) -> { // more segments need to be handled earlier int comparison = -1 * Integer.compare(countSegments(p1), countSegments(p2)); if(comparison == 0) { // if segments are the same, check if one path is a substring of another // the shorter path wins in that case, e.g. / vs /** if(p1.getPath().startsWith(p2.getPath())) { return 1; } else if (p2.getPath().startsWith(p1.getPath())) { return -1; } } return comparison; }); } /** * Returns the base paths found in the model. * * @return a {@link Stream} of {@link UrlResourcePath} defining the base endpoints. */ public Stream getBasePaths() { return servletPaths.stream(); } /** * The interface of a visitor */ public interface UrlResourcePathVisitor { /** * Called when a public {@link UrlResourcePath} is found. * @param publicPath The public {@link UrlResourcePath} */ void foundPublicPath(UrlResourcePath publicPath); /** * Called when a {@link UrlResourcePath} is found with a public event. * @param path The {@link UrlResourcePath} * @param publicEvents The public events on the given path */ void foundPublicEvents(UrlResourcePath path, Stream publicEvents); } /** * Starts enumerating all cds servlet paths recursively (depth-first order). * @param visitor a visitor being notified during iteration */ public void visit(UrlResourcePathVisitor visitor) { Objects.requireNonNull(visitor, "visitor is required to handle public endpoints"); servletPaths.forEach(p -> visitServletPath(p, visitor)); } private void visitServletPath(UrlResourcePath servletPath, UrlResourcePathVisitor visitor) { // first decide each sub path recursively servletPath.subPaths().forEach(subPath -> { visitServletPath(subPath, visitor); }); if (servletPath.isPublic()) { visitor.foundPublicPath(servletPath); } else { // some http methods might still be public even if the path itself is closed visitor.foundPublicEvents(servletPath, servletPath.publicEvents()); } } private int countSegments(UrlResourcePath path) { int count = 0; for(char c : path.getPath().toCharArray()) { if(c == '/') { ++count; } } return count; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy