JDK 1.6+ API baseline across the codebase

This commit is contained in:
Juergen Hoeller 2013-03-19 13:10:25 +01:00
parent 7331937511
commit 87e5f19c3f
5 changed files with 10 additions and 209 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2013 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -98,9 +98,6 @@ import org.springframework.util.StringUtils;
* <p>The common annotations supported by this post-processor are available in * <p>The common annotations supported by this post-processor are available in
* Java 6 (JDK 1.6) as well as in Java EE 5/6 (which provides a standalone jar for * Java 6 (JDK 1.6) as well as in Java EE 5/6 (which provides a standalone jar for
* its common annotations as well, allowing for use in any Java 5 based application). * its common annotations as well, allowing for use in any Java 5 based application).
* Hence, this post-processor works out of the box on JDK 1.6, and requires the
* JSR-250 API jar (and optionally the JAX-WS API jar and/or the EJB 3 API jar)
* to be added to the classpath on JDK 1.5 (when running outside of Java EE 5/6).
* *
* <p>For default usage, resolving resource names as Spring bean names, * <p>For default usage, resolving resource names as Spring bean names,
* simply define the following in your application context: * simply define the following in your application context:

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2013 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -33,7 +33,6 @@ import java.util.PropertyResourceBundle;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.core.JdkVersion;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -153,8 +152,6 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
* Set the default charset to use for parsing resource bundle files. * Set the default charset to use for parsing resource bundle files.
* <p>Default is none, using the {@code java.util.ResourceBundle} * <p>Default is none, using the {@code java.util.ResourceBundle}
* default encoding: ISO-8859-1. * default encoding: ISO-8859-1.
* <p><b>NOTE: Only works on JDK 1.6 and higher.</b> Consider using
* {@link ReloadableResourceBundleMessageSource} for JDK 1.5 support
* and more flexibility in setting of an encoding per file. * and more flexibility in setting of an encoding per file.
*/ */
public void setDefaultEncoding(String defaultEncoding) { public void setDefaultEncoding(String defaultEncoding) {
@ -170,8 +167,6 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
* {@code java.util.ResourceBundle}. However, this is often not desirable * {@code java.util.ResourceBundle}. However, this is often not desirable
* in an application server environment, where the system Locale is not relevant * in an application server environment, where the system Locale is not relevant
* to the application at all: Set this flag to "false" in such a scenario. * to the application at all: Set this flag to "false" in such a scenario.
* <p><b>NOTE: Only works on JDK 1.6 and higher.</b> Consider using
* {@link ReloadableResourceBundleMessageSource} for JDK 1.5 support.
*/ */
public void setFallbackToSystemLocale(boolean fallbackToSystemLocale) { public void setFallbackToSystemLocale(boolean fallbackToSystemLocale) {
this.fallbackToSystemLocale = fallbackToSystemLocale; this.fallbackToSystemLocale = fallbackToSystemLocale;
@ -193,10 +188,6 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
* Consider {@link ReloadableResourceBundleMessageSource} in combination * Consider {@link ReloadableResourceBundleMessageSource} in combination
* with resource bundle files in a non-classpath location. * with resource bundle files in a non-classpath location.
* </ul> * </ul>
* <p><b>NOTE: Only works on JDK 1.6 and higher.</b> Consider using
* {@link ReloadableResourceBundleMessageSource} for JDK 1.5 support
* and more flexibility in terms of the kinds of resources to load from
* (in particular from outside of the classpath where expiration works reliably).
*/ */
public void setCacheSeconds(int cacheSeconds) { public void setCacheSeconds(int cacheSeconds) {
this.cacheMillis = (cacheSeconds * 1000); this.cacheMillis = (cacheSeconds * 1000);
@ -318,13 +309,7 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
protected ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException { protected ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException {
if ((this.defaultEncoding != null && !"ISO-8859-1".equals(this.defaultEncoding)) || if ((this.defaultEncoding != null && !"ISO-8859-1".equals(this.defaultEncoding)) ||
!this.fallbackToSystemLocale || this.cacheMillis >= 0) { !this.fallbackToSystemLocale || this.cacheMillis >= 0) {
// Custom Control required... return ResourceBundle.getBundle(basename, locale, getBundleClassLoader(), new MessageSourceControl());
if (JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_16) {
throw new IllegalStateException("Cannot use 'defaultEncoding', 'fallbackToSystemLocale' and " +
"'cacheSeconds' on the standard ResourceBundleMessageSource when running on Java 5. " +
"Consider using ReloadableResourceBundleMessageSource instead.");
}
return new ControlBasedResourceBundleFactory().getBundle(basename, locale);
} }
else { else {
// Good old standard call... // Good old standard call...
@ -398,20 +383,6 @@ public class ResourceBundleMessageSource extends AbstractMessageSource implement
} }
/**
* Factory indirection for runtime isolation of the optional dependencv on
* Java 6's Control class.
* @see ResourceBundle#getBundle(String, java.util.Locale, ClassLoader, java.util.ResourceBundle.Control)
* @see MessageSourceControl
*/
private class ControlBasedResourceBundleFactory {
public ResourceBundle getBundle(String basename, Locale locale) {
return ResourceBundle.getBundle(basename, locale, getBundleClassLoader(), new MessageSourceControl());
}
}
/** /**
* Custom implementation of Java 6's {@code ResourceBundle.Control}, * Custom implementation of Java 6's {@code ResourceBundle.Control},
* adding support for custom file encodings, deactivating the fallback to the * adding support for custom file encodings, deactivating the fallback to the

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2013 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,7 +22,6 @@ import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.JdkVersion;
import org.springframework.core.task.TaskExecutor; import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -73,10 +72,7 @@ public class TaskExecutorFactoryBean implements
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
Class<?> executorClass = (shouldUseBackport() ? BeanWrapper bw = new BeanWrapperImpl(ThreadPoolTaskExecutor.class);
getClass().getClassLoader().loadClass("org.springframework.scheduling.backportconcurrent.ThreadPoolTaskExecutor") :
ThreadPoolTaskExecutor.class);
BeanWrapper bw = new BeanWrapperImpl(executorClass);
determinePoolSizeRange(bw); determinePoolSizeRange(bw);
if (this.queueCapacity != null) { if (this.queueCapacity != null) {
bw.setPropertyValue("queueCapacity", this.queueCapacity); bw.setPropertyValue("queueCapacity", this.queueCapacity);
@ -96,11 +92,6 @@ public class TaskExecutorFactoryBean implements
} }
} }
private boolean shouldUseBackport() {
return (StringUtils.hasText(this.poolSize) && this.poolSize.startsWith("0") &&
JdkVersion.getMajorJavaVersion() < JdkVersion.JAVA_16);
}
private void determinePoolSizeRange(BeanWrapper bw) { private void determinePoolSizeRange(BeanWrapper bw) {
if (StringUtils.hasText(this.poolSize)) { if (StringUtils.hasText(this.poolSize)) {
try { try {
@ -150,10 +141,7 @@ public class TaskExecutorFactoryBean implements
} }
public Class<? extends TaskExecutor> getObjectType() { public Class<? extends TaskExecutor> getObjectType() {
if (this.target != null) { return (this.target != null ? this.target.getClass() : ThreadPoolTaskExecutor.class);
return this.target.getClass();
}
return (!shouldUseBackport() ? ThreadPoolTaskExecutor.class : TaskExecutor.class);
} }
public boolean isSingleton() { public boolean isSingleton() {

View File

@ -16,15 +16,11 @@
package org.springframework.util; package org.springframework.util;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.Reader; import java.io.Reader;
import java.io.Writer; import java.io.Writer;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties; import java.util.Properties;
/** /**
@ -38,7 +34,7 @@ import java.util.Properties;
* *
* <p>Loading from and storing to a stream delegates to {@code Properties.load} * <p>Loading from and storing to a stream delegates to {@code Properties.load}
* and {@code Properties.store}, respectively, to be fully compatible with * and {@code Properties.store}, respectively, to be fully compatible with
* the Unicode conversion as implemented by the JDK Properties class. On JDK 1.6, * the Unicode conversion as implemented by the JDK Properties class. As of JDK 1.6,
* {@code Properties.load/store} will also be used for readers/writers, * {@code Properties.load/store} will also be used for readers/writers,
* effectively turning this class into a plain backwards compatibility adapter. * effectively turning this class into a plain backwards compatibility adapter.
* *
@ -57,166 +53,21 @@ import java.util.Properties;
*/ */
public class DefaultPropertiesPersister implements PropertiesPersister { public class DefaultPropertiesPersister implements PropertiesPersister {
// Determine whether Properties.load(Reader) is available (on JDK 1.6+)
private static final boolean loadFromReaderAvailable =
ClassUtils.hasMethod(Properties.class, "load", new Class[] {Reader.class});
// Determine whether Properties.store(Writer, String) is available (on JDK 1.6+)
private static final boolean storeToWriterAvailable =
ClassUtils.hasMethod(Properties.class, "store", new Class[] {Writer.class, String.class});
public void load(Properties props, InputStream is) throws IOException { public void load(Properties props, InputStream is) throws IOException {
props.load(is); props.load(is);
} }
public void load(Properties props, Reader reader) throws IOException { public void load(Properties props, Reader reader) throws IOException {
if (loadFromReaderAvailable) {
// On JDK 1.6+
props.load(reader); props.load(reader);
} }
else {
// Fall back to manual parsing.
doLoad(props, reader);
}
}
protected void doLoad(Properties props, Reader reader) throws IOException {
BufferedReader in = new BufferedReader(reader);
while (true) {
String line = in.readLine();
if (line == null) {
return;
}
line = StringUtils.trimLeadingWhitespace(line);
if (line.length() > 0) {
char firstChar = line.charAt(0);
if (firstChar != '#' && firstChar != '!') {
while (endsWithContinuationMarker(line)) {
String nextLine = in.readLine();
line = line.substring(0, line.length() - 1);
if (nextLine != null) {
line += StringUtils.trimLeadingWhitespace(nextLine);
}
}
int separatorIndex = line.indexOf("=");
if (separatorIndex == -1) {
separatorIndex = line.indexOf(":");
}
String key = (separatorIndex != -1 ? line.substring(0, separatorIndex) : line);
String value = (separatorIndex != -1) ? line.substring(separatorIndex + 1) : "";
key = StringUtils.trimTrailingWhitespace(key);
value = StringUtils.trimLeadingWhitespace(value);
props.put(unescape(key), unescape(value));
}
}
}
}
protected boolean endsWithContinuationMarker(String line) {
boolean evenSlashCount = true;
int index = line.length() - 1;
while (index >= 0 && line.charAt(index) == '\\') {
evenSlashCount = !evenSlashCount;
index--;
}
return !evenSlashCount;
}
protected String unescape(String str) {
StringBuilder result = new StringBuilder(str.length());
for (int index = 0; index < str.length();) {
char c = str.charAt(index++);
if (c == '\\') {
c = str.charAt(index++);
if (c == 't') {
c = '\t';
}
else if (c == 'r') {
c = '\r';
}
else if (c == 'n') {
c = '\n';
}
else if (c == 'f') {
c = '\f';
}
}
result.append(c);
}
return result.toString();
}
public void store(Properties props, OutputStream os, String header) throws IOException { public void store(Properties props, OutputStream os, String header) throws IOException {
props.store(os, header); props.store(os, header);
} }
public void store(Properties props, Writer writer, String header) throws IOException { public void store(Properties props, Writer writer, String header) throws IOException {
if (storeToWriterAvailable) {
// On JDK 1.6+
props.store(writer, header); props.store(writer, header);
} }
else {
// Fall back to manual parsing.
doStore(props, writer, header);
}
}
protected void doStore(Properties props, Writer writer, String header) throws IOException {
BufferedWriter out = new BufferedWriter(writer);
if (header != null) {
out.write("#" + header);
out.newLine();
}
out.write("#" + new Date());
out.newLine();
for (Enumeration keys = props.keys(); keys.hasMoreElements();) {
String key = (String) keys.nextElement();
String val = props.getProperty(key);
out.write(escape(key, true) + "=" + escape(val, false));
out.newLine();
}
out.flush();
}
protected String escape(String str, boolean isKey) {
int len = str.length();
StringBuilder result = new StringBuilder(len * 2);
for (int index = 0; index < len; index++) {
char c = str.charAt(index);
switch (c) {
case ' ':
if (index == 0 || isKey) {
result.append('\\');
}
result.append(' ');
break;
case '\\':
result.append("\\\\");
break;
case '\t':
result.append("\\t");
break;
case '\n':
result.append("\\n");
break;
case '\r':
result.append("\\r");
break;
case '\f':
result.append("\\f");
break;
default:
if ("=: \t\r\n\f#!".indexOf(c) != -1) {
result.append('\\');
}
result.append(c);
}
}
return result.toString();
}
public void loadFromXml(Properties props, InputStream is) throws IOException { public void loadFromXml(Properties props, InputStream is) throws IOException {
props.loadFromXML(is); props.loadFromXML(is);

View File

@ -22,7 +22,6 @@ import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.springframework.core.JdkVersion;
import org.springframework.dao.CannotAcquireLockException; import org.springframework.dao.CannotAcquireLockException;
import org.springframework.dao.CannotSerializeTransactionException; import org.springframework.dao.CannotSerializeTransactionException;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
@ -82,13 +81,8 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
* The SqlErrorCodes or DataSource property must be set. * The SqlErrorCodes or DataSource property must be set.
*/ */
public SQLErrorCodeSQLExceptionTranslator() { public SQLErrorCodeSQLExceptionTranslator() {
if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_16) {
setFallbackTranslator(new SQLExceptionSubclassTranslator()); setFallbackTranslator(new SQLExceptionSubclassTranslator());
} }
else {
setFallbackTranslator(new SQLStateSQLExceptionTranslator());
}
}
/** /**
* Create a SQL error code translator for the given DataSource. * Create a SQL error code translator for the given DataSource.