package com.intellij.flex.uiDesigner.libraries; import com.intellij.flex.uiDesigner.DebugPathManager; import com.intellij.flex.uiDesigner.abc.AbcTranscoder; import com.intellij.flex.uiDesigner.io.IOUtil; import com.intellij.ide.highlighter.XmlFileType; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.xml.NanoXmlUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.TestOnly; import java.io.*; import java.nio.charset.StandardCharsets; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; final class LibraryUtil { public static Pair<CharArrayReader, ByteArrayInputStream> openSwc(final File in) throws IOException { //noinspection IOResourceOpenedButNotSafelyClosed return openSwc(new BufferedInputStream(new FileInputStream(in))); } public static Pair<CharArrayReader, ByteArrayInputStream> openSwc(final InputStream in) throws IOException { final MyZipInputStream zipIn = new MyZipInputStream(in); MyCharArrayReader catalogReader = null; ByteArrayInputStream swfIn = null; try { ZipEntry entry; while ((entry = zipIn.getNextEntry()) != null) { if (catalogReader == null && entry.getName().equals("catalog.xml")) { final InputStreamReader reader = new InputStreamReader(zipIn, StandardCharsets.UTF_8); try { catalogReader = new MyCharArrayReader(FileUtil.adaptiveLoadText(reader)); } finally { reader.close(); } } else if (swfIn == null && entry.getName().equals("library.swf")) { swfIn = new ByteArrayInputStream(FileUtil.adaptiveLoadBytes(zipIn)); } if (catalogReader != null && swfIn != null) { break; } } } finally { zipIn.ignoreClose = false; zipIn.close(); } assert catalogReader != null; assert swfIn != null; return new Pair<>(catalogReader, swfIn); } @TestOnly // we cannot use LocalFileSystem, because our test can run outside the idea static VirtualFile getTestGlobalLibrary(boolean isPlayer) { String name = (isPlayer ? "player" : "air") + "-catalog.xml"; File file = new File(DebugPathManager.getTestDataPath() + "/lib/playerglobal", name); assert file.exists(); try { return new LightVirtualFile(name, XmlFileType.INSTANCE, IOUtil.getCharSequence(file), StandardCharsets.UTF_8, 0); } catch (IOException e) { throw new RuntimeException(e); } } public static Set<CharSequence> getDefinitions(VirtualFile file) throws IOException { return getDefinitions(IOUtil.getCharArrayReader(file.getInputStream(), (int)file.getLength())); } public static Set<CharSequence> getDefinitions(Reader reader) { final THashSet<CharSequence> set = new THashSet<>(512, AbcTranscoder.HASHING_STRATEGY); NanoXmlUtil.parse(reader, new NanoXmlUtil.IXMLBuilderAdapter() { private boolean processingDef; @Override public void startElement(String name, String nsPrefix, String nsURI, String systemID, int lineNr) throws Exception { if (name.equals("def")) { processingDef = true; } } @Override public void endElement(String name, String nsPrefix, String nsURI) throws Exception { if (name.equals("def")) { processingDef = false; } } @Override public void addAttribute(String name, String nsPrefix, String nsURI, String value, String type) throws Exception { if (processingDef && name.equals("id")) { set.add(value); } } }); return set; } private static class MyZipInputStream extends ZipInputStream { private boolean ignoreClose = true; public MyZipInputStream(InputStream in) { super(in); } @Override public void close() throws IOException { if (!ignoreClose) { super.close(); } } } private static class MyCharArrayReader extends CharArrayReader { public MyCharArrayReader(char[] buf) { super(buf); } @Override public void close() { pos = 0; } } }