freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [09/54] [partial] incubator-freemarker git commit: Top level package name change to org.apache.freemarker, and some of of the internal package structure changes. Other smaller cleanup. To be continued...
Date Thu, 16 Feb 2017 23:08:34 GMT
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/DateUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/DateUtil.java b/src/main/java/freemarker/template/utility/DateUtil.java
deleted file mode 100644
index 238da7a..0000000
--- a/src/main/java/freemarker/template/utility/DateUtil.java
+++ /dev/null
@@ -1,911 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.template.utility;
-
-import java.text.ParseException;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
-import java.util.TimeZone;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Date and time related utilities.
- */
-public class DateUtil {
-
-    /**
-     * Show hours (24h); always 2 digits, like {@code 00}, {@code 05}, etc.
-     */
-    public static final int ACCURACY_HOURS = 4;
-    
-    /**
-     * Show hours and minutes (even if minutes is 00).
-     */
-    public static final int ACCURACY_MINUTES = 5;
-    
-    /**
-     * Show hours, minutes and seconds (even if seconds is 00).
-     */
-    public static final int ACCURACY_SECONDS = 6;
-    
-    /**
-     * Show hours, minutes and seconds and up to 3 fraction second digits, without trailing 0-s in the fraction part. 
-     */
-    public static final int ACCURACY_MILLISECONDS = 7;
-    
-    /**
-     * Show hours, minutes and seconds and exactly 3 fraction second digits (even if it's 000)
-     */
-    public static final int ACCURACY_MILLISECONDS_FORCED = 8;
-    
-    public static final TimeZone UTC = TimeZone.getTimeZone("UTC");
-    
-    private static final String REGEX_XS_TIME_ZONE
-            = "Z|(?:[-+][0-9]{2}:[0-9]{2})";
-    private static final String REGEX_ISO8601_BASIC_TIME_ZONE
-            = "Z|(?:[-+][0-9]{2}(?:[0-9]{2})?)";
-    private static final String REGEX_ISO8601_EXTENDED_TIME_ZONE
-            = "Z|(?:[-+][0-9]{2}(?::[0-9]{2})?)";
-    
-    private static final String REGEX_XS_OPTIONAL_TIME_ZONE
-            = "(" + REGEX_XS_TIME_ZONE + ")?";
-    private static final String REGEX_ISO8601_BASIC_OPTIONAL_TIME_ZONE
-            = "(" + REGEX_ISO8601_BASIC_TIME_ZONE + ")?";
-    private static final String REGEX_ISO8601_EXTENDED_OPTIONAL_TIME_ZONE
-            = "(" + REGEX_ISO8601_EXTENDED_TIME_ZONE + ")?";
-    
-    private static final String REGEX_XS_DATE_BASE
-            = "(-?[0-9]+)-([0-9]{2})-([0-9]{2})";
-    private static final String REGEX_ISO8601_BASIC_DATE_BASE
-            = "(-?[0-9]{4,}?)([0-9]{2})([0-9]{2})";
-    private static final String REGEX_ISO8601_EXTENDED_DATE_BASE
-            = "(-?[0-9]{4,})-([0-9]{2})-([0-9]{2})";
-    
-    private static final String REGEX_XS_TIME_BASE
-            = "([0-9]{2}):([0-9]{2}):([0-9]{2})(?:\\.([0-9]+))?";
-    private static final String REGEX_ISO8601_BASIC_TIME_BASE
-            = "([0-9]{2})(?:([0-9]{2})(?:([0-9]{2})(?:[\\.,]([0-9]+))?)?)?";
-    private static final String REGEX_ISO8601_EXTENDED_TIME_BASE
-            = "([0-9]{2})(?::([0-9]{2})(?::([0-9]{2})(?:[\\.,]([0-9]+))?)?)?";
-        
-    private static final Pattern PATTERN_XS_DATE = Pattern.compile(
-            REGEX_XS_DATE_BASE + REGEX_XS_OPTIONAL_TIME_ZONE);
-    private static final Pattern PATTERN_ISO8601_BASIC_DATE = Pattern.compile(
-            REGEX_ISO8601_BASIC_DATE_BASE); // No time zone allowed here
-    private static final Pattern PATTERN_ISO8601_EXTENDED_DATE = Pattern.compile(
-            REGEX_ISO8601_EXTENDED_DATE_BASE); // No time zone allowed here
-
-    private static final Pattern PATTERN_XS_TIME = Pattern.compile(
-            REGEX_XS_TIME_BASE + REGEX_XS_OPTIONAL_TIME_ZONE);
-    private static final Pattern PATTERN_ISO8601_BASIC_TIME = Pattern.compile(
-            REGEX_ISO8601_BASIC_TIME_BASE + REGEX_ISO8601_BASIC_OPTIONAL_TIME_ZONE);
-    private static final Pattern PATTERN_ISO8601_EXTENDED_TIME = Pattern.compile(
-            REGEX_ISO8601_EXTENDED_TIME_BASE + REGEX_ISO8601_EXTENDED_OPTIONAL_TIME_ZONE);
-    
-    private static final Pattern PATTERN_XS_DATE_TIME = Pattern.compile(
-            REGEX_XS_DATE_BASE
-            + "T" + REGEX_XS_TIME_BASE
-            + REGEX_XS_OPTIONAL_TIME_ZONE);
-    private static final Pattern PATTERN_ISO8601_BASIC_DATE_TIME = Pattern.compile(
-            REGEX_ISO8601_BASIC_DATE_BASE
-            + "T" + REGEX_ISO8601_BASIC_TIME_BASE
-            + REGEX_ISO8601_BASIC_OPTIONAL_TIME_ZONE);
-    private static final Pattern PATTERN_ISO8601_EXTENDED_DATE_TIME = Pattern.compile(
-            REGEX_ISO8601_EXTENDED_DATE_BASE
-            + "T" + REGEX_ISO8601_EXTENDED_TIME_BASE
-            + REGEX_ISO8601_EXTENDED_OPTIONAL_TIME_ZONE);
-    
-    private static final Pattern PATTERN_XS_TIME_ZONE = Pattern.compile(
-            REGEX_XS_TIME_ZONE);
-    
-    private static final String MSG_YEAR_0_NOT_ALLOWED
-            = "Year 0 is not allowed in XML schema dates. BC 1 is -1, AD 1 is 1.";
-    
-    private DateUtil() {
-        // can't be instantiated
-    }
-    
-    /**
-     * Returns the time zone object for the name (or ID). This differs from
-     * {@link TimeZone#getTimeZone(String)} in that the latest returns GMT
-     * if it doesn't recognize the name, while this throws an
-     * {@link UnrecognizedTimeZoneException}.
-     * 
-     * @throws UnrecognizedTimeZoneException If the time zone name wasn't understood
-     */
-    public static TimeZone getTimeZone(String name)
-    throws UnrecognizedTimeZoneException {
-        if (isGMTish(name)) {
-            if (name.equalsIgnoreCase("UTC")) {
-                return UTC;
-            }
-            return TimeZone.getTimeZone(name);
-        }
-        TimeZone tz = TimeZone.getTimeZone(name);
-        if (isGMTish(tz.getID())) {
-            throw new UnrecognizedTimeZoneException(name);
-        }
-        return tz;
-    }
-
-    /**
-     * Tells if a offset or time zone is GMT. GMT is a fuzzy term, it used to
-     * referred both to UTC and UT1.
-     */
-    private static boolean isGMTish(String name) {
-        if (name.length() < 3) {
-            return false;
-        }
-        char c1 = name.charAt(0);
-        char c2 = name.charAt(1);
-        char c3 = name.charAt(2);
-        if (
-                !(
-                       (c1 == 'G' || c1 == 'g')
-                    && (c2 == 'M' || c2 == 'm')
-                    && (c3 == 'T' || c3 == 't')
-                )
-                &&
-                !(
-                       (c1 == 'U' || c1 == 'u')
-                    && (c2 == 'T' || c2 == 't')
-                    && (c3 == 'C' || c3 == 'c')
-                )
-                &&
-                !(
-                       (c1 == 'U' || c1 == 'u')
-                    && (c2 == 'T' || c2 == 't')
-                    && (c3 == '1')
-                )
-                ) {
-            return false;
-        }
-        
-        if (name.length() == 3) {
-            return true;
-        }
-        
-        String offset = name.substring(3);
-        if (offset.startsWith("+")) {
-            return offset.equals("+0") || offset.equals("+00")
-                    || offset.equals("+00:00");
-        } else {
-            return offset.equals("-0") || offset.equals("-00")
-            || offset.equals("-00:00");
-        }
-    }
-
-    /**
-     * Format a date, time or dateTime with one of the ISO 8601 extended
-     * formats that is also compatible with the XML Schema format (as far as you
-     * don't have dates in the BC era). Examples of possible outputs:
-     * {@code "2005-11-27T15:30:00+02:00"}, {@code "2005-11-27"},
-     * {@code "15:30:00Z"}. Note the {@code ":00"} in the time zone offset;
-     * this is not required by ISO 8601, but included for compatibility with
-     * the XML Schema format. Regarding the B.C. issue, those dates will be
-     * one year off when read back according the XML Schema format, because of a
-     * mismatch between that format and ISO 8601:2000 Second Edition.  
-     * 
-     * <p>This method is thread-safe.
-     * 
-     * @param date the date to convert to ISO 8601 string
-     * @param datePart whether the date part (year, month, day) will be included
-     *        or not
-     * @param timePart whether the time part (hours, minutes, seconds,
-     *        milliseconds) will be included or not
-     * @param offsetPart whether the time zone offset part will be included or
-     *        not. This will be shown as an offset to UTC (examples:
-     *        {@code "+01"}, {@code "-02"}, {@code "+04:30"}) or as {@code "Z"}
-     *        for UTC (and for UT1 and for GMT+00, since the Java platform
-     *        doesn't really care about the difference).
-     *        Note that this can't be {@code true} when {@code timePart} is
-     *        {@code false}, because ISO 8601 (2004) doesn't mention such
-     *        patterns.
-     * @param accuracy tells which parts of the date/time to drop. The
-     *        {@code datePart} and {@code timePart} parameters are stronger than
-     *        this. Note that when {@link #ACCURACY_MILLISECONDS} is specified,
-     *        the milliseconds part will be displayed as fraction seconds
-     *        (like {@code "15:30.00.25"}) with the minimum number of
-     *        digits needed to show the milliseconds without precision lose.
-     *        Thus, if the milliseconds happen to be exactly 0, no fraction
-     *        seconds will be shown at all.
-     * @param timeZone the time zone in which the date/time will be shown. (You
-     *        may find {@link DateUtil#UTC} handy here.) Note
-     *        that although date-only formats has no time zone offset part,
-     *        the result still depends on the time zone, as days start and end
-     *        at different points on the time line in different zones.      
-     * @param calendarFactory the factory that will create the calendar used
-     *        internally for calculations. The point of this parameter is that
-     *        creating a new calendar is relatively expensive, so it's desirable
-     *        to reuse calendars and only set their time and zone. (This was
-     *        tested on Sun JDK 1.6 x86 Win, where it gave 2x-3x speedup.) 
-     */
-    public static String dateToISO8601String(
-            Date date,
-            boolean datePart, boolean timePart, boolean offsetPart,
-            int accuracy,
-            TimeZone timeZone,
-            DateToISO8601CalendarFactory calendarFactory) {
-        return dateToString(date, datePart, timePart, offsetPart, accuracy, timeZone, false, calendarFactory);
-    }
-
-    /**
-     * Same as {@link #dateToISO8601String}, but gives XML Schema compliant format.
-     */
-    public static String dateToXSString(
-            Date date,
-            boolean datePart, boolean timePart, boolean offsetPart,
-            int accuracy,
-            TimeZone timeZone,
-            DateToISO8601CalendarFactory calendarFactory) {
-        return dateToString(date, datePart, timePart, offsetPart, accuracy, timeZone, true, calendarFactory);
-    }
-    
-    private static String dateToString(
-            Date date,
-            boolean datePart, boolean timePart, boolean offsetPart,
-            int accuracy,
-            TimeZone timeZone, boolean xsMode,
-            DateToISO8601CalendarFactory calendarFactory) {
-        if (!xsMode && !timePart && offsetPart) {
-            throw new IllegalArgumentException(
-                    "ISO 8601:2004 doesn't specify any formats where the "
-                    + "offset is shown but the time isn't.");
-        }
-        
-        if (timeZone == null) {
-            timeZone = UTC;
-        }
-        
-        GregorianCalendar cal = calendarFactory.get(timeZone, date);
-
-        int maxLength;
-        if (!timePart) {
-            maxLength = 10 + (xsMode ? 6 : 0);  // YYYY-MM-DD+00:00
-        } else {
-            if (!datePart) {
-                maxLength = 12 + 6;  // HH:MM:SS.mmm+00:00
-            } else {
-                maxLength = 10 + 1 + 12 + 6;
-            }
-        }
-        char[] res = new char[maxLength];
-        int dstIdx = 0;
-        
-        if (datePart) {
-            int x = cal.get(Calendar.YEAR);
-            if (x > 0 && cal.get(Calendar.ERA) == GregorianCalendar.BC) {
-                x = -x + (xsMode ? 0 : 1);
-            }
-            if (x >= 0 && x < 9999) {
-                res[dstIdx++] = (char) ('0' + x / 1000);
-                res[dstIdx++] = (char) ('0' + x % 1000 / 100);
-                res[dstIdx++] = (char) ('0' + x % 100 / 10);
-                res[dstIdx++] = (char) ('0' + x % 10);
-            } else {
-                String yearString = String.valueOf(x);
-                
-                // Re-allocate buffer:
-                maxLength = maxLength - 4 + yearString.length();
-                res = new char[maxLength];
-                
-                for (int i = 0; i < yearString.length(); i++) {
-                    res[dstIdx++] = yearString.charAt(i);
-                }
-            }
-    
-            res[dstIdx++] = '-';
-            
-            x = cal.get(Calendar.MONTH) + 1;
-            dstIdx = append00(res, dstIdx, x);
-    
-            res[dstIdx++] = '-';
-            
-            x = cal.get(Calendar.DAY_OF_MONTH);
-            dstIdx = append00(res, dstIdx, x);
-
-            if (timePart) {
-                res[dstIdx++] = 'T';
-            }
-        }
-
-        if (timePart) {
-            int x = cal.get(Calendar.HOUR_OF_DAY);
-            dstIdx = append00(res, dstIdx, x);
-    
-            if (accuracy >= ACCURACY_MINUTES) {
-                res[dstIdx++] = ':';
-        
-                x = cal.get(Calendar.MINUTE);
-                dstIdx = append00(res, dstIdx, x);
-        
-                if (accuracy >= ACCURACY_SECONDS) {
-                    res[dstIdx++] = ':';
-            
-                    x = cal.get(Calendar.SECOND);
-                    dstIdx = append00(res, dstIdx, x);
-            
-                    if (accuracy >= ACCURACY_MILLISECONDS) {
-                        x = cal.get(Calendar.MILLISECOND);
-                        int forcedDigits = accuracy == ACCURACY_MILLISECONDS_FORCED ? 3 : 0;
-                        if (x != 0 || forcedDigits != 0) {
-                            if (x > 999) {
-                                // Shouldn't ever happen...
-                                throw new RuntimeException(
-                                        "Calendar.MILLISECOND > 999");
-                            }
-                            res[dstIdx++] = '.';
-                            do {
-                                res[dstIdx++] = (char) ('0' + (x / 100));
-                                forcedDigits--;
-                                x = x % 100 * 10;
-                            } while (x != 0 || forcedDigits > 0);
-                        }
-                    }
-                }
-            }
-        }
-
-        if (offsetPart) {
-            if (timeZone == UTC) {
-                res[dstIdx++] = 'Z';
-            } else {
-                int dt = timeZone.getOffset(date.getTime());
-                boolean positive;
-                if (dt < 0) {
-                    positive = false;
-                    dt = -dt;
-                } else {
-                    positive = true;
-                }
-                
-                dt /= 1000;
-                int offS = dt % 60;
-                dt /= 60;
-                int offM = dt % 60;
-                dt /= 60;
-                int offH = dt;
-                
-                if (offS == 0 && offM == 0 && offH == 0) {
-                    res[dstIdx++] = 'Z';
-                } else {
-                    res[dstIdx++] = positive ? '+' : '-';
-                    dstIdx = append00(res, dstIdx, offH);
-                    res[dstIdx++] = ':';
-                    dstIdx = append00(res, dstIdx, offM);
-                    if (offS != 0) {
-                        res[dstIdx++] = ':';
-                        dstIdx = append00(res, dstIdx, offS);
-                    }
-                }
-            }
-        }
-        
-        return new String(res, 0, dstIdx);
-    }
-    
-    /** 
-     * Appends a number between 0 and 99 padded to 2 digits.
-     */
-    private static int append00(char[] res, int dstIdx, int x) {
-        res[dstIdx++] = (char) ('0' + x / 10);
-        res[dstIdx++] = (char) ('0' + x % 10);
-        return dstIdx;
-    }
-    
-    /**
-     * Parses an W3C XML Schema date string (not time or date-time).
-     * Unlike in ISO 8601:2000 Second Edition, year -1 means B.C 1, and year 0 is invalid. 
-     * 
-     * @param dateStr the string to parse. 
-     * @param defaultTimeZone used if the date doesn't specify the
-     *     time zone offset explicitly. Can't be {@code null}.
-     * @param calToDateConverter Used internally to calculate the result from the calendar field values.
-     *     If you don't have a such object around, you can just use
-     *     {@code new }{@link TrivialCalendarFieldsToDateConverter}{@code ()}. 
-     * 
-     * @throws DateParseException if the date is malformed, or if the time
-     *     zone offset is unspecified and the {@code defaultTimeZone} is
-     *     {@code null}.
-     */
-    public static Date parseXSDate(
-            String dateStr, TimeZone defaultTimeZone,
-            CalendarFieldsToDateConverter calToDateConverter) 
-            throws DateParseException {
-        Matcher m = PATTERN_XS_DATE.matcher(dateStr);
-        if (!m.matches()) {
-            throw new DateParseException("The value didn't match the expected pattern: " + PATTERN_XS_DATE); 
-        }
-        return parseDate_parseMatcher(
-                m, defaultTimeZone, true, calToDateConverter);
-    }
-
-    /**
-     * Same as {@link #parseXSDate(String, TimeZone, CalendarFieldsToDateConverter)}, but for ISO 8601 dates.
-     */
-    public static Date parseISO8601Date(
-            String dateStr, TimeZone defaultTimeZone,
-            CalendarFieldsToDateConverter calToDateConverter) 
-            throws DateParseException {
-        Matcher m = PATTERN_ISO8601_EXTENDED_DATE.matcher(dateStr);
-        if (!m.matches()) {
-            m = PATTERN_ISO8601_BASIC_DATE.matcher(dateStr);
-            if (!m.matches()) {
-                throw new DateParseException("The value didn't match the expected pattern: "
-                            + PATTERN_ISO8601_EXTENDED_DATE + " or "
-                            + PATTERN_ISO8601_BASIC_DATE);
-            }
-        }
-        return parseDate_parseMatcher(
-                m, defaultTimeZone, false, calToDateConverter);
-    }
-    
-    private static Date parseDate_parseMatcher(
-            Matcher m, TimeZone defaultTZ,
-            boolean xsMode,
-            CalendarFieldsToDateConverter calToDateConverter) 
-            throws DateParseException {
-        NullArgumentException.check("defaultTZ", defaultTZ);
-        try {
-            int year = groupToInt(m.group(1), "year", Integer.MIN_VALUE, Integer.MAX_VALUE);
-            
-            int era;
-            // Starting from ISO 8601:2000 Second Edition, 0001 is AD 1, 0000 is BC 1, -0001 is BC 2.
-            // However, according to http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/, XML schemas are based
-            // on the earlier version where 0000 didn't exist, and year -1 is BC 1.
-            if (year <= 0) {
-                era = GregorianCalendar.BC;
-                year = -year + (xsMode ? 0 : 1);
-                if (year == 0) {
-                    throw new DateParseException(MSG_YEAR_0_NOT_ALLOWED);
-                }
-            } else {
-                era = GregorianCalendar.AD;
-            }
-            
-            int month = groupToInt(m.group(2), "month", 1, 12) - 1;
-            int day = groupToInt(m.group(3), "day-of-month", 1, 31);
-
-            TimeZone tz = xsMode ? parseMatchingTimeZone(m.group(4), defaultTZ) : defaultTZ;
-            
-            return calToDateConverter.calculate(era, year, month, day, 0, 0, 0, 0, false, tz);
-        } catch (IllegalArgumentException e) {
-            // Calendar methods used to throw this for illegal dates.
-            throw new DateParseException(
-                    "Date calculation faliure. "
-                    + "Probably the date is formally correct, but refers "
-                    + "to an unexistent date (like February 30)."); 
-        }
-    }
-    
-    /**
-     * Parses an W3C XML Schema time string (not date or date-time).
-     * If the time string doesn't specify the time zone offset explicitly,
-     * the value of the {@code defaultTZ} paramter will be used. 
-     */  
-    public static Date parseXSTime(
-            String timeStr, TimeZone defaultTZ, CalendarFieldsToDateConverter calToDateConverter) 
-            throws DateParseException {
-        Matcher m = PATTERN_XS_TIME.matcher(timeStr);
-        if (!m.matches()) {
-            throw new DateParseException("The value didn't match the expected pattern: " + PATTERN_XS_TIME);
-        }
-        return parseTime_parseMatcher(m, defaultTZ, calToDateConverter);
-    }
-
-    /**
-     * Same as {@link #parseXSTime(String, TimeZone, CalendarFieldsToDateConverter)} but for ISO 8601 times.
-     */
-    public static Date parseISO8601Time(
-            String timeStr, TimeZone defaultTZ, CalendarFieldsToDateConverter calToDateConverter) 
-            throws DateParseException {
-        Matcher m = PATTERN_ISO8601_EXTENDED_TIME.matcher(timeStr);
-        if (!m.matches()) {
-            m = PATTERN_ISO8601_BASIC_TIME.matcher(timeStr);
-            if (!m.matches()) {
-                throw new DateParseException("The value didn't match the expected pattern: "
-                            + PATTERN_ISO8601_EXTENDED_TIME + " or "
-                            + PATTERN_ISO8601_BASIC_TIME);
-            }
-        }
-        return parseTime_parseMatcher(m, defaultTZ, calToDateConverter);
-    }
-    
-    private static Date parseTime_parseMatcher(
-            Matcher m, TimeZone defaultTZ,
-            CalendarFieldsToDateConverter calToDateConverter) 
-            throws DateParseException {
-        NullArgumentException.check("defaultTZ", defaultTZ);
-        try {
-            // ISO 8601 allows both 00:00 and 24:00,
-            // but Calendar.set(...) doesn't if the Calendar is not lenient.
-            int hours = groupToInt(m.group(1), "hour-of-day", 0, 24);
-            boolean hourWas24;
-            if (hours == 24) {
-                hours = 0;
-                hourWas24 = true;
-                // And a day will be added later...
-            } else {
-                hourWas24 = false;
-            }
-            
-            final String minutesStr = m.group(2);
-            int minutes = minutesStr != null ? groupToInt(minutesStr, "minute", 0, 59) : 0;
-            
-            final String secsStr = m.group(3);
-            // Allow 60 because of leap seconds
-            int secs = secsStr != null ? groupToInt(secsStr, "second", 0, 60) : 0;
-            
-            int millisecs = groupToMillisecond(m.group(4));
-            
-            // As a time is just the distance from the beginning of the day,
-            // the time-zone offest should be 0 usually.
-            TimeZone tz = parseMatchingTimeZone(m.group(5), defaultTZ);
-            
-            // Continue handling the 24:00 special case
-            int day;
-            if (hourWas24) {
-                if (minutes == 0 && secs == 0 && millisecs == 0) {
-                    day = 2;
-                } else {
-                    throw new DateParseException(
-                            "Hour 24 is only allowed in the case of "
-                            + "midnight."); 
-                }
-            } else {
-                day = 1;
-            }
-            
-            return calToDateConverter.calculate(
-                    GregorianCalendar.AD, 1970, 0, day, hours, minutes, secs, millisecs, false, tz);
-        } catch (IllegalArgumentException e) {
-            // Calendar methods used to throw this for illegal dates.
-            throw new DateParseException(
-                    "Unexpected time calculation faliure."); 
-        }
-    }
-    
-    /**
-     * Parses an W3C XML Schema date-time string (not date or time).
-     * Unlike in ISO 8601:2000 Second Edition, year -1 means B.C 1, and year 0 is invalid. 
-     * 
-     * @param dateTimeStr the string to parse. 
-     * @param defaultTZ used if the dateTime doesn't specify the
-     *     time zone offset explicitly. Can't be {@code null}. 
-     * 
-     * @throws DateParseException if the dateTime is malformed.
-     */
-    public static Date parseXSDateTime(
-            String dateTimeStr, TimeZone defaultTZ, CalendarFieldsToDateConverter calToDateConverter) 
-            throws DateParseException {
-        Matcher m = PATTERN_XS_DATE_TIME.matcher(dateTimeStr);
-        if (!m.matches()) {
-            throw new DateParseException(
-                    "The value didn't match the expected pattern: " + PATTERN_XS_DATE_TIME);
-        }
-        return parseDateTime_parseMatcher(
-                m, defaultTZ, true, calToDateConverter);
-    }
-
-    /**
-     * Same as {@link #parseXSDateTime(String, TimeZone, CalendarFieldsToDateConverter)} but for ISO 8601 format. 
-     */
-    public static Date parseISO8601DateTime(
-            String dateTimeStr, TimeZone defaultTZ, CalendarFieldsToDateConverter calToDateConverter) 
-            throws DateParseException {
-        Matcher m = PATTERN_ISO8601_EXTENDED_DATE_TIME.matcher(dateTimeStr);
-        if (!m.matches()) {
-            m = PATTERN_ISO8601_BASIC_DATE_TIME.matcher(dateTimeStr);
-            if (!m.matches()) {
-                throw new DateParseException("The value (" + dateTimeStr + ") didn't match the expected pattern: "
-                            + PATTERN_ISO8601_EXTENDED_DATE_TIME + " or "
-                            + PATTERN_ISO8601_BASIC_DATE_TIME);
-            }
-        }
-        return parseDateTime_parseMatcher(
-                m, defaultTZ, false, calToDateConverter);
-    }
-    
-    private static Date parseDateTime_parseMatcher(
-            Matcher m, TimeZone defaultTZ,
-            boolean xsMode,
-            CalendarFieldsToDateConverter calToDateConverter) 
-            throws DateParseException {
-        NullArgumentException.check("defaultTZ", defaultTZ);
-        try {
-            int year = groupToInt(m.group(1), "year", Integer.MIN_VALUE, Integer.MAX_VALUE);
-            
-            int era;
-            // Starting from ISO 8601:2000 Second Edition, 0001 is AD 1, 0000 is BC 1, -0001 is BC 2.
-            // However, according to http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/, XML schemas are based
-            // on the earlier version where 0000 didn't exist, and year -1 is BC 1.
-            if (year <= 0) {
-                era = GregorianCalendar.BC;
-                year = -year + (xsMode ? 0 : 1);
-                if (year == 0) {
-                    throw new DateParseException(MSG_YEAR_0_NOT_ALLOWED);
-                }
-            } else {
-                era = GregorianCalendar.AD;
-            }
-            
-            int month = groupToInt(m.group(2), "month", 1, 12) - 1;
-            int day = groupToInt(m.group(3), "day-of-month", 1, 31);
-            
-            // ISO 8601 allows both 00:00 and 24:00,
-            // but cal.set(...) doesn't if the Calendar is not lenient.
-            int hours = groupToInt(m.group(4), "hour-of-day", 0, 24);
-            boolean hourWas24;
-            if (hours == 24) {
-                hours = 0;
-                hourWas24 = true;
-                // And a day will be added later...
-            } else {
-                hourWas24 = false;
-            }
-            
-            final String minutesStr = m.group(5);
-            int minutes = minutesStr != null ? groupToInt(minutesStr, "minute", 0, 59) : 0;
-            
-            final String secsStr = m.group(6);
-            // Allow 60 because of leap seconds
-            int secs = secsStr != null ? groupToInt(secsStr, "second", 0, 60) : 0;
-            
-            int millisecs = groupToMillisecond(m.group(7));
-            
-            // As a time is just the distance from the beginning of the day,
-            // the time-zone offest should be 0 usually.
-            TimeZone tz = parseMatchingTimeZone(m.group(8), defaultTZ);
-            
-            // Continue handling the 24:00 specail case
-            if (hourWas24) {
-                if (minutes != 0 || secs != 0 || millisecs != 0) {
-                    throw new DateParseException(
-                            "Hour 24 is only allowed in the case of "
-                            + "midnight."); 
-                }
-            }
-            
-            return calToDateConverter.calculate(
-                    era, year, month, day, hours, minutes, secs, millisecs, hourWas24, tz);
-        } catch (IllegalArgumentException e) {
-            // Calendar methods used to throw this for illegal dates.
-            throw new DateParseException(
-                    "Date-time calculation faliure. "
-                    + "Probably the date-time is formally correct, but "
-                    + "refers to an unexistent date-time "
-                    + "(like February 30)."); 
-        }
-    }
-
-    /**
-     * Parses the time zone part from a W3C XML Schema date/time/dateTime. 
-     * @throws DateParseException if the zone is malformed.
-     */
-    public static TimeZone parseXSTimeZone(String timeZoneStr)
-            throws DateParseException {
-        Matcher m = PATTERN_XS_TIME_ZONE.matcher(timeZoneStr);
-        if (!m.matches()) {
-            throw new DateParseException(
-                    "The time zone offset didn't match the expected pattern: " + PATTERN_XS_TIME_ZONE);
-        }
-        return parseMatchingTimeZone(timeZoneStr, null);
-    }
-
-    private static int groupToInt(String g, String gName,
-            int min, int max)
-            throws DateParseException {
-        if (g == null) {
-            throw new DateParseException("The " + gName + " part "
-                    + "is missing.");
-        }
-
-        int start;
-        
-        // Remove minus sign, so we can remove the 0-s later:
-        boolean negative;
-        if (g.startsWith("-")) {
-            negative = true;
-            start = 1;
-        } else {
-            negative = false;
-            start = 0;
-        }
-        
-        // Remove leading 0-s:
-        while (start < g.length() - 1 && g.charAt(start) == '0') {
-            start++;
-        }
-        if (start != 0) {
-            g = g.substring(start);
-        }
-        
-        try {
-            int r = Integer.parseInt(g);
-            if (negative) {
-                r = -r;
-            }
-            if (r < min) {
-                throw new DateParseException("The " + gName + " part "
-                    + "must be at least " + min + ".");
-            }
-            if (r > max) {
-                throw new DateParseException("The " + gName + " part "
-                    + "can't be more than " + max + ".");
-            }
-            return r;
-        } catch (NumberFormatException e) {
-            throw new DateParseException("The " + gName + " part "
-                    + "is a malformed integer.");
-        }
-    }
-
-    private static TimeZone parseMatchingTimeZone(
-            String s, TimeZone defaultZone)
-            throws DateParseException {
-        if (s == null) {
-            return defaultZone;
-        }
-        if (s.equals("Z")) {
-            return DateUtil.UTC;
-        }
-        
-        StringBuilder sb = new StringBuilder(9);
-        sb.append("GMT");
-        sb.append(s.charAt(0));
-        
-        String h = s.substring(1, 3);
-        groupToInt(h, "offset-hours", 0, 23);
-        sb.append(h);
-        
-        String m;
-        int ln = s.length();
-        if (ln > 3) {
-            int startIdx = s.charAt(3) == ':' ? 4 : 3;
-            m = s.substring(startIdx, startIdx + 2);
-            groupToInt(m, "offset-minutes", 0, 59);
-            sb.append(':');
-            sb.append(m);
-        }
-        
-        return TimeZone.getTimeZone(sb.toString());
-    }
-
-    private static int groupToMillisecond(String g)
-            throws DateParseException {
-        if (g == null) {
-            return 0;
-        }
-        
-        if (g.length() > 3) {
-            g = g.substring(0, 3);
-        }
-        int i = groupToInt(g, "partial-seconds", 0, Integer.MAX_VALUE);
-        return g.length() == 1 ? i * 100 : (g.length() == 2 ? i * 10 : i);
-    }
-    
-    /**
-     * Used internally by {@link DateUtil}; don't use its implementations for
-     * anything else.
-     */
-    public interface DateToISO8601CalendarFactory {
-        
-        /**
-         * Returns a {@link GregorianCalendar} with the desired time zone and
-         * time and US locale. The returned calendar is used as read-only.
-         * It must be guaranteed that within a thread the instance returned last time
-         * is not in use anymore when this method is called again.
-         */
-        GregorianCalendar get(TimeZone tz, Date date);
-        
-    }
-
-    /**
-     * Used internally by {@link DateUtil}; don't use its implementations for anything else.
-     */
-    public interface CalendarFieldsToDateConverter {
-
-        /**
-         * Calculates the {@link Date} from the specified calendar fields.
-         */
-        Date calculate(int era, int year, int month, int day, int hours, int minutes, int secs, int millisecs,
-                boolean addOneDay,
-                TimeZone tz);
-
-    }
-
-    /**
-     * Non-thread-safe factory that hard-references a calendar internally.
-     */
-    public static final class TrivialDateToISO8601CalendarFactory
-            implements DateToISO8601CalendarFactory {
-        
-        private GregorianCalendar calendar;
-        private TimeZone lastlySetTimeZone;
-    
-        public GregorianCalendar get(TimeZone tz, Date date) {
-            if (calendar == null) {
-                calendar = new GregorianCalendar(tz, Locale.US);
-                calendar.setGregorianChange(new Date(Long.MIN_VALUE));  // never use Julian calendar
-            } else {
-                // At least on Java 6, calendar.getTimeZone is slow due to a bug, so we need lastlySetTimeZone.
-                if (lastlySetTimeZone != tz) {  // Deliberately `!=` instead of `!<...>.equals()`  
-                    calendar.setTimeZone(tz);
-                    lastlySetTimeZone = tz;
-                }
-            }
-            calendar.setTime(date);
-            return calendar;
-        }
-        
-    }
-
-    /**
-     * Non-thread-safe implementation that hard-references a calendar internally.
-     */
-    public static final class TrivialCalendarFieldsToDateConverter
-            implements CalendarFieldsToDateConverter {
-
-        private GregorianCalendar calendar;
-        private TimeZone lastlySetTimeZone;
-
-        public Date calculate(int era, int year, int month, int day, int hours, int minutes, int secs, int millisecs,
-                boolean addOneDay, TimeZone tz) {
-            if (calendar == null) {
-                calendar = new GregorianCalendar(tz, Locale.US);
-                calendar.setLenient(false);
-                calendar.setGregorianChange(new Date(Long.MIN_VALUE));  // never use Julian calendar
-            } else {
-                // At least on Java 6, calendar.getTimeZone is slow due to a bug, so we need lastlySetTimeZone.
-                if (lastlySetTimeZone != tz) {  // Deliberately `!=` instead of `!<...>.equals()`  
-                    calendar.setTimeZone(tz);
-                    lastlySetTimeZone = tz;
-                }
-            }
-
-            calendar.set(Calendar.ERA, era);
-            calendar.set(Calendar.YEAR, year);
-            calendar.set(Calendar.MONTH, month);
-            calendar.set(Calendar.DAY_OF_MONTH, day);
-            calendar.set(Calendar.HOUR_OF_DAY, hours);
-            calendar.set(Calendar.MINUTE, minutes);
-            calendar.set(Calendar.SECOND, secs);
-            calendar.set(Calendar.MILLISECOND, millisecs);
-            if (addOneDay) {
-                calendar.add(Calendar.DAY_OF_MONTH, 1);
-            }
-            
-            return calendar.getTime();
-        }
-
-    }
-    
-    public static final class DateParseException extends ParseException {
-        
-        public DateParseException(String message) {
-            super(message, 0);
-        }
-        
-    }
-        
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/DeepUnwrap.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/DeepUnwrap.java b/src/main/java/freemarker/template/utility/DeepUnwrap.java
deleted file mode 100644
index c35dd89..0000000
--- a/src/main/java/freemarker/template/utility/DeepUnwrap.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.template.utility;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import freemarker.core.Environment;
-import freemarker.ext.util.WrapperTemplateModel;
-import freemarker.template.AdapterTemplateModel;
-import freemarker.template.ObjectWrapper;
-import freemarker.template.TemplateBooleanModel;
-import freemarker.template.TemplateCollectionModel;
-import freemarker.template.TemplateDateModel;
-import freemarker.template.TemplateHashModelEx;
-import freemarker.template.TemplateModel;
-import freemarker.template.TemplateModelException;
-import freemarker.template.TemplateModelIterator;
-import freemarker.template.TemplateNumberModel;
-import freemarker.template.TemplateScalarModel;
-import freemarker.template.TemplateSequenceModel;
-
-/**
- * Utility methods for unwrapping {@link TemplateModel}-s.
- */
-public class DeepUnwrap {
-    private static final Class OBJECT_CLASS = Object.class;
-    /**
-     * Unwraps {@link TemplateModel}-s recursively.
-     * The converting of the {@link TemplateModel} object happens with the following rules:
-     * <ol>
-     *   <li>If the object implements {@link AdapterTemplateModel}, then the result
-     *       of {@link AdapterTemplateModel#getAdaptedObject(Class)} for <tt>Object.class</tt> is returned.
-     *   <li>If the object implements {@link WrapperTemplateModel}, then the result
-     *       of {@link WrapperTemplateModel#getWrappedObject()} is returned.
-     *   <li>If the object is identical to the null model of the current object 
-     *       wrapper, null is returned. 
-     *   <li>If the object implements {@link TemplateScalarModel}, then the result
-     *       of {@link TemplateScalarModel#getAsString()} is returned.
-     *   <li>If the object implements {@link TemplateNumberModel}, then the result
-     *       of {@link TemplateNumberModel#getAsNumber()} is returned.
-     *   <li>If the object implements {@link TemplateDateModel}, then the result
-     *       of {@link TemplateDateModel#getAsDate()} is returned.
-     *   <li>If the object implements {@link TemplateBooleanModel}, then the result
-     *       of {@link TemplateBooleanModel#getAsBoolean()} is returned.
-     *   <li>If the object implements {@link TemplateSequenceModel} or
-     *       {@link TemplateCollectionModel}, then a <code>java.util.ArrayList</code> is
-     *       constructed from the subvariables, and each subvariable is unwrapped with
-     *       the rules described here (recursive unwrapping).
-     *   <li>If the object implements {@link TemplateHashModelEx}, then a
-     *       <code>java.util.HashMap</code> is constructed from the subvariables, and each
-     *       subvariable is unwrapped with the rules described here (recursive unwrapping).
-     *   <li>Throw a <code>TemplateModelException</code>, because it doesn't know how to
-     *       unwrap the object.
-     * </ol>
-     */
-    public static Object unwrap(TemplateModel model) throws TemplateModelException {
-        return unwrap(model, false);
-    }
-
-    /**
-     * Same as {@link #unwrap(TemplateModel)}, but it doesn't throw exception 
-     * if it doesn't know how to unwrap the model, but rather returns it as-is.
-     * @since 2.3.14
-     */
-    public static Object permissiveUnwrap(TemplateModel model) throws TemplateModelException {
-        return unwrap(model, true);
-    }
-    
-    /**
-     * @deprecated the name of this method is mistyped. Use 
-     * {@link #permissiveUnwrap(TemplateModel)} instead.
-     */
-    @Deprecated
-    public static Object premissiveUnwrap(TemplateModel model) throws TemplateModelException {
-        return unwrap(model, true);
-    }
-    
-    private static Object unwrap(TemplateModel model, boolean permissive) throws TemplateModelException {
-        Environment env = Environment.getCurrentEnvironment();
-        TemplateModel nullModel = null;
-        if (env != null) {
-            ObjectWrapper wrapper = env.getObjectWrapper();
-            if (wrapper != null) {
-                nullModel = wrapper.wrap(null);
-            }
-        }
-        return unwrap(model, nullModel, permissive);
-    }
-
-    private static Object unwrap(TemplateModel model, TemplateModel nullModel, boolean permissive) throws TemplateModelException {
-        if (model instanceof AdapterTemplateModel) {
-            return ((AdapterTemplateModel) model).getAdaptedObject(OBJECT_CLASS);
-        }
-        if (model instanceof WrapperTemplateModel) {
-            return ((WrapperTemplateModel) model).getWrappedObject();
-        }
-        if (model == nullModel) {
-            return null;
-        }
-        if (model instanceof TemplateScalarModel) {
-            return ((TemplateScalarModel) model).getAsString();
-        }
-        if (model instanceof TemplateNumberModel) {
-            return ((TemplateNumberModel) model).getAsNumber();
-        }
-        if (model instanceof TemplateDateModel) {
-            return ((TemplateDateModel) model).getAsDate();
-        }
-        if (model instanceof TemplateBooleanModel) {
-            return Boolean.valueOf(((TemplateBooleanModel) model).getAsBoolean());
-        }
-        if (model instanceof TemplateSequenceModel) {
-            TemplateSequenceModel seq = (TemplateSequenceModel) model;
-            ArrayList list = new ArrayList(seq.size());
-            for (int i = 0; i < seq.size(); ++i) {
-                list.add(unwrap(seq.get(i), nullModel, permissive));
-            }
-            return list;
-        }
-        if (model instanceof TemplateCollectionModel) {
-            TemplateCollectionModel coll = (TemplateCollectionModel) model;
-            ArrayList list = new ArrayList();
-            TemplateModelIterator it = coll.iterator();            
-            while (it.hasNext()) {
-                list.add(unwrap(it.next(), nullModel, permissive));
-            }
-            return list;
-        }
-        if (model instanceof TemplateHashModelEx) {
-            TemplateHashModelEx hash = (TemplateHashModelEx) model;
-            HashMap map = new HashMap();
-            TemplateModelIterator keys = hash.keys().iterator();
-            while (keys.hasNext()) {
-                String key = (String) unwrap(keys.next(), nullModel, permissive); 
-                map.put(key, unwrap(hash.get(key), nullModel, permissive));
-            }
-            return map;
-        }
-        if (permissive) {
-            return model;
-        }
-        throw new TemplateModelException("Cannot deep-unwrap model of type " + model.getClass().getName());
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/HtmlEscape.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/HtmlEscape.java b/src/main/java/freemarker/template/utility/HtmlEscape.java
deleted file mode 100644
index 25bbee0..0000000
--- a/src/main/java/freemarker/template/utility/HtmlEscape.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.template.utility;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Map;
-
-import freemarker.template.TemplateTransformModel;
-
-/**
- * Performs an HTML escape of a given template fragment. Specifically,
- * &lt; &gt; &quot; and &amp; are all turned into entities.
- *
- * <p>Usage:<br>
- * From java:</p>
- * <pre>
- * SimpleHash root = new SimpleHash();
- *
- * root.put( "htmlEscape", new freemarker.template.utility.HtmlEscape() );
- *
- * ...
- * </pre>
- *
- * <p>From your FreeMarker template:</p>
- * <pre>
- *
- * The following is HTML-escaped:
- * &lt;transform htmlEscape&gt;
- *   &lt;p&gt;This paragraph has all HTML special characters escaped.&lt;/p&gt;
- * &lt;/transform&gt;
- *
- * ...
- * </pre>
- *
- * @see freemarker.template.utility.XmlEscape
- */
-public class HtmlEscape implements TemplateTransformModel {
-
-    private static final char[] LT = "&lt;".toCharArray();
-    private static final char[] GT = "&gt;".toCharArray();
-    private static final char[] AMP = "&amp;".toCharArray();
-    private static final char[] QUOT = "&quot;".toCharArray();
-
-    public Writer getWriter(final Writer out, Map args) {
-        return new Writer()
-        {
-            @Override
-            public void write(int c)
-            throws IOException {
-                switch(c)
-                {
-                    case '<': out.write(LT, 0, 4); break;
-                    case '>': out.write(GT, 0, 4); break;
-                    case '&': out.write(AMP, 0, 5); break;
-                    case '"': out.write(QUOT, 0, 6); break;
-                    default: out.write(c);
-                }
-            }
-
-            @Override
-            public void write(char cbuf[], int off, int len)
-            throws IOException {
-                int lastoff = off;
-                int lastpos = off + len;
-                for (int i = off; i < lastpos; i++) {
-                    switch (cbuf[i])
-                    {
-                        case '<': out.write(cbuf, lastoff, i - lastoff); out.write(LT, 0, 4); lastoff = i + 1; break;
-                        case '>': out.write(cbuf, lastoff, i - lastoff); out.write(GT, 0, 4); lastoff = i + 1; break;
-                        case '&': out.write(cbuf, lastoff, i - lastoff); out.write(AMP, 0, 5); lastoff = i + 1; break;
-                        case '"': out.write(cbuf, lastoff, i - lastoff); out.write(QUOT, 0, 6); lastoff = i + 1; break;
-                    }
-                }
-                int remaining = lastpos - lastoff;
-                if (remaining > 0) {
-                    out.write(cbuf, lastoff, remaining);
-                }
-            }
-            @Override
-            public void flush() throws IOException {
-                out.flush();
-            }
-
-            @Override
-            public void close() {
-            }
-        };
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/NormalizeNewlines.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/NormalizeNewlines.java b/src/main/java/freemarker/template/utility/NormalizeNewlines.java
deleted file mode 100644
index 7075c42..0000000
--- a/src/main/java/freemarker/template/utility/NormalizeNewlines.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.template.utility;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Map;
-
-import freemarker.template.TemplateTransformModel;
-
-/**
- * <p>Transformer that supports FreeMarker legacy behavior: all newlines appearing
- * within the transformed area will be transformed into the platform's default
- * newline. Unlike the old behavior, however, newlines generated by the data
- * model are also converted. Legacy behavior was to leave newlines in the
- * data model unaltered.</p>
- *
- * <p>Usage:<br>
- * From java:</p>
- * <pre>
- * SimpleHash root = new SimpleHash();
- *
- * root.put( "normalizeNewlines", new freemarker.template.utility.NormalizeNewlines() );
- *
- * ...
- * </pre>
- *
- * <p>From your FreeMarker template:</p>
- * <pre>
- * &lt;transform normalizeNewlines&gt;
- *   &lt;html&gt;
- *   &lt;head&gt;
- *   ...
- *   &lt;p&gt;This template has all newlines normalized to the current platform's
- *   default.&lt;/p&gt;
- *   ...
- *   &lt;/body&gt;
- *   &lt;/html&gt;
- * &lt;/transform&gt;
- * </pre>
- */
-public class NormalizeNewlines implements TemplateTransformModel {
-
-    public Writer getWriter(final Writer out,
-                            final Map args) {
-        final StringBuilder buf = new StringBuilder();
-        return new Writer() {
-            @Override
-            public void write(char cbuf[], int off, int len) {
-                buf.append(cbuf, off, len);
-            }
-
-            @Override
-            public void flush() throws IOException {
-                out.flush();
-            }
-
-            @Override
-            public void close() throws IOException {
-                StringReader sr = new StringReader(buf.toString());
-                StringWriter sw = new StringWriter();
-                transform(sr, sw);
-                out.write(sw.toString());
-            }
-        };
-    }
-
-    /**
-     * Performs newline normalization on FreeMarker output.
-     *
-     * @param in the input to be transformed
-     * @param out the destination of the transformation
-     */
-    public void transform(Reader in, Writer out) throws IOException {
-        BufferedReader br = (in instanceof BufferedReader)
-                            ? (BufferedReader) in
-                            : new BufferedReader(in);
-        PrintWriter pw = (out instanceof PrintWriter)
-                         ? (PrintWriter) out
-                         : new PrintWriter(out);
-        String line = br.readLine();
-        if (line != null) {
-            if ( line.length() > 0 ) {
-                pw.println(line);
-            }
-        }
-        while ((line = br.readLine()) != null) {
-            pw.println(line);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/NullArgumentException.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/NullArgumentException.java b/src/main/java/freemarker/template/utility/NullArgumentException.java
deleted file mode 100644
index 02268fd..0000000
--- a/src/main/java/freemarker/template/utility/NullArgumentException.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.template.utility;
-
-/**
- * Indicates that an argument that must be non-{@code null} was {@code null}. 
- * 
- * @since 2.3.20
- */
-public class NullArgumentException extends IllegalArgumentException {
-
-    public NullArgumentException() {
-        super("The argument can't be null");
-    }
-    
-    public NullArgumentException(String argumentName) {
-        super("The \"" + argumentName + "\" argument can't be null");
-    }
-
-    public NullArgumentException(String argumentName, String details) {
-        super("The \"" + argumentName + "\" argument can't be null. " + details);
-    }
-    
-    /**
-     * Convenience method to protect against a {@code null} argument.
-     */
-    public static void check(String argumentName, Object argumentValue) {
-        if (argumentValue == null) {
-            throw new NullArgumentException(argumentName);
-        }
-    }
-
-    /**
-     * @since 2.3.22
-     */
-    public static void check(Object argumentValue) {
-        if (argumentValue == null) {
-            throw new NullArgumentException();
-        }
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/NullWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/NullWriter.java b/src/main/java/freemarker/template/utility/NullWriter.java
deleted file mode 100644
index 878d4fa..0000000
--- a/src/main/java/freemarker/template/utility/NullWriter.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.template.utility;
-
-import java.io.IOException;
-import java.io.Writer;
-
-/**
- * A {@link Writer} that simply drops what it gets.
- * 
- * @since 2.3.20
- */
-public final class NullWriter extends Writer {
-    
-    public static final NullWriter INSTANCE = new NullWriter();
-    
-    /** Can't be instantiated; use {@link #INSTANCE}. */
-    private NullWriter() { }
-    
-    @Override
-    public void write(char[] cbuf, int off, int len) throws IOException {
-        // Do nothing
-    }
-
-    @Override
-    public void flush() throws IOException {
-        // Do nothing
-    }
-
-    @Override
-    public void close() throws IOException {
-        // Do nothing
-    }
-
-    @Override
-    public void write(int c) throws IOException {
-        // Do nothing
-    }
-
-    @Override
-    public void write(char[] cbuf) throws IOException {
-        // Do nothing
-    }
-
-    @Override
-    public void write(String str) throws IOException {
-        // Do nothing
-    }
-
-    @Override
-    public void write(String str, int off, int len) throws IOException {
-        // Do nothing
-    }
-
-    @Override
-    public Writer append(CharSequence csq) throws IOException {
-        // Do nothing
-        return this;
-    }
-
-    @Override
-    public Writer append(CharSequence csq, int start, int end) throws IOException {
-        // Do nothing
-        return this;
-    }
-
-    @Override
-    public Writer append(char c) throws IOException {
-        // Do nothing
-        return this;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/NumberUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/NumberUtil.java b/src/main/java/freemarker/template/utility/NumberUtil.java
deleted file mode 100644
index 39a9b3b..0000000
--- a/src/main/java/freemarker/template/utility/NumberUtil.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.template.utility;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-/**
- * Number- and math-related utilities.
- * 
- * @since 2.3.20
- */
-public class NumberUtil {
-
-    private static final BigDecimal BIG_DECIMAL_INT_MIN = BigDecimal.valueOf(Integer.MIN_VALUE);
-    private static final BigDecimal BIG_DECIMAL_INT_MAX = BigDecimal.valueOf(Integer.MAX_VALUE);
-    private static final BigInteger BIG_INTEGER_INT_MIN = BIG_DECIMAL_INT_MIN.toBigInteger();
-    private static final BigInteger BIG_INTEGER_INT_MAX = BIG_DECIMAL_INT_MAX.toBigInteger();
-
-    private NumberUtil() { }
-    
-    public static boolean isInfinite(Number num) {
-        if (num instanceof Double) {
-            return ((Double) num).isInfinite();
-        } else if (num instanceof Float) {
-            return ((Float) num).isInfinite();
-        } else if (isNonFPNumberOfSupportedClass(num)) {
-            return false;
-        } else {
-            throw new UnsupportedNumberClassException(num.getClass());
-        }           
-    }
-
-    public static boolean isNaN(Number num) {
-        if (num instanceof Double) {
-            return ((Double) num).isNaN();
-        } else if (num instanceof Float) {
-            return ((Float) num).isNaN();
-        } else if (isNonFPNumberOfSupportedClass(num)) {
-            return false;
-        } else {
-            throw new UnsupportedNumberClassException(num.getClass());
-        }           
-    }
-
-    /**
-     * @return -1 for negative, 0 for zero, 1 for positive.
-     * @throws ArithmeticException if the number is NaN
-     */
-    public static int getSignum(Number num) throws ArithmeticException {
-        if (num instanceof Integer) {
-            int n = ((Integer) num).intValue();
-            return n > 0 ? 1 : (n == 0 ? 0 : -1);
-        } else if (num instanceof BigDecimal) {
-            BigDecimal n = (BigDecimal) num;
-            return n.signum();
-        } else if (num instanceof Double) {
-            double n = ((Double) num).doubleValue();
-            if (n > 0) return 1;
-            else if (n == 0) return 0;
-            else if (n < 0) return -1;
-            else throw new ArithmeticException("The signum of " + n + " is not defined.");  // NaN
-        } else if (num instanceof Float) {
-            float n = ((Float) num).floatValue();
-            if (n > 0) return 1;
-            else if (n == 0) return 0;
-            else if (n < 0) return -1;
-            else throw new ArithmeticException("The signum of " + n + " is not defined.");  // NaN
-        } else if (num instanceof Long) {
-            long n = ((Long) num).longValue();
-            return n > 0 ? 1 : (n == 0 ? 0 : -1);
-        } else if (num instanceof Short) {
-            short n = ((Short) num).shortValue();
-            return n > 0 ? 1 : (n == 0 ? 0 : -1);
-        } else if (num instanceof Byte) {
-            byte n = ((Byte) num).byteValue();
-            return n > 0 ? 1 : (n == 0 ? 0 : -1);
-        } else if (num instanceof BigInteger) {
-            BigInteger n = (BigInteger) num;
-            return n.signum();
-        } else {
-            throw new UnsupportedNumberClassException(num.getClass());
-        }
-    }
-    
-    /**
-     * Tells if a {@link BigDecimal} stores a whole number. For example, it returns {@code true} for {@code 1.0000},
-     * but {@code false} for {@code 1.0001}.
-     * 
-     * @since 2.3.21
-     */
-    static public boolean isIntegerBigDecimal(BigDecimal bd) {
-        // [Java 1.5] Try to utilize BigDecimal.toXxxExact methods
-        return bd.scale() <= 0  // A fast check that whole numbers usually (not always) match
-               || bd.setScale(0, BigDecimal.ROUND_DOWN).compareTo(bd) == 0;  // This is rather slow
-        // Note that `bd.signum() == 0 || bd.stripTrailingZeros().scale() <= 0` was also tried for the last
-        // condition, but stripTrailingZeros was slower than setScale + compareTo.
-    }
-    
-    private static boolean isNonFPNumberOfSupportedClass(Number num) {
-        return num instanceof Integer || num instanceof BigDecimal || num instanceof Long
-                || num instanceof Short || num instanceof Byte || num instanceof BigInteger;
-    }
-
-    /**
-     * Converts a {@link Number} to {@code int} whose mathematical value is exactly the same as of the original number.
-     * 
-     * @throws ArithmeticException
-     *             if the conversion to {@code int} is not possible without losing precision or overflow/underflow.
-     * 
-     * @since 2.3.22
-     */
-    public static int toIntExact(Number num) {
-        if (num instanceof Integer || num instanceof Short || num instanceof Byte) {
-            return num.intValue();
-        } else if (num instanceof Long) {
-            final long n = num.longValue();
-            final int result = (int) n;
-            if (n != result) {
-                throw newLossyConverionException(num, Integer.class);
-            }
-            return result;
-        } else if (num instanceof Double || num instanceof Float) {
-            final double n = num.doubleValue();
-            if (n % 1 != 0 || n < Integer.MIN_VALUE || n > Integer.MAX_VALUE) {
-                throw newLossyConverionException(num, Integer.class);
-            }
-            return (int) n;
-        } else if (num instanceof BigDecimal) {
-            // [Java 1.5] Use BigDecimal.toIntegerExact()
-            BigDecimal n = (BigDecimal) num;
-            if (!isIntegerBigDecimal(n)
-                    || n.compareTo(BIG_DECIMAL_INT_MAX) > 0 || n.compareTo(BIG_DECIMAL_INT_MIN) < 0) {
-                throw newLossyConverionException(num, Integer.class);
-            }
-            return n.intValue();
-        } else if (num instanceof BigInteger) {
-            BigInteger n = (BigInteger) num;
-            if (n.compareTo(BIG_INTEGER_INT_MAX) > 0 || n.compareTo(BIG_INTEGER_INT_MIN) < 0) {
-                throw newLossyConverionException(num, Integer.class);
-            }
-            return n.intValue();
-        } else {
-            throw new UnsupportedNumberClassException(num.getClass());
-        }
-    }
-
-    private static ArithmeticException newLossyConverionException(Number fromValue, Class/*<Number>*/ toType) {
-        return new ArithmeticException(
-                "Can't convert " + fromValue + " to type " + ClassUtil.getShortClassName(toType) + " without loss.");
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/ObjectFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/ObjectFactory.java b/src/main/java/freemarker/template/utility/ObjectFactory.java
deleted file mode 100644
index 75571b4..0000000
--- a/src/main/java/freemarker/template/utility/ObjectFactory.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.template.utility;
-
-/**
- * Used for the trivial cases of the factory pattern. Has a generic type argument since 2.3.24.
- * 
- * @since 2.3.22
- */
-public interface ObjectFactory<T> {
-    
-    T createObject() throws Exception;
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/ObjectWrapperWithAPISupport.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/ObjectWrapperWithAPISupport.java b/src/main/java/freemarker/template/utility/ObjectWrapperWithAPISupport.java
deleted file mode 100644
index c139ffe..0000000
--- a/src/main/java/freemarker/template/utility/ObjectWrapperWithAPISupport.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.template.utility;
-
-import freemarker.template.ObjectWrapper;
-import freemarker.template.TemplateHashModel;
-import freemarker.template.TemplateModel;
-import freemarker.template.TemplateModelException;
-
-/**
- * <b>Experimental - subject to change:</b> Implemented by {@link ObjectWrapper}-s to help {@link TemplateModel}-s to
- * implement the {@code someValue?api} operation.
- * 
- * <p>
- * <b>Experimental status warning:</b> This interface is subject to change on non-backward compatible ways, hence, it
- * shouldn't be implemented outside FreeMarker yet.
- * 
- * @since 2.3.22
- */
-public interface ObjectWrapperWithAPISupport extends ObjectWrapper {
-
-    /**
-     * Wraps an object to a {@link TemplateModel} that exposes the object's "native" (usually, Java) API.
-     * 
-     * @param obj
-     *            The object for which the API model has to be returned. Shouldn't be {@code null}.
-     * 
-     * @return The {@link TemplateModel} through which the API of the object can be accessed. Can't be {@code null}.
-     * 
-     * @since 2.3.22
-     */
-    TemplateHashModel wrapAsAPI(Object obj) throws TemplateModelException;
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/OptimizerUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/OptimizerUtil.java b/src/main/java/freemarker/template/utility/OptimizerUtil.java
deleted file mode 100644
index 89af48e..0000000
--- a/src/main/java/freemarker/template/utility/OptimizerUtil.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.template.utility;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- */
-public class OptimizerUtil {
-    private static final BigInteger INTEGER_MIN = new BigInteger(Integer.toString(Integer.MIN_VALUE));
-    private static final BigInteger INTEGER_MAX = new BigInteger(Integer.toString(Integer.MAX_VALUE));
-    private static final BigInteger LONG_MIN = new BigInteger(Long.toString(Long.MIN_VALUE));
-    private static final BigInteger LONG_MAX = new BigInteger(Long.toString(Long.MAX_VALUE));
-
-    private OptimizerUtil() {
-    }
-    
-    public static List optimizeListStorage(List list) {
-        switch(list.size())
-        {
-            case 0:
-            {
-                return Collections.EMPTY_LIST;
-            }
-            case 1:
-            {
-                return Collections.singletonList(list.get(0));
-            }
-            default:
-            {
-                if (list instanceof ArrayList) {
-                    ((ArrayList) list).trimToSize();
-                }
-                return list;
-            }
-        }
-    }
-    
-    /**
-     * This is needed to reverse the extreme conversions in arithmetic 
-     * operations so that numbers can be meaningfully used with models that
-     * don't know what to do with a BigDecimal. Of course, this will make
-     * impossible for these models (i.e. Jython) to receive a BigDecimal even if 
-     * it was originally placed as such in the data model. However, since 
-     * arithmetic operations aggressively erase the information regarding the 
-     * original number type, we have no other choice to ensure expected operation
-     * in majority of cases.
-     */
-    public static Number optimizeNumberRepresentation(Number number) {
-        if (number instanceof BigDecimal) {
-            BigDecimal bd = (BigDecimal) number;
-            if (bd.scale() == 0) {
-                // BigDecimal -> BigInteger
-                number = bd.unscaledValue();
-            } else {
-                double d = bd.doubleValue();
-                if (d != Double.POSITIVE_INFINITY && d != Double.NEGATIVE_INFINITY) {
-                    // BigDecimal -> Double
-                    return Double.valueOf(d);
-                }
-            }
-        }
-        if (number instanceof BigInteger) {
-            BigInteger bi = (BigInteger) number;
-            if (bi.compareTo(INTEGER_MAX) <= 0 && bi.compareTo(INTEGER_MIN) >= 0) {
-                // BigInteger -> Integer
-                return Integer.valueOf(bi.intValue());
-            }
-            if (bi.compareTo(LONG_MAX) <= 0 && bi.compareTo(LONG_MIN) >= 0) {
-                // BigInteger -> Long
-                return Long.valueOf(bi.longValue());
-            }
-        }
-        return number;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/RichObjectWrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/RichObjectWrapper.java b/src/main/java/freemarker/template/utility/RichObjectWrapper.java
deleted file mode 100644
index f24f757..0000000
--- a/src/main/java/freemarker/template/utility/RichObjectWrapper.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.template.utility;
-
-import freemarker.template.ObjectWrapper;
-import freemarker.template.ObjectWrapperAndUnwrapper;
-
-/**
- * <b>Experimental - subject to change:</b> Union of the interfaces that a typical feature rich {@link ObjectWrapper} is
- * expected to implement.
- * 
- * <p>
- * <b>Experimental status warning:</b> This interface is subject to change on non-backward compatible ways, hence, it
- * shouldn't be implemented outside FreeMarker yet.
- * 
- * @since 2.3.22
- */
-public interface RichObjectWrapper extends ObjectWrapperAndUnwrapper, ObjectWrapperWithAPISupport {
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ecb4e230/src/main/java/freemarker/template/utility/SecurityUtilities.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/SecurityUtilities.java b/src/main/java/freemarker/template/utility/SecurityUtilities.java
deleted file mode 100644
index 95bcf4b..0000000
--- a/src/main/java/freemarker/template/utility/SecurityUtilities.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.template.utility;
-
-import java.security.AccessControlException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- */
-public class SecurityUtilities {
-    private static final Logger LOG = LoggerFactory.getLogger("freemarker.security");
-    private SecurityUtilities() {
-    }
-    
-    public static String getSystemProperty(final String key) {
-        return (String) AccessController.doPrivileged(
-            new PrivilegedAction()
-            {
-                @Override
-                public Object run() {
-                    return System.getProperty(key);
-                }
-            });
-    }
-
-    public static String getSystemProperty(final String key, final String defValue) {
-        try {
-            return (String) AccessController.doPrivileged(
-                new PrivilegedAction()
-                {
-                    @Override
-                    public Object run() {
-                        return System.getProperty(key, defValue);
-                    }
-                });
-        } catch (AccessControlException e) {
-            if (LOG.isWarnEnabled()) {
-                LOG.warn("Insufficient permissions to read system property " + 
-                        StringUtil.jQuoteNoXSS(key) + ", using default value " +
-                        StringUtil.jQuoteNoXSS(defValue));
-            }
-            return defValue;
-        }
-    }
-
-    public static Integer getSystemProperty(final String key, final int defValue) {
-        try {
-            return (Integer) AccessController.doPrivileged(
-                new PrivilegedAction()
-                {
-                    @Override
-                    public Object run() {
-                        return Integer.getInteger(key, defValue);
-                    }
-                });
-        } catch (AccessControlException e) {
-            if (LOG.isWarnEnabled()) {
-                LOG.warn("Insufficient permissions to read system property " + 
-                        StringUtil.jQuote(key) + ", using default value " + defValue);
-            }
-            return Integer.valueOf(defValue);
-        }
-    }
-}


Mime
View raw message