001/* 002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.nuxeo.runtime.test; 017 018import java.io.IOException; 019import java.net.URI; 020import java.net.URISyntaxException; 021import java.net.URL; 022import java.nio.file.FileSystem; 023import java.nio.file.FileSystems; 024import java.nio.file.Path; 025import java.nio.file.Paths; 026import java.util.Enumeration; 027import java.util.HashMap; 028import java.util.Map; 029 030public class TargetResourceLocator { 031 032 protected final ClassLoader loader; 033 034 protected final Path basepath; 035 036 public TargetResourceLocator(Class<?> clazz) { 037 basepath = basepath(clazz); 038 loader = clazz.getClassLoader(); 039 } 040 041 public Path getBasepath() { 042 return basepath; 043 } 044 045 protected int depthOfClass(String name) { 046 int depth = 0; 047 int index = name.indexOf('.'); 048 while (index > 0) { 049 depth += 1; 050 index = name.indexOf('.', index + 1); 051 } 052 return depth; 053 } 054 055 protected Path basepath(Class<?> clazz) { 056 String name = clazz.getName(); 057 int depth = depthOfClass(name) + 1; 058 Path path; 059 try { 060 path = toPath(clazz.getResource("/".concat(name).replace('.', '/').concat(".class")).toURI()); 061 Path root = path.getRoot(); 062 if (path.getNameCount() > depth) { 063 path = path.subpath(0, path.getNameCount() - depth); 064 path = root.resolve(path); 065 } 066 return path; 067 } catch (URISyntaxException | IOException cause) { 068 throw new AssertionError("Cannot convert " + name + " to base dir", cause); 069 } 070 } 071 072 public URL getTargetTestResource(String name) throws IOException { 073 try { 074 final Enumeration<URL> resources = loader.getResources(name); 075 while (resources.hasMoreElements()) { 076 URL resource = resources.nextElement(); 077 if (!resources.hasMoreElements()) { 078 return resource; 079 } 080 URI uri = resource.toURI(); 081 Path path = toPath(uri); 082 if (path.getFileSystem().equals(basepath.getFileSystem()) && path.startsWith(basepath)) { 083 return path.toUri().toURL(); 084 } 085 } 086 } catch (URISyntaxException cause) { 087 throw new AssertionError("Cannot find location of " + name, cause); 088 } 089 return null; 090 } 091 092 protected Path toPath(URI uri) throws IOException { 093 final Map<String, String> env = new HashMap<>(); 094 final String[] array = uri.toString().split("!"); 095 if (array.length == 1) { 096 return Paths.get(uri); 097 } 098 // work-around for jar paths on JDK7 099 try (FileSystem fs = FileSystems.newFileSystem(URI.create(array[0]), env)) { 100 return fs.getPath(array[1]); 101 } 102 } 103}