/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.jetspeed.healthcheck.validators; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.support.JdbcUtils; /** * Validator to check if the defined datasources are up and running * * @author Ruben Carvalho * @version $Id$ */ public class DatasourceAvailableHealthCheckValidator implements HealthCheckValidator { private static final Logger log = LoggerFactory.getLogger(DatasourceAvailableHealthCheckValidator.class); public static boolean isInfoEnabled = log.isInfoEnabled(); public static boolean isDebugEnabled = log.isDebugEnabled(); /** * Spring property resources. Maps the database name to a list of datasources. */ private Map resources; /** * Spring property numberOfRetries. */ private int numberOfRetries; /** * Spring property retryDelay. */ private long retryDelay; /** * Spring property stopValidationOnError. */ private boolean stopValidationOnError; /** * Spring property requireAllValid. */ private boolean requireAllValid; public DatasourceAvailableHealthCheckValidator(Map resources, int numberOfRetries, long retryDelay, boolean stopValidationOnError, boolean requireAllValid) { this.resources = resources; this.numberOfRetries = numberOfRetries; this.retryDelay = retryDelay; this.stopValidationOnError = stopValidationOnError; this.requireAllValid = requireAllValid; } public HealthCheckValidatorResult validate() { if (isDebugEnabled) { log.debug("Starting method: DatasourceAvailableHealthCheckValidator.validate()"); } HealthCheckValidatorResult result = new HealthCheckValidatorResult(); boolean allDataSourcesStatus = true; StringBuffer messages = new StringBuffer(); try { Set dbNames = resources.keySet(); for (Iterator it = dbNames.iterator(); it.hasNext();) { String dbName = (String) it.next(); if (messages.length()>0) { messages.append(LINE_SEPARATOR); } messages.append(dbName + ":"); if (isDebugEnabled) { log.debug("Database: " + dbName); } DataSourcesValidationBean dsBean = (DataSourcesValidationBean) resources.get(dbName); String validationQuery = dsBean.getValidationQuery(); boolean dbStatus = true; for (Iterator it2 = dsBean.getDatasources().iterator(); it2.hasNext();) { DataSource ds = (DataSource) it2.next(); dbStatus = isDatasourceValid(validationQuery, ds); if (dbStatus) { // the ds is up if (!requireAllValid) { // only 1 datasource is required to be available so // we can interrupt this loop break; } } else { // the ds is not available if (requireAllValid) { // all datasource(s) need to be available so // we can interrupt this loop break; } } } if (dbStatus) { messages.append(" is up"); } else { // none of the datasources for this DB is available so // fail the whole validator allDataSourcesStatus = false; messages.append(" is down"); } if (stopValidationOnError && !allDataSourcesStatus) { // the validator has failed and stopValidationOnError // is true so we have to interrupt the validator break; } } if (!allDataSourcesStatus) { result.setHealthCheckResult(HealthCheckValidatorResult.VALIDATOR_FAILED); } } catch (Exception e) { // if any exceptions occur, even runtime exceptions, return a failed // result log.error("Exception while running the datasource validator", e); result.setHealthCheckResult(HealthCheckValidatorResult.VALIDATOR_FAILED); messages.append("Exception while running the datasource validator: " + e.getMessage()); } if (isDebugEnabled) { log.debug(messages.toString()); } result.setResultMessage(messages.toString()); return result; } /** * Checks is a datasource is valid or not by executing a validationQuery * * @param validationQuery * The query to be executed * @param dataSource * The datasource to be checked * @return Whether the datasource is available or not */ private boolean isDatasourceValid(String validationQuery, DataSource dataSource) { boolean dsStatus = true; Connection con = null; Statement stmt = null; try { con = dataSource.getConnection(); stmt = con.createStatement(); stmt.execute(validationQuery); } catch (SQLException ex) { dsStatus = false; log.error("The datasource is not available", ex); } finally { JdbcUtils.closeStatement(stmt); JdbcUtils.closeConnection(con); } return dsStatus; } public int getNumberOfRetries() { return numberOfRetries; } public long getRetryDelay() { return retryDelay; } }