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

org.eclipse.jetty.util.resource.AttributeNormalizer Maven / Gradle / Ivy

There is a newer version: 12.1.0.alpha0
Show newest version
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//

package org.eclipse.jetty.util.resource;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import org.eclipse.jetty.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Normalize Attribute to String.
 * 

* Replaces and expands: *

    *
  • ${WAR}
  • *
  • ${WAR.path}
  • *
  • ${WAR.uri}
  • *
  • ${jetty.base}
  • *
  • ${jetty.base.uri}
  • *
  • ${jetty.home}
  • *
  • ${jetty.home.uri}
  • *
  • ${user.home}
  • *
  • ${user.home.uri}
  • *
  • ${user.dir}
  • *
  • ${user.dir.uri}
  • *
*/ public class AttributeNormalizer { private static final Logger LOG = LoggerFactory.getLogger(AttributeNormalizer.class); private static final Pattern __propertyPattern = Pattern.compile("(?<=[^$]|^)\\$\\{([^}]*)\\}"); private static class Attribute { final String key; final String value; final int weight; public Attribute(String key, String value, int weight) { this.key = key; this.value = value; this.weight = weight; } } public static URI toCanonicalURI(URI uri) { uri = uri.normalize(); String path = uri.getPath(); if (path != null && path.length() > 1 && path.endsWith("/")) { try { String ascii = uri.toASCIIString(); uri = new URI(ascii.substring(0, ascii.length() - 1)); } catch (URISyntaxException e) { throw new IllegalArgumentException(e); } } return uri; } public static String toCanonicalURI(String uri) { if (uri != null && uri.length() > 1 && uri.endsWith("/")) { return uri.substring(0, uri.length() - 1); } return uri; } public static Path toCanonicalPath(String path) { if (path == null) return null; if (path.length() > 1 && path.endsWith("/")) path = path.substring(0, path.length() - 1); return toCanonicalPath(FileSystems.getDefault().getPath(path)); } private static Path toCanonicalPath(Path path) { if (path == null) { return null; } if (Files.exists(path)) { try { return path.toRealPath(); } catch (IOException e) { throw new IllegalArgumentException(e); } } return path.toAbsolutePath(); } private static class PathAttribute extends Attribute { public final Path path; public PathAttribute(String key, Path path, int weight) { super(key, path.toString(), weight); this.path = path; } @Override public String toString() { return String.format("PathAttribute[%s=>%s]", key, path); } } private static class URIAttribute extends Attribute { public final URI uri; public URIAttribute(String key, URI uri, int weight) { super(key, toCanonicalURI(uri.toASCIIString()), weight); this.uri = toCanonicalURI(uri); } @Override public String toString() { return String.format("URIAttribute[%s=>%s]", key, uri); } } private static final Comparator attrComparator = (o1, o2) -> { if ((o1.value == null) && (o2.value != null)) { return -1; } if ((o1.value != null) && (o2.value == null)) { return 1; } if (o1.value == null) { return 0; } // Different lengths? int diff = o2.value.length() - o1.value.length(); if (diff != 0) { return diff; } // Different names? diff = o2.value.compareTo(o1.value); if (diff != 0) { return diff; } // The paths are the same, base now on weight return o2.weight - o1.weight; }; private final Resource baseResource; private final List paths = new ArrayList<>(); private final List uris = new ArrayList<>(); public AttributeNormalizer(Resource baseResource) { if (baseResource == null) throw new IllegalArgumentException("No base resource!"); this.baseResource = baseResource; addSystemProperty("jetty.base", 9); addSystemProperty("jetty.home", 8); addSystemProperty("user.home", 7); addSystemProperty("user.dir", 6); int weight = 9; for (Resource base : baseResource) { URI uri = base.getURI(); if (uri == null) continue; URI warURI = toCanonicalURI(uri); if (!warURI.isAbsolute()) throw new IllegalArgumentException("WAR URI is not absolute: " + warURI); Path path = base.getPath(); if (path != null) paths.add(new PathAttribute("WAR.path", toCanonicalPath(path), weight)); uris.add(new URIAttribute("WAR.uri", warURI, weight - 1)); // preferred encoding uris.add(new URIAttribute("WAR", warURI, weight - 2)); // legacy encoding weight += 3; } paths.sort(attrComparator); uris.sort(attrComparator); if (LOG.isDebugEnabled()) Stream.concat(paths.stream(), uris.stream()).map(Object::toString).forEach(LOG::debug); } private void addSystemProperty(String key, int weight) { String value = System.getProperty(key); if (value != null) { Path path = toCanonicalPath(value); paths.add(new PathAttribute(key, path, weight)); uris.add(new URIAttribute(key + ".uri", path.toUri(), weight)); } } /** * Normalize a URI, URL, or File reference by replacing known attributes with ${key} attributes. * * @param o the object to normalize into a string * @return the string representation of the object, with expansion keys. */ public String normalize(Object o) { try { // Find a URI URI uri = null; Path path = null; if (o instanceof URI) uri = toCanonicalURI(((URI)o)); else if (o instanceof Resource) uri = toCanonicalURI(((Resource)o).getURI()); else if (o instanceof URL) uri = toCanonicalURI(((URL)o).toURI()); else if (o instanceof File) path = ((File)o).getAbsoluteFile().getCanonicalFile().toPath(); else if (o instanceof Path) path = (Path)o; else { String s = o.toString(); try { uri = new URI(s); if (uri.getScheme() == null) { // Unknown scheme? not relevant to normalize return s; } } catch (URISyntaxException e) { // This path occurs for many reasons, but most common is when this // is executed on MS Windows, on a string like "D:\jetty" // and the new URI() fails for // java.net.URISyntaxException: Illegal character in opaque part at index 2: D:\jetty return s; } } if (uri != null) { if ("jar".equalsIgnoreCase(uri.getScheme())) { String raw = uri.getRawSchemeSpecificPart(); int bang = raw.indexOf("!/"); String normal = normalize(raw.substring(0, bang)); String suffix = raw.substring(bang); return "jar:" + normal + suffix; } else { if (uri.isAbsolute()) { return normalizeUri(uri); } } } else if (path != null) return normalizePath(path); } catch (Exception e) { LOG.warn("Failed to normalize {}", o, e); } return String.valueOf(o); } protected String normalizeUri(URI uri) { for (URIAttribute a : uris) { if (uri.compareTo(a.uri) == 0) return String.format("${%s}", a.key); if (!a.uri.getScheme().equalsIgnoreCase(uri.getScheme())) continue; if (a.uri.getHost() == null && uri.getHost() != null) continue; if (a.uri.getHost() != null && !a.uri.getHost().equals(uri.getHost())) continue; String aPath = a.uri.getPath(); String uPath = uri.getPath(); if (aPath.equals(uPath)) return a.value; if (!uPath.startsWith(aPath)) continue; if (uPath.length() == aPath.length()) return String.format("${%s}", a.key); String s = uPath.substring(aPath.length()); if (s.charAt(0) != '/') continue; return String.format("${%s}%s", a.key, s); } return uri.toASCIIString(); } protected String normalizePath(Path path) { for (PathAttribute a : paths) { try { if (path.equals(a.path) || Files.isSameFile(path, a.path)) return String.format("${%s}", a.key); } catch (IOException x) { LOG.trace("IGNORED", x); } if (path.startsWith(a.path)) return String.format("${%s}%c%s", a.key, File.separatorChar, a.path.relativize(path)); } return path.toString(); } public String expand(String str) { if (str == null) { return str; } if (!str.contains("${")) { // Contains no potential expressions. return str; } Matcher mat = __propertyPattern.matcher(str); if (mat.find(0)) { String prefix = str.substring(0, mat.start()); String property = mat.group(1); String suffix = str.substring(mat.end()); str = expand(prefix, property, suffix); } return StringUtil.replace(str, "$$", "$"); } private String expand(String prefix, String property, String suffix) { if (property == null) return null; switch (property) { case "WAR", "WAR.path" -> { return prefix + baseResource.resolve(suffix).getPath(); } case "WAR.uri" -> { return prefix + baseResource.resolve(suffix).getURI(); } } // Check for URI matches for (URIAttribute attr : uris) { if (property.equals(attr.key)) return prefix + attr.value + suffix; } // Check for path matches for (PathAttribute attr : paths) { if (property.equals(attr.key)) return prefix + attr.value + suffix; } // Use system properties next String system = System.getProperty(property); if (system != null) return prefix + system + suffix; String unexpanded = prefix + "${" + property + "}" + suffix; LOG.warn("Cannot expand: {}", unexpanded); return unexpanded; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy