JdbcActions.java

1
package org.europa.together.application;
2
3
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
4
import java.beans.PropertyVetoException;
5
import java.io.BufferedReader;
6
import java.io.IOException;
7
import java.io.InputStreamReader;
8
import java.sql.Connection;
9
import java.sql.DatabaseMetaData;
10
import java.sql.ResultSet;
11
import java.sql.SQLException;
12
import java.sql.Statement;
13
import java.util.HashMap;
14
import java.util.Map;
15
import java.util.regex.Matcher;
16
import java.util.regex.Pattern;
17
import org.apache.commons.dbcp2.BasicDataSource;
18
import org.europa.together.business.DatabaseActions;
19
import org.europa.together.business.Logger;
20
import org.europa.together.business.PropertyReader;
21
import org.europa.together.domain.JdbcConnection;
22
import org.europa.together.domain.LogLevel;
23
import org.europa.together.exceptions.MisconfigurationException;
24
import org.europa.together.exceptions.TimeOutException;
25
import org.europa.together.utils.StringUtils;
26
import org.europa.together.utils.Validator;
27
import org.springframework.context.ApplicationContext;
28
import org.springframework.context.support.ClassPathXmlApplicationContext;
29
import org.springframework.stereotype.Repository;
30
31
/**
32
 * Implementation of Database JDBC Actions.
33
 */
