    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *   http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 *
    017 */
    018
    019package org.apache.commons.dbcp2;
    020
    021import java.sql.Connection;
    022import java.sql.ResultSet;
    023import java.sql.Statement;
    024import java.text.MessageFormat;
    025import java.util.HashSet;
    026import java.util.Properties;
    027import java.util.ResourceBundle;
    028import java.util.Set;
    029
    030/**
    031 * Utility methods.
    032 *
    033 * @since 2.0
    034 */
    035public final class Utils {
    036
    037    private static final ResourceBundle messages = ResourceBundle
    038        .getBundle(Utils.class.getPackage().getName() + ".LocalStrings");
    039
    040    /**
    041     * Whether the security manager is enabled.
    042     */
    043    public static final boolean IS_SECURITY_ENABLED = System.getSecurityManager() != null;
    044
    045    /** Any SQL_STATE starting with this value is considered a fatal disconnect */
    046    public static final String DISCONNECTION_SQL_CODE_PREFIX = "08";
    047
    048    /**
    049     * SQL codes of fatal connection errors.
    050     * <ul>
    051     * <li>57P01 (Admin shutdown)</li>
    052     * <li>57P02 (Crash shutdown)</li>
    053     * <li>57P03 (Cannot connect now)</li>
    054     * <li>01002 (SQL92 disconnect error)</li>
    055     * <li>JZ0C0 (Sybase disconnect error)</li>
    056     * <li>JZ0C1 (Sybase disconnect error)</li>
    057     * </ul>
    058     */
    059    public static final Set<String> DISCONNECTION_SQL_CODES;
    060
    061    static {
    062        DISCONNECTION_SQL_CODES = new HashSet<>();
    063        DISCONNECTION_SQL_CODES.add("57P01"); // Admin shutdown
    064        DISCONNECTION_SQL_CODES.add("57P02"); // Crash shutdown
    065        DISCONNECTION_SQL_CODES.add("57P03"); // Cannot connect now
    066        DISCONNECTION_SQL_CODES.add("01002"); // SQL92 disconnect error
    067        DISCONNECTION_SQL_CODES.add("JZ0C0"); // Sybase disconnect error
    068        DISCONNECTION_SQL_CODES.add("JZ0C1"); // Sybase disconnect error
    069    }
    070
    071    /**
    072     * Clones the given char[] if not null.
    073     *
    074     * @param value may be null.
    075     * @return a cloned char[] or null.
    076     */
    077    public static char[] clone(final char[] value) {
    078        return value == null ? null : value.clone();
    079    }
    080
    081    /**
    082     * Clones the given {@link Properties} without the standard "user" or "password" entries.
    083     *
    084     * @param properties may be null
    085     * @return a clone of the input without the standard "user" or "password" entries.
    086     * @since 2.8.0
    087     */
    088    public static Properties cloneWithoutCredentials(final Properties properties) {
    089        if (properties != null) {
    090            Properties temp = (Properties) properties.clone();
    091            temp.remove("user");
    092            temp.remove("password");
    093            return temp;
    094        }
    095        return properties;
    096    }
    097
    098    /**
    099     * Closes the AutoCloseable (which may be null).
    100     *
    101     * @param autoCloseable an AutoCloseable, may be {@code null}
    102     * @since 2.6.0
    103     */
    104    public static void closeQuietly(final AutoCloseable autoCloseable) {
    105        if (autoCloseable != null) {
    106            try {
    107                autoCloseable.close();
    108            } catch (final Exception e) {
    109                // ignored
    110            }
    111        }
    112    }
    113
    114    /**
    115     * Closes the Connection (which may be null).
    116     *
    117     * @param connection a Connection, may be {@code null}
    118     * @deprecated Use {@link #closeQuietly(AutoCloseable)}.
    119     */
    120    @Deprecated
    121    public static void closeQuietly(final Connection connection) {
    122        if (connection != null) {
    123            try {
    124                connection.close();
    125            } catch (final Exception e) {
    126                // ignored
    127            }
    128        }
    129    }
    130
    131    /**
    132     * Closes the ResultSet (which may be null).
    133     *
    134     * @param resultSet a ResultSet, may be {@code null}
    135     * @deprecated Use {@link #closeQuietly(AutoCloseable)}.
    136     */
    137    @Deprecated
    138    public static void closeQuietly(final ResultSet resultSet) {
    139        if (resultSet != null) {
    140            try {
    141                resultSet.close();
    142            } catch (final Exception e) {
    143                // ignored
    144            }
    145        }
    146    }
    147
    148    /**
    149     * Closes the Statement (which may be null).
    150     *
    151     * @param statement a Statement, may be {@code null}.
    152     * @deprecated Use {@link #closeQuietly(AutoCloseable)}.
    153     */
    154    @Deprecated
    155    public static void closeQuietly(final Statement statement) {
    156        if (statement != null) {
    157            try {
    158                statement.close();
    159            } catch (final Exception e) {
    160                // ignored
    161            }
    162        }
    163    }
    164
    165    /**
    166     * Gets the correct i18n message for the given key.
    167     *
    168     * @param key The key to look up an i18n message.
    169     * @return The i18n message.
    170     */
    171    public static String getMessage(final String key) {
    172        return getMessage(key, (Object[]) null);
    173    }
    174
    175    /**
    176     * Gets the correct i18n message for the given key with placeholders replaced by the supplied arguments.
    177     *
    178     * @param key A message key.
    179     * @param args The message arguments.
    180     * @return An i18n message.
    181     */
    182    public static String getMessage(final String key, final Object... args) {
    183        final String msg = messages.getString(key);
    184        if (args == null || args.length == 0) {
    185            return msg;
    186        }
    187        final MessageFormat mf = new MessageFormat(msg);
    188        return mf.format(args, new StringBuffer(), null).toString();
    189    }
    190
    191    /**
    192     * Converts the given String to a char[].
    193     *
    194     * @param value may be null.
    195     * @return a char[] or null.
    196     */
    197    public static char[] toCharArray(final String value) {
    198        return value != null ? value.toCharArray() : null;
    199    }
    200
    201    /**
    202     * Converts the given char[] to a String.
    203     *
    204     * @param value may be null.
    205     * @return a String or null.
    206     */
    207    public static String toString(final char[] value) {
    208        return value == null ? null : String.valueOf(value);
    209    }
    210
    211    private Utils() {
    212        // not instantiable
    213    }
    214
    215}