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