Search in sources :

Example 6 with FilterParseException

use of org.opennms.netmgt.filter.api.FilterParseException in project opennms by OpenNMS.

the class JdbcFilterDao method getIPAddressList.

private List<InetAddress> getIPAddressList(final String rule, final boolean filterDeleted, final String address) throws FilterParseException {
    final List<InetAddress> resultList = new ArrayList<>();
    final boolean filterByAddress = address != null && address.length() > 0;
    String sqlString;
    LOG.debug("Filter.getIPAddressList({})", rule);
    // get the database connection
    Connection conn = null;
    final DBUtils d = new DBUtils(getClass());
    try {
        // parse the rule and get the sql select statement
        sqlString = getSQLStatement(rule);
        if (filterDeleted) {
            if (!sqlString.contains("isManaged")) {
                sqlString += " AND (ipInterface.isManaged != 'D' or ipInterface.isManaged IS NULL)";
            }
        }
        if (filterByAddress) {
            sqlString += " AND ipInterface.ipaddr = ?";
        }
        conn = getDataSource().getConnection();
        d.watch(conn);
        LOG.debug("Filter.getIPAddressList({}): SQL statement: {}", rule, sqlString);
        // execute query and return the list of ip addresses
        final ResultSet rset;
        if (filterByAddress) {
            final PreparedStatement preparedStatement = conn.prepareStatement(sqlString);
            preparedStatement.setString(1, address);
            d.watch(preparedStatement);
            rset = preparedStatement.executeQuery();
        } else {
            final Statement stmt = conn.createStatement();
            d.watch(stmt);
            rset = stmt.executeQuery(sqlString);
        }
        d.watch(rset);
        // fill up the array list if the result set has values
        if (rset != null) {
            // Iterate through the result and build the array list
            while (rset.next()) {
                resultList.add(addr(rset.getString(1)));
            }
        }
    } catch (final FilterParseException e) {
        LOG.warn("Filter Parse Exception occurred getting IP List.", e);
        throw new FilterParseException("Filter Parse Exception occurred getting IP List: " + e.getLocalizedMessage(), e);
    } catch (final SQLException e) {
        LOG.warn("SQL Exception occurred getting IP List.", e);
        throw new FilterParseException("SQL Exception occurred getting IP List: " + e.getLocalizedMessage(), e);
    } catch (final Throwable e) {
        LOG.error("Exception getting database connection.", e);
        throw new UndeclaredThrowableException(e);
    } finally {
        d.cleanUp();
    }
    LOG.debug("Filter.getIPAddressList({}): resultList = {}", rule, resultList);
    return resultList;
}
Also used : FilterParseException(org.opennms.netmgt.filter.api.FilterParseException) SQLException(java.sql.SQLException) PreparedStatement(java.sql.PreparedStatement) Statement(java.sql.Statement) ArrayList(java.util.ArrayList) Connection(java.sql.Connection) PreparedStatement(java.sql.PreparedStatement) UndeclaredThrowableException(java.lang.reflect.UndeclaredThrowableException) DBUtils(org.opennms.core.utils.DBUtils) ResultSet(java.sql.ResultSet) InetAddress(java.net.InetAddress)

Example 7 with FilterParseException

use of org.opennms.netmgt.filter.api.FilterParseException in project opennms by OpenNMS.

the class JdbcFilterDao method parseRule.

/**
 * SQL Key Word regex
 *
 * Binary Logic / Operators - \\s+(?:AND|OR|(?:NOT )?(?:LIKE|IN)|IS (?:NOT )?DISTINCT FROM)\\s+
 * Unary Operators - \\s+IS (?:NOT )?NULL(?!\\w)
 * Typecasts - ::(?:TIMESTAMP|INET)(?!\\w)
 * Unary Logic - (?&lt;!\\w)NOT\\s+
 * Functions - (?&lt;!\\w)IPLIKE(?=\\()
 */
/**
 * Generic method to parse and translate a rule into SQL.
 *
 * Only columns listed in database-schema.xml may be used in a filter
 * (explicit "table.column" specification is not supported in filters)
 *
 * To differentiate column names from SQL key words (operators, functions, typecasts, etc)
 * SQL_KEYWORD_REGEX must match any SQL key words that may be used in filters,
 * and must not match any column names or prefixed values
 *
 * To make filter syntax more simple and intuitive than SQL
 * - Filters support some aliases for common SQL key words / operators
 *    "&amp;" or "&amp;&amp;" = "AND"
 *    "|" or "||" = "OR"
 *    "!" = "NOT"
 *    "==" = "="
 * - "IPLIKE" may be used as an operator instead of a function in filters ("ipAddr IPLIKE '*.*.*.*'")
 *   When using "IPLIKE" as an operator, the value does not have to be quoted ("ipAddr IPLIKE *.*.*.*" is ok)
 * - Some common SQL expressions may be generated by adding a (lower-case) prefix to an unquoted value in the filter
 *    "isVALUE" = "serviceName = VALUE"
 *    "notisVALUE" = interface does not support the specified service
 *    "catincVALUE" = node is in the specified category
 * - Double-quoted (") strings in filters are converted to single-quoted (') strings in SQL
 *   SQL treats single-quoted strings as constants (values) and double-quoted strings as identifiers (columns, tables, etc)
 *   So, all quoted strings in filters are treated as constants, and filters don't support quoted identifiers
 *
 * This function does not do complete syntax/grammar checking - that is left to the database itself - do not assume the output is valid SQL
 *
 * @param tables
 *            a list to be populated with any tables referenced by the returned SQL
 * @param rule
 *            the rule to parse
 *
 * @return an SQL WHERE clause
 *
 * @throws FilterParseException
 *             if any errors occur during parsing
 */