34
@Repository
35
public class JdbcActions implements DatabaseActions {
36
37
    private static final long serialVersionUID = 8L;
38
    private static final Logger LOGGER = new LogbackLogger(JdbcActions.class);
39
40
    private static final String JDBC_PROPERTIES
41
            = "org/europa/together/configuration/jdbc.properties";
42
    private Connection jdbcConnection = null;
43
    private Statement statement = null;
44
    private DatabaseMetaData metadata;
45
    private String connectionUrl;
46
    private String driverClass;
47
    private String pwd;
48
    private String user;
49
50
    /**
51
     * Constructor.
52
     */
53
    public JdbcActions() {
54
        LOGGER.log("instance class", LogLevel.INFO);
55
    }
56
57
    @Override
58
    public boolean connect(final String propertyFile) {
59
        boolean connected = true;
60
        try {
61 1 1. connect : removed call to org/europa/together/application/JdbcActions::fetchProperties → KILLED
            fetchProperties(propertyFile);
62 1 1. connect : removed call to org/europa/together/application/JdbcActions::establishPooledConnection → KILLED
            establishPooledConnection();
63
        } catch (Exception ex) {
64
            connected = false;
65
            LOGGER.log("Connection failed!", LogLevel.WARN);
66
            LOGGER.catchException(ex);
67
        }
68 2 1. connect : replaced boolean return with true for org/europa/together/application/JdbcActions::connect → KILLED
2. connect : replaced boolean return with false for org/europa/together/application/JdbcActions::connect → KILLED
        return connected;
69
    }
70
71
    @Override
72
    public boolean executeSqlFromClasspath(final String sqlFile) {
73
        boolean success = true;
74
        LOGGER.log("SQL from Classpath -> File(" + sqlFile + ")", LogLevel.DEBUG);
75
        BufferedReader reader = null;
76
        StringBuilder sql = new StringBuilder();
77
        ApplicationContext context = new ClassPathXmlApplicationContext();
78
        try {
79
            reader = new BufferedReader(
80
                    new InputStreamReader(
81
                            context.getResource(sqlFile).getInputStream(), "UTF8")
82
            );
83
            String line;
84 1 1. executeSqlFromClasspath : negated conditional → KILLED
            while ((line = reader.readLine()) != null) {
85 1 1. executeSqlFromClasspath : negated conditional → KILLED
                if (!line.startsWith("--")) {
86
                    sql.append(line);
87
                }
88
            }
89
            this.executeQuery(sql.toString());
90 1 1. executeSqlFromClasspath : removed call to java/io/BufferedReader::close → SURVIVED
            reader.close();
91
        } catch (Exception ex) {
92
            success = false;
93
            LOGGER.catchException(ex);
94
        }
95 2 1. executeSqlFromClasspath : replaced boolean return with true for org/europa/together/application/JdbcActions::executeSqlFromClasspath → KILLED
2. executeSqlFromClasspath : replaced boolean return with false for org/europa/together/application/JdbcActions::executeSqlFromClasspath → KILLED
        return success;
96
    }
97
98
    @Override
99
    public ResultSet executeQuery(final String sql)
100
            throws SQLException {
101
        ResultSet resultSet = null;
102
        LOGGER.log("Execute SQL: " + sql, LogLevel.DEBUG);
103 1 1. executeQuery : negated conditional → KILLED
        if (jdbcConnection != null) {
104
            statement = jdbcConnection.createStatement();
105
            statement.execute(sql);
106
            resultSet = statement.getResultSet();
107
        } else {
108
            LOGGER.log("No JDBC Connection established.", LogLevel.ERROR);
109
        }
110 1 1. executeQuery : replaced return value with null for org/europa/together/application/JdbcActions::executeQuery → KILLED
        return resultSet;
111
    }
112
113
    @Override
114
    public int countResultSets(final ResultSet results)
115
            throws SQLException {
116
        int count = 0;
117 1 1. countResultSets : negated conditional → KILLED
        while (results.next()) {
118 1 1. countResultSets : Changed increment from 1 to -1 → KILLED
            count++;
119
        }
120 1 1. countResultSets : replaced int return with 0 for org/europa/together/application/JdbcActions::countResultSets → KILLED
        return count;
121
    }
122
123
    @Override
124
    public JdbcConnection getJdbcMetaData()
125
            throws SQLException {
126
        Map<String, String> properties = new HashMap<>();
127
        metadata = jdbcConnection.getMetaData();
128
        String url = metadata.getURL();
129
        properties.put("metaJdbcVersion",
130
                metadata.getJDBCMajorVersion() + "." + metadata.getJDBCMinorVersion());
131
        properties.put("metaJdbcDriverName",
132
                metadata.getDriverName());
133
        properties.put("metaJdbcDriverVersion",
134
                metadata.getDriverVersion());
135
        properties.put("metaDbmsName",
136
                metadata.getDatabaseProductName());
137
        properties.put("metaDbmsVersion",
138
                metadata.getDatabaseProductVersion());
139
        properties.put("metaUser",
140
                metadata.getUserName());
141
        properties.put("metaCatalog",
142
                metadata.getConnection().getCatalog());
143
        properties.put("metaUrl", url);
144
        String[] result = grabIpAndPort(url).split(":");
145
        String ip = result[0];
146
        String port = result[1];
147
        properties.put("metaIP", ip);
148
        properties.put("metaPort", port);
149 1 1. getJdbcMetaData : replaced return value with null for org/europa/together/application/JdbcActions::getJdbcMetaData → KILLED
        return new JdbcConnection(properties);
150
    }
151
152
    //  ----------------------------------------------------------------------------
153
    @SuppressFBWarnings
154
    //SpotBugs: vulnerable to a denial of service attack (ReDOS)
155
    private String grabIpAndPort(final String connectionUrl) {
156
        String result = "";
157
        LOGGER.log("Grab IP4 Adress an Port from connection string: "
158
                + connectionUrl, LogLevel.DEBUG);
159
        Pattern pattern = Pattern.compile(Validator.IP4_ADDRESS);
160
        Matcher matcher = pattern.matcher(connectionUrl);
161
        LOGGER.log("RegEx match found: " + matcher.find()
162
                + " GroupCount: " + matcher.groupCount(), LogLevel.DEBUG);
163
        result = matcher.group(0);
164
        LOGGER.log("Result: " + result + " - Search: " + connectionUrl, LogLevel.DEBUG);
165 1 1. grabIpAndPort : replaced return value with "" for org/europa/together/application/JdbcActions::grabIpAndPort → KILLED
        return result;
166
    }
167
168
    private void establishPooledConnection()
169
            throws TimeOutException, ClassNotFoundException, PropertyVetoException, SQLException {
170
        LOGGER.log("Try to establish JDBC connection.", LogLevel.DEBUG);
171
        Class.forName(driverClass);
172
        BasicDataSource cpds = new BasicDataSource();
173 1 1. establishPooledConnection : removed call to org/apache/commons/dbcp2/BasicDataSource::setDriverClassName → SURVIVED
        cpds.setDriverClassName(driverClass);
174 1 1. establishPooledConnection : removed call to org/apache/commons/dbcp2/BasicDataSource::setUrl → KILLED
        cpds.setUrl(connectionUrl);
175 1 1. establishPooledConnection : removed call to org/apache/commons/dbcp2/BasicDataSource::setUsername → KILLED
        cpds.setUsername(user);
176 1 1. establishPooledConnection : removed call to org/apache/commons/dbcp2/BasicDataSource::setPassword → KILLED
        cpds.setPassword(pwd);
177
        this.jdbcConnection = cpds.getConnection();
178
        LOGGER.log(getJdbcMetaData().toString(), LogLevel.DEBUG);
179
    }
180
181
    private void fetchProperties(final String propertyFile) throws IOException {
182
        String properties = propertyFile;
183
        PropertyReader reader = new PropertyFileReader();
184 2 1. fetchProperties : negated conditional → KILLED
2. fetchProperties : negated conditional → KILLED
        if (StringUtils.isEmpty(properties) || propertyFile.equals("test")) {
185
            LOGGER.log("Append (test) properties: " + JDBC_PROPERTIES, LogLevel.DEBUG);
186
            reader.appendPropertiesFromClasspath(JDBC_PROPERTIES);
187
        } else {
188
            LOGGER.log("Append properties from: " + propertyFile, LogLevel.DEBUG);
189
            reader.appendPropertiesFromFile(propertyFile);
190
        }
191
        try {
192
            this.driverClass = reader.getPropertyAsString("jdbc.driverClassName");
193
            this.user = reader.getPropertyAsString("jdbc.user");
194
            this.pwd = reader.getPropertyAsString("jdbc.password");
195
            this.connectionUrl = reader.getPropertyAsString("jdbc.url");
196
        } catch (MisconfigurationException ex) {
197
            LOGGER.catchException(ex);
198
        }
199
    }
200
}

