View Javadoc
1   /*
2    * Licensed under the GPL License. You may not use this file except in compliance with the License.
3    * You may obtain a copy of the License at
4    *
5    *   https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
6    *
7    * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
8    * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
9    * PURPOSE.
10   */
11  package psiprobe.beans.accessors;
12  
13  import java.sql.SQLException;
14  import java.util.List;
15  
16  import psiprobe.model.DataSourceInfo;
17  
18  /**
19   * Datasource accessor for Flexy Pool wrappers.
20   */
21  public class FlexyPoolDatasourceAccessor implements DatasourceAccessor {
22  
23    /** The Constant flexyPoolDataSourceClassName. */
24    private static final String FLEXY_POOL_DATASOURCE_CLASS_NAME =
25        "com.vladmihalcea.flexypool.FlexyPoolDataSource";
26  
27    /** The Constant delegateAccessorClassNames. */
28    private static final List<String> DELEGATE_ACCESSOR_CLASS_NAMES =
29        List.of("psiprobe.beans.accessors.C3P0DatasourceAccessor",
30            "psiprobe.beans.accessors.Dbcp2DatasourceAccessor",
31            "psiprobe.beans.accessors.HikariCpDatasourceAccessor",
32            "psiprobe.beans.accessors.OracleDatasourceAccessor",
33            "psiprobe.beans.accessors.OracleUcpDatasourceAccessor",
34            "psiprobe.beans.accessors.OpenEjbBasicDatasourceAccessor",
35            "psiprobe.beans.accessors.OpenEjbManagedDatasourceAccessor",
36            "psiprobe.beans.accessors.Tomcat10DbcpDatasourceAccessor",
37            "psiprobe.beans.accessors.Tomcat11DbcpDatasourceAccessor",
38            "psiprobe.beans.accessors.TomcatJdbcPoolDatasourceAccessor",
39            "psiprobe.beans.accessors.TomEeJdbcPoolDatasourceAccessor",
40            "psiprobe.beans.accessors.ViburCpDatasourceAccessor");
41  
42    /** The Constant DELEGATE_ACCESSORS. */
43    private static final List<DatasourceAccessor> DELEGATE_ACCESSORS =
44        DELEGATE_ACCESSOR_CLASS_NAMES.stream().map(FlexyPoolDatasourceAccessor::newAccessor).toList();
45  
46    @Override
47    public DataSourceInfo getInfo(Object resource) throws SQLException {
48      Object targetDataSource = getTargetDataSource(resource);
49      if (targetDataSource == null) {
50        return null;
51      }
52  
53      for (DatasourceAccessor accessor : DELEGATE_ACCESSORS) {
54        if (accessor.canMap(targetDataSource)) {
55          return accessor.getInfo(targetDataSource);
56        }
57      }
58  
59      return null;
60    }
61  
62    @Override
63    public boolean reset(Object resource) throws SQLException {
64      Object targetDataSource = getTargetDataSource(resource);
65      if (targetDataSource == null) {
66        return false;
67      }
68  
69      for (DatasourceAccessor accessor : DELEGATE_ACCESSORS) {
70        if (accessor.canMap(targetDataSource)) {
71          return accessor.reset(targetDataSource);
72        }
73      }
74  
75      return false;
76    }
77  
78    @Override
79    public boolean canMap(Object resource) {
80      return resource != null
81          && FLEXY_POOL_DATASOURCE_CLASS_NAME.equals(resource.getClass().getName());
82    }
83  
84    /**
85     * Gets the target datasource from a Flexy Pool wrapper.
86     *
87     * @param resource the resource
88     * @return the target datasource
89     */
90    private Object getTargetDataSource(Object resource) {
91      if (!canMap(resource)) {
92        return null;
93      }
94  
95      try {
96        return resource.getClass().getMethod("getTargetDataSource").invoke(resource);
97      } catch (ReflectiveOperationException e) {
98        return null;
99      }
100   }
101 
102   /**
103    * Creates a datasource accessor.
104    *
105    * @param accessorClassName the accessor class name
106    * @return the datasource accessor
107    */
108   private static DatasourceAccessor newAccessor(String accessorClassName) {
109     try {
110       return Class.forName(accessorClassName).asSubclass(DatasourceAccessor.class)
111           .getDeclaredConstructor().newInstance();
112     } catch (ReflectiveOperationException e) {
113       return new UnsupportedDatasourceAccessor();
114     }
115   }
116 
117   /**
118    * Unsupported datasource accessor.
119    */
120   private static final class UnsupportedDatasourceAccessor implements DatasourceAccessor {
121 
122     @Override
123     public DataSourceInfo getInfo(Object resource) {
124       return null;
125     }
126 
127     @Override
128     public boolean reset(Object resource) {
129       return false;
130     }
131 
132     @Override
133     public boolean canMap(Object resource) {
134       return false;
135     }
136   }
137 }