private String parseRule(final List<Table> tables, final String rule) throws FilterParseException {
    if (rule != null && rule.length() > 0) {
        final List<String> extractedStrings = new ArrayList<>();
        String sqlRule = rule;
        // Extract quoted strings from rule and convert double-quoted strings to single-quoted strings
        // Quoted strings need to be extracted first to avoid accidentally matching/modifying anything within them
        // As in SQL, pairs of quotes within a quoted string are treated as an escaped quote character:
        // 'a''b' = a'b ; "a""b" = a"b ; 'a"b' = a"b ; "a'b" = a'b
        Matcher regex = SQL_QUOTE_PATTERN.matcher(sqlRule);
        StringBuffer tempStringBuff = new StringBuffer();
        while (regex.find()) {
            final String tempString = regex.group();
            if (tempString.charAt(0) == '"') {
                extractedStrings.add("'" + tempString.substring(1, tempString.length() - 1).replaceAll("\"\"", "\"").replaceAll("'", "''") + "'");
            } else {
                extractedStrings.add(regex.group());
            }
            regex.appendReplacement(tempStringBuff, "###@" + (extractedStrings.size() - 1) + "@###");
        }
        final int tempIndex = tempStringBuff.length();
        regex.appendTail(tempStringBuff);
        if (tempStringBuff.substring(tempIndex).indexOf('\'') > -1) {
            final String message = "Unmatched ' in filter rule '" + rule + "'";
            LOG.error(message);
            throw new FilterParseException(message);
        }
        if (tempStringBuff.substring(tempIndex).indexOf('"') > -1) {
            final String message = "Unmatched \" in filter rule '" + rule + "'";
            LOG.error(message);
            throw new FilterParseException(message);
        }
        sqlRule = tempStringBuff.toString();
        // Translate filter-specific operators to SQL operators
        sqlRule = sqlRule.replaceAll("\\s*(?:&|&&)\\s*", " AND ");
        sqlRule = sqlRule.replaceAll("\\s*(?:\\||\\|\\|)\\s*", " OR ");
        sqlRule = sqlRule.replaceAll("\\s*!(?!=)\\s*", " NOT ");
        sqlRule = sqlRule.replaceAll("==", "=");
        // Translate IPLIKE operators to IPLIKE() functions
        // If IPLIKE is already used as a function in the filter, this regex should not match it
        regex = SQL_IPLIKE_PATTERN.matcher(sqlRule);
        tempStringBuff = new StringBuffer();
        while (regex.find()) {
            // Is the second argument already a quoted string?
            if (regex.group().charAt(0) == '#') {
                regex.appendReplacement(tempStringBuff, "IPLIKE($1, $2)");
            } else {
                regex.appendReplacement(tempStringBuff, "IPLIKE($1, '$2')");
            }
        }
        regex.appendTail(tempStringBuff);
        sqlRule = tempStringBuff.toString();
        // Extract SQL key words to avoid identifying them as columns or prefixed values
        regex = SQL_KEYWORD_PATTERN.matcher(sqlRule);
        tempStringBuff = new StringBuffer();
        while (regex.find()) {
            extractedStrings.add(regex.group().toUpperCase());
            regex.appendReplacement(tempStringBuff, "###@" + (extractedStrings.size() - 1) + "@###");
        }
        regex.appendTail(tempStringBuff);
        sqlRule = tempStringBuff.toString();
        // Identify prefixed values and columns
        regex = SQL_VALUE_COLUMN_PATTERN.matcher(sqlRule);
        tempStringBuff = new StringBuffer();
        while (regex.find()) {
            // Convert prefixed values to SQL expressions
            if (regex.group().startsWith("is")) {
                regex.appendReplacement(tempStringBuff, m_databaseSchemaConfigFactory.addColumn(tables, "serviceName") + " = '" + regex.group().substring(2) + "'");
            } else if (regex.group().startsWith("notis")) {
                regex.appendReplacement(tempStringBuff, m_databaseSchemaConfigFactory.addColumn(tables, "ipAddr") + " NOT IN (SELECT ifServices.ipAddr FROM ifServices, service WHERE service.serviceName ='" + regex.group().substring(5) + "' AND service.serviceID = ifServices.serviceID)");
            } else if (regex.group().startsWith("catinc")) {
                regex.appendReplacement(tempStringBuff, m_databaseSchemaConfigFactory.addColumn(tables, "nodeID") + " IN (SELECT category_node.nodeID FROM category_node, categories WHERE categories.categoryID = category_node.categoryID AND categories.categoryName = '" + regex.group().substring(6) + "')");
            } else if (regex.group().matches(SQL_IPLIKE6_RHS_REGEX)) {
            // Do nothing, it's apparently an IPv6 IPLIKE expression right-hand side
            } else {
                // Call m_databaseSchemaConfigFactory.addColumn() on each column
                regex.appendReplacement(tempStringBuff, m_databaseSchemaConfigFactory.addColumn(tables, regex.group()));
            }
        }
        regex.appendTail(tempStringBuff);
        sqlRule = tempStringBuff.toString();
        // Merge extracted strings back into expression
        regex = SQL_ESCAPED_PATTERN.matcher(sqlRule);
        tempStringBuff = new StringBuffer();
        while (regex.find()) {
            regex.appendReplacement(tempStringBuff, Matcher.quoteReplacement(extractedStrings.get(Integer.parseInt(regex.group(1)))));
        }
        regex.appendTail(tempStringBuff);
        sqlRule = tempStringBuff.toString();
        return "WHERE " + sqlRule;
    }
    return "";
}
Also used : FilterParseException(org.opennms.netmgt.filter.api.FilterParseException) Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList)

Example 8 with FilterParseException

use of org.opennms.netmgt.filter.api.FilterParseException in project opennms by OpenNMS.

the class DataManager method afterPropertiesSet.

/**
 * Constructor. Parses categories from the categories.xml and populates them
 * with 'RTCNode' objects created from data read from the database (services
 * and outage tables)
 *
 * @exception SQLException
 *                if there is an error reading initial data from the
 *                database
 * @exception FilterParseException
 *                if a rule in the categories.xml was incorrect
 * @exception RTCException
 *                if the initialization/data reading does not go through
 * @throws org.xml.sax.SAXException if any.
 * @throws java.io.IOException if any.
 * @throws java.sql.SQLException if any.
 * @throws org.opennms.netmgt.filter.api.FilterParseException if any.
 * @throws org.opennms.netmgt.rtc.RTCException if any.
 */
@Override
public void afterPropertiesSet() throws Exception {
    // read the categories.xml to get all the categories
    m_categories = RTCUtils.createCategoriesMap();
    if (m_categories == null || m_categories.isEmpty()) {
        throw new RTCException("No categories found in categories.xml");
    }
    LOG.debug("Number of categories read: {}", m_categories.size());
    // create data holder
    m_map = new RTCHashMap(30000);
    m_transactionTemplate.execute(new TransactionCallbackWithoutResult() {

        @Override
        protected void doInTransactionWithoutResult(TransactionStatus arg0) {
            // Populate the nodes initially from the database
            try {
                populateNodesFromDB(null, null);
            } catch (FilterParseException e) {
                throw new IllegalStateException("Cannot load RTC data from the database: " + e.getMessage(), e);
            } catch (SQLException e) {
                throw new IllegalStateException("Cannot load RTC data from the database: " + e.getMessage(), e);
            } catch (RTCException e) {
                throw new IllegalStateException("Cannot load RTC data from the database: " + e.getMessage(), e);
            }
        }
    });
}
Also used : FilterParseException(org.opennms.netmgt.filter.api.FilterParseException) SQLException(java.sql.SQLException) RTCHashMap(org.opennms.netmgt.rtc.datablock.RTCHashMap) TransactionStatus(org.springframework.transaction.TransactionStatus) TransactionCallbackWithoutResult(org.springframework.transaction.support.TransactionCallbackWithoutResult)

Aggregations

FilterParseException (org.opennms.netmgt.filter.api.FilterParseException)8 SQLException (java.sql.SQLException)6 UndeclaredThrowableException (java.lang.reflect.UndeclaredThrowableException)4 Connection (java.sql.Connection)4 PreparedStatement (java.sql.PreparedStatement)4 ResultSet (java.sql.ResultSet)4 Statement (java.sql.Statement)4 DBUtils (org.opennms.core.utils.DBUtils)4 InetAddress (java.net.InetAddress)2 ArrayList (java.util.ArrayList)2 TreeMap (java.util.TreeMap)2 HashMap (java.util.HashMap)1 Set (java.util.Set)1 TreeSet (java.util.TreeSet)1 Matcher (java.util.regex.Matcher)1 InetAddressComparator (org.opennms.core.utils.InetAddressComparator)1 Notification (org.opennms.netmgt.config.notifications.Notification)1 RTCHashMap (org.opennms.netmgt.rtc.datablock.RTCHashMap)1 TransactionStatus (org.springframework.transaction.TransactionStatus)1 TransactionCallbackWithoutResult (org.springframework.transaction.support.TransactionCallbackWithoutResult)1