/** * Copyright (c) 2014 Eclipse contributorsand others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * stefan schalomon, msg-systems.com - Initial API and implementation */ package org.eclipse.emf.test.xml; import java.io.IOException; import java.io.OutputStream; import java.io.StringWriter; import java.io.Writer; import org.eclipse.emf.ecore.resource.URIConverter; import org.eclipse.emf.ecore.xmi.impl.XMLString; import org.junit.Test; public class XMLStringTest { /** * A test that causes {@link ArrayIndexOutOfBoundsException}. */ @Test public void testXMLString() throws Exception { XMLString doc = new XMLString(); // write XML with default encoding - this will resize // doc.outputchars to a length greater default BUFFER_SIZE, // doc.outputbytes is not used during this call writeDoc( doc, false, 5, 10, 1000 ); // now write a bigger XML with ASCII encoding - doc.outputbytes // will be initialized with default BUFFER_SIZE, that is, // doc.outputbytes.length < doc.outputchars.length which will // eventually trigger the ArrayIndexOutOfBoundsException writeDoc( doc, true, 20, 20, 1000 ); } /** * A test with overridden {@link XMLString} that fixes the AIOOBE bug. */ @Test public void testFixedXMLString() throws Exception { XMLString doc = new XMLString() { private static final long serialVersionUID = 1L; @Override public void writeAscii( OutputStream os, int flushThreshold ) throws IOException { int requiredLength = Math.max( BUFFER_SIZE, outputchars.length ); // ensure the byte and character buffers have the same length if( outputbytes == null || outputbytes.length < requiredLength ) { outputbytes = new byte[requiredLength]; } super.writeAscii( os, flushThreshold ); } }; writeDoc( doc, false, 5, 10, 1000 ); // with the fix above, the following call will work writeDoc( doc, true, 20, 20, 1000 ); } private void writeDoc( XMLString doc, boolean ascii, int elementCount, int attributeCount, int contentSize ) throws Exception { doc.reset( null, null, Integer.MAX_VALUE, null ); doc.startElement( "doc" ); for( int e = 1; e <= elementCount; e++ ) { StringBuilder content = new StringBuilder(); for( int c = 1; c <= contentSize; c++ ) { content.append( Long.toHexString( 0xBAADF00DDE7EC7EDL ) ); } doc.startElement( "elem" + e ); for( int a = 1; a <= attributeCount; a++ ) { doc.startAttribute( "attr" + a ); doc.addAttributeContent( "AttributeValue:" + content.toString() ); doc.endAttribute(); } doc.endContentElement( "ElementContent:" + content.toString() ); } doc.endElement(); StringWriter writer = new StringWriter(); if( ascii ) { doc.writeAscii( new URIConverter.WriteableOutputStream( writer, "ASCII"), Integer.MAX_VALUE ); } else { doc.write( (Writer) writer, Integer.MAX_VALUE ); } } }