Mutations

61

1.1
Location : connect
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]
removed call to org/europa/together/application/JdbcActions::fetchProperties → KILLED

62

1.1
Location : connect
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]
removed call to org/europa/together/application/JdbcActions::establishPooledConnection → KILLED

68

1.1
Location : connect
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]/[method:failConnect()]
replaced boolean return with true for org/europa/together/application/JdbcActions::connect → KILLED

2.2
Location : connect
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]/[method:fallbackLoadProperties()]
replaced boolean return with false for org/europa/together/application/JdbcActions::connect → KILLED

84

1.1
Location : executeSqlFromClasspath
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]/[method:getResultSet()]
negated conditional → KILLED

85

1.1
Location : executeSqlFromClasspath
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]/[method:getResultSet()]
negated conditional → KILLED

90

1.1
Location : executeSqlFromClasspath
Killed by : none
removed call to java/io/BufferedReader::close → SURVIVED
Covering tests

95

1.1
Location : executeSqlFromClasspath
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]/[method:sqlFileNotFound()]
replaced boolean return with true for org/europa/together/application/JdbcActions::executeSqlFromClasspath → KILLED

2.2
Location : executeSqlFromClasspath
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]/[method:executeSqlFileFromClasspath()]
replaced boolean return with false for org/europa/together/application/JdbcActions::executeSqlFromClasspath → KILLED

103

1.1
Location : executeQuery
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]/[method:failExecuteQueryNoConnection()]
negated conditional → KILLED

110

1.1
Location : executeQuery
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]/[method:getResultSet()]
replaced return value with null for org/europa/together/application/JdbcActions::executeQuery → KILLED

117

1.1
Location : countResultSets
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]/[method:getResultSet()]
negated conditional → KILLED

118

1.1
Location : countResultSets
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]/[method:getResultSet()]
Changed increment from 1 to -1 → KILLED

120

1.1
Location : countResultSets
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]/[method:getResultSet()]
replaced int return with 0 for org/europa/together/application/JdbcActions::countResultSets → KILLED

149

1.1
Location : getJdbcMetaData
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]
replaced return value with null for org/europa/together/application/JdbcActions::getJdbcMetaData → KILLED

165

1.1
Location : grabIpAndPort
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]
replaced return value with "" for org/europa/together/application/JdbcActions::grabIpAndPort → KILLED

173

1.1
Location : establishPooledConnection
Killed by : none
removed call to org/apache/commons/dbcp2/BasicDataSource::setDriverClassName → SURVIVED
Covering tests

174

1.1
Location : establishPooledConnection
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]
removed call to org/apache/commons/dbcp2/BasicDataSource::setUrl → KILLED

175

1.1
Location : establishPooledConnection
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]
removed call to org/apache/commons/dbcp2/BasicDataSource::setUsername → KILLED

176

1.1
Location : establishPooledConnection
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]
removed call to org/apache/commons/dbcp2/BasicDataSource::setPassword → KILLED

184

1.1
Location : fetchProperties
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]
negated conditional → KILLED

2.2
Location : fetchProperties
Killed by : org.europa.together.application.JdbcActionsTest.[engine:junit-jupiter]/[class:org.europa.together.application.JdbcActionsTest]/[method:failConnect()]
negated conditional → KILLED

Active mutators

Tests examined


Report generated by PIT 1.22.0