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

org.nuiton.eugene.ResourceResolver Maven / Gradle / Ivy

There is a newer version: 3.0-beta-2
Show newest version
package org.nuiton.eugene;

/*-
 * #%L
 * EUGene :: EUGene Core
 * %%
 * Copyright (C) 2004 - 2017 Code Lutin, Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import io.ultreia.java4all.lang.ClassLoaders;
import io.ultreia.java4all.lang.Strings;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamSource;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 

* ResourceResolver is a URIResolver for XSL transformation. *

*

* Its purpose is to catch the XSL document(...) function call and return a * valid data source only if the wanted resource is present in the project * resources. *

*

The main goal of ResourceResolver is to retrieve datasources locally, if the * wanted resource is not present in project resource then null will be * returned. *

* The resolve function search for the file part of href parameter: *
    *
  • href: http://argouml.org/profiles/uml14/default-uml14.xmi
  • *
  • file part: default-uml14.xmi.
  • *
* The resource is searched this way: *
    *
  • eg: {@code [file part extension]/[file part]}
  • *
  • eg: {@code xmi/default-uml14.xmi}
  • *
*

* You should assign this ResourceResolver on * {@link Transformer} but not on {@link TransformerFactory}. * * @author chorlet */ public class ResourceResolver implements URIResolver { /** * le pattern de detection d'une uri */ public static final Pattern HREF_PATTERN = Pattern.compile("([a-zA-Z]+)\\:\\/\\/(.+)"); /** * Shared Cache to not search in full classpath at each request. */ protected static final SortedMap sourceCache = new TreeMap<>(); /** * Shared Cache of not local resources */ protected static final Set unresolvedCache = new HashSet<>(); /** * log. */ private static final Logger log = LogManager.getLogger(ResourceResolver.class); protected String base; /** * le niveau de verbosite */ protected boolean verbose = log.isDebugEnabled(); /** * le classe loader utilise pour recuperer les resources */ protected ClassLoader cl = getClass().getClassLoader(); public ResourceResolver() { this(null); } public ResourceResolver(String base) { if (base != null && base.endsWith("/") && base.length() > 1) { base = base.substring(0, base.length() - 1); } this.base = base; if (log.isTraceEnabled()) { log.trace(this + ", base : " + this.base); } } /** * Pour vider le cache partage. */ public static synchronized void clearCache() { sourceCache.clear(); unresolvedCache.clear(); } /** * Resolve href on local resource. * * @return null if local resource not found */ @Override public synchronized Source resolve(String href, String base) { if (unresolvedCache.contains(href)) { // href was already unfound in class-path, // do not search twice (class-path search can be expensive) if (verbose) { log.info("Skip unresolved " + href); } return null; } if (sourceCache.containsKey(href)) { // directly use the cached source, skip all other stuff if (verbose) { log.info("use cached source " + href); } return sourceCache.get(href); } // at this point, the href is undiscovered, try to find in in class-path if (verbose) { log.info("Resolving " + href); } // URI : // example 1 : pathmap://UML_METAMODELS/UML.metamodel.uml // example 2 : http://argouml.org/profiles/uml14/default-java.xmi // relative path : // example 3 : xxx/zzz/ttt.uml Source source; // if URI Matcher matcher = HREF_PATTERN.matcher(href); if (matcher.matches()) { // String protocol = matcher.group(1); String path = matcher.group(2); // try look only with the filename // this is the last chance to find something :) source = findHrefSource(path); } else { // no protocol, so should be a relative path location source = findRelativeSource(href); } if (source == null) { // means this resolver was not able to find the source if (verbose) { log.info("detect unresolved source " + href); } unresolvedCache.add(href); } else { // find a new cacheable source, add it in cache if (verbose) { log.info("detect cacheable source " + href); } sourceCache.put(href, source); } // if (href.matches("[a-zA-Z]+://.+")) { // String filename = null; // int beginIndex = href.lastIndexOf('/'); // if (beginIndex > -1) { // filename = href.substring(beginIndex + 1); // } // if (filename != null && !filename.isEmpty()) { // source = findSource(filename, true); // } // } else { // source = findSource(href, false); // } return source; } public void setVerbose(boolean verbose) { this.verbose = verbose; } public void setCl(ClassLoader cl) { this.cl = cl; } protected Source findHrefSource(String path) { long t0 = System.nanoTime(); String filename; int beginIndex = path.lastIndexOf('/'); if (beginIndex > -1) { filename = path.substring(beginIndex + 1); } else { filename = path; } if (filename == null || filename.isEmpty()) { return null; } String resource; resource = ".*/" + filename; if (verbose) { log.info("will discover " + resource); } URL url = null; // use given classloader to work in maven List urls = null; URLClassLoader ucl = null; if (cl == null) { ClassLoader cl2 = getClass().getClassLoader(); if (cl2 instanceof URLClassLoader) { ucl = (URLClassLoader) cl2; } } if (cl instanceof URLClassLoader) { ucl = (URLClassLoader) cl; } try { urls = ClassLoaders.getURLs(resource, ucl); } catch (Exception rnfe) { // Nothing to do } if (urls != null && !urls.isEmpty()) { url = urls.get(0); } Source source = null; if (url != null) { if (verbose) { log.info(url.toString()); } source = new StreamSource(url.toString()); } if (verbose) { String time = Strings.convertTime(System.nanoTime() - t0); log.info("resolved in " + time); } return source; } protected Source findRelativeSource(String path) { long t0 = System.nanoTime(); String filename = path; // int beginIndex = path.lastIndexOf('/'); // if (beginIndex > -1) { // filename = path.substring(beginIndex + 1); // } else { // filename = path; // } // if (filename == null || filename.isEmpty()) { // return null; // } String resource; if (base != null) { resource = base + "/" + filename; } else { resource = filename; } if (verbose) { log.info("will discover " + resource); } URL url = ClassLoaders.getURLOrNull(resource); Source source = null; if (url != null) { if (verbose) { log.info(url.toString()); } source = new StreamSource(url.toString()); } if (verbose) { String time = Strings.convertTime(System.nanoTime() - t0); log.info("resolved in " + time); } return source; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy