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.net.URL; 023import java.util.List; 024import java.util.Map; 025import java.util.jar.JarFile; 026 027/** 028 * @author matic 029 */ 030public class URLClassLoaderCloser { 031 032 protected List<?> loaders; 033 034 protected final URLJarFileIntrospector introspector; 035 036 protected final Map<?, ?> index; 037 038 public URLClassLoaderCloser(URLJarFileIntrospector anIntrospector, Map<?, ?> anIndex, List<?> someLoaders) { 039 introspector = anIntrospector; 040 index = anIndex; 041 loaders = someLoaders; 042 } 043 044 protected static String serializeURL(URL location) { 045 StringBuilder localStringBuilder = new StringBuilder(128); 046 String str1 = location.getProtocol(); 047 if (str1 != null) { 048 str1 = str1.toLowerCase(); 049 localStringBuilder.append(str1); 050 localStringBuilder.append("://"); 051 } 052 String str2 = location.getHost(); 053 if (str2 != null) { 054 str2 = str2.toLowerCase(); 055 localStringBuilder.append(str2); 056 int i = location.getPort(); 057 if (i == -1) { 058 i = location.getDefaultPort(); 059 } 060 if (i != -1) { 061 localStringBuilder.append(":").append(i); 062 } 063 } 064 String str3 = location.getFile(); 065 if (str3 != null) { 066 localStringBuilder.append(str3); 067 } 068 return localStringBuilder.toString(); 069 } 070 071 public boolean close(URL location) throws IOException { 072 if (index.isEmpty()) { 073 return false; 074 } 075 Object firstKey = index.keySet().iterator().next(); 076 Object loader = firstKey instanceof URL ? index.remove(location) : index.remove(serializeURL(location)); 077 if (loader == null) { 078 return false; 079 } 080 loaders.remove(loader); 081 JarFile jar = null; 082 try { 083 jar = (JarFile) introspector.jarField.get(loader); 084 introspector.jarField.set(loader, null); 085 } catch (IllegalArgumentException e) { 086 throw new RuntimeException("Cannot use reflection on url class path", e); 087 } catch (IllegalAccessException e) { 088 throw new RuntimeException("Cannot use reflection on url class path", e); 089 } 090 jar.close(); 091 return true; 092 } 093 094}