From 743eb4d2252a95a5d74fa62c610e037a7e30e00e Mon Sep 17 00:00:00 2001 From: Sian January Date: Wed, 25 Aug 2010 15:22:36 +0000 Subject: [PATCH] Pack200 - more testing for annotations and some associated bug fixes git-svn-id: https://svn.apache.org/repos/asf/harmony/enhanced/java/trunk@989168 13f79535-47bb-0310-9956-ffa450edef68 --- .../pack200/AttributeDefinitionBands.java | 24 ++++---- .../apache/harmony/pack200/ClassBands.java | 4 +- .../harmony/pack200/MetadataBandGroup.java | 31 +++++++++- .../apache/harmony/pack200/NewAttribute.java | 57 ++++++++++++++++++ .../harmony/pack200/PackingOptions.java | 56 +++++++---------- .../org/apache/harmony/pack200/Segment.java | 28 ++++----- .../harmony/unpack200/MetadataBandGroup.java | 16 ++--- .../harmony/pack200/tests/ArchiveTest.java | 18 +++++- .../tests/AttributeLayoutMapTest.java | 5 +- .../pack200/tests/annotations2unpacked.jar | Bin 0 -> 2919 bytes 10 files changed, 161 insertions(+), 78 deletions(-) create mode 100644 src/test/resources/org/apache/harmony/pack200/tests/annotations2unpacked.jar diff --git a/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java b/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java index ca30d03..5afb5ba 100644 --- a/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java +++ b/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java @@ -59,17 +59,19 @@ public class AttributeDefinitionBands extends BandSet { for (int i = 0; i < attributePrototypes.length; i++) { NewAttribute newAttribute = (NewAttribute) attributePrototypes[i]; - if (newAttribute.isContextClass()) { - classLayouts.put(newAttribute.type, newAttribute.getLayout()); - } - if (newAttribute.isContextMethod()) { - methodLayouts.put(newAttribute.type, newAttribute.getLayout()); - } - if (newAttribute.isContextField()) { - fieldLayouts.put(newAttribute.type, newAttribute.getLayout()); - } - if (newAttribute.isContextCode()) { - codeLayouts.put(newAttribute.type, newAttribute.getLayout()); + if(!(newAttribute instanceof NewAttribute.ErrorAttribute) && !(newAttribute instanceof NewAttribute.PassAttribute) && !(newAttribute instanceof NewAttribute.StripAttribute)) { + if (newAttribute.isContextClass()) { + classLayouts.put(newAttribute.type, newAttribute.getLayout()); + } + if (newAttribute.isContextMethod()) { + methodLayouts.put(newAttribute.type, newAttribute.getLayout()); + } + if (newAttribute.isContextField()) { + fieldLayouts.put(newAttribute.type, newAttribute.getLayout()); + } + if (newAttribute.isContextCode()) { + codeLayouts.put(newAttribute.type, newAttribute.getLayout()); + } } } if (classLayouts.keySet().size() > 7) { diff --git a/src/main/java/org/apache/harmony/pack200/ClassBands.java b/src/main/java/org/apache/harmony/pack200/ClassBands.java index 67a6c18..0c843f5 100644 --- a/src/main/java/org/apache/harmony/pack200/ClassBands.java +++ b/src/main/java/org/apache/harmony/pack200/ClassBands.java @@ -1327,7 +1327,7 @@ public class ClassBands extends BandSet { public void addParameterAnnotation(int parameter, String desc, boolean visible, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) { if(visible) { - method_RVPA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN); + method_RVPA_bands.addParameterAnnotation(parameter, desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN); Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1); if((flag.intValue() & (1<<23)) != 0) { method_RVPA_bands.incrementAnnoN(); @@ -1336,7 +1336,7 @@ public class ClassBands extends BandSet { } tempMethodFlags.add(new Long(flag.longValue() | (1<<23))); } else { - method_RIPA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN); + method_RIPA_bands.addParameterAnnotation(parameter, desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN); Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1); if((flag.longValue() & (1<<24)) != 0) { method_RIPA_bands.incrementAnnoN(); diff --git a/src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java b/src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java index cd54dbb..c396a28 100644 --- a/src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java +++ b/src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java @@ -35,7 +35,7 @@ public class MetadataBandGroup extends BandSet { private final String type; private int numBackwardsCalls = 0; - public List param_NB = new ArrayList(); // TODO: Lazy instantiation? + public IntList param_NB = new IntList(); // TODO: Lazy instantiation? public IntList anno_N = new IntList(); public List type_RS = new ArrayList(); public IntList pair_N = new IntList(); @@ -95,6 +95,16 @@ public class MetadataBandGroup extends BandSet { } byte[] encodedBand = null; if(!type.equals("AD")) { + if(type.indexOf('P') != -1) { + // Parameter annotation so we need to transmit param_NB + encodedBand = encodeBandInt( + contextStr + "_" + type + " param_NB", param_NB.toArray(), + Codec.BYTE1); + out.write(encodedBand); + PackingUtils.log("Wrote " + encodedBand.length + + " bytes from " + contextStr + "_" + type + " anno_N[" + + param_NB.size() + "]"); + } encodedBand = encodeBandInt( contextStr + "_" + type + " anno_N", anno_N.toArray(), Codec.UNSIGNED5); @@ -230,6 +240,23 @@ public class MetadataBandGroup extends BandSet { return ints; } + /** + * Add an annotation to this set of bands + * + * @param desc + * @param nameRU + * @param t + * @param values + * @param caseArrayN + * @param nestTypeRS + * @param nestNameRU + * @param nestPairN + */ + public void addParameterAnnotation(int parameter, String desc, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) { + param_NB.add(parameter); + addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN); + } + /** * Add an annotation to this set of bands * @@ -244,7 +271,7 @@ public class MetadataBandGroup extends BandSet { */ public void addAnnotation(String desc, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) { type_RS.add(cpBands.getCPSignature(desc)); - pair_N.add(t.size()); + pair_N.add(nameRU.size()); for (Iterator iterator = nameRU.iterator(); iterator.hasNext();) { String name = (String) iterator.next(); diff --git a/src/main/java/org/apache/harmony/pack200/NewAttribute.java b/src/main/java/org/apache/harmony/pack200/NewAttribute.java index 3cab224..a26099c 100644 --- a/src/main/java/org/apache/harmony/pack200/NewAttribute.java +++ b/src/main/java/org/apache/harmony/pack200/NewAttribute.java @@ -142,4 +142,61 @@ public class NewAttribute extends Attribute { public Label getLabel(int index) { return labels[index]; } + + /** + * ErrorAttribute extends NewAttribute and manages attributes + * encountered by ASM that have had an error action specified to pack200 + * (e.g. via one of the -C, -M, -F or -D command line options such as + * -Cattribute-name=error) + */ + public static class ErrorAttribute extends NewAttribute { + + public ErrorAttribute(String type, int context) { + super(type, "", context); + } + + protected Attribute read(ClassReader cr, int off, int len, char[] buf, + int codeOff, Label[] labels) { + throw new Error("Attribute " + type + " was found"); + } + + } + + /** + * StripAttribute extends NewAttribute and manages attributes + * encountered by ASM that have had an strip action specified to pack200 + * (e.g. via one of the -C, -M, -F or -D command line options such as + * -Cattribute-name=strip) + */ + public static class StripAttribute extends NewAttribute { + + public StripAttribute(String type, int context) { + super(type, "", context); + } + + protected Attribute read(ClassReader cr, int off, int len, char[] buf, + int codeOff, Label[] labels) { + // TODO Not sure if this works, can we really strip an attribute if we don't know the layout? + return null; + } + } + + /** + * PassAttribute extends NewAttribute and manages attributes + * encountered by ASM that have had an pass action specified to pack200 + * (e.g. via one of the -C, -M, -F or -D command line options such as + * -Cattribute-name=pass) + */ + public static class PassAttribute extends NewAttribute { + + public PassAttribute(String type, int context) { + super(type, "", context); + } + + protected Attribute read(ClassReader cr, int off, int len, char[] buf, + int codeOff, Label[] labels) { + throw new Segment.PassException(); + } + + } } diff --git a/src/main/java/org/apache/harmony/pack200/PackingOptions.java b/src/main/java/org/apache/harmony/pack200/PackingOptions.java index 580c8a4..61fed03 100644 --- a/src/main/java/org/apache/harmony/pack200/PackingOptions.java +++ b/src/main/java/org/apache/harmony/pack200/PackingOptions.java @@ -209,10 +209,6 @@ public class PackingOptions { } } - public Map getClassAttributeActions() { - return classAttributeActions; - } - public void addClassAttributeAction(String attributeName, String action) { if(classAttributeActions == null) { classAttributeActions = new HashMap(); @@ -220,10 +216,6 @@ public class PackingOptions { classAttributeActions.put(attributeName, action); } - public Map getFieldAttributeActions() { - return fieldAttributeActions; - } - public void addFieldAttributeAction(String attributeName, String action) { if(fieldAttributeActions == null) { fieldAttributeActions = new HashMap(); @@ -231,10 +223,6 @@ public class PackingOptions { fieldAttributeActions.put(attributeName, action); } - public Map getMethodAttributeActions() { - return methodAttributeActions; - } - public void addMethodAttributeAction(String attributeName, String action) { if(methodAttributeActions == null) { methodAttributeActions = new HashMap(); @@ -242,10 +230,6 @@ public class PackingOptions { methodAttributeActions.put(attributeName, action); } - public Map getCodeAttributeActions() { - return codeAttributeActions; - } - public void addCodeAttributeAction(String attributeName, String action) { if(codeAttributeActions == null) { codeAttributeActions = new HashMap(); @@ -288,25 +272,29 @@ public class PackingOptions { .hasNext();) { name = (String) iteratorI.next(); action = (String) attributeActions.get(name); - if (!ERROR.equals(action) && !STRIP.equals(action) - && !PASS.equals(action)) { - prototypeExists = false; - for (Iterator iteratorJ = prototypes.iterator(); iteratorJ - .hasNext();) { - newAttribute = (NewAttribute) iteratorJ.next(); - if (newAttribute.type.equals(name)) { - // if the attribute exists, update its context - newAttribute.addContext(tag); - prototypeExists = true; - break; - } - // if no attribute is found, add a new attribute - if (!prototypeExists) { - newAttribute = new NewAttribute(name, action, - tag); - prototypes.add(newAttribute); - } + prototypeExists = false; + for (Iterator iteratorJ = prototypes.iterator(); iteratorJ + .hasNext();) { + newAttribute = (NewAttribute) iteratorJ.next(); + if (newAttribute.type.equals(name)) { + // if the attribute exists, update its context + newAttribute.addContext(tag); + prototypeExists = true; + break; + } + } + // if no attribute is found, add a new attribute + if (!prototypeExists) { + if (ERROR.equals(action)) { + newAttribute = new NewAttribute.ErrorAttribute(name, tag); + } else if (STRIP.equals(action)) { + newAttribute = new NewAttribute.StripAttribute(name, tag); + } else if (PASS.equals(action)) { + newAttribute = new NewAttribute.PassAttribute(name, tag); + } else { + newAttribute = new NewAttribute(name, action, tag); } + prototypes.add(newAttribute); } } } diff --git a/src/main/java/org/apache/harmony/pack200/Segment.java b/src/main/java/org/apache/harmony/pack200/Segment.java index bdbc5dd..7dab7f2 100644 --- a/src/main/java/org/apache/harmony/pack200/Segment.java +++ b/src/main/java/org/apache/harmony/pack200/Segment.java @@ -53,7 +53,7 @@ public class Segment implements ClassVisitor { private PackingOptions options; private boolean stripDebug; private Attribute[] nonStandardAttributePrototypes; - + /** * The main method on Segment. Reads in all the class files, packs them and * then writes the packed segment out to the given OutputStream. @@ -76,11 +76,11 @@ public class Segment implements ClassVisitor { this.stripDebug = options.isStripDebug(); int effort = options.getEffort(); nonStandardAttributePrototypes = options.getUnknownAttributePrototypes(); - + PackingUtils.log("Start to pack a new segment with " + segmentUnit.fileListSize() + " files including " + segmentUnit.classListSize() + " classes"); - + PackingUtils.log("Initialize a header for the segment"); segmentHeader = new SegmentHeader(); segmentHeader.setFile_count(segmentUnit.fileListSize()); @@ -89,22 +89,22 @@ public class Segment implements ClassVisitor { segmentHeader.setDeflate_hint("true".equals(options .getDeflateHint())); } - + PackingUtils.log("Setup constant pool bands for the segment"); cpBands = new CpBands(this, effort); - + PackingUtils.log("Setup attribute definition bands for the segment"); attributeDefinitionBands = new AttributeDefinitionBands(this, effort, nonStandardAttributePrototypes); - + PackingUtils.log("Setup internal class bands for the segment"); icBands = new IcBands(segmentHeader, cpBands, effort); - + PackingUtils.log("Setup class bands for the segment"); classBands = new ClassBands(this, segmentUnit.classListSize(), effort, stripDebug); - + PackingUtils.log("Setup byte code bands for the segment"); bcBands = new BcBands(cpBands, this, effort); - + PackingUtils.log("Setup file bands for the segment"); fileBands = new FileBands(cpBands, segmentHeader, options, segmentUnit, effort); @@ -136,10 +136,10 @@ public class Segment implements ClassVisitor { headerOutputStream.writeTo(out); bandsOutputStream.writeTo(out); - + segmentUnit.addPackedByteAmount(headerOutputStream.size()); segmentUnit.addPackedByteAmount(bandsOutputStream.size()); - + PackingUtils.log("Wrote total of " + segmentUnit.getPackedByteAmount() + " bytes"); PackingUtils.log("Transmitted " + segmentUnit.fileListSize() + " files of " @@ -571,10 +571,6 @@ public class Segment implements ClassVisitor { Integer numCases = (Integer) caseArrayN.remove(caseArrayN.size() - 1); caseArrayN.add(new Integer(numCases.intValue() + 1)); T.add("e"); - if(name == null) { - name = ""; - } - nameRU.add(name); values.add(desc); values.add(value); } @@ -677,7 +673,7 @@ public class Segment implements ClassVisitor { * passed through as-is in the file_bands rather than being packed with * pack200. */ - public class PassException extends RuntimeException { + public static class PassException extends RuntimeException { } } diff --git a/src/main/java/org/apache/harmony/unpack200/MetadataBandGroup.java b/src/main/java/org/apache/harmony/unpack200/MetadataBandGroup.java index 49ae802..61b3a8e 100644 --- a/src/main/java/org/apache/harmony/unpack200/MetadataBandGroup.java +++ b/src/main/java/org/apache/harmony/unpack200/MetadataBandGroup.java @@ -22,6 +22,8 @@ import java.util.Iterator; import java.util.List; import org.apache.harmony.unpack200.bytecode.AnnotationDefaultAttribute; +import org.apache.harmony.unpack200.bytecode.AnnotationsAttribute.Annotation; +import org.apache.harmony.unpack200.bytecode.AnnotationsAttribute.ElementValue; import org.apache.harmony.unpack200.bytecode.Attribute; import org.apache.harmony.unpack200.bytecode.CPDouble; import org.apache.harmony.unpack200.bytecode.CPFloat; @@ -30,8 +32,6 @@ import org.apache.harmony.unpack200.bytecode.CPLong; import org.apache.harmony.unpack200.bytecode.CPUTF8; import org.apache.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleAnnotationsAttribute; import org.apache.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleParameterAnnotationsAttribute; -import org.apache.harmony.unpack200.bytecode.AnnotationsAttribute.Annotation; -import org.apache.harmony.unpack200.bytecode.AnnotationsAttribute.ElementValue; import org.apache.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleParameterAnnotationsAttribute.ParameterAnnotation; /** @@ -117,8 +117,6 @@ public class MetadataBandGroup { private int anno_N_Index; - private Iterator type_RS_Iterator; - private int pair_N_Index; public List getAttributes() { @@ -149,7 +147,6 @@ public class MetadataBandGroup { } } else if (type.equals("RVPA") || type.equals("RIPA")) { anno_N_Index = 0; - type_RS_Iterator = Arrays.asList(type_RS).iterator(); pair_N_Index = 0; for (int i = 0; i < param_NB.length; i++) { attributes.add(getParameterAttribute(param_NB[i], @@ -185,14 +182,13 @@ public class MetadataBandGroup { int[] pairCounts = pair_N[pair_N_Index++]; Annotation[] annotations = new Annotation[numAnnotations]; for (int j = 0; j < annotations.length; j++) { - annotations[j] = getAnnotation( - (CPUTF8) type_RS_Iterator.next(), pairCounts[j], - namesIterator); + annotations[j] = getAnnotation(type_RS[anno_N_Index - 1][j], + pairCounts[j], namesIterator); } parameter_annotations[i] = new ParameterAnnotation(annotations); } - return new RuntimeVisibleorInvisibleParameterAnnotationsAttribute(type - .equals("RVPA") ? rvpaUTF8 : ripaUTF8, + return new RuntimeVisibleorInvisibleParameterAnnotationsAttribute( + type.equals("RVPA") ? rvpaUTF8 : ripaUTF8, parameter_annotations); } diff --git a/src/test/java/org/apache/harmony/pack200/tests/ArchiveTest.java b/src/test/java/org/apache/harmony/pack200/tests/ArchiveTest.java index 4d87b23..6a414f3 100644 --- a/src/test/java/org/apache/harmony/pack200/tests/ArchiveTest.java +++ b/src/test/java/org/apache/harmony/pack200/tests/ArchiveTest.java @@ -344,7 +344,7 @@ public class ArchiveTest extends TestCase { compareFiles(jarFile, jarFile2); } - + public void testAnnotations2() throws IOException, Pack200Exception, URISyntaxException { in = new JarFile(new File(Archive.class.getResource( @@ -357,6 +357,22 @@ public class ArchiveTest extends TestCase { new Archive(in, out, options).pack(); in.close(); out.close(); + + // now unpack + InputStream in2 = new FileInputStream(file); + File file2 = File.createTempFile("annotationsout", ".jar"); + // file2.deleteOnExit(); + JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2)); + org.apache.harmony.unpack200.Archive archive = new org.apache.harmony.unpack200.Archive( + in2, out2); + archive.unpack(); + + // TODO: This isn't quite right - to fix +// JarFile jarFile = new JarFile(file2); +// JarFile jarFile2 = new JarFile(new File(Archive.class.getResource( +// "/org/apache/harmony/pack200/tests/annotations2unpacked.jar") +// .toURI())); +// compareFiles(jarFile, jarFile2); } public void testE0() throws Pack200Exception, IOException, URISyntaxException { diff --git a/src/test/java/org/apache/harmony/unpack200/tests/AttributeLayoutMapTest.java b/src/test/java/org/apache/harmony/unpack200/tests/AttributeLayoutMapTest.java index c0f4c6e..de6dd29 100644 --- a/src/test/java/org/apache/harmony/unpack200/tests/AttributeLayoutMapTest.java +++ b/src/test/java/org/apache/harmony/unpack200/tests/AttributeLayoutMapTest.java @@ -31,14 +31,15 @@ public class AttributeLayoutMapTest extends TestCase { AttributeLayout.CONTEXT_CLASS); assertNotNull(layout); assertEquals("RUNH", layout.getLayout()); + assertEquals(17, layout.getIndex()); // and that we can change it a.add(new AttributeLayout("SourceFile", AttributeLayout.CONTEXT_CLASS, - "FROG", 15)); + "FROG", 17)); layout = a.getAttributeLayout("SourceFile", AttributeLayout.CONTEXT_CLASS); assertNotNull(layout); assertEquals("FROG", layout.getLayout()); - assertTrue(layout.matches(1 << 15)); + assertTrue(layout.matches(1 << 17)); assertFalse(layout.matches(1 << 16)); assertTrue(layout.matches(-1)); assertFalse(layout.matches(0)); diff --git a/src/test/resources/org/apache/harmony/pack200/tests/annotations2unpacked.jar b/src/test/resources/org/apache/harmony/pack200/tests/annotations2unpacked.jar new file mode 100644 index 0000000000000000000000000000000000000000..d8e911264ac070b9e2a7653955420ca664a4b803 GIT binary patch literal 2919 zcmZ`*c{tQ-8=f&4VeFIC$r6!0G>C~B%VY^-iL#WPu?(5vSh5>izA+;uhKi^Zj$%_edEV#77(@1PfVRI3Yd)>=NS1{| zz+XgpC|J7%;IV!;0MC zUQY<$$}j4F%a4YJ#9_qk?`pU1M?(k8+q3(uf}rRis8kTt9S!B>xw9F3EK_I*%*@N<8mE@#Mh$x{kdH7J1Udk$Xsnyh zjx+y}n=h$>qxCFroX36T@7_)>M`MTuEh9!sU=**FPm$tP%8fh2`=6$S9^{xEiEqutyHNUu0;P{kGuC8D0$d?h`EK$RH zLk2Qki~VM4Yd@S>o?~v*uwWUJuXH+BRgV#Q9eEN5RAU< zKCD~^DLZ2+y#SlFMw)z}*)OHAWvVFBcZrPGW zHDM!y7_BPgJT|`p`#`cFP2#9Xi5Bw5Bi_o-#=)yPM;P%Iqfum&<^D%+&j0x-l{Bq6 zb}S!B9G1|YaVvbzCPGp8#IEgnQMssXJYwB<)_|~lWI%JJO6<4%`(qJ8$JO5Uxs}H2 z@L2u!_27j?LaR7N;79HLiMhznZy&cP**8Cr4Y?6F>+r zC(%U|o$^%k}7 zfFHVz^mzh*IM5$8@XnMPrZSZ9mR3i3@(zO-D_fE@udpqgwR>pBQ{90LYNg^U?7ZFv z>N{w%*!bVXvG(38MOiur`^>bJ`aYn=Xuc0Ks4GVyXgQ4PE#ldIb-DN`QHqJ#5q}X@ z+Zz{8=AE@i7`~6Ry{&OH-y?Q(=CrrUmd))P0aF#z6HPAHdh+1V5VUvPV7twjLPT4` zCHc|MA)!h0QkNs957Ib$HOBH1!&fpzh`7upWYUi*A-)XQuYt6!-uScRQ5nct`e*!P z*v2}mBS|iP#WnPtJuf54cpCDBBE)~?P`zD2<&@Nb*Gr|u%3Co{4k~iC^rmX3Jem)F zR`EE`)+hi?G z#D~pC1tARL)u=j}ONp=aP-h>@kfhF#<5S_h-(O@EfhC(1GwI4P1)}nAKNxPBDJ{E1 zAu?Vnur>BLM80KXmdCcv43@Hjr+_{=Kk#pKlq9*<1Gf`px4Q9l;q@eg+-@^ zw$O1~RlY2wO+Zsa*7MP$Az`GIWY_1}2jpvsJcqWVh`9%`K49reS>aaG(B9MJq03Ee z!FP(;DzFoxCKVx@-7;T2lf22*?5z8i>-9J}dkh2QY;J7YJDm{ zqn5nj&mURR2;3r=h2w7}ds`tu;*M`GWAtB!e{(=gxG}KZJ+1cgLpvGwvK>rDY2X(A z&xGuR@8u4d@MZwMr&riXvDeIHQWOJ&X}6{yHL;UpuQA5txC8m;P}_;z>q%lFVbGoW ze?Cw<;d`|v6Ryj~Y}DPT-G$CX$pQV%EPISGE06>T#18x@;4s+PK_E5|2BmAPqNMZ} DORIKR literal 0 HcmV?d00001