bug 59805: add LocaleUtil#resetUserTimeZone and #resetUserLocale methods that call ThreadLocal.remove to fix PermGen memory leaks for long-running threaded applications; patch from apptaro

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1751641 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Javen O'Neal 2016-07-06 09:23:34 +00:00
parent 83e27bd10c
commit 1766825f62
2 changed files with 37 additions and 7 deletions

View File

@ -85,6 +85,10 @@ public final class LocaleUtil {
public static TimeZone getUserTimeZone() { public static TimeZone getUserTimeZone() {
return userTimeZone.get(); return userTimeZone.get();
} }
public static void resetUserTimeZone() {
userTimeZone.remove();
}
/** /**
* Sets default user locale. * Sets default user locale.
@ -93,6 +97,10 @@ public final class LocaleUtil {
public static void setUserLocale(Locale locale) { public static void setUserLocale(Locale locale) {
userLocale.set(locale); userLocale.set(locale);
} }
public static void resetUserLocale() {
userLocale.remove();
}
/** /**
* @return the default user locale, defaults to {@link Locale#ROOT} * @return the default user locale, defaults to {@link Locale#ROOT}
@ -105,7 +113,7 @@ public final class LocaleUtil {
* @return a calendar for the user locale and time zone * @return a calendar for the user locale and time zone
*/ */
public static Calendar getLocaleCalendar() { public static Calendar getLocaleCalendar() {
return getLocaleCalendar(getUserTimeZone()); return getLocaleCalendar(getUserTimeZone());
} }
/** /**
@ -142,7 +150,7 @@ public final class LocaleUtil {
* @return a calendar for the user locale and time zone * @return a calendar for the user locale and time zone
*/ */
public static Calendar getLocaleCalendar(TimeZone timeZone) { public static Calendar getLocaleCalendar(TimeZone timeZone) {
return Calendar.getInstance(timeZone, getUserLocale()); return Calendar.getInstance(timeZone, getUserLocale());
} }
} }

View File

@ -19,29 +19,45 @@ package org.apache.poi.util;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotEquals;
import static org.junit.Assume.assumeFalse;
import java.util.Calendar; import java.util.Calendar;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
public class TestLocaleUtil { public class TestLocaleUtil {
// This unit test assumes that the user's locale isn't ja-JP and timezone isn't Asia/Tokyo
// If this is the case, change the values to something else
private static final Locale ja_JP = Locale.JAPAN; private static final Locale ja_JP = Locale.JAPAN;
private static final TimeZone TOKYO = TimeZone.getTimeZone("Asia/Tokyo"); private static final TimeZone TOKYO = TimeZone.getTimeZone("Asia/Tokyo");
private static final Calendar JAPAN_CALENDAR = Calendar.getInstance(TOKYO, ja_JP); private static final Calendar JAPAN_CALENDAR = Calendar.getInstance(TOKYO, ja_JP);
/**
* Reset the Locale to the user default before the test so that it isn't influenced
* by the LocaleUtil's state being changed by previous tests.
*
* Reset the Locale to the user default after the test so that it doesn't influence
* other tests.
*/
@Before @Before
public void setUp() { @After
@SuppressForbidden("implementation around default locales in POI")
public void reset() {
// clear the user locale and time zone so that tests do not interfere with each other // clear the user locale and time zone so that tests do not interfere with each other
// the other way and better way would be to run each test in its own thread since // the other way and better way would be to run each test in its own thread since
// LocaleUtil uses per-thread settings. // LocaleUtil uses per-thread settings.
// Helpful, but not ASL 2.0 licensed: // Helpful, but not ASL 2.0 licensed:
// http://www.codeaffine.com/2014/07/21/a-junit-rule-to-run-a-test-in-its-own-thread/ // http://www.codeaffine.com/2014/07/21/a-junit-rule-to-run-a-test-in-its-own-thread/
LocaleUtil.setUserLocale(Locale.GERMANY); LocaleUtil.setUserLocale(Locale.getDefault());
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("Europe/Berlin")); LocaleUtil.setUserTimeZone(TimeZone.getDefault());
assumeFalse(ja_JP.equals(LocaleUtil.getUserLocale()));
assumeFalse(TOKYO.equals(LocaleUtil.getUserTimeZone()));
} }
@Test @Test
@ -54,6 +70,9 @@ public class TestLocaleUtil {
LocaleUtil.setUserLocale(ja_JP); LocaleUtil.setUserLocale(ja_JP);
assertEquals(ja_JP, LocaleUtil.getUserLocale()); assertEquals(ja_JP, LocaleUtil.getUserLocale());
LocaleUtil.resetUserLocale();
assertEquals(DEFAULT_LOCALE, LocaleUtil.getUserLocale());
} }
@Test @Test
@ -85,15 +104,18 @@ public class TestLocaleUtil {
LocaleUtil.setUserLocale(ja_JP); LocaleUtil.setUserLocale(ja_JP);
LocaleUtil.setUserTimeZone(TOKYO); LocaleUtil.setUserTimeZone(TOKYO);
assertCalendarEquals(JAPAN_CALENDAR, LocaleUtil.getLocaleCalendar()); assertCalendarEquals(JAPAN_CALENDAR, LocaleUtil.getLocaleCalendar());
assertCalendarEquals(JAPAN_CALENDAR, LocaleUtil.getLocaleCalendar(TOKYO));
// FIXME: These might affect the time zone due to daylight savings: // FIXME: These might affect the time zone due to daylight savings:
//assertCalendarEquals(JAPAN_CALENDAR, LocaleUtil.getLocaleCalendar(2016, 01, 01)); //assertCalendarEquals(JAPAN_CALENDAR, LocaleUtil.getLocaleCalendar(2016, 00, 01));
//assertCalendarEquals(JAPAN_CALENDAR, LocaleUtil.getLocaleCalendar(2016, 01, 01, 00, 00, 00)); //assertCalendarEquals(JAPAN_CALENDAR, LocaleUtil.getLocaleCalendar(2016, 00, 01, 00, 00, 00));
} }
private static void assertCalendarNotEquals(Calendar expected, Calendar actual) { private static void assertCalendarNotEquals(Calendar expected, Calendar actual) {
// FIXME: add more tests to compare calendars, ignoring whether the dates are equal
assertNotEquals("time zone", expected.getTimeZone(), actual.getTimeZone()); assertNotEquals("time zone", expected.getTimeZone(), actual.getTimeZone());
} }
private static void assertCalendarEquals(Calendar expected, Calendar actual) { private static void assertCalendarEquals(Calendar expected, Calendar actual) {
// FIXME: add more tests to compare calendars, ignoring whether the set dates are equal
assertEquals("time zone", expected.getTimeZone(), actual.getTimeZone()); assertEquals("time zone", expected.getTimeZone(), actual.getTimeZone());
} }
} }