001/* 002 * Copyright (C) 2012 eXo Platform SAS. 003 * 004 * This is free software; you can redistribute it and/or modify it 005 * under the terms of the GNU Lesser General Public License as 006 * published by the Free Software Foundation; either version 2.1 of 007 * the License, or (at your option) any later version. 008 * 009 * This software 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 * You should have received a copy of the GNU Lesser General Public 015 * License along with this software; if not, write to the Free 016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 018 */ 019package org.crsh.lang.java; 020 021import org.crsh.util.ZipIterator; 022 023import javax.tools.JavaFileObject; 024import java.io.File; 025import java.io.IOException; 026import java.net.URI; 027import java.net.URISyntaxException; 028import java.net.URL; 029import java.util.ArrayList; 030import java.util.Arrays; 031import java.util.Enumeration; 032import java.util.zip.ZipEntry; 033 034/** @author Julien Viet */ 035class ClasspathResolver { 036 037 /** . */ 038 final ClassLoader loader; 039 040 public ClasspathResolver(ClassLoader loader) { 041 this.loader = loader; 042 } 043 044 public Iterable<JavaFileObject> resolve(String pkg, boolean recurse) throws IOException, URISyntaxException { 045 String pkgName = pkg.replace('.', '/'); 046 ArrayList<JavaFileObject> ret = new ArrayList<JavaFileObject>(); 047 final Enumeration<URL> en = loader.getResources(pkgName); 048 while (en.hasMoreElements()) { 049 URL url = en.nextElement(); 050 String protocol = url.getProtocol(); 051 if (protocol.equals("file")) { 052 File root = new File(url.toURI()); 053 resolve(pkgName, ret, root, recurse); 054 } else if ("jar".equals(protocol)) { 055 String path = url.getPath(); 056 int index = path.lastIndexOf('!'); 057 String containerURLs = path.substring(0, index); 058 URL containerURL = new URL(containerURLs); 059 ZipIterator i = ZipIterator.create(containerURL); 060 while (i.hasNext()) { 061 ZipEntry entry = i.next(); 062 String name = entry.getName(); 063 if (!entry.isDirectory() && name.startsWith(pkgName) && (name.indexOf('/', pkgName.length() + 1) == -1 || recurse)) { 064 String binaryName = name.substring(0, name.length() - ".class".length()).replace('/', '.'); 065 URI entryURI = new URI("jar:" + containerURLs + "!/" + name); 066 ret.add(new URIJavaFileObject(binaryName, entryURI, entry.getTime())); 067 } 068 } 069 } else { 070 throw new UnsupportedOperationException("Protocol for url " + url + " not supported"); 071 } 072 } 073 return ret; 074 } 075 076 private void resolve(String pkgName, ArrayList<JavaFileObject> ret, File file, boolean recurse) { 077 final File[] children = file.listFiles(); 078 if (children != null) { 079 Arrays.sort(children); 080 for (File child : children) { 081 if (child.isDirectory()) { 082 if (recurse) { 083 resolve(pkgName, ret, child, recurse); 084 } 085 } else { 086 String childName = child.getName(); 087 if (childName.endsWith(".class")) { 088 String binaryName = pkgName + "." + childName.substring(0, childName.length() - ".class".length()); 089 ret.add(new URIJavaFileObject(binaryName, child.toURI(), child.lastModified())); 090 } 091 } 092 } 093 } 094 } 095}