From 55f54de9cb50707434eb970cc715384ef8e056a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Sun, 2 Mar 2014 17:34:45 +0100 Subject: [PATCH] generic tag editor: disable instantiation of abstract classes, make Action list related types not editable (it does not work yet) --- .../flash/gui/GenericTagTreePanel.java | 33 ++++++++- .../generictageditors/ReflectionTools.java | 69 +++++++++++++++++-- .../flash/tags/PlaceObject2Tag.java | 2 + .../flash/tags/PlaceObject3Tag.java | 1 + .../flash/tags/PlaceObject4Tag.java | 1 + .../flash/types/CLIPACTIONRECORD.java | 8 +++ 6 files changed, 106 insertions(+), 8 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java index 0c0b71293..dd17377ca 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java @@ -61,6 +61,7 @@ import javax.swing.AbstractCellEditor; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JMenuItem; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; @@ -242,6 +243,11 @@ public class GenericTagTreePanel extends GenericTagPanel { itemStr = AppStrings.translate("generictag.array.item"); } if (ReflectionTools.needsIndex(fnode.field)) { + + boolean canAdd = true; + if (!ReflectionTools.canAddToField(fnode.obj, fnode.field)) { + canAdd = false; + } JPopupMenu p = new JPopupMenu(); JMenuItem mi; mi = new JMenuItem(AppStrings.translate("generictag.array.insertbeginning").replace("%item%", itemStr)); @@ -252,6 +258,9 @@ public class GenericTagTreePanel extends GenericTagPanel { addItem(fnode.obj, fnode.field, 0); } }); + if (!canAdd) { + mi.setEnabled(false); + } p.add(mi); if (fnode.index > -1) { @@ -263,6 +272,9 @@ public class GenericTagTreePanel extends GenericTagPanel { addItem(fnode.obj, fnode.field, fnode.index); } }); + if (!canAdd) { + mi.setEnabled(false); + } p.add(mi); mi = new JMenuItem(AppStrings.translate("generictag.array.remove").replace("%item%", itemStr)); @@ -283,6 +295,9 @@ public class GenericTagTreePanel extends GenericTagPanel { addItem(fnode.obj, fnode.field, fnode.index + 1); } }); + if (!canAdd) { + mi.setEnabled(false); + } p.add(mi); } @@ -294,6 +309,9 @@ public class GenericTagTreePanel extends GenericTagPanel { addItem(fnode.obj, fnode.field, ReflectionTools.getFieldSubSize(fnode.obj, fnode.field)); } }); + if (!canAdd) { + mi.setEnabled(false); + } p.add(mi); //} p.show(tree, e.getX(), e.getY()); @@ -789,12 +807,21 @@ public class GenericTagTreePanel extends GenericTagPanel { SWFArray swfArray = field.getAnnotation(SWFArray.class); if (swfArray != null && !swfArray.countField().equals("")) { //Fields with same countField must be enlarged too Field fields[] = obj.getClass().getDeclaredFields(); + List sameFlds = new ArrayList<>(); for (int f = 0; f < fields.length; f++) { SWFArray fieldSwfArray = fields[f].getAnnotation(SWFArray.class); if (fieldSwfArray != null && fieldSwfArray.countField().equals(swfArray.countField())) { - ReflectionTools.addToField(obj, fields[f], index, true); + sameFlds.add(f); + if (!ReflectionTools.canAddToField(obj, fields[f])) { + JOptionPane.showMessageDialog(this, "This field is abstract, cannot be instantiated, sorry."); //TODO!!! + return; + } + } } + for (int f : sameFlds) { + ReflectionTools.addToField(obj, fields[f], index, true); + } try { //If countField exists, increment, otherwise do nothing Field countField = obj.getClass().getDeclaredField(swfArray.countField()); @@ -807,6 +834,10 @@ public class GenericTagTreePanel extends GenericTagPanel { //ignored } } else { + if (!ReflectionTools.canAddToField(obj, field)) { + JOptionPane.showMessageDialog(this, "This field is abstract, cannot be instantiated, sorry."); //TODO!!! + return; + } ReflectionTools.addToField(obj, field, index, true); } refreshTree(); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/ReflectionTools.java b/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/ReflectionTools.java index 204c0840f..51bed4a2a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/ReflectionTools.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/generictageditors/ReflectionTools.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.gui.generictageditors; import java.lang.reflect.Array; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.util.List; import java.util.logging.Level; @@ -85,6 +86,42 @@ public class ReflectionTools { } } + public static boolean canInstantiate(Class cls) { + if (cls.isInterface()) { + return false; + } + if (Modifier.isAbstract(cls.getModifiers())) { + return false; + } + return true; + } + + public static boolean canAddToField(Object object, Field field) { + if (List.class.isAssignableFrom(field.getType())) { + + ParameterizedType listType = (ParameterizedType) field.getGenericType(); + Class parameterClass = (Class) listType.getActualTypeArguments()[0]; + return canInstantiate(parameterClass); + } + + if (field.getType().isArray()) { + Object arrValue; + try { + arrValue = field.get(object); + } catch (IllegalArgumentException | IllegalAccessException ex) { + Logger.getLogger(ReflectionTools.class.getName()).log(Level.SEVERE, null, ex); + return false; + } + Class componentClass = arrValue.getClass().getComponentType(); + if (componentClass.isPrimitive()) { + return true; + } + return canInstantiate(componentClass); + } + return false; + + } + public static Object newInstanceOf(Class cls) throws InstantiationException, IllegalAccessException { if (cls == Integer.class || cls == int.class) { return new Integer(0); @@ -95,6 +132,12 @@ public class ReflectionTools { } else if (cls == Long.class || cls == long.class) { return new Long(0L); } + if (cls.isInterface()) { + return null; + } + if (Modifier.isAbstract(cls.getModifiers())) { + return null; + } return cls.newInstance(); } @@ -114,6 +157,9 @@ public class ReflectionTools { Class parameterClass = (Class) listType.getActualTypeArguments()[0]; try { Object val = newInstanceOf(parameterClass); + if (val == null) { + return false; + } list.add(index, val); } catch (InstantiationException | IllegalAccessException ex) { Logger.getLogger(ReflectionTools.class.getName()).log(Level.SEVERE, null, ex); @@ -151,19 +197,28 @@ public class ReflectionTools { return false; } Class componentClass = arrValue.getClass().getComponentType(); - int originalSize = Array.getLength(arrValue); - Object copy = Array.newInstance(componentClass, originalSize + 1); - //Copy items before - for (int i = 0; i < index; i++) { - Array.set(copy, i, Array.get(arrValue, i)); - } + Object val = null; if (!componentClass.isPrimitive()) { try { - Array.set(copy, index, componentClass.newInstance()); + val = newInstanceOf(componentClass); } catch (InstantiationException | IllegalAccessException ex) { Logger.getLogger(ReflectionTools.class.getName()).log(Level.SEVERE, null, ex); return false; } + if (val == null) { + return false; + } + } + + int originalSize = Array.getLength(arrValue); + Object copy = Array.newInstance(componentClass, originalSize + 1); + + //Copy items before + for (int i = 0; i < index; i++) { + Array.set(copy, i, Array.get(arrValue, i)); + } + if (val != null) { + Array.set(copy, index, val); } //Copy items after for (int i = index; i < originalSize; i++) { diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject2Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject2Tag.java index ffc70c43f..c7dada19f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject2Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject2Tag.java @@ -32,6 +32,7 @@ import com.jpexs.decompiler.flash.types.ColorTransform; import com.jpexs.decompiler.flash.types.MATRIX; import com.jpexs.decompiler.flash.types.RGBA; import com.jpexs.decompiler.flash.types.annotations.Conditional; +import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.flash.types.annotations.SWFType; import com.jpexs.decompiler.flash.types.filters.FILTER; import java.io.ByteArrayInputStream; @@ -123,6 +124,7 @@ public class PlaceObject2Tag extends CharacterIdTag implements Container, PlaceO * @since SWF 5 If PlaceFlagHasClipActions, Clip Actions Data */ @Conditional("placeFlagHasClipActions") + @Internal //TODO: make editable public CLIPACTIONS clipActions; public static final int ID = 26; diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject3Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject3Tag.java index 56cc73343..56315c9d9 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject3Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject3Tag.java @@ -181,6 +181,7 @@ public class PlaceObject3Tag extends CharacterIdTag implements Container, PlaceO * @since SWF 5 If PlaceFlagHasClipActions, Clip Actions Data */ @Conditional(value = "placeFlagHasClipActions", minSwfVersion = 5) + @Internal //TODO: make editable public CLIPACTIONS clipActions; /** * If PlaceFlagHasVisible, 0 = Place invisible, 1 = Place visible diff --git a/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject4Tag.java b/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject4Tag.java index dcd2d6318..691c0558c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject4Tag.java +++ b/trunk/src/com/jpexs/decompiler/flash/tags/PlaceObject4Tag.java @@ -181,6 +181,7 @@ public class PlaceObject4Tag extends CharacterIdTag implements Container, PlaceO * @since SWF 5 If PlaceFlagHasClipActions, Clip Actions Data */ @Conditional(value = "placeFlagHasClipActions", minSwfVersion = 5) + @Internal //TODO: make editable public CLIPACTIONS clipActions; /** * If PlaceFlagHasVisible, 0 = Place invisible, 1 = Place visible diff --git a/trunk/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java b/trunk/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java index 390fb44ee..989800390 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java @@ -95,6 +95,14 @@ public class CLIPACTIONRECORD implements ASMSource, Exportable, ContainerItem, S @Internal private long hdrPos; + //Constructor for Generic tag editor. TODO:Handle this somehow better + public CLIPACTIONRECORD(){ + swf = null; + eventFlags = new CLIPEVENTFLAGS(); + actionBytes = new byte[0]; + hdrPos = 0; + } + public CLIPACTIONRECORD(SWF swf, InputStream is, int version, long pos) throws IOException { this.swf = swf; SWFInputStream sis = new SWFInputStream(is, version);