diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfXmlExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfXmlExporter.java index f6da6d500..9ca46f68b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfXmlExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfXmlExporter.java @@ -67,11 +67,15 @@ public class SwfXmlExporter { private final Map> cachedFields = new HashMap<>(); - public List exportXml(SWF swf, File outFile) throws IOException { + public List exportXml(SWF swf, File outFile) throws IOException { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); Document xmlDoc = docBuilder.newDocument(); + + xmlDoc.appendChild(xmlDoc.createComment("WARNING: The structure of this XML is not final. In later versions of FFDec it can be changed.")); + xmlDoc.appendChild(xmlDoc.createComment(ApplicationInfo.applicationVerName)); + exportXml(swf, xmlDoc, xmlDoc); try (Writer writer = new Utf8OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(outFile)))) { writer.append(getXml(xmlDoc)); @@ -102,7 +106,7 @@ public class SwfXmlExporter { } public void exportXml(SWF swf, Document doc, Node node) throws IOException { - generateXml(doc, node, "swf", swf, false, 0, false); + generateXml(doc, node, "swf", swf, false, false); } public List getSwfFieldsCached(Class cls) { @@ -115,7 +119,7 @@ public class SwfXmlExporter { return result; } - private void generateXml(Document doc, Node node, String name, Object obj, boolean isListItem, int level, boolean needsCData) { + private void generateXml(Document doc, Node node, String name, Object obj, boolean isListItem, boolean needsCData) { Class cls = obj != null ? obj.getClass() : null; if (obj != null && needsCData && cls == String.class) { @@ -156,20 +160,16 @@ public class SwfXmlExporter { } else if (obj instanceof byte[]) { byte[] data = (byte[]) obj; ((Element) node).setAttribute(name, Helper.byteArrayToHex(data)); - } else if (cls != null && obj != null && List.class.isAssignableFrom(cls)) { - List list = (List) obj; - Element listNode = doc.createElement(name); - node.appendChild(listNode); - for (int i = 0; i < list.size(); i++) { - generateXml(doc, listNode, "item", list.get(i), true, level + 1, false); + } else if (cls != null && (cls.isArray() || List.class.isAssignableFrom(cls))) { + if(List.class.isAssignableFrom(cls)) { + obj = ((List)obj).toArray(); } - } else if (cls != null && cls.isArray()) { - Class arrayType = cls.getComponentType(); + Element arrayNode = doc.createElement(name); node.appendChild(arrayNode); int length = Array.getLength(obj); for (int i = 0; i < length; i++) { - generateXml(doc, arrayNode, "item", Array.get(obj, i), true, level + 1, false); + generateXml(doc, arrayNode, "item", Array.get(obj, i), true, false); } } else if (obj != null) { if (obj instanceof LazyObject) { @@ -186,15 +186,10 @@ public class SwfXmlExporter { Element objNode = doc.createElement(name); objNode.setAttribute("type", className); if (obj instanceof UnknownTag) { - objNode.setAttribute("tagId", "" + ((Tag) obj).getId()); + objNode.setAttribute("tagId", String.valueOf(((Tag) obj).getId())); } node.appendChild(objNode); - if (level == 0) { - objNode.appendChild(doc.createComment("WARNING: The structure of this XML is not final. In later versions of FFDec it can be changed.")); - objNode.appendChild(doc.createComment(ApplicationInfo.applicationVerName)); - } - for (Field f : fields) { if (Modifier.isStatic(f.getModifiers())) { continue; @@ -208,7 +203,7 @@ public class SwfXmlExporter { try { f.setAccessible(true); - generateXml(doc, objNode, f.getName(), f.get(obj), false, level + 1, multilineA != null); + generateXml(doc, objNode, f.getName(), f.get(obj), false, multilineA != null); } catch (IllegalArgumentException | IllegalAccessException ex) { logger.log(Level.SEVERE, null, ex); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SwfXmlImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SwfXmlImporter.java index 0dea42900..c31727119 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SwfXmlImporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SwfXmlImporter.java @@ -133,11 +133,63 @@ public class SwfXmlImporter { private static final Logger logger = Logger.getLogger(SwfXmlImporter.class.getName()); - private Map swfTags; + private static final Map swfTags; - private Map swfObjects; + private static final Map swfObjects; - private Map swfObjectsParam; + private static final Map swfObjectsParam; + + static { + Map tags = new HashMap<>(); + Map knownTags = Tag.getKnownClasses(); + for (Integer key : knownTags.keySet()) { + Class cls = knownTags.get(key).getCls(); + if (!ReflectionTools.canInstantiate(cls)) { + System.err.println("Can't instantiate: " + cls.getName()); + } + tags.put(cls.getSimpleName(), cls); + } + + swfTags = tags; + + Map objects = new HashMap<>(); + Class[] knownObjects = new Class[]{ALPHABITMAPDATA.class, ALPHACOLORMAPDATA.class, ARGB.class, BITMAPDATA.class, + BUTTONCONDACTION.class, BUTTONRECORD.class, CLIPACTIONRECORD.class, CLIPACTIONS.class, CLIPEVENTFLAGS.class, + COLORMAPDATA.class, ColorTransform.class, CXFORM.class, CXFORMWITHALPHA.class, + FILLSTYLE.class, FILLSTYLEARRAY.class, FOCALGRADIENT.class, GLYPHENTRY.class, GRADIENT.class, GRADRECORD.class, + KERNINGRECORD.class, LANGCODE.class, LINESTYLE.class, LINESTYLE2.class, LINESTYLEARRAY.class, MATRIX.class, + MORPHFILLSTYLE.class, MORPHFILLSTYLEARRAY.class, MORPHFOCALGRADIENT.class, MORPHGRADIENT.class, + MORPHGRADRECORD.class, MORPHLINESTYLE.class, MORPHLINESTYLE2.class, MORPHLINESTYLEARRAY.class, PIX15.class, + PIX24.class, RECT.class, RGB.class, RGBA.class, SHAPE.class, SHAPEWITHSTYLE.class, SOUNDENVELOPE.class, + SOUNDINFO.class, TEXTRECORD.class, ZONEDATA.class, ZONERECORD.class, + CurvedEdgeRecord.class, EndShapeRecord.class, StraightEdgeRecord.class, StyleChangeRecord.class, + BEVELFILTER.class, BLURFILTER.class, COLORMATRIXFILTER.class, CONVOLUTIONFILTER.class, + DROPSHADOWFILTER.class, GLOWFILTER.class, GRADIENTBEVELFILTER.class, GRADIENTGLOWFILTER.class, + AVM2ConstantPool.class, Decimal.class, Namespace.class, NamespaceSet.class, Multiname.class, MethodInfo.class, MetadataInfo.class, + ValueKind.class, InstanceInfo.class, Traits.class, TraitClass.class, TraitFunction.class, + TraitMethodGetterSetter.class, TraitSlotConst.class, ClassInfo.class, ScriptInfo.class, MethodBody.class, + ABCException.class, ABCVersion.class, Amf3Value.class}; + + for (Class cls2 : knownObjects) { + if (!ReflectionTools.canInstantiateDefaultConstructor(cls2)) { + System.err.println("Can't instantiate: " + cls2.getName()); + } + objects.put(cls2.getSimpleName(), cls2); + } + + swfObjects = objects; + + Map objectsParam = new HashMap<>(); + Class[] knownObjectsParam = new Class[]{ABC.class}; + for (Class cls2 : knownObjectsParam) { + if (!ReflectionTools.canInstantiate(cls2)) { + System.err.println("Can't instantiate: " + cls2.getName()); + } + objectsParam.put(cls2.getSimpleName(), cls2); + } + + swfObjectsParam = objectsParam; + } public void importSwf(SWF swf, String xml) throws IOException { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); @@ -309,20 +361,6 @@ public class SwfXmlImporter { } private Object createObject(String type, int tagTypeId, SWF swf, Tag tag) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { - if (swfTags == null) { - Map tags = new HashMap<>(); - Map knownTags = Tag.getKnownClasses(); - for (Integer key : knownTags.keySet()) { - Class cls = knownTags.get(key).getCls(); - if (!ReflectionTools.canInstantiate(cls)) { - System.err.println("Can't instantiate: " + cls.getName()); - } - tags.put(cls.getSimpleName(), cls); - } - - swfTags = tags; - } - if ("UnknownTag".equals(type)) { return new UnknownTag(swf, tagTypeId); } @@ -332,52 +370,11 @@ public class SwfXmlImporter { return cls.getConstructor(SWF.class).newInstance(swf); } - if (swfObjects == null) { - Map objects = new HashMap<>(); - Class[] knownObjects = new Class[]{ALPHABITMAPDATA.class, ALPHACOLORMAPDATA.class, ARGB.class, BITMAPDATA.class, - BUTTONCONDACTION.class, BUTTONRECORD.class, CLIPACTIONRECORD.class, CLIPACTIONS.class, CLIPEVENTFLAGS.class, - COLORMAPDATA.class, ColorTransform.class, CXFORM.class, CXFORMWITHALPHA.class, - FILLSTYLE.class, FILLSTYLEARRAY.class, FOCALGRADIENT.class, GLYPHENTRY.class, GRADIENT.class, GRADRECORD.class, - KERNINGRECORD.class, LANGCODE.class, LINESTYLE.class, LINESTYLE2.class, LINESTYLEARRAY.class, MATRIX.class, - MORPHFILLSTYLE.class, MORPHFILLSTYLEARRAY.class, MORPHFOCALGRADIENT.class, MORPHGRADIENT.class, - MORPHGRADRECORD.class, MORPHLINESTYLE.class, MORPHLINESTYLE2.class, MORPHLINESTYLEARRAY.class, PIX15.class, - PIX24.class, RECT.class, RGB.class, RGBA.class, SHAPE.class, SHAPEWITHSTYLE.class, SOUNDENVELOPE.class, - SOUNDINFO.class, TEXTRECORD.class, ZONEDATA.class, ZONERECORD.class, - CurvedEdgeRecord.class, EndShapeRecord.class, StraightEdgeRecord.class, StyleChangeRecord.class, - BEVELFILTER.class, BLURFILTER.class, COLORMATRIXFILTER.class, CONVOLUTIONFILTER.class, - DROPSHADOWFILTER.class, GLOWFILTER.class, GRADIENTBEVELFILTER.class, GRADIENTGLOWFILTER.class, - AVM2ConstantPool.class, Decimal.class, Namespace.class, NamespaceSet.class, Multiname.class, MethodInfo.class, MetadataInfo.class, - ValueKind.class, InstanceInfo.class, Traits.class, TraitClass.class, TraitFunction.class, - TraitMethodGetterSetter.class, TraitSlotConst.class, ClassInfo.class, ScriptInfo.class, MethodBody.class, - ABCException.class, ABCVersion.class, Amf3Value.class}; - for (Class cls2 : knownObjects) { - if (!ReflectionTools.canInstantiateDefaultConstructor(cls2)) { - System.err.println("Can't instantiate: " + cls2.getName()); - } - objects.put(cls2.getSimpleName(), cls2); - } - - swfObjects = objects; - } - cls = swfObjects.get(type); if (cls != null) { return cls.getConstructor().newInstance(); } - if (swfObjectsParam == null) { - Map objects = new HashMap<>(); - Class[] knownObjects = new Class[]{ABC.class}; - for (Class cls2 : knownObjects) { - if (!ReflectionTools.canInstantiate(cls2)) { - System.err.println("Can't instantiate: " + cls2.getName()); - } - objects.put(cls2.getSimpleName(), cls2); - } - - swfObjectsParam = objects; - } - cls = swfObjectsParam.get(type); if (cls != null) { for (Constructor constructor : cls.getConstructors()) {