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 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 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 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 result, String entryName, JarFile jarFile) throws IOException { int entryNameLength = entryName.length(); JarEntry entry; for(Enumeration 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 l = new ArrayList(); 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; } }