--- /dev/null
+package org.simantics.scl.compiler.source.repository;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import org.junit.Test;
+import org.simantics.scl.runtime.SCLContext;
+
+public class ModuleBrowsingUtil {
+
+ public static final String SCL_EXTENSION = ".scl";
+ public static final int SCL_EXTENSION_LENGTH = SCL_EXTENSION.length();
+
+ public static void collectModuleSourcesAt(Collection<String> result, URL url) throws IOException {
+ String protocol = url.getProtocol();
+ if("jar".equals(protocol)) {
+ URLConnection connection = url.openConnection();
+ if(!(connection instanceof JarURLConnection))
+ throw new UnsupportedOperationException("Expected JarURLConnection when opening connection to " + url + ".");
+ JarURLConnection jarConnection = (JarURLConnection)connection;
+ collectModuleSourcesAt(result, jarConnection.getEntryName(), jarConnection.getJarFile());
+ }
+ else if("file".equals(protocol)) {
+ File file = new File(url.getPath());
+ if(!file.exists())
+ throw new UnsupportedOperationException("File " + url + " not found.");
+ collectModuleSourcesAt(result, file);
+ }
+ else if("bundleresource".equals(protocol)) {
+ URLConnection connection = url.openConnection();
+ Class<?> connectionClass = connection.getClass();
+ // We don't want an explicit dependency to osgi, therefore using reflection
+ if(!connectionClass.getSimpleName().equals("BundleURLConnection")) {
+ throw new UnsupportedOperationException("Expected BundleURLConnection when opening connection to " + url + ".");
+ }
+ URL localURL;
+ try {
+ localURL = (URL) connectionClass.getMethod("getLocalURL").invoke(connection);
+ } catch (Exception e) {
+ throw new UnsupportedOperationException("Couldn't browse " + url + ".", e);
+ }
+ collectModuleSourcesAt(result, localURL);
+ }
+ else
+ throw new UnsupportedOperationException("Protocol of " + url + " does not support directory browsing.");
+ }
+
+ public static void collectModuleSourcesAt(Collection<String> result, File file) {
+ for(File child : file.listFiles()) {
+ String name = child.getName();
+ if(child.isDirectory())
+ collectModuleSourcesAt(result, name + "/", child);
+ else
+ if(name.endsWith(SCL_EXTENSION))
+ result.add(name.substring(0, name.length()-SCL_EXTENSION_LENGTH));
+ }
+ }
+
+ private static void collectModuleSourcesAt(Collection<String> result, String prefix, File file) {
+ for(File child : file.listFiles()) {
+ String name = child.getName();
+ if(child.isDirectory())
+ collectModuleSourcesAt(result, prefix + name + "/", child);
+ else
+ if(name.endsWith(SCL_EXTENSION))
+ result.add(prefix + name.substring(0, name.length()-SCL_EXTENSION_LENGTH));
+ }
+ }
+
+ private static void collectModuleSourcesAt(Collection<String> result, String entryName, JarFile jarFile) throws IOException {
+ int entryNameLength = entryName.length();
+ JarEntry entry;
+ for(Enumeration<JarEntry> e = jarFile.entries();e.hasMoreElements()
+ && (entry = e.nextElement()) != null;) {
+ String name = entry.getName();
+ if(name.startsWith(entryName) && name.endsWith(SCL_EXTENSION))
+ result.add(name.substring(entryNameLength+1, name.length()-SCL_EXTENSION_LENGTH));
+ }
+ }
+
+ @Test
+ public void osgiTest() throws IOException {
+ ArrayList<String> l = new ArrayList<String>();
+ collectModuleSourcesAt(l, SCLContext.class.getResource("prelude"));
+ System.out.println(l);
+ }
+
+ public static File toFile(URL url) {
+ String protocol = url.getProtocol();
+ if("file".equals(protocol)) {
+ File file = new File(url.getPath());
+ if(file.exists())
+ return file;
+ }
+ return null;
+ }
+
+}