001/* 002 * (C) Copyright 2012 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 * 016 * Contributors: 017 * matic 018 */ 019package org.nuxeo.osgi.util.jar; 020 021import java.io.IOException; 022import java.lang.reflect.Field; 023import java.lang.reflect.InvocationTargetException; 024import java.lang.reflect.Method; 025import java.net.URL; 026import java.util.jar.JarFile; 027 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogFactory; 030 031/** 032 * @author matic 033 */ 034public class JarFileFactoryCloser { 035 036 private static final Log log = LogFactory.getLog(JarFileFactoryCloser.class); 037 038 protected boolean ok; 039 040 protected Object factory; 041 042 protected Method factoryGetMethod; 043 044 protected Method factoryCloseMethod; 045 046 public JarFileFactoryCloser() { 047 try { 048 introspectClasses(); 049 } catch (ClassNotFoundException e) { 050 log.error("Cannot introspect jar file factory class", e); 051 } catch (SecurityException e) { 052 log.error("Cannot introspect jar file factory class", e); 053 } catch (NoSuchFieldException e) { 054 log.error("Cannot introspect jar file factory class", e); 055 } catch (IllegalAccessException e) { 056 log.error("Cannot introspect jar file factory class", e); 057 } catch (NoSuchMethodException e) { 058 log.error("Cannot introspect jar file factory class", e); 059 } 060 } 061 062 protected void introspectClasses() throws ClassNotFoundException, SecurityException, NoSuchFieldException, 063 IllegalAccessException, NoSuchMethodException { 064 Class<?> jarURLConnectionClass = loadClass("sun.net.www.protocol.jar.JarURLConnection"); 065 Field jarFileFactoryField = jarURLConnectionClass.getDeclaredField("factory"); 066 jarFileFactoryField.setAccessible(true); 067 factory = jarFileFactoryField.get(null); 068 Class<?> factoryClass = loadClass("sun.net.www.protocol.jar.JarFileFactory"); 069 factoryGetMethod = factoryClass.getMethod("get", new Class<?>[] { URL.class }); 070 factoryGetMethod.setAccessible(true); 071 factoryCloseMethod = factoryClass.getMethod("close", new Class<?>[] { JarFile.class }); 072 factoryCloseMethod.setAccessible(true); 073 ok = true; 074 } 075 076 protected static Class<?> loadClass(String name) throws ClassNotFoundException { 077 return URLClassLoaderCloser.class.getClassLoader().loadClass(name); 078 } 079 080 public void close(URL location) throws IOException { 081 if (!ok) { 082 return; 083 } 084 JarFile jar = null; 085 try { 086 jar = (JarFile) factoryGetMethod.invoke(factory, new Object[] { location }); 087 factoryCloseMethod.invoke(factory, jar); 088 } catch (IllegalAccessException e) { 089 throw new RuntimeException("Cannot use reflection on jar file factory", e); 090 } catch (InvocationTargetException e) { 091 throw new RuntimeException("Cannot use reflection on jar file factory", e); 092 } 093 jar.close(); 094 } 095 096}