001/******************************************************************************* 002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 *******************************************************************************/ 014package org.nuxeo.runtime.test; 015 016import java.io.IOException; 017import java.net.URI; 018import java.net.URISyntaxException; 019import java.net.URL; 020import java.nio.file.FileSystem; 021import java.nio.file.FileSystems; 022import java.nio.file.Path; 023import java.nio.file.Paths; 024import java.util.Enumeration; 025import java.util.HashMap; 026import java.util.Map; 027 028public class TargetResourceLocator { 029 030 protected final ClassLoader loader; 031 032 protected final Path basepath; 033 034 public TargetResourceLocator(Class<?> clazz) { 035 basepath = basepath(clazz); 036 loader = clazz.getClassLoader(); 037 } 038 039 public Path getBasepath() { 040 return basepath; 041 } 042 043 protected int depthOfClass(String name) { 044 int depth = 0; 045 int index = name.indexOf('.'); 046 while (index > 0) { 047 depth += 1; 048 index = name.indexOf('.', index + 1); 049 } 050 return depth; 051 } 052 053 protected Path basepath(Class<?> clazz) { 054 String name = clazz.getName(); 055 int depth = depthOfClass(name) + 1; 056 Path path; 057 try { 058 path = toPath(clazz.getResource("/".concat(name).replace('.', '/').concat(".class")).toURI()); 059 Path root = path.getRoot(); 060 if (path.getNameCount() > depth) { 061 path = path.subpath(0, path.getNameCount() - depth); 062 path = root.resolve(path); 063 } 064 return path; 065 } catch (URISyntaxException | IOException cause) { 066 throw new AssertionError("Cannot convert " + name + " to base dir", cause); 067 } 068 } 069 070 public URL getTargetTestResource(String name) throws IOException { 071 try { 072 final Enumeration<URL> resources = loader.getResources(name); 073 while (resources.hasMoreElements()) { 074 URL resource = resources.nextElement(); 075 if (!resources.hasMoreElements()) { 076 return resource; 077 } 078 URI uri = resource.toURI(); 079 Path path = toPath(uri); 080 if (path.getFileSystem().equals(basepath.getFileSystem()) && path.startsWith(basepath)) { 081 return path.toUri().toURL(); 082 } 083 } 084 } catch (URISyntaxException cause) { 085 throw new AssertionError("Cannot find location of " + name, cause); 086 } 087 return null; 088 } 089 090 protected Path toPath(URI uri) throws IOException { 091 final Map<String, String> env = new HashMap<>(); 092 final String[] array = uri.toString().split("!"); 093 if (array.length == 1) { 094 return Paths.get(uri); 095 } 096 // work-around for jar paths on JDK7 097 try (FileSystem fs = FileSystems.newFileSystem(URI.create(array[0]), env)) { 098 return fs.getPath(array[1]); 099 } 100 } 101}