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

com.aspectran.undertow.server.handler.resource.TowResourceHandler Maven / Gradle / Ivy

There is a newer version: 8.1.5
Show newest version
/*
 * Copyright (c) 2008-2024 The Aspectran Project
 *
 * 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 com.aspectran.undertow.server.handler.resource;

import com.aspectran.utils.StringUtils;
import com.aspectran.utils.annotation.jsr305.NonNull;
import com.aspectran.utils.logging.Logger;
import com.aspectran.utils.logging.LoggerFactory;
import com.aspectran.utils.wildcard.PluralWildcardPattern;
import com.aspectran.utils.wildcard.WildcardPattern;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.handlers.resource.PathResourceManager;
import io.undertow.server.handlers.resource.ResourceHandler;
import io.undertow.server.handlers.resource.ResourceManager;
import io.undertow.server.handlers.resource.ResourceSupplier;

import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

public class TowResourceHandler extends ResourceHandler {

    private static final Logger logger = LoggerFactory.getLogger(TowResourceHandler.class);

    private final HttpHandler next;

    private volatile PluralWildcardPattern resourcePathPatterns;

    public TowResourceHandler(ResourceManager resourceManager) {
        this(resourceManager, null);
    }

    public TowResourceHandler(ResourceManager resourceManager, HttpHandler next) {
        super(resourceManager);
        this.next = next;
    }

    public TowResourceHandler(ResourceSupplier resourceSupplier) {
        this(resourceSupplier, null);
    }

    public TowResourceHandler(ResourceSupplier resourceSupplier, HttpHandler next) {
        super(resourceSupplier);
        this.next = next;
    }

    public synchronized void setResourcePathPatterns(@NonNull ResourcePathPatterns resourcePathPatterns) {
        String[] includePatterns = resourcePathPatterns.getIncludePatterns();
        String[] excludePatterns = resourcePathPatterns.getExcludePatterns();
        this.resourcePathPatterns = new PluralWildcardPattern(includePatterns, excludePatterns, '/');
    }

    public void autoDetect(String pathPrefix) throws IOException {
        if (getResourceManager() instanceof PathResourceManager pathResourceManager) {
            Set staticResources = findStaticResources(pathResourceManager.getBasePath());
            Set patterns = new LinkedHashSet<>();
            if (resourcePathPatterns != null && resourcePathPatterns.hasIncludePatterns()) {
                for (WildcardPattern pattern : resourcePathPatterns.getIncludePatterns()) {
                    boolean exists = false;
                    for (String resource : staticResources) {
                        if (resource.endsWith("/") && pattern.toString().startsWith(resource)) {
                            exists = true;
                            break;
                        }
                    }
                    if (!exists) {
                        patterns.add(pattern);
                    }
                }
            }
            for (String resource : staticResources) {
                if (StringUtils.hasLength(pathPrefix)) {
                    resource = pathPrefix + resource;
                }
                if (resource.endsWith("/")) {
                    patterns.add(WildcardPattern.compile(resource + "**", '/'));
                } else {
                    patterns.add(WildcardPattern.compile(resource));
                }
            }
            if (patterns.isEmpty()) {
                resourcePathPatterns = null;
            } else {
                WildcardPattern[] includePatterns = patterns.toArray(new WildcardPattern[0]);
                WildcardPattern[] excludePatterns = (resourcePathPatterns != null ? resourcePathPatterns.getExcludePatterns() : null);
                resourcePathPatterns = new PluralWildcardPattern(includePatterns, excludePatterns);

                logger.info("TowResourceHandler includePatterns=" + Arrays.toString(includePatterns));
                if (excludePatterns != null) {
                    logger.info("TowResourceHandler excludePatterns=" + Arrays.toString(excludePatterns));
                }
            }
        }
    }

    @NonNull
    private Set findStaticResources(Path base) throws IOException {
        Set resources = new HashSet<>();
        try (DirectoryStream stream = Files.newDirectoryStream(base)) {
            for (Path child : stream) {
                String fileName = child.getFileName().toString();
                if ("WEB-INF".equalsIgnoreCase(fileName) || "META-INF".equalsIgnoreCase(fileName)) {
                    resources.add("/" + fileName + "/");
                } else if (Files.isDirectory(child)) {
                    findStaticResourceDirs(child, "/" + fileName + "/", resources);
                } else {
                    resources.add("/" + fileName);
                }
            }
        }
        return resources;
    }

    private void findStaticResourceDirs(Path parent, String prefix, Set resources) throws IOException {
        Set children = new HashSet<>();
        boolean found = false;
        try (DirectoryStream stream = Files.newDirectoryStream(parent)) {
            for (Path child : stream) {
                if (Files.isDirectory(child)) {
                    children.add(child);
                } else {
                    children.clear();
                    found = true;
                    break;
                }
            }
        }
        if (found) {
            resources.add(prefix);
        } else if (!children.isEmpty()) {
            for (Path child: children) {
                findStaticResourceDirs(child, prefix + child.getFileName() + "/", resources);
            }
        }
    }

    public boolean hasPatterns() {
        return (resourcePathPatterns != null);
    }

    @Override
    public void handleRequest(@NonNull HttpServerExchange exchange) throws Exception {
        String requestPath = exchange.getRequestPath();
        if (next == null || (resourcePathPatterns != null && resourcePathPatterns.matches(requestPath))) {
            super.handleRequest(exchange);
        } else {
            next.handleRequest(exchange);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy