Java tutorial
/* * Copyright 2016 Fumiharu Kinoshita * * Licensed 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 info.bunji.jdbc.logger; import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.naming.InitialContext; import javax.naming.NameClassPair; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.sql.DataSource; import info.bunji.jdbc.DriverEx; import info.bunji.jdbc.logger.impl.CommonsLoggingJdbcLogger; import info.bunji.jdbc.logger.impl.JdkJdbcLogger; import info.bunji.jdbc.logger.impl.Log4jJdbcLogger; import info.bunji.jdbc.logger.impl.Slf4jJdbcLogger; import net.arnx.jsonic.JSON; /** * logger factory. * <pre> * find a log implementation from class path. * * Search priority * 1. slf4j * 2. commons-logging * 3. log4j * 4. java.util.logging * * logging setting examples: * { * "_default_": { * timeThreshold": 0, * acceptFilter : ".*", * ignoreFilter : null, * historyCount : 30, * format : true, * connectionLogging : false * }, * * "jdbc:h2:tcp://localhost/~/test;SCHEMA=INFORMATION_SCHEMA": { * "timeThreshold": 0, * "acceptFilter": ".*", * "ignoreFilter": null, * "historyCount": 30, * "limmitLength": 100, * "format": true * } * } * </pre> * @author f.kinoshita */ public class JdbcLoggerFactory { private static final String SETTING_FILE = DriverEx.DRIVER_NAME + ".json"; private static final String DEFAULT_SETTING = "_default_"; private static final String DEFAULT_LOGGER = "_defaultLogger_"; private static Map<String, JdbcLogger> loggerCache = new HashMap<String, JdbcLogger>(); private static Map<String, String> dsNameMap = new HashMap<String, String>(); private Constructor<?> constructor; private static JdbcLoggerFactory instance = new JdbcLoggerFactory(); /** ???? */ private static Map<String, Map<String, Object>> settingMap = new HashMap<String, Map<String, Object>>(); static { InputStream is = null; try { // ??? is = JdbcLoggerFactory.class.getResourceAsStream("/" + SETTING_FILE); settingMap = JSON.decode(is); } catch (Throwable t) { // do nothihg. //System.out.println("jdbc logging setting load error. [" + t.getMessage() + "]"); } finally { try { if (is != null) is.close(); } catch (Exception e) { } } } /** ******************************************** * private constructor. ******************************************** */ private JdbcLoggerFactory() { // ?Logger? constructor = getLoggerConstructor(); } /** ******************************************** * find logger constructor. * * @return logger constructor ******************************************** */ private Constructor<?> getLoggerConstructor() { // ??Logging Map<String, Class<? extends JdbcLogger>> checkLogger = new LinkedHashMap<String, Class<? extends JdbcLogger>>() { { put("org.slf4j.Logger", Slf4jJdbcLogger.class); put("org.apache.commons.logging.Log", CommonsLoggingJdbcLogger.class); put("org.apache.log4j.Logger", Log4jJdbcLogger.class); put("java.util.logging.Logger", JdkJdbcLogger.class); } }; // find use logger Constructor<?> c = null; for (Entry<String, Class<? extends JdbcLogger>> entry : checkLogger.entrySet()) { try { Class.forName(entry.getKey()); c = entry.getValue().getConstructor(String.class); break; } catch (Throwable t) { printThrowable(t); } } return c; } private static JdbcLogger getLoggerInstance(String name) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { return (JdbcLogger) instance.constructor.newInstance(name); } /** ******************************************** * get loggerName from jdbc url. * * @param url connection url * @return loggerName(jdbc url or DataSourceName) ******************************************** */ private static String getLoggerName(String url) { if (!dsNameMap.containsKey(url)) { dsNameMap.put(url, url); // datasource???? InitialContext ctx = null; try { // JNDI?????? ctx = new InitialContext(); NamingEnumeration<NameClassPair> ne = ctx.list("java:comp/env/jdbc"); while (ne.hasMoreElements()) { NameClassPair nc = ne.nextElement(); DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/" + nc.getName()); // ?DataSource????getUrl() Method method = ds.getClass().getMethod("getUrl"); String dsUrl = (String) method.invoke(ds); if (dsUrl.startsWith(DriverEx.DRIVER_URL_PREFIX)) { dsUrl = dsUrl.replace(DriverEx.DRIVER_URL_PREFIX, "jdbc:"); if (dsUrl.equals(url)) { dsNameMap.put(url, nc.getName()); break; } } } } catch (Throwable t) { printThrowable(t); } finally { try { if (ctx != null) ctx.close(); } catch (NamingException e) { } } } return dsNameMap.get(url); } /** ******************************************** * get logger from jdbc url. * * @param url connection url * @return logger ******************************************** */ public static JdbcLogger getLogger(String url) { String name = getLoggerName(url); synchronized (loggerCache) { if (!hasLogger(name)) { try { loggerCache.put(name, getLoggerInstance(name)); if (settingMap.containsKey(DEFAULT_SETTING)) { // ???? loggerCache.get(name).setSetting(settingMap.get(DEFAULT_SETTING)); } loggerCache.get(name).setSetting(settingMap.get(name)); } catch (Throwable t) { printThrowable(t); } } } return loggerCache.get(name); } /** ******************************************** * URL????????? * * @param url URL * @return ???????true?????????false? ******************************************** */ private static boolean hasLogger(String url) { return loggerCache.containsKey(getLoggerName(url)); } /** ******************************************** * hss valid loggger (exclude default logger) * @return ******************************************** */ public static boolean hasValidLogger() { return loggerCache.size() > 1; } /** ******************************************** * get default logger. * * @return default logger ******************************************** */ public static JdbcLogger getLogger() { return getLogger(DEFAULT_LOGGER); } /** ******************************************** * get enable logger list(exclude default logger). * * @return logger list ******************************************** */ public static List<JdbcLogger> getLoggers() { List<JdbcLogger> loggers = new ArrayList<JdbcLogger>(); for (Entry<String, JdbcLogger> logger : loggerCache.entrySet()) { if (!logger.getKey().equals(DEFAULT_LOGGER)) { loggers.add(logger.getValue()); } } return loggers; } /** ******************************************** * get logger setting. * * @param loggerName loggerName * @return setting map ******************************************** */ public static Map<String, Object> getSetting(String loggerName) { return settingMap.get(loggerName); } private static void printThrowable(Throwable t) { //t.printStackTrace(); } }