001/* 002 * Copyright 2002-2018 the original author or authors. 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 * https://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 */ 016 017package org.springframework.core.io; 018 019import java.io.File; 020import java.io.IOException; 021import java.io.InputStream; 022import java.lang.reflect.Field; 023import java.lang.reflect.InvocationTargetException; 024import java.lang.reflect.Method; 025import java.net.URI; 026import java.net.URL; 027 028import org.springframework.lang.Nullable; 029import org.springframework.util.ReflectionUtils; 030 031/** 032 * Utility for detecting and accessing JBoss VFS in the classpath. 033 * 034 * <p>As of Spring 4.0, this class supports VFS 3.x on JBoss AS 6+ 035 * (package {@code org.jboss.vfs}) and is in particular compatible with 036 * JBoss AS 7 and WildFly 8+. 037 * 038 * <p>Thanks go to Marius Bogoevici for the initial patch. 039 * <b>Note:</b> This is an internal class and should not be used outside the framework. 040 * 041 * @author Costin Leau 042 * @author Juergen Hoeller 043 * @since 3.0.3 044 */ 045public abstract class VfsUtils { 046 047 private static final String VFS3_PKG = "org.jboss.vfs."; 048 private static final String VFS_NAME = "VFS"; 049 050 private static final Method VFS_METHOD_GET_ROOT_URL; 051 private static final Method VFS_METHOD_GET_ROOT_URI; 052 053 private static final Method VIRTUAL_FILE_METHOD_EXISTS; 054 private static final Method VIRTUAL_FILE_METHOD_GET_INPUT_STREAM; 055 private static final Method VIRTUAL_FILE_METHOD_GET_SIZE; 056 private static final Method VIRTUAL_FILE_METHOD_GET_LAST_MODIFIED; 057 private static final Method VIRTUAL_FILE_METHOD_TO_URL; 058 private static final Method VIRTUAL_FILE_METHOD_TO_URI; 059 private static final Method VIRTUAL_FILE_METHOD_GET_NAME; 060 private static final Method VIRTUAL_FILE_METHOD_GET_PATH_NAME; 061 private static final Method VIRTUAL_FILE_METHOD_GET_PHYSICAL_FILE; 062 private static final Method VIRTUAL_FILE_METHOD_GET_CHILD; 063 064 protected static final Class<?> VIRTUAL_FILE_VISITOR_INTERFACE; 065 protected static final Method VIRTUAL_FILE_METHOD_VISIT; 066 067 private static final Field VISITOR_ATTRIBUTES_FIELD_RECURSE; 068 069 static { 070 ClassLoader loader = VfsUtils.class.getClassLoader(); 071 try { 072 Class<?> vfsClass = loader.loadClass(VFS3_PKG + VFS_NAME); 073 VFS_METHOD_GET_ROOT_URL = vfsClass.getMethod("getChild", URL.class); 074 VFS_METHOD_GET_ROOT_URI = vfsClass.getMethod("getChild", URI.class); 075 076 Class<?> virtualFile = loader.loadClass(VFS3_PKG + "VirtualFile"); 077 VIRTUAL_FILE_METHOD_EXISTS = virtualFile.getMethod("exists"); 078 VIRTUAL_FILE_METHOD_GET_INPUT_STREAM = virtualFile.getMethod("openStream"); 079 VIRTUAL_FILE_METHOD_GET_SIZE = virtualFile.getMethod("getSize"); 080 VIRTUAL_FILE_METHOD_GET_LAST_MODIFIED = virtualFile.getMethod("getLastModified"); 081 VIRTUAL_FILE_METHOD_TO_URI = virtualFile.getMethod("toURI"); 082 VIRTUAL_FILE_METHOD_TO_URL = virtualFile.getMethod("toURL"); 083 VIRTUAL_FILE_METHOD_GET_NAME = virtualFile.getMethod("getName"); 084 VIRTUAL_FILE_METHOD_GET_PATH_NAME = virtualFile.getMethod("getPathName"); 085 VIRTUAL_FILE_METHOD_GET_PHYSICAL_FILE = virtualFile.getMethod("getPhysicalFile"); 086 VIRTUAL_FILE_METHOD_GET_CHILD = virtualFile.getMethod("getChild", String.class); 087 088 VIRTUAL_FILE_VISITOR_INTERFACE = loader.loadClass(VFS3_PKG + "VirtualFileVisitor"); 089 VIRTUAL_FILE_METHOD_VISIT = virtualFile.getMethod("visit", VIRTUAL_FILE_VISITOR_INTERFACE); 090 091 Class<?> visitorAttributesClass = loader.loadClass(VFS3_PKG + "VisitorAttributes"); 092 VISITOR_ATTRIBUTES_FIELD_RECURSE = visitorAttributesClass.getField("RECURSE"); 093 } 094 catch (Throwable ex) { 095 throw new IllegalStateException("Could not detect JBoss VFS infrastructure", ex); 096 } 097 } 098 099 protected static Object invokeVfsMethod(Method method, @Nullable Object target, Object... args) throws IOException { 100 try { 101 return method.invoke(target, args); 102 } 103 catch (InvocationTargetException ex) { 104 Throwable targetEx = ex.getTargetException(); 105 if (targetEx instanceof IOException) { 106 throw (IOException) targetEx; 107 } 108 ReflectionUtils.handleInvocationTargetException(ex); 109 } 110 catch (Exception ex) { 111 ReflectionUtils.handleReflectionException(ex); 112 } 113 114 throw new IllegalStateException("Invalid code path reached"); 115 } 116 117 static boolean exists(Object vfsResource) { 118 try { 119 return (Boolean) invokeVfsMethod(VIRTUAL_FILE_METHOD_EXISTS, vfsResource); 120 } 121 catch (IOException ex) { 122 return false; 123 } 124 } 125 126 static boolean isReadable(Object vfsResource) { 127 try { 128 return (Long) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_SIZE, vfsResource) > 0; 129 } 130 catch (IOException ex) { 131 return false; 132 } 133 } 134 135 static long getSize(Object vfsResource) throws IOException { 136 return (Long) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_SIZE, vfsResource); 137 } 138 139 static long getLastModified(Object vfsResource) throws IOException { 140 return (Long) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_LAST_MODIFIED, vfsResource); 141 } 142 143 static InputStream getInputStream(Object vfsResource) throws IOException { 144 return (InputStream) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_INPUT_STREAM, vfsResource); 145 } 146 147 static URL getURL(Object vfsResource) throws IOException { 148 return (URL) invokeVfsMethod(VIRTUAL_FILE_METHOD_TO_URL, vfsResource); 149 } 150 151 static URI getURI(Object vfsResource) throws IOException { 152 return (URI) invokeVfsMethod(VIRTUAL_FILE_METHOD_TO_URI, vfsResource); 153 } 154 155 static String getName(Object vfsResource) { 156 try { 157 return (String) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_NAME, vfsResource); 158 } 159 catch (IOException ex) { 160 throw new IllegalStateException("Cannot get resource name", ex); 161 } 162 } 163 164 static Object getRelative(URL url) throws IOException { 165 return invokeVfsMethod(VFS_METHOD_GET_ROOT_URL, null, url); 166 } 167 168 static Object getChild(Object vfsResource, String path) throws IOException { 169 return invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_CHILD, vfsResource, path); 170 } 171 172 static File getFile(Object vfsResource) throws IOException { 173 return (File) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_PHYSICAL_FILE, vfsResource); 174 } 175 176 static Object getRoot(URI url) throws IOException { 177 return invokeVfsMethod(VFS_METHOD_GET_ROOT_URI, null, url); 178 } 179 180 // protected methods used by the support sub-package 181 182 protected static Object getRoot(URL url) throws IOException { 183 return invokeVfsMethod(VFS_METHOD_GET_ROOT_URL, null, url); 184 } 185 186 @Nullable 187 protected static Object doGetVisitorAttributes() { 188 return ReflectionUtils.getField(VISITOR_ATTRIBUTES_FIELD_RECURSE, null); 189 } 190 191 @Nullable 192 protected static String doGetPath(Object resource) { 193 return (String) ReflectionUtils.invokeMethod(VIRTUAL_FILE_METHOD_GET_PATH_NAME, resource); 194 } 195 196}