package melnorme.lang.ide.core.tests.utils; import static melnorme.utilbox.core.Assert.AssertNamespace.assertFail; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Enumeration; import melnorme.lang.ide.core.tests.CoreTests; import melnorme.utilbox.misc.StreamUtil; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.osgi.framework.Bundle; public class BundleResourcesUtil { /*** * Copies the contents of given resourcePath in bundle with given bundleId into targetDir. * If targetDir doesn't exists, it is created (top level directory only). */ public static void copyDirContents(String bundleId, String resourcePath, final File targetDir) throws IOException { CoreTests.testsLogger.println(">>> Copying " + bundleId + "::" + resourcePath); CoreTests.testsLogger.println(" to: " + targetDir); // normalize path with regards to separators final String normalizedBasePath = new Path(resourcePath).makeRelative().addTrailingSeparator().toString(); final Bundle bundle = Platform.getBundle(bundleId); assertNotNull(bundle); assertNotNull(bundle.getEntry(normalizedBasePath)); BundleResourcesIterator bundleResourcesIter = new BundleResourcesIterator() { @Override protected void handleFile(String srcPath) { URL sourceFile = FileLocator.find(bundle, new Path(srcPath), null); InputStream inputStream = null; try { inputStream = sourceFile.openConnection().getInputStream(); String srcSubPath = determineSubPath(srcPath); CoreTests.testsLogVerbose.println(srcSubPath); File newFile = new File(targetDir, srcSubPath); newFile.getParentFile().mkdir(); // Likely not necessary, but do it just in case newFile.createNewFile(); StreamUtil.copyStream(inputStream, new FileOutputStream(newFile)); } catch (IOException e) { throw new RuntimeException(e); } finally { StreamUtil.uncheckedClose(inputStream, true); } } @Override protected void handleDirectory(String srcPath) { String srcSubPath = determineSubPath(srcPath); CoreTests.testsLogVerbose.println(srcSubPath); File newDir = new File(targetDir, srcSubPath); if(!newDir.exists()) { boolean result = newDir.mkdirs(); if(result == false) { throw new RuntimeException(new IOException("Could not create directory")); } } } protected String determineSubPath(String srcPath) { assertTrue(srcPath.startsWith(normalizedBasePath)); return srcPath.substring(normalizedBasePath.length()); } }; try { bundleResourcesIter.traversePath(bundleId, normalizedBasePath); } catch (RuntimeException e) { if(e.getCause() instanceof IOException) { throw (IOException) e.getCause(); } else { throw e; } } } /** Return a URI for given url, which must comply to RFC 2396. */ public static URI getURIFromProperURL(URL validUrl) { try { return validUrl.toURI(); } catch(URISyntaxException e) { throw assertFail(); } } public static class BundleResourcesIterator { public void traversePath(String bundleId, String path) { Enumeration<String> childPaths = Platform.getBundle(bundleId).getEntryPaths(path); if(childPaths == null) return; while(childPaths.hasMoreElements()) { String childPath = childPaths.nextElement(); if(childPath.endsWith("/")) { handleDirectory(childPath); traversePath(bundleId, childPath); } else { handleFile(childPath); } } } @SuppressWarnings("unused") protected void handleCommon(String path) { } protected void handleFile(String path) { handleCommon(path); } protected void handleDirectory(String path) { handleCommon(path); } } }