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.InputStreamFactory;
022import org.crsh.util.Strings;
023import org.crsh.util.ZipIterator;
024import org.crsh.vfs.spi.url.Node;
025import org.crsh.vfs.spi.url.Resource;
026import org.crsh.vfs.spi.url.URLDriver;
027
028import javax.tools.JavaFileObject;
029import java.io.File;
030import java.io.FileInputStream;
031import java.io.IOException;
032import java.io.InputStream;
033import java.net.URI;
034import java.net.URISyntaxException;
035import java.net.URL;
036import java.util.ArrayList;
037import java.util.Arrays;
038import java.util.Collections;
039import java.util.Enumeration;
040import java.util.Iterator;
041import java.util.List;
042import java.util.zip.ZipEntry;
043
044/** @author Julien Viet */
045class ClasspathResolver {
046
047  /** . */
048  final ClassLoader loader;
049
050  /** . */
051  final URLDriver driver;
052
053  public ClasspathResolver(ClassLoader loader) {
054
055    URLDriver driver = null;
056    try {
057      driver = new URLDriver();
058      driver.merge(loader);
059    }
060    catch (Exception e) {
061      e.printStackTrace();
062    }
063
064    //
065    this.loader = loader;
066    this.driver = driver;
067  }
068
069  private void resolve(List<JavaFileObject> files, Node node, String binaryName, boolean recurse) throws IOException, URISyntaxException {
070    for (Node child : driver.children(node)) {
071      Iterator<Resource> i = child.iterator();
072      if (i.hasNext()) {
073        if (child.name.endsWith(".class")) {
074          Resource r = i.next();
075          URI uri = r.url.toURI();
076          files.add(new NodeJavaFileObject(
077              binaryName + "." + child.name.substring(0, child.name.length() - ".class".length()),
078              uri,
079              r.streamFactory,
080              r.lastModified));
081        }
082      } else {
083        if (recurse) {
084          resolve(files, child, binaryName + "." + child.name, recurse);
085        }
086      }
087    }
088  }
089
090  public Iterable<JavaFileObject> resolve(String pkg, boolean recurse) throws IOException, URISyntaxException {
091
092    Node current = driver.root();
093
094    String[] elts = Strings.split(pkg, '.');
095
096    for (String elt : elts) {
097      current = driver.child(current, elt);
098      if (current == null) {
099        return Collections.emptyList();
100      }
101    }
102
103    //
104    List<JavaFileObject> files = new ArrayList<JavaFileObject>();
105    resolve(files, current, pkg, recurse);
106    return files;
107
108
109
110/*
111    String pkgName = pkg.replace('.', '/');
112    ArrayList<JavaFileObject> ret = new ArrayList<JavaFileObject>();
113    final Enumeration<URL> en = loader.getResources(pkgName);
114    while (en.hasMoreElements()) {
115      URL url = en.nextElement();
116      String protocol = url.getProtocol();
117      if (protocol.equals("file")) {
118        File root = new File(url.toURI());
119        resolve(pkgName, ret, root, recurse);
120      } else if ("jar".equals(protocol)) {
121        String path = url.getPath();
122        int index = path.lastIndexOf('!');
123        String containerURLs = path.substring(0, index);
124        URL containerURL = new URL(containerURLs);
125        ZipIterator i = ZipIterator.create(containerURL);
126        while (i.hasNext()) {
127          ZipEntry entry = i.next();
128          String name = entry.getName();
129          if (!entry.isDirectory() && name.startsWith(pkgName) && (name.indexOf('/', pkgName.length() + 1) == -1 || recurse)) {
130            String binaryName = name.substring(0, name.length() - ".class".length()).replace('/', '.');
131            URI entryURI = new URI("jar:" + containerURLs + "!/" + name);
132            ret.add(new URIJavaFileObject(binaryName, entryURI, i.getStreamFactory(), entry.getTime()));
133          }
134        }
135      } else {
136        throw new UnsupportedOperationException("Protocol for url " + url + " not supported");
137      }
138    }
139    return ret;
140*/
141  }
142
143/*
144  private void resolve(String pkgName, ArrayList<JavaFileObject> ret, File file, boolean recurse) {
145    final File[] children = file.listFiles();
146    if (children != null) {
147      Arrays.sort(children);
148      for (final File child : children) {
149        if (child.isDirectory()) {
150          if (recurse) {
151            resolve(pkgName, ret, child, recurse);
152          }
153        } else {
154          String childName = child.getName();
155          if (childName.endsWith(".class")) {
156            String binaryName = pkgName + "." + childName.substring(0, childName.length() - ".class".length());
157            InputStreamFactory streamFactory = new InputStreamFactory() {
158              @Override
159              public InputStream open() throws IOException {
160                return new FileInputStream(child);
161              }
162            };
163            ret.add(new URIJavaFileObject(binaryName, child.toURI(), streamFactory, child.lastModified()));
164          }
165        }
166      }
167    }
168  }
169*/
170}