/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.camel.component.undertow.handlers; import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; import io.undertow.util.PathTemplate; import io.undertow.util.URLUtils; /** * Custom root handler to enable hot swapping individual handlers assigned for each path template and/or HTTP method. */ public class CamelRootHandler implements HttpHandler { private CamelPathHandler pathHandler; public CamelRootHandler(HttpHandler defaultHandler) { pathHandler = new CamelPathHandler(defaultHandler); } public void handleRequest(HttpServerExchange exchange) throws Exception { pathHandler.handleRequest(exchange); } public synchronized void add(String path, String[] methods, boolean prefixMatch, HttpHandler handler) { String basePath = getBasePath(path); HttpHandler basePathHandler = pathHandler.getHandler(basePath); CamelMethodHandler targetHandler; if (path.contains("{")) { // Adding a handler for the template path String relativePath = path.substring(basePath.length()); if (basePathHandler instanceof CamelPathTemplateHandler) { CamelPathTemplateHandler templateHandler = (CamelPathTemplateHandler)basePathHandler; targetHandler = templateHandler.get(relativePath); if (targetHandler == null) { targetHandler = new CamelMethodHandler(); templateHandler.add(relativePath, targetHandler); } } else { CamelPathTemplateHandler templateHandler; if (basePathHandler instanceof CamelMethodHandler) { // A static path handler is already set for the base path. Use it as a default handler templateHandler = new CamelPathTemplateHandler((CamelMethodHandler)basePathHandler); } else if (basePathHandler == null) { templateHandler = new CamelPathTemplateHandler(new CamelMethodHandler()); } else { throw new IllegalArgumentException(String.format("Unsupported handler '%s' was found", basePathHandler)); } targetHandler = new CamelMethodHandler(); templateHandler.add(relativePath, targetHandler); pathHandler.addPrefixPath(basePath, templateHandler); } } else { // Adding a handler for the static path if (basePathHandler instanceof CamelPathTemplateHandler) { CamelPathTemplateHandler templateHandler = (CamelPathTemplateHandler)basePathHandler; if (prefixMatch) { targetHandler = templateHandler.getDefault(); } else { throw new IllegalArgumentException(String.format("Duplicate handlers on a path '%s'", path)); } } else { if (basePathHandler instanceof CamelMethodHandler) { targetHandler = (CamelMethodHandler)basePathHandler; } else if (basePathHandler == null) { targetHandler = new CamelMethodHandler(); if (prefixMatch) { pathHandler.addPrefixPath(basePath, targetHandler); } else { pathHandler.addExactPath(basePath, targetHandler); } } else { throw new IllegalArgumentException(String.format("Unsupported handler '%s' was found", basePathHandler)); } } } if (methods != null && methods.length != 0) { targetHandler.add(methods, handler); } else { targetHandler.addDefault(handler); } } public synchronized void remove(String path, String[] methods, boolean prefixMatch) { String basePath = getBasePath(path); HttpHandler basePathHandler = pathHandler.getHandler(basePath); if (basePathHandler == null) { return; } if (path.contains("{")) { // Removing a handler for the template path String relativePath = path.substring(basePath.length()); CamelPathTemplateHandler templateHandler = (CamelPathTemplateHandler)basePathHandler; CamelMethodHandler targetHandler = templateHandler.get(relativePath); if (methods != null && methods.length != 0) { targetHandler.remove(methods); } else { targetHandler.removeDefault(); } if (targetHandler.isEmpty()) { templateHandler.remove(relativePath); if (templateHandler.isEmpty()) { pathHandler.removePrefixPath(basePath); } } } else { // Removing a handler for the static path if (basePathHandler instanceof CamelPathTemplateHandler) { String relativePath = path.substring(basePath.length()); CamelPathTemplateHandler templateHandler = (CamelPathTemplateHandler)basePathHandler; CamelMethodHandler targetHandler = templateHandler.getDefault(); if (methods != null && methods.length != 0) { targetHandler.remove(methods); } else { targetHandler.removeDefault(); } if (targetHandler.isEmpty()) { templateHandler.remove(relativePath); if (templateHandler.isEmpty()) { pathHandler.removePrefixPath(basePath); } } } else { CamelMethodHandler targetHandler = (CamelMethodHandler)basePathHandler; if (methods != null && methods.length != 0) { targetHandler.remove(methods); } else { targetHandler.removeDefault(); } if (targetHandler.isEmpty()) { if (prefixMatch) { pathHandler.removePrefixPath(basePath); } else { pathHandler.removeExactPath(basePath); } } } } } public synchronized boolean isEmpty() { return pathHandler.isEmpty(); } public String toString() { return pathHandler.toString(); } private String getBasePath(String path) { if (path.contains("{")) { path = PathTemplate.create(path).getBase(); } return URLUtils.normalizeSlashes(path); } }