From 12a191de9bb9d088ea992e0140f592f3c19fb826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Thu, 18 Jul 2013 12:28:07 +0200 Subject: [PATCH] Issue #253 Abort/Retry/Ignore dialog on IO errors --- .../flash/AbortRetryIgnoreHandler.java | 30 ++ .../com/jpexs/decompiler/flash/RetryTask.java | 55 ++++ .../jpexs/decompiler/flash/RunnableIOEx.java | 28 ++ .../decompiler/flash/RunnableIOExResult.java | 27 ++ trunk/src/com/jpexs/decompiler/flash/SWF.java | 277 +++++++++++------- .../com/jpexs/decompiler/flash/TagNode.java | 66 +++-- .../avm2/instructions/other/SetSlotIns.java | 1 + .../com/jpexs/decompiler/flash/gui/Main.java | 76 +++-- .../jpexs/decompiler/flash/gui/MainFrame.java | 50 ++-- .../flash/gui/locales/MainFrame.properties | 8 +- .../flash/gui/locales/MainFrame_cs.properties | 7 +- .../decompiler/flash/xfl/XFLConverter.java | 76 +++-- 12 files changed, 497 insertions(+), 204 deletions(-) create mode 100644 trunk/src/com/jpexs/decompiler/flash/AbortRetryIgnoreHandler.java create mode 100644 trunk/src/com/jpexs/decompiler/flash/RetryTask.java create mode 100644 trunk/src/com/jpexs/decompiler/flash/RunnableIOEx.java create mode 100644 trunk/src/com/jpexs/decompiler/flash/RunnableIOExResult.java diff --git a/trunk/src/com/jpexs/decompiler/flash/AbortRetryIgnoreHandler.java b/trunk/src/com/jpexs/decompiler/flash/AbortRetryIgnoreHandler.java new file mode 100644 index 000000000..2526b1f27 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/AbortRetryIgnoreHandler.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2013 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +/** + * + * @author JPEXS + */ +public interface AbortRetryIgnoreHandler { + + public static int ABORT = 0; + public static int RETRY = 1; + public static int IGNORE = 2; + + public int handle(Throwable thrown); +} diff --git a/trunk/src/com/jpexs/decompiler/flash/RetryTask.java b/trunk/src/com/jpexs/decompiler/flash/RetryTask.java new file mode 100644 index 000000000..410b44320 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/RetryTask.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +import java.io.IOException; + +/** + * + * @author JPEXS + */ +public class RetryTask { + + private RunnableIOEx r; + private AbortRetryIgnoreHandler handler; + public Object result; + + public RetryTask(RunnableIOEx r, AbortRetryIgnoreHandler handler) { + this.r = r; + this.handler = handler; + } + + public void run() throws IOException { + boolean retry; + do { + retry = false; + try { + r.run(); + } catch (Exception ex) { + switch (handler.handle(ex)) { + case AbortRetryIgnoreHandler.ABORT: + throw ex; + case AbortRetryIgnoreHandler.RETRY: + retry = true; + break; + case AbortRetryIgnoreHandler.IGNORE: + break; + } + } + } while (retry); + } +} diff --git a/trunk/src/com/jpexs/decompiler/flash/RunnableIOEx.java b/trunk/src/com/jpexs/decompiler/flash/RunnableIOEx.java new file mode 100644 index 000000000..5650d963e --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/RunnableIOEx.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +import java.io.IOException; + +/** + * + * @author JPEXS + */ +public interface RunnableIOEx { + + public void run() throws IOException; +} diff --git a/trunk/src/com/jpexs/decompiler/flash/RunnableIOExResult.java b/trunk/src/com/jpexs/decompiler/flash/RunnableIOExResult.java new file mode 100644 index 000000000..f536f8c17 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/RunnableIOExResult.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2013 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash; + +/** + * + * @param + * @author JPEXS + */ +public abstract class RunnableIOExResult implements RunnableIOEx { + + public T result; +} diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index d4a831f40..71faaec3e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -547,8 +547,9 @@ public class SWF { AtomicInteger index; int count; boolean paralel; + AbortRetryIgnoreHandler handler; - public ExportPackTask(AtomicInteger index, int count, ClassPath path, ScriptPack pack, String directory, List abcList, boolean pcode, String informStr, boolean paralel) { + public ExportPackTask(AbortRetryIgnoreHandler handler, AtomicInteger index, int count, ClassPath path, ScriptPack pack, String directory, List abcList, boolean pcode, String informStr, boolean paralel) { this.pack = pack; this.directory = directory; this.abcList = abcList; @@ -558,15 +559,18 @@ public class SWF { this.index = index; this.count = count; this.paralel = paralel; + this.handler = handler; } @Override public File call() throws Exception { - try { - return pack.export(directory, abcList, pcode, paralel); - } catch (IOException ex) { - Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, null, ex); - } + RunnableIOExResult rio = new RunnableIOExResult() { + @Override + public void run() throws IOException { + this.result = pack.export(directory, abcList, pcode, paralel); + } + }; + new RetryTask(rio, handler).run(); synchronized (ABC.class) { informListeners("export", "Exported " + informStr + " script " + index.getAndIncrement() + "/" + count + " " + path); } @@ -574,7 +578,7 @@ public class SWF { } } - public List exportActionScript2(String outdir, boolean isPcode, boolean paralel, EventListener evl) { + public List exportActionScript2(AbortRetryIgnoreHandler handler, String outdir, boolean isPcode, boolean paralel, EventListener evl) throws IOException { List ret = new ArrayList<>(); List list2 = new ArrayList<>(); list2.addAll(tags); @@ -585,11 +589,11 @@ public class SWF { outdir += File.separator; } outdir += "scripts" + File.separator; - ret.addAll(TagNode.exportNodeAS(list, outdir, isPcode, evl)); + ret.addAll(TagNode.exportNodeAS(handler, list, outdir, isPcode, evl)); return ret; } - public List exportActionScript3(String outdir, boolean isPcode, boolean paralel) { + public List exportActionScript3(AbortRetryIgnoreHandler handler, String outdir, boolean isPcode, boolean paralel) { ExecutorService executor = Executors.newFixedThreadPool(20); List> futureResults = new ArrayList<>(); AtomicInteger cnt = new AtomicInteger(1); @@ -601,7 +605,7 @@ public class SWF { } List> packs = getAS3Packs(); for (MyEntry item : packs) { - Future future = executor.submit(new ExportPackTask(cnt, packs.size(), item.key, item.value, outdir, abcTags, isPcode, "", paralel)); + Future future = executor.submit(new ExportPackTask(handler, cnt, packs.size(), item.key, item.value, outdir, abcTags, isPcode, "", paralel)); futureResults.add(future); } @@ -623,7 +627,7 @@ public class SWF { return ret; } - public List exportActionScript(String outdir, boolean isPcode, boolean paralel) throws Exception { + public List exportActionScript(AbortRetryIgnoreHandler handler, String outdir, boolean isPcode, boolean paralel) throws Exception { boolean asV3Found = false; List ret = new ArrayList<>(); final EventListener evl = new EventListener() { @@ -641,9 +645,9 @@ public class SWF { } if (asV3Found) { - ret.addAll(exportActionScript3(outdir, isPcode, paralel)); + ret.addAll(exportActionScript3(handler, outdir, isPcode, paralel)); } else { - ret.addAll(exportActionScript2(outdir, isPcode, paralel, evl)); + ret.addAll(exportActionScript2(handler, outdir, isPcode, paralel, evl)); } return ret; } @@ -867,12 +871,12 @@ public class SWF { } } - public void exportMovies(String outdir) throws IOException { - exportMovies(outdir, tags); + public void exportMovies(AbortRetryIgnoreHandler handler, String outdir) throws IOException { + exportMovies(handler, outdir, tags); } - public void exportSounds(String outdir, boolean mp3, boolean wave) throws IOException { - exportSounds(outdir, tags, mp3, wave); + public void exportSounds(AbortRetryIgnoreHandler handler, String outdir, boolean mp3, boolean wave) throws IOException { + exportSounds(handler, outdir, tags, mp3, wave); } public byte[] exportSound(Tag t) throws IOException { @@ -986,7 +990,7 @@ public class SWF { } } - public List exportSounds(String outdir, List tags, boolean mp3, boolean wave) throws IOException { + public List exportSounds(AbortRetryIgnoreHandler handler, String outdir, List tags, boolean mp3, boolean wave) throws IOException { List ret = new ArrayList<>(); if (tags.isEmpty()) { return ret; @@ -1000,8 +1004,9 @@ public class SWF { } } for (Tag t : tags) { + File newfile = null; FileOutputStream fos = null; - File file = null; + //File file = null; try { int id = 0; if (t instanceof DefineSoundTag) { @@ -1010,60 +1015,96 @@ public class SWF { if (t instanceof DefineSoundTag) { - DefineSoundTag st = (DefineSoundTag) t; + final DefineSoundTag st = (DefineSoundTag) t; if ((st.soundFormat == DefineSoundTag.FORMAT_ADPCM) && wave) { - file = new File(outdir + File.separator + st.getCharacterExportFileName() + ".wav"); - fos = new FileOutputStream(file); - createWavFromAdpcm(fos, st.soundRate, st.soundSize, st.soundType, st.soundData); + final File file = new File(outdir + File.separator + st.getCharacterExportFileName() + ".wav"); + newfile = file; + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + FileOutputStream fos = new FileOutputStream(file); + createWavFromAdpcm(fos, st.soundRate, st.soundSize, st.soundType, st.soundData); + } + }, handler).run(); } else if ((st.soundFormat == DefineSoundTag.FORMAT_MP3) && mp3) { - file = new File(outdir + File.separator + st.getCharacterExportFileName() + ".mp3"); - fos = new FileOutputStream(file); - fos.write(st.soundData, 2, st.soundData.length - 2); + final File file = new File(outdir + File.separator + st.getCharacterExportFileName() + ".mp3"); + newfile = file; + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + FileOutputStream fos = new FileOutputStream(file); + fos.write(st.soundData, 2, st.soundData.length - 2); + } + }, handler).run(); } else { - file = new File(outdir + File.separator + st.getCharacterExportFileName() + ".flv"); - fos = new FileOutputStream(file); - try (FLVOutputStream flv = new FLVOutputStream(fos)) { - flv.writeHeader(true, false); - flv.writeTag(new FLVTAG(0, new AUDIODATA(st.soundFormat, st.soundRate, st.soundSize, st.soundType, st.soundData))); - } + final File file = new File(outdir + File.separator + st.getCharacterExportFileName() + ".flv"); + newfile = file; + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + FileOutputStream fos = new FileOutputStream(file); + try (FLVOutputStream flv = new FLVOutputStream(fos)) { + flv.writeHeader(true, false); + flv.writeTag(new FLVTAG(0, new AUDIODATA(st.soundFormat, st.soundRate, st.soundSize, st.soundType, st.soundData))); + } + } + }, handler).run(); } } if (t instanceof SoundStreamHeadTypeTag) { - SoundStreamHeadTypeTag shead = (SoundStreamHeadTypeTag) t; - List blocks = new ArrayList<>(); + final SoundStreamHeadTypeTag shead = (SoundStreamHeadTypeTag) t; + final List blocks = new ArrayList<>(); List objs = new ArrayList(this.tags); populateSoundStreamBlocks(objs, t, blocks); if ((shead.getSoundFormat() == DefineSoundTag.FORMAT_ADPCM) && wave) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); for (int b = 0; b < blocks.size(); b++) { byte data[] = blocks.get(b).getData(SWF.DEFAULT_VERSION); baos.write(data); } - file = new File(outdir + File.separator + id + ".wav"); - fos = new FileOutputStream(file); - createWavFromAdpcm(fos, shead.getSoundRate(), shead.getSoundSize(), shead.getSoundType(), baos.toByteArray()); - } else if ((shead.getSoundFormat() == DefineSoundTag.FORMAT_MP3) && mp3) { - file = new File(outdir + File.separator + id + ".mp3"); - fos = new FileOutputStream(file); - for (int b = 0; b < blocks.size(); b++) { - byte data[] = blocks.get(b).getData(SWF.DEFAULT_VERSION); - fos.write(data, 2, data.length - 2); - } - } else { - file = new File(outdir + File.separator + id + ".flv"); - fos = new FileOutputStream(file); - FLVOutputStream flv = new FLVOutputStream(fos); - flv.writeHeader(true, false); - - int ms = (int) (1000.0f / ((float) frameRate)); - for (int b = 0; b < blocks.size(); b++) { - byte data[] = blocks.get(b).getData(SWF.DEFAULT_VERSION); - if (shead.getSoundFormat() == 2) { //MP3 - data = Arrays.copyOfRange(data, 4, data.length); + final File file = new File(outdir + File.separator + id + ".wav"); + newfile = file; + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + FileOutputStream fos = new FileOutputStream(file); + createWavFromAdpcm(fos, shead.getSoundRate(), shead.getSoundSize(), shead.getSoundType(), baos.toByteArray()); } - flv.writeTag(new FLVTAG(ms * b, new AUDIODATA(shead.getSoundFormat(), shead.getSoundRate(), shead.getSoundSize(), shead.getSoundType(), data))); - } + }, handler).run(); + } else if ((shead.getSoundFormat() == DefineSoundTag.FORMAT_MP3) && mp3) { + final File file = new File(outdir + File.separator + id + ".mp3"); + newfile = file; + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + FileOutputStream fos = new FileOutputStream(file); + for (int b = 0; b < blocks.size(); b++) { + byte data[] = blocks.get(b).getData(SWF.DEFAULT_VERSION); + fos.write(data, 2, data.length - 2); + } + } + }, handler).run(); + } else { + final File file = new File(outdir + File.separator + id + ".flv"); + newfile = file; + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + FileOutputStream fos = new FileOutputStream(file); + FLVOutputStream flv = new FLVOutputStream(fos); + flv.writeHeader(true, false); + + int ms = (int) (1000.0f / ((float) frameRate)); + for (int b = 0; b < blocks.size(); b++) { + byte data[] = blocks.get(b).getData(SWF.DEFAULT_VERSION); + if (shead.getSoundFormat() == 2) { //MP3 + data = Arrays.copyOfRange(data, 4, data.length); + } + flv.writeTag(new FLVTAG(ms * b, new AUDIODATA(shead.getSoundFormat(), shead.getSoundRate(), shead.getSoundSize(), shead.getSoundType(), data))); + } + } + }, handler).run(); } } } finally { @@ -1075,8 +1116,8 @@ public class SWF { } } } - if (file != null) { - ret.add(file); + if (newfile != null) { + ret.add(newfile); } } return ret; @@ -1176,7 +1217,7 @@ public class SWF { return fos.toByteArray(); } - public List exportMovies(String outdir, List tags) throws IOException { + public List exportMovies(AbortRetryIgnoreHandler handler, String outdir, List tags) throws IOException { List ret = new ArrayList<>(); if (tags.isEmpty()) { return ret; @@ -1191,17 +1232,23 @@ public class SWF { } for (Tag t : tags) { if (t instanceof DefineVideoStreamTag) { - DefineVideoStreamTag videoStream = (DefineVideoStreamTag) t; - File file = new File(outdir + File.separator + ((DefineVideoStreamTag) t).getCharacterExportFileName() + ".flv"); - try (FileOutputStream fos = new FileOutputStream(file)) { - fos.write(exportMovie(videoStream)); - } + final DefineVideoStreamTag videoStream = (DefineVideoStreamTag) t; + final File file = new File(outdir + File.separator + ((DefineVideoStreamTag) t).getCharacterExportFileName() + ".flv"); + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + try (FileOutputStream fos = new FileOutputStream(file)) { + fos.write(exportMovie(videoStream)); + } + } + }, handler).run(); + } } return ret; } - public List exportTexts(String outdir, List tags, boolean formatted) throws IOException { + public List exportTexts(AbortRetryIgnoreHandler handler, String outdir, List tags, final boolean formatted) throws IOException { List ret = new ArrayList<>(); if (tags.isEmpty()) { return ret; @@ -1214,27 +1261,33 @@ public class SWF { } } } - for (Tag t : tags) { + for (final Tag t : tags) { if (t instanceof TextTag) { - File file = new File(outdir + File.separator + ((TextTag) t).getCharacterId() + ".txt"); - try (FileOutputStream fos = new FileOutputStream(file)) { - if (formatted) { - fos.write(((TextTag) t).getFormattedText(this.tags).getBytes("UTF-8")); - } else { - fos.write(((TextTag) t).getText(this.tags).getBytes("UTF-8")); + final File file = new File(outdir + File.separator + ((TextTag) t).getCharacterId() + ".txt"); + final List ttags = this.tags; + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + try (FileOutputStream fos = new FileOutputStream(file)) { + if (formatted) { + fos.write(((TextTag) t).getFormattedText(ttags).getBytes("UTF-8")); + } else { + fos.write(((TextTag) t).getText(ttags).getBytes("UTF-8")); + } + } } - } + }, handler).run(); ret.add(file); } } return ret; } - public void exportTexts(String outdir, boolean formatted) throws IOException { - exportTexts(outdir, tags, formatted); + public void exportTexts(AbortRetryIgnoreHandler handler, String outdir, boolean formatted) throws IOException { + exportTexts(handler, outdir, tags, formatted); } - public static List exportShapes(String outdir, List tags) throws IOException { + public static List exportShapes(AbortRetryIgnoreHandler handler, String outdir, List tags) throws IOException { List ret = new ArrayList<>(); if (tags.isEmpty()) { return ret; @@ -1247,23 +1300,29 @@ public class SWF { } } } - for (Tag t : tags) { + loopb: + for (final Tag t : tags) { if (t instanceof ShapeTag) { int characterID = 0; if (t instanceof CharacterTag) { characterID = ((CharacterTag) t).getCharacterId(); } - File file = new File(outdir + File.separator + characterID + ".svg"); - try (FileOutputStream fos = new FileOutputStream(file)) { - fos.write(((ShapeTag) t).toSVG().getBytes("utf-8")); - } + final File file = new File(outdir + File.separator + characterID + ".svg"); + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + try (FileOutputStream fos = new FileOutputStream(file)) { + fos.write(((ShapeTag) t).toSVG().getBytes("utf-8")); + } + } + }, handler).run(); ret.add(file); } } return ret; } - public static List exportBinaryData(String outdir, List tags) throws IOException { + public static List exportBinaryData(AbortRetryIgnoreHandler handler, String outdir, List tags) throws IOException { List ret = new ArrayList<>(); if (tags.isEmpty()) { return ret; @@ -1276,20 +1335,26 @@ public class SWF { } } } - for (Tag t : tags) { + loopb: + for (final Tag t : tags) { if (t instanceof DefineBinaryDataTag) { int characterID = ((DefineBinaryDataTag) t).getCharacterId(); - File file = new File(outdir + File.separator + characterID + ".bin"); - try (FileOutputStream fos = new FileOutputStream(file)) { - fos.write(((DefineBinaryDataTag) t).binaryData); - } + final File file = new File(outdir + File.separator + characterID + ".bin"); + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + try (FileOutputStream fos = new FileOutputStream(file)) { + fos.write(((DefineBinaryDataTag) t).binaryData); + } + } + }, handler).run(); ret.add(file); } } return ret; } - public List exportImages(String outdir, List tags) throws IOException { + public List exportImages(AbortRetryIgnoreHandler handler, String outdir, List tags) throws IOException { List ret = new ArrayList<>(); if (tags.isEmpty()) { return ret; @@ -1302,26 +1367,32 @@ public class SWF { } } } - for (Tag t : tags) { + for (final Tag t : tags) { if (t instanceof ImageTag) { - File file = new File(outdir + File.separator + ((ImageTag) t).getCharacterId() + "." + ((ImageTag) t).getImageFormat()); - ImageIO.write(((ImageTag) t).getImage(this.tags), ((ImageTag) t).getImageFormat().toUpperCase(Locale.ENGLISH), file); + final File file = new File(outdir + File.separator + ((ImageTag) t).getCharacterId() + "." + ((ImageTag) t).getImageFormat()); + final List ttags = this.tags; + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + ImageIO.write(((ImageTag) t).getImage(ttags), ((ImageTag) t).getImageFormat().toUpperCase(Locale.ENGLISH), file); + } + }, handler).run(); ret.add(file); } } return ret; } - public void exportImages(String outdir) throws IOException { - exportImages(outdir, tags); + public void exportImages(AbortRetryIgnoreHandler handler, String outdir) throws IOException { + exportImages(handler, outdir, tags); } - public void exportShapes(String outdir) throws IOException { - exportShapes(outdir, tags); + public void exportShapes(AbortRetryIgnoreHandler handler, String outdir) throws IOException { + exportShapes(handler, outdir, tags); } - public void exportBinaryData(String outdir) throws IOException { - exportBinaryData(outdir, tags); + public void exportBinaryData(AbortRetryIgnoreHandler handler, String outdir) throws IOException { + exportBinaryData(handler, outdir, tags); } public static final String[] reservedWords = { "as", "break", "case", "catch", "class", "const", "continue", "default", "delete", "do", "each", "else", @@ -2015,12 +2086,12 @@ public class SWF { return ret; } - public void exportFla(String outfile, String swfName, String generator, String generatorVerName, String generatorVersion, boolean paralel) throws IOException { - XFLConverter.convertSWF(this, swfName, outfile, true, generator, generatorVerName, generatorVersion, paralel); + public void exportFla(AbortRetryIgnoreHandler handler, String outfile, String swfName, String generator, String generatorVerName, String generatorVersion, boolean paralel) throws IOException { + XFLConverter.convertSWF(handler, this, swfName, outfile, true, generator, generatorVerName, generatorVersion, paralel); } - public void exportXfl(String outfile, String swfName, String generator, String generatorVerName, String generatorVersion, boolean paralel) throws IOException { - XFLConverter.convertSWF(this, swfName, outfile, false, generator, generatorVerName, generatorVersion, paralel); + public void exportXfl(AbortRetryIgnoreHandler handler, String outfile, String swfName, String generator, String generatorVerName, String generatorVersion, boolean paralel) throws IOException { + XFLConverter.convertSWF(handler, this, swfName, outfile, false, generator, generatorVerName, generatorVersion, paralel); } public static float twipToPixel(int twip) { diff --git a/trunk/src/com/jpexs/decompiler/flash/TagNode.java b/trunk/src/com/jpexs/decompiler/flash/TagNode.java index 15904f013..1255637ad 100644 --- a/trunk/src/com/jpexs/decompiler/flash/TagNode.java +++ b/trunk/src/com/jpexs/decompiler/flash/TagNode.java @@ -49,6 +49,7 @@ import com.jpexs.decompiler.flash.tags.base.Container; import com.jpexs.decompiler.flash.tags.base.Exportable; import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -229,11 +230,11 @@ public class TagNode { } } - public static List exportNodeAS(List nodeList, String outdir, boolean isPcode) { - return exportNodeAS(nodeList, outdir, isPcode, null); + public static List exportNodeAS(AbortRetryIgnoreHandler handler, List nodeList, String outdir, boolean isPcode) throws IOException { + return exportNodeAS(handler, nodeList, outdir, isPcode, null); } - public static List exportNodeAS(List nodeList, String outdir, boolean isPcode, EventListener ev) { + public static List exportNodeAS(AbortRetryIgnoreHandler handler, List nodeList, String outdir, boolean isPcode, EventListener ev) throws IOException { File dir = new File(outdir); List ret = new ArrayList<>(); if (!outdir.endsWith(File.separator)) { @@ -263,30 +264,47 @@ public class TagNode { } } } - try { - String f = outdir + name + ".as"; - File file = new File(f); - if (ev != null) { - ev.handleEvent("export", "Exporting " + f + " ..."); + boolean retry; + do { + retry = false; + try { + String f = outdir + name + ".as"; + File file = new File(f); + if (ev != null) { + ev.handleEvent("export", "Exporting " + f + " ..."); + } + String res; + ASMSource asm = ((ASMSource) node.tag); + if (isPcode) { + res = asm.getActionSourcePrefix() + Helper.indentRows(asm.getActionSourceIndent(), Highlighting.stripHilights(asm.getASMSource(SWF.DEFAULT_VERSION, false)), Graph.INDENT_STRING) + asm.getActionSourceSuffix(); + } else { + List as = asm.getActions(SWF.DEFAULT_VERSION); + Action.setActionsAddresses(as, 0, SWF.DEFAULT_VERSION); + res = asm.getActionSourcePrefix() + Helper.indentRows(asm.getActionSourceIndent(), Highlighting.stripHilights(Action.actionsToSource(as, SWF.DEFAULT_VERSION, ""/*FIXME*/)), Graph.INDENT_STRING) + asm.getActionSourceSuffix(); + } + try (FileOutputStream fos = new FileOutputStream(f)) { + fos.write(res.getBytes("utf-8")); + } + ret.add(file); + } catch (Exception ex) { + if (handler != null) { + int action = handler.handle(ex); + switch (action) { + case AbortRetryIgnoreHandler.ABORT: + throw ex; + case AbortRetryIgnoreHandler.RETRY: + retry = true; + break; + case AbortRetryIgnoreHandler.IGNORE: + retry = false; + break; + } + } } - String res; - ASMSource asm = ((ASMSource) node.tag); - if (isPcode) { - res = asm.getActionSourcePrefix() + Helper.indentRows(asm.getActionSourceIndent(), Highlighting.stripHilights(asm.getASMSource(SWF.DEFAULT_VERSION, false)), Graph.INDENT_STRING) + asm.getActionSourceSuffix(); - } else { - List as = asm.getActions(SWF.DEFAULT_VERSION); - Action.setActionsAddresses(as, 0, SWF.DEFAULT_VERSION); - res = asm.getActionSourcePrefix() + Helper.indentRows(asm.getActionSourceIndent(), Highlighting.stripHilights(Action.actionsToSource(as, SWF.DEFAULT_VERSION, ""/*FIXME*/)), Graph.INDENT_STRING) + asm.getActionSourceSuffix(); - } - try (FileOutputStream fos = new FileOutputStream(f)) { - fos.write(res.getBytes("utf-8")); - } - ret.add(file); - } catch (Exception ex) { - } + } while (retry); } } else { - ret.addAll(exportNodeAS(node.subItems, outdir + name, isPcode, ev)); + ret.addAll(exportNodeAS(handler, node.subItems, outdir + name, isPcode, ev)); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java index a806ff59a..c35b35964 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java @@ -58,6 +58,7 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns { int slotIndex = ins.operands[0]; GraphTargetItem value = (GraphTargetItem) stack.pop(); GraphTargetItem obj = (GraphTargetItem) stack.pop(); //scopeId + GraphTargetItem objnoreg = obj; obj = obj.getThroughRegister(); Multiname slotname = null; if (obj instanceof NewActivationAVM2Item) { diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java index 401484967..6e30ff80b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.gui; +import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; import com.jpexs.decompiler.flash.Configuration; import com.jpexs.decompiler.flash.EventListener; import com.jpexs.decompiler.flash.PercentListener; @@ -27,6 +28,7 @@ import com.jpexs.decompiler.flash.gui.jna.platform.win32.Advapi32Util; import com.jpexs.decompiler.flash.gui.jna.platform.win32.Kernel32; import com.jpexs.decompiler.flash.gui.jna.platform.win32.SHELLEXECUTEINFO; import com.jpexs.decompiler.flash.gui.jna.platform.win32.Shell32; +import com.jpexs.decompiler.flash.gui.jna.platform.win32.Win32Exception; import com.jpexs.decompiler.flash.gui.jna.platform.win32.WinReg; import com.jpexs.decompiler.flash.gui.jna.platform.win32.WinUser; import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel; @@ -50,6 +52,7 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Locale; import java.util.Properties; +import java.util.Scanner; import java.util.logging.ConsoleHandler; import java.util.logging.FileHandler; import java.util.logging.Level; @@ -618,6 +621,27 @@ public class Main { "fla", "xfl" }; + + AbortRetryIgnoreHandler handler = new AbortRetryIgnoreHandler() { + @Override + public int handle(Throwable thrown) { + Scanner sc = new Scanner(System.in); + System.out.println("Error occured: " + thrown.getLocalizedMessage()); + String n = null; + do { + System.out.print("Select action: (A)bort, (R)Retry, (I)Ignore:"); + n = sc.nextLine(); + switch (n.toLowerCase()) { + case "a": + return AbortRetryIgnoreHandler.ABORT; + case "r": + return AbortRetryIgnoreHandler.RETRY; + case "i": + return AbortRetryIgnoreHandler.IGNORE; + } + } while (true); + } + }; String exportFormat = args[pos + 1].toLowerCase(); if (!Arrays.asList(validExportFormats).contains(exportFormat)) { System.err.println("Invalid export format:" + exportFormat); @@ -646,27 +670,27 @@ public class Main { switch (exportFormat) { case "all": System.out.println("Exporting images..."); - exfile.exportImages(outDir.getAbsolutePath() + File.separator + "images"); + exfile.exportImages(handler, outDir.getAbsolutePath() + File.separator + "images"); System.out.println("Exporting shapes..."); - exfile.exportShapes(outDir.getAbsolutePath() + File.separator + "shapes"); + exfile.exportShapes(handler, outDir.getAbsolutePath() + File.separator + "shapes"); System.out.println("Exporting scripts..."); - exfile.exportActionScript(outDir.getAbsolutePath() + File.separator + "scripts", false, (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); + exfile.exportActionScript(handler, outDir.getAbsolutePath() + File.separator + "scripts", false, (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); System.out.println("Exporting movies..."); - exfile.exportMovies(outDir.getAbsolutePath() + File.separator + "movies"); + exfile.exportMovies(handler, outDir.getAbsolutePath() + File.separator + "movies"); System.out.println("Exporting sounds..."); - exfile.exportSounds(outDir.getAbsolutePath() + File.separator + "sounds", true, true); + exfile.exportSounds(handler, outDir.getAbsolutePath() + File.separator + "sounds", true, true); System.out.println("Exporting binaryData..."); - exfile.exportBinaryData(outDir.getAbsolutePath() + File.separator + "binaryData"); + exfile.exportBinaryData(handler, outDir.getAbsolutePath() + File.separator + "binaryData"); System.out.println("Exporting texts..."); - exfile.exportTexts(outDir.getAbsolutePath() + File.separator + "texts", true); + exfile.exportTexts(handler, outDir.getAbsolutePath() + File.separator + "texts", true); exportOK = true; break; case "image": - exfile.exportImages(outDir.getAbsolutePath()); + exfile.exportImages(handler, outDir.getAbsolutePath()); exportOK = true; break; case "shape": - exfile.exportShapes(outDir.getAbsolutePath()); + exfile.exportShapes(handler, outDir.getAbsolutePath()); exportOK = true; break; case "as": @@ -677,35 +701,35 @@ public class Main { exportOK = exportOK && exfile.exportAS3Class(args[i], outDir.getAbsolutePath(), exportFormat.equals("pcode"), (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); } } else { - exportOK = !exfile.exportActionScript(outDir.getAbsolutePath(), exportFormat.equals("pcode"), (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)).isEmpty(); + exportOK = !exfile.exportActionScript(handler, outDir.getAbsolutePath(), exportFormat.equals("pcode"), (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)).isEmpty(); } break; case "movie": - exfile.exportMovies(outDir.getAbsolutePath()); + exfile.exportMovies(handler, outDir.getAbsolutePath()); exportOK = true; break; case "sound": - exfile.exportSounds(outDir.getAbsolutePath(), true, true); + exfile.exportSounds(handler, outDir.getAbsolutePath(), true, true); exportOK = true; break; case "binarydata": - exfile.exportBinaryData(outDir.getAbsolutePath()); + exfile.exportBinaryData(handler, outDir.getAbsolutePath()); exportOK = true; break; case "text": - exfile.exportTexts(outDir.getAbsolutePath(), true); + exfile.exportTexts(handler, outDir.getAbsolutePath(), true); exportOK = true; break; case "textplain": - exfile.exportTexts(outDir.getAbsolutePath(), false); + exfile.exportTexts(handler, outDir.getAbsolutePath(), false); exportOK = true; break; case "fla": - exfile.exportFla(outDir.getAbsolutePath(), inFile.getName(), applicationName, applicationVerName, version, (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); + exfile.exportFla(handler, outDir.getAbsolutePath(), inFile.getName(), applicationName, applicationVerName, version, (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); exportOK = true; break; case "xfl": - exfile.exportXfl(outDir.getAbsolutePath(), inFile.getName(), applicationName, applicationVerName, version, (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); + exfile.exportXfl(handler, outDir.getAbsolutePath(), inFile.getName(), applicationName, applicationVerName, version, (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); exportOK = true; break; default: @@ -1100,15 +1124,19 @@ public class Main { if (!Platform.isWindows()) { return false; } - final String classesPath = "Software\\Classes\\"; - if (!Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, classesPath + ".swf")) { + try { + final String classesPath = "Software\\Classes\\"; + if (!Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, classesPath + ".swf")) { + return false; + } + String clsName = Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, classesPath + ".swf", ""); + if (clsName == null) { + return false; + } + return Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName + "\\shell\\ffdec"); + } catch (Win32Exception ex) { return false; } - String clsName = Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, classesPath + ".swf", ""); - if (clsName == null) { - return false; - } - return Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, classesPath + clsName + "\\shell\\ffdec"); } public static String getAppDir() { diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java index 90d70a9ff..6ab2daa44 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.gui; +import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; import com.jpexs.decompiler.flash.Configuration; import com.jpexs.decompiler.flash.FrameNode; import com.jpexs.decompiler.flash.PackageNode; @@ -240,6 +241,15 @@ public class MainFrame extends AppFrame implements ActionListener, TreeSelection private JTextField fontAddCharactersField; private JButton errorNotificationButton; private ErrorLogFrame errorLogFrame; + private AbortRetryIgnoreHandler errorHandler = new AbortRetryIgnoreHandler() { + @Override + public int handle(Throwable thrown) { + synchronized (MainFrame.class) { + String options[] = new String[]{translate("button.abort"), translate("button.retry"), translate("button.ignore")}; + return JOptionPane.showOptionDialog(null, translate("error.occured").replace("%error%", thrown.getLocalizedMessage()), translate("error"), JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, null, options, ""); + } + } + }; public void setPercent(int percent) { progressBar.setValue(percent); @@ -633,7 +643,7 @@ public class MainFrame extends AppFrame implements ActionListener, TreeSelection try { File ftemp = new File(tempDir); - files = exportSelection(tempDir, export); + files = exportSelection(errorHandler, tempDir, export); files.clear(); File fs[] = ftemp.listFiles(); @@ -1612,7 +1622,7 @@ public class MainFrame extends AppFrame implements ActionListener, TreeSelection } private SearchDialog searchDialog; - public List exportSelection(String selFile, ExportDialog export) throws IOException { + public List exportSelection(AbortRetryIgnoreHandler handler, String selFile, ExportDialog export) throws IOException { final boolean isPcode = export.getOption(ExportDialog.OPTION_ACTIONSCRIPT) == 1; final boolean isMp3OrWav = export.getOption(ExportDialog.OPTION_SOUNDS) == 0; final boolean isFormatted = export.getOption(ExportDialog.OPTION_TEXTS) == 1; @@ -1666,12 +1676,12 @@ public class MainFrame extends AppFrame implements ActionListener, TreeSelection } } } - ret.addAll(swf.exportImages(selFile + File.separator + "images", images)); - ret.addAll(SWF.exportShapes(selFile + File.separator + "shapes", shapes)); - ret.addAll(swf.exportTexts(selFile + File.separator + "texts", texts, isFormatted)); - ret.addAll(swf.exportMovies(selFile + File.separator + "movies", movies)); - ret.addAll(swf.exportSounds(selFile + File.separator + "sounds", sounds, isMp3OrWav, isMp3OrWav)); - ret.addAll(swf.exportBinaryData(selFile + File.separator + "binaryData", binaryData)); + ret.addAll(swf.exportImages(handler, selFile + File.separator + "images", images)); + ret.addAll(SWF.exportShapes(handler, selFile + File.separator + "shapes", shapes)); + ret.addAll(swf.exportTexts(handler, selFile + File.separator + "texts", texts, isFormatted)); + ret.addAll(swf.exportMovies(handler, selFile + File.separator + "movies", movies)); + ret.addAll(swf.exportSounds(handler, selFile + File.separator + "sounds", sounds, isMp3OrWav, isMp3OrWav)); + ret.addAll(swf.exportBinaryData(handler, selFile + File.separator + "binaryData", binaryData)); if (abcPanel != null) { for (int i = 0; i < tlsList.size(); i++) { ScriptPack tls = tlsList.get(i); @@ -1685,7 +1695,7 @@ public class MainFrame extends AppFrame implements ActionListener, TreeSelection allNodes.add(asn); TagNode.setExport(allNodes, false); TagNode.setExport(actionNodes, true); - ret.addAll(TagNode.exportNodeAS(allNodes, selFile, isPcode)); + ret.addAll(TagNode.exportNodeAS(handler, allNodes, selFile, isPcode)); } } return ret; @@ -2071,9 +2081,9 @@ public class MainFrame extends AppFrame implements ActionListener, TreeSelection public void run() { try { if (compressed) { - swf.exportFla(selfile.getAbsolutePath(), new File(Main.file).getName(), Main.applicationName, Main.applicationVerName, Main.version, (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); + swf.exportFla(errorHandler, selfile.getAbsolutePath(), new File(Main.file).getName(), Main.applicationName, Main.applicationVerName, Main.version, (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); } else { - swf.exportXfl(selfile.getAbsolutePath(), new File(Main.file).getName(), Main.applicationName, Main.applicationVerName, Main.version, (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); + swf.exportXfl(errorHandler, selfile.getAbsolutePath(), new File(Main.file).getName(), Main.applicationName, Main.applicationVerName, Main.version, (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); } } catch (IOException ex) { JOptionPane.showMessageDialog(null, translate("error.export") + ": " + ex.getLocalizedMessage(), translate("error"), JOptionPane.ERROR_MESSAGE); @@ -2107,19 +2117,19 @@ public class MainFrame extends AppFrame implements ActionListener, TreeSelection public void run() { try { if (onlySel) { - exportSelection(selFile, export); + exportSelection(errorHandler, selFile, export); } else { - swf.exportImages(selFile + File.separator + "images"); - swf.exportShapes(selFile + File.separator + "shapes"); - swf.exportTexts(selFile + File.separator + "texts", isFormatted); - swf.exportMovies(selFile + File.separator + "movies"); - swf.exportSounds(selFile + File.separator + "sounds", isMp3OrWav, isMp3OrWav); - swf.exportBinaryData(selFile + File.separator + "binaryData"); - swf.exportActionScript(selFile, isPcode, (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); + swf.exportImages(errorHandler, selFile + File.separator + "images"); + swf.exportShapes(errorHandler, selFile + File.separator + "shapes"); + swf.exportTexts(errorHandler, selFile + File.separator + "texts", isFormatted); + swf.exportMovies(errorHandler, selFile + File.separator + "movies"); + swf.exportSounds(errorHandler, selFile + File.separator + "sounds", isMp3OrWav, isMp3OrWav); + swf.exportBinaryData(errorHandler, selFile + File.separator + "binaryData"); + swf.exportActionScript(errorHandler, selFile, isPcode, (Boolean) Configuration.getConfig("paralelSpeedUp", Boolean.TRUE)); } } catch (Exception ex) { Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, "Error during export", ex); - JOptionPane.showMessageDialog(null, translate("error.export")); + JOptionPane.showMessageDialog(null, translate("error.export") + ": " + ex.getLocalizedMessage()); } Main.stopWork(); long timeAfter = System.currentTimeMillis(); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 811bb43ea..ed08d7e85 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -316,4 +316,10 @@ FileChooser.viewMenuLabelText = View FileChooser.fileSizeKiloBytes = {0} KB FileChooser.fileSizeMegaBytes = {0} MB FileChooser.fileSizeGigaBytes = {0} GB -FileChooser.folderNameLabelText = Folder name: \ No newline at end of file +FileChooser.folderNameLabelText = Folder name: + + +error.occured = Error occured : %error% +button.abort = Abort +button.retry = Retry +button.ignore = Ignore \ No newline at end of file diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index 3a4f15b7a..e786b2a60 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -315,4 +315,9 @@ FileChooser.viewMenuLabelText = Zobrazit FileChooser.fileSizeKiloBytes = {0} KB FileChooser.fileSizeMegaBytes = {0} MB FileChooser.fileSizeGigaBytes = {0} GB -FileChooser.folderNameLabelText = N\u00e1zev slo\u017eky: \ No newline at end of file +FileChooser.folderNameLabelText = N\u00e1zev slo\u017eky: + +error.occured = Error occured : %error% +button.abort = P\u0159eru\u0161it +button.retry = Znovu +button.ignore = Ignorovat \ No newline at end of file diff --git a/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index 7ae2ae771..b1355a19c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -16,6 +16,9 @@ */ package com.jpexs.decompiler.flash.xfl; +import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; +import com.jpexs.decompiler.flash.RetryTask; +import com.jpexs.decompiler.flash.RunnableIOEx; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.graph.Graph; @@ -95,6 +98,7 @@ import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; @@ -2109,12 +2113,15 @@ public class XFLConverter { return ret; } - private static void writeFile(byte data[], String file) { - try (FileOutputStream fos = new FileOutputStream(file)) { - fos.write(data); - } catch (IOException iex) { - Logger.getLogger(XFLConverter.class.getName()).log(Level.SEVERE, "Error during file write", iex); - } + private static void writeFile(AbortRetryIgnoreHandler handler, final byte data[], final String file) throws IOException { + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + try (FileOutputStream fos = new FileOutputStream(file)) { + fos.write(data); + } + } + }, handler).run(); } private static Map getCharacterClasses(List tags) { @@ -2457,7 +2464,7 @@ public class XFLConverter { return ret; } - public static void convertSWF(SWF swf, String swfFileName, String outfile, boolean compressed, String generator, String generatorVerName, String generatorVersion, boolean paralel) throws IOException { + public static void convertSWF(AbortRetryIgnoreHandler handler, SWF swf, String swfFileName, String outfile, boolean compressed, String generator, String generatorVerName, String generatorVersion, boolean paralel) throws IOException { File file = new File(outfile); File outDir = file.getParentFile(); if (!outDir.exists()) { @@ -2474,8 +2481,8 @@ public class XFLConverter { if (baseName.contains(".")) { baseName = baseName.substring(0, baseName.lastIndexOf(".")); } - HashMap files = new HashMap<>(); - HashMap datfiles = new HashMap<>(); + final HashMap files = new HashMap<>(); + final HashMap datfiles = new HashMap<>(); HashMap characters = getCharacters(swf.tags); List oneInstaceShapes = getOneInstanceShapes(swf.tags, characters); Map characterClasses = getCharacterClasses(swf.tags); @@ -2551,7 +2558,7 @@ public class XFLConverter { } } try { - writeFile(data.getBytes("UTF-8"), outDir.getAbsolutePath() + File.separator + expPath + ".as"); + writeFile(handler, data.getBytes("UTF-8"), outDir.getAbsolutePath() + File.separator + expPath + ".as"); } catch (UnsupportedEncodingException ex) { Logger.getLogger(XFLConverter.class.getName()).log(Level.SEVERE, null, ex); } @@ -2769,22 +2776,29 @@ public class XFLConverter { + ""; if (compressed) { - try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outfile))) { - out.putNextEntry(new ZipEntry("DOMDocument.xml")); - out.write(domDocument.getBytes("UTF-8")); - out.putNextEntry(new ZipEntry("PublishSettings.xml")); - out.write(publishSettings.getBytes("UTF-8")); - for (String fileName : files.keySet()) { - out.putNextEntry(new ZipEntry("LIBRARY/" + fileName)); - out.write(files.get(fileName)); + final String domDocumentF = domDocument; + final String publishSettingsF = publishSettings; + final String outfileF = outfile; + new RetryTask(new RunnableIOEx() { + @Override + public void run() throws IOException { + try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outfileF))) { + out.putNextEntry(new ZipEntry("DOMDocument.xml")); + out.write(domDocumentF.getBytes("UTF-8")); + out.putNextEntry(new ZipEntry("PublishSettings.xml")); + out.write(publishSettingsF.getBytes("UTF-8")); + for (String fileName : files.keySet()) { + out.putNextEntry(new ZipEntry("LIBRARY/" + fileName)); + out.write(files.get(fileName)); + } + for (String fileName : datfiles.keySet()) { + out.putNextEntry(new ZipEntry("bin/" + fileName)); + out.write(datfiles.get(fileName)); + } + } } - for (String fileName : datfiles.keySet()) { - out.putNextEntry(new ZipEntry("bin/" + fileName)); - out.write(datfiles.get(fileName)); - } - } catch (IOException ex) { - Logger.getLogger(XFLConverter.class.getName()).log(Level.SEVERE, null, ex); - } + }, handler).run(); + } else { @@ -2796,12 +2810,12 @@ public class XFLConverter { } } try { - writeFile(domDocument.getBytes("UTF-8"), outDir.getAbsolutePath() + File.separator + "DOMDocument.xml"); + writeFile(handler, domDocument.getBytes("UTF-8"), outDir.getAbsolutePath() + File.separator + "DOMDocument.xml"); } catch (UnsupportedEncodingException ex) { Logger.getLogger(XFLConverter.class.getName()).log(Level.SEVERE, null, ex); } try { - writeFile(publishSettings.getBytes("UTF-8"), outDir.getAbsolutePath() + File.separator + "PublishSettings.xml"); + writeFile(handler, publishSettings.getBytes("UTF-8"), outDir.getAbsolutePath() + File.separator + "PublishSettings.xml"); } catch (UnsupportedEncodingException ex) { Logger.getLogger(XFLConverter.class.getName()).log(Level.SEVERE, null, ex); } @@ -2810,20 +2824,20 @@ public class XFLConverter { File binDir = new File(outDir.getAbsolutePath() + File.separator + "bin"); binDir.mkdir(); for (String fileName : files.keySet()) { - writeFile(files.get(fileName), libraryDir.getAbsolutePath() + File.separator + fileName); + writeFile(handler, files.get(fileName), libraryDir.getAbsolutePath() + File.separator + fileName); } for (String fileName : datfiles.keySet()) { - writeFile(datfiles.get(fileName), binDir.getAbsolutePath() + File.separator + fileName); + writeFile(handler, datfiles.get(fileName), binDir.getAbsolutePath() + File.separator + fileName); } try { - writeFile("PROXY-CS5".getBytes("utf-8"), outfile); + writeFile(handler, "PROXY-CS5".getBytes("utf-8"), outfile); } catch (UnsupportedEncodingException ex) { Logger.getLogger(XFLConverter.class.getName()).log(Level.SEVERE, null, ex); } } if (useAS3) { try { - swf.exportActionScript(outDir.getAbsolutePath(), false, paralel); + swf.exportActionScript(handler, outDir.getAbsolutePath(), false, paralel); } catch (Exception ex) { Logger.getLogger(XFLConverter.class.getName()).log(Level.SEVERE, "Error during ActionScript3 export", ex); }