content: /*
   * Copyright 1999-2018 Alibaba Group Holding Ltd.
   *
   * 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 com.alibaba.druid.pool.ui;
  
  import com.alibaba.druid.TestUtil;
  import com.alibaba.druid.pool.DruidDataSource;
  
  import javax.management.ObjectName;
  import javax.swing.*;
  
  import java.awt.BorderLayout;
  import java.awt.Dimension;
  import java.awt.EventQueue;
  import java.awt.Toolkit;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.lang.management.ManagementFactory;
  import java.sql.Connection;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.sql.Statement;
  import java.text.NumberFormat;
  import java.util.concurrent.ConcurrentLinkedQueue;
  import java.util.concurrent.CountDownLatch;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
  import java.util.concurrent.atomic.AtomicInteger;
  
  public class DruidDataSourceUIManager extends JFrame {
      private static final long serialVersionUID = 1L;
  
      private DruidDataSource dataSource;
  
      private SpringLayout layout = new SpringLayout();
  
      private JButton btnInitDataSource = new JButton("Init Pool");
      private JButton btnCloseDataSource = new JButton("Close Pool");
      private JButton btnConnect = new JButton("Get Connection");
      private JButton btnClose = new JButton("Close Connection");
  
      private JButton btnCase_0 = new JButton("Case 0");
  
      private JPanel mainPanel = new JPanel();
      private JScrollPane scrollPane = new JScrollPane(mainPanel);
  
      private JLabel lbUrl = new JLabel("URL : ");
      private JTextField txtUrl = new JTextField(
              "jdbc:oracle:thin:@a.b.c.d:1521:ocndb");
  
      private JLabel lbDriverClass = new JLabel("DriverClassName : ");
      private JTextField txtDriverClass = new JTextField();
  
      private JLabel lbUser = new JLabel("User : ");
      private JTextField txtUser = new JTextField();
  
      private JLabel lbPassword = new JLabel("Password : ");
      private JTextField txtPassword = new JTextField();
  
      private JLabel lbConnectionProperties = new JLabel(
              "Connection Properties : ");
      private JTextField txtConnectionProperties = new JTextField();
  
      private JLabel lbInitialSize = new JLabel("InitialSize : ");
      private JTextField txtInitialSize = new JTextField("1");
  
      private JLabel lbMaxActive = new JLabel("MaxActive : ");
      private JTextField txtMaxActive = new JTextField("14");
  
      private JLabel lbMaxIdle = new JLabel("MaxIdle : ");
      private JTextField txtMaxIdle = new JTextField("14");
  
      private JLabel lbMinIdle = new JLabel("MinIdle : ");
      private JTextField txtMinIdle = new JTextField("1");
  
      private JLabel lbMaxWait = new JLabel("MaxWait : ");
      private JTextField txtMaxWait = new JTextField("-1");
  
      private JLabel lbMinEvictableIdleTimeMillis = new JLabel(
              "MinEvictableIdleTimeMillis : ");
      private JTextField txtMinEvictableIdleTimeMillis = new JTextField("1800000");
  
      private DruidDataStatusPanel statusPanel = new DruidDataStatusPanel();
  
      private JLabel lbValidationQuery = new JLabel("ValidationQuery : ");
      private JTextField txtValidationQuery = new JTextField("");
  
      private JLabel lbTestWhileIdle = new JLabel("TestWhileIdle : ");
      private JTextField txtTestWhileIdle = new JTextField("false");
  
      private JLabel lbTestOnBorrow = new JLabel("TestOnBorrow : ");
      private JTextField txtTestOnBorrow = new JTextField("false");
  
      private JTextField txtGetStep = new JTextField("1");
      private JTextField txtReleaseStep = new JTextField("1");
  
      private AtomicInteger connectingCount = new AtomicInteger();
      private AtomicInteger connectCount = new AtomicInteger();
      private AtomicInteger closeCount = new AtomicInteger();
      private AtomicInteger executingCount = new AtomicInteger();
  
      private Thread statusThread;
  
      private final ConcurrentLinkedQueue<Connection> activeConnections = new ConcurrentLinkedQueue<Connection>();
  
      private ExecutorService executor;
  
      public DruidDataSourceUIManager() {
          this.setLayout(new BorderLayout());
  
          Toolkit kit = Toolkit.getDefaultToolkit(); // 定义工具包
          Dimension screenSize = kit.getScreenSize(); // 获取屏幕的尺寸
          int screenWidth = screenSize.width / 2; // 获取屏幕的宽
          int screenHeight = screenSize.height / 2; // 获取屏幕的高
          int height = this.getHeight();
          int width = this.getWidth();
  
          setLocation(screenWidth - width / 2, screenHeight - height / 2);
  
          this.getContentPane().add(scrollPane, BorderLayout.CENTER);
  
          mainPanel.setLayout(layout);
  
          mainPanel.add(lbUrl);
          layout.putConstraint(SpringLayout.NORTH, lbUrl, 10, SpringLayout.NORTH, mainPanel);
          layout.putConstraint(SpringLayout.WEST, lbUrl, 10, SpringLayout.WEST, mainPanel);
          layout.putConstraint(SpringLayout.EAST, lbUrl, 200, SpringLayout.WEST, lbUrl);
  
          mainPanel.add(txtUrl);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtUrl, 0, SpringLayout.VERTICAL_CENTER, lbUrl);
          layout.putConstraint(SpringLayout.WEST, txtUrl, 10, SpringLayout.EAST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, txtUrl, -10, SpringLayout.EAST, mainPanel);
  
          // ////
  
          mainPanel.add(lbDriverClass);
          layout.putConstraint(SpringLayout.NORTH, lbDriverClass, 10, SpringLayout.SOUTH, lbUrl);
          layout.putConstraint(SpringLayout.WEST, lbDriverClass, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbDriverClass, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtDriverClass);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtDriverClass, 0, SpringLayout.VERTICAL_CENTER,
                  lbDriverClass);
          layout.putConstraint(SpringLayout.WEST, txtDriverClass, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtDriverClass, 0, SpringLayout.EAST, txtUrl);
  
          // ////
  
          mainPanel.add(lbUser);
          layout.putConstraint(SpringLayout.NORTH, lbUser, 10, SpringLayout.SOUTH, lbDriverClass);
          layout.putConstraint(SpringLayout.WEST, lbUser, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbUser, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtUser);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtUser, 0, SpringLayout.VERTICAL_CENTER, lbUser);
          layout.putConstraint(SpringLayout.WEST, txtUser, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtUser, 0, SpringLayout.EAST, txtUrl);
  
          // ////
  
          mainPanel.add(lbPassword);
          layout.putConstraint(SpringLayout.NORTH, lbPassword, 10, SpringLayout.SOUTH, lbUser);
          layout.putConstraint(SpringLayout.WEST, lbPassword, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbPassword, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtPassword);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtPassword, 0, SpringLayout.VERTICAL_CENTER, lbPassword);
          layout.putConstraint(SpringLayout.WEST, txtPassword, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtPassword, 0, SpringLayout.EAST, txtUrl);
  
          // ////
  
          mainPanel.add(lbConnectionProperties);
          layout.putConstraint(SpringLayout.NORTH, lbConnectionProperties, 10, SpringLayout.SOUTH, lbPassword);
          layout.putConstraint(SpringLayout.WEST, lbConnectionProperties, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbConnectionProperties, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtConnectionProperties);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtConnectionProperties, 0, SpringLayout.VERTICAL_CENTER,
                  lbConnectionProperties);
          layout.putConstraint(SpringLayout.WEST, txtConnectionProperties, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtConnectionProperties, 0, SpringLayout.EAST, txtUrl);
  
          // ////
  
          mainPanel.add(lbInitialSize);
          layout.putConstraint(SpringLayout.NORTH, lbInitialSize, 10, SpringLayout.SOUTH, lbConnectionProperties);
          layout.putConstraint(SpringLayout.WEST, lbInitialSize, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbInitialSize, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtInitialSize);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtInitialSize, 0, SpringLayout.VERTICAL_CENTER,
                  lbInitialSize);
          layout.putConstraint(SpringLayout.WEST, txtInitialSize, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtInitialSize, 0, SpringLayout.EAST, txtUrl);
  
          // ////
  
          mainPanel.add(lbMaxActive);
          layout.putConstraint(SpringLayout.NORTH, lbMaxActive, 10, SpringLayout.SOUTH, lbInitialSize);
          layout.putConstraint(SpringLayout.WEST, lbMaxActive, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbMaxActive, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtMaxActive);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtMaxActive, 0, SpringLayout.VERTICAL_CENTER, lbMaxActive);
          layout.putConstraint(SpringLayout.WEST, txtMaxActive, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtMaxActive, 0, SpringLayout.EAST, txtUrl);
  
          // ////
  
          mainPanel.add(lbMaxIdle);
          layout.putConstraint(SpringLayout.NORTH, lbMaxIdle, 10, SpringLayout.SOUTH, lbMaxActive);
          layout.putConstraint(SpringLayout.WEST, lbMaxIdle, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbMaxIdle, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtMaxIdle);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtMaxIdle, 0, SpringLayout.VERTICAL_CENTER, lbMaxIdle);
          layout.putConstraint(SpringLayout.WEST, txtMaxIdle, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtMaxIdle, 0, SpringLayout.EAST, txtUrl);
  
          // ////
  
          mainPanel.add(lbMinIdle);
          layout.putConstraint(SpringLayout.NORTH, lbMinIdle, 10, SpringLayout.SOUTH, lbMaxIdle);
          layout.putConstraint(SpringLayout.WEST, lbMinIdle, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbMinIdle, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtMinIdle);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtMinIdle, 0, SpringLayout.VERTICAL_CENTER, lbMinIdle);
          layout.putConstraint(SpringLayout.WEST, txtMinIdle, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtMinIdle, 0, SpringLayout.EAST, txtUrl);
  
          // ////
  
          mainPanel.add(lbMaxWait);
          layout.putConstraint(SpringLayout.NORTH, lbMaxWait, 10, SpringLayout.SOUTH, lbMinIdle);
          layout.putConstraint(SpringLayout.WEST, lbMaxWait, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbMaxWait, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtMaxWait);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtMaxWait, 0, SpringLayout.VERTICAL_CENTER, lbMaxWait);
          layout.putConstraint(SpringLayout.WEST, txtMaxWait, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtMaxWait, 0, SpringLayout.EAST, txtUrl);
  
          // ////
  
          mainPanel.add(lbMinEvictableIdleTimeMillis);
          layout.putConstraint(SpringLayout.NORTH, lbMinEvictableIdleTimeMillis, 10, SpringLayout.SOUTH, lbMaxWait);
          layout.putConstraint(SpringLayout.WEST, lbMinEvictableIdleTimeMillis, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbMinEvictableIdleTimeMillis, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtMinEvictableIdleTimeMillis);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtMinEvictableIdleTimeMillis, 0,
                  SpringLayout.VERTICAL_CENTER, lbMinEvictableIdleTimeMillis);
          layout.putConstraint(SpringLayout.WEST, txtMinEvictableIdleTimeMillis, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtMinEvictableIdleTimeMillis, 0, SpringLayout.EAST, txtUrl);
  
          // ////
  
          mainPanel.add(lbValidationQuery);
          layout.putConstraint(SpringLayout.NORTH, lbValidationQuery, 10, SpringLayout.SOUTH,
                  lbMinEvictableIdleTimeMillis);
          layout.putConstraint(SpringLayout.WEST, lbValidationQuery, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbValidationQuery, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtValidationQuery);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtValidationQuery, 0, SpringLayout.VERTICAL_CENTER,
                  lbValidationQuery);
          layout.putConstraint(SpringLayout.WEST, txtValidationQuery, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtValidationQuery, 0, SpringLayout.EAST, txtUrl);
          // ////
  
          mainPanel.add(lbTestWhileIdle);
          layout.putConstraint(SpringLayout.NORTH, lbTestWhileIdle, 10, SpringLayout.SOUTH, lbValidationQuery);
          layout.putConstraint(SpringLayout.WEST, lbTestWhileIdle, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbTestWhileIdle, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtTestWhileIdle);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtTestWhileIdle, 0, SpringLayout.VERTICAL_CENTER,
                  lbTestWhileIdle);
          layout.putConstraint(SpringLayout.WEST, txtTestWhileIdle, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtTestWhileIdle, 0, SpringLayout.EAST, txtUrl);
  
          mainPanel.add(lbTestOnBorrow);
          layout.putConstraint(SpringLayout.NORTH, lbTestOnBorrow, 10, SpringLayout.SOUTH, lbTestWhileIdle);
          layout.putConstraint(SpringLayout.WEST, lbTestOnBorrow, 0, SpringLayout.WEST, lbUrl);
          layout.putConstraint(SpringLayout.EAST, lbTestOnBorrow, 0, SpringLayout.EAST, lbUrl);
  
          mainPanel.add(txtTestOnBorrow);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtTestOnBorrow, 0, SpringLayout.VERTICAL_CENTER,
                  lbTestOnBorrow);
          layout.putConstraint(SpringLayout.WEST, txtTestOnBorrow, 0, SpringLayout.WEST, txtUrl);
          layout.putConstraint(SpringLayout.EAST, txtTestOnBorrow, 0, SpringLayout.EAST, txtUrl);
  
          // ////
  
          mainPanel.add(btnInitDataSource);
          layout.putConstraint(SpringLayout.NORTH, btnInitDataSource, 10, SpringLayout.SOUTH, lbTestOnBorrow);
          layout.putConstraint(SpringLayout.WEST, btnInitDataSource, 0, SpringLayout.WEST, lbUrl);
          btnInitDataSource.addActionListener(new ActionListener() {
              @Override
              public void actionPerformed(ActionEvent e) {
                  init_actionPerformed(e);
              }
          });
  
          mainPanel.add(btnCloseDataSource);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, btnCloseDataSource, 0, SpringLayout.VERTICAL_CENTER,
                  btnInitDataSource);
          layout.putConstraint(SpringLayout.WEST, btnCloseDataSource, 10, SpringLayout.EAST, btnInitDataSource);
          btnCloseDataSource.addActionListener(new ActionListener() {
              @Override
              public void actionPerformed(ActionEvent e) {
                  closeDataSource_actionPerformed(e);
              }
          });
          btnCloseDataSource.setEnabled(false);
          btnConnect.setEnabled(false);
          btnClose.setEnabled(false);
          btnCase_0.setEnabled(false);
  
          mainPanel.add(btnConnect);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, btnConnect, 0, SpringLayout.VERTICAL_CENTER,
                  btnInitDataSource);
          layout.putConstraint(SpringLayout.WEST, btnConnect, 10, SpringLayout.EAST, btnCloseDataSource);
          btnConnect.addActionListener(new ActionListener() {
              @Override
              public void actionPerformed(ActionEvent e) {
                  connect_actionPerformed(e);
              }
          });
  
          mainPanel.add(txtGetStep);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtGetStep, 0, SpringLayout.VERTICAL_CENTER,
                  btnInitDataSource);
          layout.putConstraint(SpringLayout.WEST, txtGetStep, 10, SpringLayout.EAST, btnConnect);
          layout.putConstraint(SpringLayout.EAST, txtGetStep, 40, SpringLayout.WEST, txtGetStep);
  
          // txtGetStep
  
          mainPanel.add(btnClose);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, btnClose, 0, SpringLayout.VERTICAL_CENTER, btnInitDataSource);
          layout.putConstraint(SpringLayout.WEST, btnClose, 10, SpringLayout.EAST, txtGetStep);
          btnClose.addActionListener(new ActionListener() {
              @Override
              public void actionPerformed(ActionEvent e) {
                  int step = Integer.parseInt(txtReleaseStep.getText().trim());
                  for (int i = 0; i < step; ++i) {
                      Connection conn = activeConnections.poll();
                      if (conn != null) {
                          try {
                              conn.close();
                              closeCount.incrementAndGet();
                          } catch (SQLException ex) {
                              ex.printStackTrace();
                          }
                      } else {
                          // System.out.println("close connection is null");
                      }
                  }
              }
          });
  
          mainPanel.add(txtReleaseStep);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtReleaseStep, 0, SpringLayout.VERTICAL_CENTER,
                  btnInitDataSource);
          layout.putConstraint(SpringLayout.WEST, txtReleaseStep, 10, SpringLayout.EAST, btnClose);
          layout.putConstraint(SpringLayout.EAST, txtReleaseStep, 40, SpringLayout.WEST, txtReleaseStep);
  
          mainPanel.add(btnCase_0);
          layout.putConstraint(SpringLayout.VERTICAL_CENTER, btnCase_0, 0, SpringLayout.VERTICAL_CENTER, txtReleaseStep);
          layout.putConstraint(SpringLayout.WEST, btnCase_0, 10, SpringLayout.EAST, txtReleaseStep);
          btnCase_0.addActionListener(new ActionListener() {
              @Override
              public void actionPerformed(ActionEvent e) {
                  try {
                      case_0();
                  } catch (Exception e1) {
                      // TODO Auto-generated catch block
                      e1.printStackTrace();
                  }
              }
          });
  
          // txtReleaseStep
  
          mainPanel.add(statusPanel);
          layout.putConstraint(SpringLayout.NORTH, statusPanel, 10, SpringLayout.SOUTH, btnInitDataSource);
          layout.putConstraint(SpringLayout.SOUTH, statusPanel, 120, SpringLayout.NORTH, statusPanel);
          layout.putConstraint(SpringLayout.WEST, statusPanel, 0, SpringLayout.WEST, lbUrl);
          // layout.putConstraint(SpringLayout.EAST, txtMaxWait, 0, SpringLayout.EAST, mainPanel);
  
          // ////
  
      }
  
      public void connect_actionPerformed(ActionEvent e) {
          int step = Integer.parseInt(txtGetStep.getText().trim());
          for (int i = 0; i < step; ++i) {
              final Runnable task = new Runnable() {
                  public void run() {
                      try {
                          connectingCount.incrementAndGet();
  
                          Connection conn = dataSource.getConnection();
  
                          connectCount.incrementAndGet();
                          connectingCount.decrementAndGet();
  
                          if (conn == null) {
                              System.out.println("get connection is null");
                              return;
                          }
  
                          executingCount.incrementAndGet();
                          try {
                              Statement stmt = conn.createStatement();
                              stmt.setQueryTimeout(5);
                              ResultSet rs = stmt.executeQuery("SELECT 1 FROM DUAL");
                              while (rs.next()) {
                                  rs.getObject(1);
                              }
                              Thread.sleep(1000 * 3);
                              rs.close();
                              stmt.close();
                          } finally {
                              executingCount.decrementAndGet();
                          }
  
                          activeConnections.add(conn);
                      } catch (Exception ex) {
                          ex.printStackTrace();
                      }
                  }
              };
              executor.submit(task);
          }
      }
  
      public void closeDataSource_actionPerformed(ActionEvent e) {
          dataSource.close();
  
          try {
              ManagementFactory.getPlatformMBeanServer().unregisterMBean(new ObjectName(
                      "com.alibaba.druid:type=DruidDataSource"));
          } catch (Exception e1) {
              e1.printStackTrace();
          }
  
          txtUrl.setEnabled(true);
          txtDriverClass.setEnabled(true);
          txtConnectionProperties.setEnabled(true);
          txtUser.setEnabled(true);
          txtPassword.setEnabled(true);
          txtInitialSize.setEnabled(true);
          txtMaxActive.setEnabled(true);
          txtMaxIdle.setEnabled(true);
          txtMinIdle.setEnabled(true);
          txtMaxWait.setEnabled(true);
          txtMinEvictableIdleTimeMillis.setEnabled(true);
  
          btnInitDataSource.setEnabled(true);
          btnCloseDataSource.setEnabled(false);
          btnConnect.setEnabled(false);
          btnClose.setEnabled(false);
          btnCase_0.setEnabled(false);
  
          statusThread.interrupt();
      }
  
      public void init_actionPerformed(ActionEvent e) {
          try {
              dataSource = new DruidDataSource();
              dataSource.setUrl(txtUrl.getText().trim());
              dataSource.setDriverClassName(txtDriverClass.getText().trim());
              dataSource.setConnectionProperties(txtConnectionProperties.getText().trim());
              dataSource.setUsername(txtUser.getText().trim());
              dataSource.setPassword(txtPassword.getText().trim());
              dataSource.setInitialSize(Integer.parseInt(txtInitialSize.getText().trim()));
              dataSource.setMaxActive(Integer.parseInt(txtMaxActive.getText().trim()));
              dataSource.setMaxIdle(Integer.parseInt(txtMaxIdle.getText().trim()));
              dataSource.setMinIdle(Integer.parseInt(txtMinIdle.getText().trim()));
              dataSource.setMaxWait(Integer.parseInt(txtMaxWait.getText().trim()));
              dataSource.setMinEvictableIdleTimeMillis(Integer.parseInt(txtMinEvictableIdleTimeMillis.getText().trim()));
              dataSource.setTestWhileIdle(Boolean.parseBoolean(txtTestWhileIdle.getText().trim()));
              dataSource.setTestOnBorrow(Boolean.parseBoolean(txtTestOnBorrow.getText().trim()));
  
              dataSource.setTimeBetweenEvictionRunsMillis(60000);
              dataSource.setNumTestsPerEvictionRun(20);
  
              ManagementFactory.getPlatformMBeanServer().registerMBean(dataSource,
                      new ObjectName(
                              "com.alibaba.druid:type=DruidDataSource"));
  
              try {
                  Connection conn = dataSource.getConnection();
                  connectCount.incrementAndGet();
                  conn.close();
                  closeCount.incrementAndGet();
              } catch (Exception ex) {
                  ex.printStackTrace();
              }
  
              executor = Executors.newCachedThreadPool();
  
              txtDriverClass.setText(dataSource.getDriverClassName());
              txtMinEvictableIdleTimeMillis.setText(Long.toString(dataSource.getMinEvictableIdleTimeMillis()));
  
              txtUrl.setEnabled(false);
              txtDriverClass.setEnabled(false);
              txtConnectionProperties.setEnabled(false);
              txtUser.setEnabled(false);
              txtPassword.setEnabled(false);
              txtInitialSize.setEnabled(false);
              txtMaxActive.setEnabled(false);
              txtMaxIdle.setEnabled(false);
              txtMinIdle.setEnabled(false);
              txtMaxWait.setEnabled(false);
              txtMinEvictableIdleTimeMillis.setEnabled(false);
  
              btnInitDataSource.setEnabled(false);
              btnCloseDataSource.setEnabled(true);
              btnConnect.setEnabled(true);
              btnClose.setEnabled(true);
              btnCase_0.setEnabled(true);
  
              statusThread = new Thread("Watch Status") {
                  public void run() {
                      for (; ; ) {
                          statusPanel.set("CreateCount", dataSource.getCreateCount());
                          statusPanel.set("CreateErrorCount", dataSource.getCreateErrorCount());
                          statusPanel.set("CreateTimespanMillis", dataSource.getCreateTimespanMillis());
                          statusPanel.set("CreateTimespanNano", dataSource.getCreateTimespanNano());
                          statusPanel.set("DestroyCount", dataSource.getDestroyCount());
                          statusPanel.set("ConnectCount", dataSource.getConnectCount());
                          statusPanel.set("ConnectErrorCount", dataSource.getConnectErrorCount());
                          statusPanel.set("CloseCount", dataSource.getCloseCount());
                          statusPanel.set("RecycleCount", dataSource.getRecycleCount());
                          statusPanel.set("ActiveCount", dataSource.getActiveCount());
                          statusPanel.set("PoolingCount", dataSource.getPoolingCount());
                          statusPanel.set("UI_GettingCount", connectingCount.get());
                          statusPanel.set("UI_GetCount", connectCount.get());
                          statusPanel.set("UI_ReleaseCount", closeCount.get());
                          statusPanel.set("UI_ExecutingCount", executingCount.get());
  
                          try {
                              Thread.sleep(100);
                          } catch (InterruptedException e) {
                              break;
                          }
                      }
                  }
              };
              statusThread.start();
          } catch (Exception ex) {
              ex.printStackTrace();
          }
      }
  
      public void case_0() throws Exception {
          Runnable task = new Runnable() {
              public void run() {
                  final int threadCount = 20;
                  final int LOOP_COUNT = 1000 * 1;
                  final String sql = "SELECT 1 FROM DUAL";
                  final CountDownLatch startLatch = new CountDownLatch(1);
                  final CountDownLatch endLatch = new CountDownLatch(threadCount);
                  for (int i = 0; i < threadCount; ++i) {
                      Thread thread = new Thread() {
                          public void run() {
                              try {
                                  startLatch.await();
  
                                  for (int i = 0; i < LOOP_COUNT; ++i) {
                                      Connection conn = dataSource.getConnection();
                                      Statement stmt = conn.createStatement();
                                      ResultSet rs = stmt.executeQuery(sql);
                                      while (rs.next()) {
                                          rs.getInt(1);
                                      }
                                      rs.close();
                                      stmt.close();
  
                                      Thread.sleep(1);
  
                                      conn.close();
                                  }
                              } catch (Exception ex) {
                                  ex.printStackTrace();
                              }
                              endLatch.countDown();
                          }
                      };
                      thread.start();
                  }
                  long startMillis = System.currentTimeMillis();
                  long startYGC = TestUtil.getYoungGC();
                  long startFullGC = TestUtil.getFullGC();
                  startLatch.countDown();
                  try {
                      endLatch.await();
                  } catch (InterruptedException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                  }
  
                  long millis = System.currentTimeMillis() - startMillis;
                  long ygc = TestUtil.getYoungGC() - startYGC;
                  long fullGC = TestUtil.getFullGC() - startFullGC;
  
                  System.out.println("thread " + threadCount + " druid millis : "
                          + NumberFormat.getInstance().format(millis) + ", YGC " + ygc + " FGC " + fullGC);
              }
          };
  
          executor.submit(task);
      }
  
      public static void main(String[] args) {
          EventQueue.invokeLater(new Runnable() {
              public void run() {
                  DruidDataSourceUIManager manager = new DruidDataSourceUIManager();
  
                  manager.pack();
                  manager.setSize(820, 580);
                  int w = (Toolkit.getDefaultToolkit().getScreenSize().width - manager.getWidth()) / 2;
                  int h = (Toolkit.getDefaultToolkit().getScreenSize().height - manager.getHeight()) / 2;
                  manager.setLocation(w, h);
  
                  manager.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  manager.setVisible(true);
              }
          });
      }
  }
  