Skip to content

Commit 6d137b5

Browse files
committed
Construct StringWriter instances with appropriate initial size
Closes gh-25789
1 parent 01d86dc commit 6d137b5

File tree

7 files changed

+60
-48
lines changed

7 files changed

+60
-48
lines changed

spring-context-support/src/main/java/org/springframework/ui/freemarker/FreeMarkerTemplateUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ public abstract class FreeMarkerTemplateUtils {
4646
public static String processTemplateIntoString(Template template, Object model)
4747
throws IOException, TemplateException {
4848

49-
StringWriter result = new StringWriter();
49+
StringWriter result = new StringWriter(1024);
5050
template.process(model, result);
5151
return result.toString();
5252
}

spring-core/src/main/java/org/springframework/util/FileCopyUtils.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,6 +43,9 @@
4343
*/
4444
public abstract class FileCopyUtils {
4545

46+
/**
47+
* The default buffer size used when copying bytes.
48+
*/
4649
public static final int BUFFER_SIZE = StreamUtils.BUFFER_SIZE;
4750

4851

@@ -178,15 +181,15 @@ public static int copy(Reader in, Writer out) throws IOException {
178181
Assert.notNull(out, "No Writer specified");
179182

180183
try {
181-
int byteCount = 0;
184+
int charCount = 0;
182185
char[] buffer = new char[BUFFER_SIZE];
183-
int bytesRead = -1;
184-
while ((bytesRead = in.read(buffer)) != -1) {
185-
out.write(buffer, 0, bytesRead);
186-
byteCount += bytesRead;
186+
int charsRead;
187+
while ((charsRead = in.read(buffer)) != -1) {
188+
out.write(buffer, 0, charsRead);
189+
charCount += charsRead;
187190
}
188191
out.flush();
189-
return byteCount;
192+
return charCount;
190193
}
191194
finally {
192195
try {
@@ -203,7 +206,7 @@ public static int copy(Reader in, Writer out) throws IOException {
203206
}
204207

205208
/**
206-
* Copy the contents of the given String to the given output Writer.
209+
* Copy the contents of the given String to the given Writer.
207210
* Closes the writer when done.
208211
* @param in the String to copy from
209212
* @param out the Writer to copy to
@@ -237,7 +240,7 @@ public static String copyToString(@Nullable Reader in) throws IOException {
237240
return "";
238241
}
239242

240-
StringWriter out = new StringWriter();
243+
StringWriter out = new StringWriter(BUFFER_SIZE);
241244
copy(in, out);
242245
return out.toString();
243246
}

spring-core/src/main/java/org/springframework/util/StreamUtils.java

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -45,14 +45,17 @@
4545
*/
4646
public abstract class StreamUtils {
4747

48+
/**
49+
* The default buffer size used when copying bytes.
50+
*/
4851
public static final int BUFFER_SIZE = 4096;
4952

5053
private static final byte[] EMPTY_CONTENT = new byte[0];
5154

5255

5356
/**
5457
* Copy the contents of the given InputStream into a new byte array.
55-
* Leaves the stream open when done.
58+
* <p>Leaves the stream open when done.
5659
* @param in the stream to copy from (may be {@code null} or empty)
5760
* @return the new byte array that has been copied to (possibly empty)
5861
* @throws IOException in case of I/O errors
@@ -69,8 +72,9 @@ public static byte[] copyToByteArray(@Nullable InputStream in) throws IOExceptio
6972

7073
/**
7174
* Copy the contents of the given InputStream into a String.
72-
* Leaves the stream open when done.
75+
* <p>Leaves the stream open when done.
7376
* @param in the InputStream to copy from (may be {@code null} or empty)
77+
* @param charset the {@link Charset} to use to decode the bytes
7478
* @return the String that has been copied to (possibly empty)
7579
* @throws IOException in case of I/O errors
7680
*/
@@ -79,19 +83,19 @@ public static String copyToString(@Nullable InputStream in, Charset charset) thr
7983
return "";
8084
}
8185

82-
StringBuilder out = new StringBuilder();
86+
StringBuilder out = new StringBuilder(BUFFER_SIZE);
8387
InputStreamReader reader = new InputStreamReader(in, charset);
8488
char[] buffer = new char[BUFFER_SIZE];
85-
int bytesRead = -1;
86-
while ((bytesRead = reader.read(buffer)) != -1) {
87-
out.append(buffer, 0, bytesRead);
89+
int charsRead;
90+
while ((charsRead = reader.read(buffer)) != -1) {
91+
out.append(buffer, 0, charsRead);
8892
}
8993
return out.toString();
9094
}
9195

9296
/**
9397
* Copy the contents of the given byte array to the given OutputStream.
94-
* Leaves the stream open when done.
98+
* <p>Leaves the stream open when done.
9599
* @param in the byte array to copy from
96100
* @param out the OutputStream to copy to
97101
* @throws IOException in case of I/O errors
@@ -101,19 +105,20 @@ public static void copy(byte[] in, OutputStream out) throws IOException {
101105
Assert.notNull(out, "No OutputStream specified");
102106

103107
out.write(in);
108+
out.flush();
104109
}
105110

106111
/**
107-
* Copy the contents of the given String to the given output OutputStream.
108-
* Leaves the stream open when done.
112+
* Copy the contents of the given String to the given OutputStream.
113+
* <p>Leaves the stream open when done.
109114
* @param in the String to copy from
110115
* @param charset the Charset
111116
* @param out the OutputStream to copy to
112117
* @throws IOException in case of I/O errors
113118
*/
114119
public static void copy(String in, Charset charset, OutputStream out) throws IOException {
115120
Assert.notNull(in, "No input String specified");
116-
Assert.notNull(charset, "No charset specified");
121+
Assert.notNull(charset, "No Charset specified");
117122
Assert.notNull(out, "No OutputStream specified");
118123

119124
Writer writer = new OutputStreamWriter(out, charset);
@@ -123,7 +128,7 @@ public static void copy(String in, Charset charset, OutputStream out) throws IOE
123128

124129
/**
125130
* Copy the contents of the given InputStream to the given OutputStream.
126-
* Leaves both streams open when done.
131+
* <p>Leaves both streams open when done.
127132
* @param in the InputStream to copy from
128133
* @param out the OutputStream to copy to
129134
* @return the number of bytes copied
@@ -135,7 +140,7 @@ public static int copy(InputStream in, OutputStream out) throws IOException {
135140

136141
int byteCount = 0;
137142
byte[] buffer = new byte[BUFFER_SIZE];
138-
int bytesRead = -1;
143+
int bytesRead;
139144
while ((bytesRead = in.read(buffer)) != -1) {
140145
out.write(buffer, 0, bytesRead);
141146
byteCount += bytesRead;
@@ -167,7 +172,7 @@ public static long copyRange(InputStream in, OutputStream out, long start, long
167172
}
168173

169174
long bytesToCopy = end - start + 1;
170-
byte[] buffer = new byte[StreamUtils.BUFFER_SIZE];
175+
byte[] buffer = new byte[(int) Math.min(StreamUtils.BUFFER_SIZE, bytesToCopy)];
171176
while (bytesToCopy > 0) {
172177
int bytesRead = in.read(buffer);
173178
if (bytesRead == -1) {
@@ -187,7 +192,7 @@ else if (bytesRead <= bytesToCopy) {
187192

188193
/**
189194
* Drain the remaining content of the given InputStream.
190-
* Leaves the InputStream open when done.
195+
* <p>Leaves the InputStream open when done.
191196
* @param in the InputStream to drain
192197
* @return the number of bytes read
193198
* @throws IOException in case of I/O errors
@@ -257,7 +262,7 @@ public NonClosingOutputStream(OutputStream out) {
257262
@Override
258263
public void write(byte[] b, int off, int let) throws IOException {
259264
// It is critical that we override this method for performance
260-
out.write(b, off, let);
265+
this.out.write(b, off, let);
261266
}
262267

263268
@Override

spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -121,7 +121,7 @@ public void setTargetType(MessageType targetType) {
121121
/**
122122
* Specify the encoding to use when converting to and from text-based
123123
* message body content. The default encoding will be "UTF-8".
124-
* <p>When reading from a a text-based message, an encoding may have been
124+
* <p>When reading from a text-based message, an encoding may have been
125125
* suggested through a special JMS property which will then be preferred
126126
* over the encoding set on this MessageConverter instance.
127127
* @see #setEncodingPropertyName
@@ -267,13 +267,13 @@ protected Message toMessage(Object object, Session session, ObjectWriter objectW
267267
* @return the resulting message
268268
* @throws JMSException if thrown by JMS methods
269269
* @throws IOException in case of I/O errors
270-
* @see Session#createBytesMessage
271270
* @since 4.3
271+
* @see Session#createBytesMessage
272272
*/
273273
protected TextMessage mapToTextMessage(Object object, Session session, ObjectWriter objectWriter)
274274
throws JMSException, IOException {
275275

276-
StringWriter writer = new StringWriter();
276+
StringWriter writer = new StringWriter(1024);
277277
objectWriter.writeValue(writer, object);
278278
return session.createTextMessage(writer.toString());
279279
}
@@ -330,7 +330,7 @@ protected Message mapToMessage(Object object, Session session, ObjectWriter obje
330330
* sets the resulting value (either a mapped id or the raw Java class name)
331331
* into the configured type id message property.
332332
* @param object the payload object to set a type id for
333-
* @param message the JMS Message to set the type id on
333+
* @param message the JMS Message on which to set the type id property
334334
* @throws JMSException if thrown by JMS methods
335335
* @see #getJavaTypeForMessage(javax.jms.Message)
336336
* @see #setTypeIdPropertyName(String)
@@ -426,7 +426,7 @@ protected Object convertFromMessage(Message message, JavaType targetJavaType)
426426
* <p>The default implementation parses the configured type id property name
427427
* and consults the configured type id mapping. This can be overridden with
428428
* a different strategy, e.g. doing some heuristics based on message origin.
429-
* @param message the JMS Message to set the type id on
429+
* @param message the JMS Message from which to get the type id property
430430
* @throws JMSException if thrown by JMS methods
431431
* @see #setTypeIdOnMessage(Object, javax.jms.Message)
432432
* @see #setTypeIdPropertyName(String)
@@ -441,11 +441,11 @@ protected JavaType getJavaTypeForMessage(Message message) throws JMSException {
441441
}
442442
Class<?> mappedClass = this.idClassMappings.get(typeId);
443443
if (mappedClass != null) {
444-
return this.objectMapper.getTypeFactory().constructType(mappedClass);
444+
return this.objectMapper.constructType(mappedClass);
445445
}
446446
try {
447447
Class<?> typeClass = ClassUtils.forName(typeId, this.beanClassLoader);
448-
return this.objectMapper.getTypeFactory().constructType(typeClass);
448+
return this.objectMapper.constructType(typeClass);
449449
}
450450
catch (Throwable ex) {
451451
throw new MessageConversionException("Failed to resolve type id [" + typeId + "]", ex);

spring-jms/src/main/java/org/springframework/jms/support/converter/MarshallingMessageConverter.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -47,8 +47,6 @@
4747
* @author Arjen Poutsma
4848
* @author Juergen Hoeller
4949
* @since 3.0
50-
* @see org.springframework.jms.core.JmsTemplate#convertAndSend
51-
* @see org.springframework.jms.core.JmsTemplate#receiveAndConvert
5250
*/
5351
public class MarshallingMessageConverter implements MessageConverter, InitializingBean {
5452

@@ -214,7 +212,7 @@ else if (message instanceof BytesMessage) {
214212
protected TextMessage marshalToTextMessage(Object object, Session session, Marshaller marshaller)
215213
throws JMSException, IOException, XmlMappingException {
216214

217-
StringWriter writer = new StringWriter();
215+
StringWriter writer = new StringWriter(1024);
218216
Result result = new StreamResult(writer);
219217
marshaller.marshal(object, result);
220218
return session.createTextMessage(writer.toString());

spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -141,6 +141,7 @@ private void configurePrettyPrint() {
141141
}
142142
}
143143

144+
144145
@Override
145146
protected boolean canConvertFrom(Message<?> message, @Nullable Class<?> targetClass) {
146147
if (targetClass == null || !supportsMimeType(message.getHeaders())) {
@@ -223,6 +224,7 @@ protected Object convertFromInternal(Message<?> message, Class<?> targetClass, @
223224
}
224225
}
225226
else {
227+
// Assuming a text-based source payload
226228
if (view != null) {
227229
return this.objectMapper.readerWithView(view).forType(javaType).readValue(payload.toString());
228230
}
@@ -246,7 +248,7 @@ private JavaType getJavaType(Class<?> targetClass, @Nullable Object conversionHi
246248
Type genericParameterType = param.getNestedGenericParameterType();
247249
Class<?> contextClass = param.getContainingClass();
248250
Type type = GenericTypeResolver.resolveType(genericParameterType, contextClass);
249-
return this.objectMapper.getTypeFactory().constructType(type);
251+
return this.objectMapper.constructType(type);
250252
}
251253
return this.objectMapper.constructType(targetClass);
252254
}
@@ -271,7 +273,8 @@ protected Object convertToInternal(Object payload, @Nullable MessageHeaders head
271273
payload = out.toByteArray();
272274
}
273275
else {
274-
Writer writer = new StringWriter();
276+
// Assuming a text-based target payload
277+
Writer writer = new StringWriter(1024);
275278
if (view != null) {
276279
this.objectMapper.writerWithView(view).writeValue(writer, payload);
277280
}
@@ -330,7 +333,7 @@ private Class<?> extractViewClass(JsonView annotation, Object conversionHint) {
330333
* @return the JSON encoding to use (never {@code null})
331334
*/
332335
protected JsonEncoding getJsonEncoding(@Nullable MimeType contentType) {
333-
if (contentType != null && (contentType.getCharset() != null)) {
336+
if (contentType != null && contentType.getCharset() != null) {
334337
Charset charset = contentType.getCharset();
335338
for (JsonEncoding encoding : JsonEncoding.values()) {
336339
if (charset.name().equals(encoding.getJavaName())) {

spring-messaging/src/main/java/org/springframework/messaging/converter/MarshallingMessageConverter.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -46,6 +46,8 @@
4646
*
4747
* @author Arjen Poutsma
4848
* @since 4.2
49+
* @see Marshaller
50+
* @see Unmarshaller
4951
*/
5052
public class MarshallingMessageConverter extends AbstractMessageConverter {
5153

@@ -61,7 +63,8 @@ public class MarshallingMessageConverter extends AbstractMessageConverter {
6163
* {@link #setUnmarshaller(Unmarshaller)} to be invoked separately.
6264
*/
6365
public MarshallingMessageConverter() {
64-
this(new MimeType("application", "xml"), new MimeType("text", "xml"), new MimeType("application", "*+xml"));
66+
this(new MimeType("application", "xml"), new MimeType("text", "xml"),
67+
new MimeType("application", "*+xml"));
6568
}
6669

6770
/**
@@ -160,7 +163,7 @@ private Source getSource(Object payload) {
160163
return new StreamSource(new ByteArrayInputStream((byte[]) payload));
161164
}
162165
else {
163-
return new StreamSource(new StringReader((String) payload));
166+
return new StreamSource(new StringReader(payload.toString()));
164167
}
165168
}
166169

@@ -172,13 +175,13 @@ protected Object convertToInternal(Object payload, @Nullable MessageHeaders head
172175
Assert.notNull(this.marshaller, "Property 'marshaller' is required");
173176
try {
174177
if (byte[].class == getSerializedPayloadClass()) {
175-
ByteArrayOutputStream out = new ByteArrayOutputStream();
178+
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
176179
Result result = new StreamResult(out);
177180
this.marshaller.marshal(payload, result);
178181
payload = out.toByteArray();
179182
}
180183
else {
181-
Writer writer = new StringWriter();
184+
Writer writer = new StringWriter(1024);
182185
Result result = new StreamResult(writer);
183186
this.marshaller.marshal(payload, result);
184187
payload = writer.toString();

0 commit comments

Comments
 (0)