svnno****@sourc*****
svnno****@sourc*****
2008年 7月 2日 (水) 13:21:31 JST
Revision: 1004 http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi?root=pal&view=rev&rev=1004 Author: sone Date: 2008-07-02 13:21:31 +0900 (Wed, 02 Jul 2008) Log Message: ----------- apply patch 'r667492: New HealthCheck feature' Modified Paths: -------------- pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/src/webapp/WEB-INF/assembly/pipelines.xml pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/src/webapp/WEB-INF/web.xml Added Paths: ----------- pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/ pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/ pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DataSourcesValidationBean.java pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DatasourceAvailableHealthCheckValidator.java pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidator.java pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidatorResult.java pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/PortletApplicationAvailableHeathCheckValidator.java pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/pipeline/valve/HealthCheckValve.java -------------- next part -------------- Added: pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DataSourcesValidationBean.java =================================================================== --- pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DataSourcesValidationBean.java (rev 0) +++ pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DataSourcesValidationBean.java 2008-07-02 04:21:31 UTC (rev 1004) @@ -0,0 +1,63 @@ +/* + * 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.util.List; + +/** + * Bean to be used by validators that need to execute a validation query against a list of datasources + * + * @author <a href="mailto:ruben****@fmr*****">Ruben Carvalho</a> + * @version $Id$ + */ +public class DataSourcesValidationBean +{ + /** + * The SQL query. + */ + private String validationQuery; + /** + * List of datasources. + */ + private List datasources; + + public DataSourcesValidationBean(String validationQuery, List datasources) + { + this.validationQuery = validationQuery; + this.datasources = datasources; + } + + /** + * Getter method for validationQuery + * + * @return The validation query. + */ + public String getValidationQuery() + { + return validationQuery; + } + + /** + * Getter method for datasources + * + * @return The list of datasources. + */ + public List getDatasources() + { + return datasources; + } +} \ No newline at end of file Added: pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DatasourceAvailableHealthCheckValidator.java =================================================================== --- pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DatasourceAvailableHealthCheckValidator.java (rev 0) +++ pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DatasourceAvailableHealthCheckValidator.java 2008-07-02 04:21:31 UTC (rev 1004) @@ -0,0 +1,207 @@ +/* + * 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.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.jdbc.support.JdbcUtils; + +/** + * Validator to check if the defined datasources are up and running + * + * @author <a href="mailto:ruben****@fmr*****">Ruben Carvalho</a> + * @version $Id$ + */ +public class DatasourceAvailableHealthCheckValidator implements HealthCheckValidator +{ + private static final Log log = LogFactory.getLog(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 <code>validationQuery</code> + * + * @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; + } +} \ No newline at end of file Added: pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidator.java =================================================================== --- pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidator.java (rev 0) +++ pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidator.java 2008-07-02 04:21:31 UTC (rev 1004) @@ -0,0 +1,51 @@ +/* + * 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 org.apache.jetspeed.pipeline.valve.HealthCheckValve; + +/** + * Interface to be implemented by validator classes which will be injected in {@link HealthCheckValve}. + * + * @author <a href="mailto:ruben****@fmr*****">Ruben Carvalho</a> + * @version $Id$ + */ +public interface HealthCheckValidator +{ + static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + /** + * This method performs the validation and returns the status of the execution + * + * @return An instance of <code>HealthCheckValidatorResult</code> with the result code + */ + HealthCheckValidatorResult validate(); + + /** + * This method returns the number of times the validate() method should be re-executed if it fails the first time. + * + * @return Number of times to re-execute validate() + */ + int getNumberOfRetries(); + + /** + * This method returns the amount of time between each execution of the validate() method + * + * @return The amount of time between each execution of validate() + */ + long getRetryDelay(); +} \ No newline at end of file Added: pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidatorResult.java =================================================================== --- pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidatorResult.java (rev 0) +++ pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidatorResult.java 2008-07-02 04:21:31 UTC (rev 1004) @@ -0,0 +1,103 @@ +/* + * 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; + +/** + * This class is returned as the result of executing the validation method from a Validator class + * + * @author <a href="mailto:ruben****@fmr*****">Ruben Carvalho</a> + * @version $Id$ + */ +public class HealthCheckValidatorResult +{ + /** + * Validator constant which indicates a successful validation + */ + public static final int VALIDATOR_SUCCEEDED = 101; + + /** + * Validator constant which indicates a failed validation + */ + public static final int VALIDATOR_FAILED = 100; + + /** + * Result code. One of <code>VALIDATOR_*</code> + */ + private int healthCheckResult; + + /** + * The result message + */ + private String resultMessage; + + public HealthCheckValidatorResult() + { + this.healthCheckResult = HealthCheckValidatorResult.VALIDATOR_SUCCEEDED; + this.resultMessage = ""; + } + + public HealthCheckValidatorResult(int healthCheckResult, String resultMessage) + { + this.healthCheckResult = healthCheckResult; + this.resultMessage = resultMessage; + } + + /** + * This method returns the result of running <code>HealthCheckValidator.validate()</code>.<br> <br> The result + * has to be one of the constants VALIDATOR_* + * + * @return Result from the execution of the validate() method. + */ + public int getHealthCheckResult() + { + return healthCheckResult; + } + + /** + * Setter method for healthCheckResult + * + * @param healthCheckResult + * The new code for healthCheckResult + */ + public void setHealthCheckResult(int healthCheckResult) + { + this.healthCheckResult = healthCheckResult; + } + + /** + * This method returns a message for this validator's execution.<br> <br> This method should not be used to check + * if a validator ran successfully or not. That should be done by checking + * <code>healthCheckResult() == VALIDATOR_FAILED</code> + * + * @return The execution message (if any) + */ + public String getResultMessage() + { + return resultMessage; + } + + /** + * Setter method for resultMessage + * + * @param resultMessage + * The new result message + */ + public void setResultMessage(String resultMessage) + { + this.resultMessage = resultMessage; + } +} \ No newline at end of file Added: pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/PortletApplicationAvailableHeathCheckValidator.java =================================================================== --- pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/PortletApplicationAvailableHeathCheckValidator.java (rev 0) +++ pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/PortletApplicationAvailableHeathCheckValidator.java 2008-07-02 04:21:31 UTC (rev 1004) @@ -0,0 +1,144 @@ +/* + * 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.util.Iterator; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jetspeed.components.portletregistry.PortletRegistry; +import org.apache.jetspeed.factory.PortletFactory; +import org.apache.jetspeed.om.common.portlet.PortletApplication; + +/** + * Validator to check if the defined required applications have been initialised in the Jetspeed engine + * + * @author <a href="mailto:ruben****@fmr*****">Ruben Carvalho</a> + * @version $Id$ + */ +public class PortletApplicationAvailableHeathCheckValidator implements HealthCheckValidator +{ + private static final Log log = LogFactory.getLog(PortletApplicationAvailableHeathCheckValidator.class); + public static boolean isInfoEnabled = log.isInfoEnabled(); + public static boolean isDebugEnabled = log.isDebugEnabled(); + /** + * Spring property numberOfRetries. + */ + private int numberOfRetries; + /** + * Spring property retryDelay. + */ + private long retryDelay; + /** + * Spring property retryDelay. + */ + private List requiredPortletApplications; + /** + * Spring property portletRegistry. + */ + private PortletRegistry portletRegistry; + /** + * Spring property portletFactory. + */ + private PortletFactory portletFactory; + /** + * Spring property stopValidationOnError. + */ + private boolean stopValidationOnError; + + public PortletApplicationAvailableHeathCheckValidator(List requiredPortletApplications, int numberOfRetries, + long retryDelay, PortletRegistry portletRegistry, + PortletFactory portletFactory, boolean stopValidationOnError) + { + this.requiredPortletApplications = requiredPortletApplications; + this.numberOfRetries = numberOfRetries; + this.retryDelay = retryDelay; + this.portletRegistry = portletRegistry; + this.portletFactory = portletFactory; + this.stopValidationOnError = stopValidationOnError; + } + + public HealthCheckValidatorResult validate() + { + HealthCheckValidatorResult result = new HealthCheckValidatorResult(); + boolean allPAStatus = true; + StringBuffer messages = new StringBuffer(); + try + { + // check if all required apps have been registered and are + // available. + for (Iterator it = requiredPortletApplications.iterator(); it.hasNext();) + { + // the portlet application name + String paName = (String) it.next(); + if (isDebugEnabled) + { + log.debug("Checking portlet application: " + paName); + } + if (messages.length()>0) + { + messages.append(LINE_SEPARATOR); + } + messages.append(paName + ": "); + PortletApplication pa = portletRegistry.getPortletApplication(paName); + boolean thisPAStatus = portletFactory.isPortletApplicationRegistered(pa); + if (thisPAStatus) + { + messages.append("is up"); + } + else + { + messages.append("is down"); + allPAStatus = false; + if (stopValidationOnError) + { + break; + } + } + } + if (!allPAStatus) + { + 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 portlet application validator", e); + result.setHealthCheckResult(HealthCheckValidatorResult.VALIDATOR_FAILED); + messages.append("Exception while running the portlet application validator: " + e.getMessage()); + } + if (isDebugEnabled) + { + log.debug(messages.toString()); + } + result.setResultMessage(messages.toString()); + return result; + } + + public int getNumberOfRetries() + { + return numberOfRetries; + } + + public long getRetryDelay() + { + return retryDelay; + } +} \ No newline at end of file Added: pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/pipeline/valve/HealthCheckValve.java =================================================================== --- pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/pipeline/valve/HealthCheckValve.java (rev 0) +++ pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/components/portal/src/java/org/apache/jetspeed/pipeline/valve/HealthCheckValve.java 2008-07-02 04:21:31 UTC (rev 1004) @@ -0,0 +1,198 @@ +/* + * 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.pipeline.valve; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jetspeed.healthcheck.validators.HealthCheckValidator; +import org.apache.jetspeed.healthcheck.validators.HealthCheckValidatorResult; +import org.apache.jetspeed.pipeline.PipelineException; +import org.apache.jetspeed.pipeline.valve.AbstractValve; +import org.apache.jetspeed.pipeline.valve.ValveContext; +import org.apache.jetspeed.request.RequestContext; + +/** + * Valve that performs a health check based on the validators injected from a Spring configutation file. + * + * @author <a href="mailto:ruben****@fmr*****">Ruben Carvalho</a> + * @version $Id$ + */ +public class HealthCheckValve extends AbstractValve +{ + static final String LINE_SEPARATOR = System.getProperty("line.separator"); + private static final Log log = LogFactory.getLog(HealthCheckValve.class); + public static boolean isInfoEnabled = log.isInfoEnabled(); + public static boolean isDebugEnabled = log.isDebugEnabled(); + /** + * Spring property validators. List of validators to be executed by this Valve + */ + private List validators; + /** + * Spring property successMessage. This String is added to the response if all validators succeed + */ + private String successMessage; + /** + * Spring property failMessage. The string to be added to the response if one of the validators fails + */ + private String failMessage; + /** + * Spring property addValidationMessagesToResponse. Whether messages returned in the validator result should be + * appended to the http response or not + */ + private boolean addValidationMessagesToResponse; + /** + * Spring property stopValidationOnError. Whether the valve execution should continue or stop if one validator fails + */ + private boolean stopValidationOnError; + + public HealthCheckValve(List validators, String successMessage, String failMessage, + boolean addValidationMessagesToResponse, boolean stopValidationOnError) + { + this.validators = validators; + this.successMessage = successMessage; + this.failMessage = failMessage; + this.addValidationMessagesToResponse = addValidationMessagesToResponse; + this.stopValidationOnError = stopValidationOnError; + } + + public void invoke(RequestContext request, ValveContext context) throws PipelineException + { + if (isDebugEnabled) + { + log.debug("Starting method: HealthCheckValve.invoke()"); + } + List messages = new ArrayList(); + HttpServletResponse response = request.getResponse(); + boolean healthCheckStatus = true; + try + { + // iterate all validators and execute its validate method. + for (Iterator it = validators.iterator(); it.hasNext();) + { + HealthCheckValidator hcv = (HealthCheckValidator) it.next(); + if (isDebugEnabled) + { + log.debug("Starting validator execution: " + hcv.getClass().getName()); + } + HealthCheckValidatorResult result = null; + // execute the validator until it succeeds or until the + // number of retries runs out + for (int i = 0; i <= hcv.getNumberOfRetries(); i++) + { + result = hcv.validate(); + if (isDebugEnabled) + { + log.debug("Validator execution: " + + (result.getHealthCheckResult() == HealthCheckValidatorResult.VALIDATOR_SUCCEEDED)); + } + if (result.getHealthCheckResult() == HealthCheckValidatorResult.VALIDATOR_SUCCEEDED) + { + // the validator succeeded so stop this loop and go for + // the next validator + break; + } + if ((i + 1) <= hcv.getNumberOfRetries()) + { + // the validator did not succeed. If there are any + // retries left and if a retry delay was defined then + // wait before re-executing the same validator + if (hcv.getRetryDelay() > 0) + { + try + { + Thread.sleep(hcv.getRetryDelay()); + } + catch (InterruptedException e) + { + } + } + } + } + if (result != null) + { + if (addValidationMessagesToResponse) + { + messages.add(result.getResultMessage()); + } + if (!(result.getHealthCheckResult() == HealthCheckValidatorResult.VALIDATOR_SUCCEEDED)) + { + // this validator failed so mark the health check as + // failed + healthCheckStatus = false; + if (stopValidationOnError) + { + // stopValidationOnError is true so stop the health + // check + break; + } + } + } + } + PrintWriter pw = response.getWriter(); + if (healthCheckStatus) + { + // if all validators succeeded, add the success message to the + // http response + pw.write(successMessage); + } + else + { + pw.write(failMessage); + } + if (addValidationMessagesToResponse) + { + for (Iterator it = messages.iterator(); it.hasNext();) + { + pw.write(LINE_SEPARATOR + (String)it.next()); + } + } + } + catch (Exception e) + { + log.error("Exception while running HealthCheckValve", e); + // if any exceptions occur, even runtime exceptions, simply reset + // the response's buffer and add any messages to it (if required) + try + { + if (!response.isCommitted()) + { + response.resetBuffer(); + } + PrintWriter pw = response.getWriter(); + pw.write(failMessage); + if (addValidationMessagesToResponse) + { + for (Iterator it = messages.iterator(); it.hasNext();) + { + pw.write(LINE_SEPARATOR + (String)it.next()); + } + } + } + catch (Exception e1) + { + log.error("Exception while running HealthCheckValve", e1); + } + } + } +} \ No newline at end of file Modified: pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/src/webapp/WEB-INF/assembly/pipelines.xml =================================================================== --- pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/src/webapp/WEB-INF/assembly/pipelines.xml 2008-07-02 01:15:31 UTC (rev 1003) +++ pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/src/webapp/WEB-INF/assembly/pipelines.xml 2008-07-02 04:21:31 UTC (rev 1004) @@ -378,6 +378,112 @@ <bean id="cleanupPortalURLValve" class="org.apache.jetspeed.container.url.impl.CleanPathInfoEncodedNavStateFromPortalURLValve"/> + <bean id="healthCheckValve" class="org.apache.jetspeed.pipeline.valve.HealthCheckValve" init-method="initialize"> + <constructor-arg index="0"> + <!-- Validators --> + <list> + <ref bean="portletApplicationValidator" /> + <ref bean="databaseValidator" /> + </list> + </constructor-arg> + <constructor-arg index="1"> + <!-- successMessage --> + <value>THE SERVER IS UP</value> + </constructor-arg> + <constructor-arg index="2"> + <!-- failMessage --> + <value>THE SERVER IS DOWN</value> + </constructor-arg> + <constructor-arg index="3"> + <!-- addValidationMessagesToResponse --> + <value>false</value> + </constructor-arg> + <constructor-arg index="4"> + <!-- stopValidationOnError --> + <value>true</value> + </constructor-arg> + </bean> + + <bean id="portletApplicationValidator" class="org.apache.jetspeed.healthcheck.validators.PortletApplicationAvailableHeathCheckValidator"> + <constructor-arg index="0"> + <!-- requiredPortletApplications --> + <list> + <!-- names of the portlet applications which are required to be available --> + <!-- + <value>j2-admin</value> + --> + </list> + </constructor-arg> + <constructor-arg index="1"> + <!-- numberOfRetries --> + <value>0</value> + </constructor-arg> + <constructor-arg index="2"> + <!-- retryDelay --> + <value>0</value> + </constructor-arg> + <constructor-arg index="3"> + <!-- portletRegistry --> + <ref bean="portletRegistry" /> + </constructor-arg> + <constructor-arg index="4"> + <!-- portletFactory --> + <ref bean="portletFactory" /> + </constructor-arg> + <constructor-arg index="5"> + <!-- stopValidationOnError --> + <value>true</value> + </constructor-arg> + </bean> + + <bean id="databaseValidator" class="org.apache.jetspeed.healthcheck.validators.DatasourceAvailableHealthCheckValidator"> + <constructor-arg index="0"> + <!-- resources --> + <map> + <!-- entries to DataSourceValidationBean instances which should be checked + see (commented out) example below --> + <!-- + <entry key="mydata"> + <bean class="org.apache.jetspeed.healthcheck.validators.DataSourcesValidationBean"> + <constructor-arg index="0"> + <!- - Oracle database specific validation query - -> + <value>SELECT * FROM SYS.DUAL</value> + </constructor-arg> + <constructor-arg index="1"> + <list> + <!- - list of datasources (all using the same validation query) + which needs to be validated - -> + <bean id="mydataDataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> + <property name="jndiName" value="java:comp/env/jdbc/mydata1" /> + </bean> + <bean id="mydataDataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> + <property name="jndiName" value="java:comp/env/jdbc/mydata2" /> + </bean> + </list> + </constructor-arg> + </bean> + </entry> + --> + </map> + </constructor-arg> + <constructor-arg index="1"> + <!-- numberOfRetries --> + <value>0</value> + </constructor-arg> + <constructor-arg index="2"> + <!-- retryDelay --> + <value>0</value> + </constructor-arg> + <constructor-arg index="3"> + <!-- stopValidationOnError --> + <value>true</value> + </constructor-arg> + <constructor-arg index="4"> + <!-- requireAllValid --> + <value>true</value> + </constructor-arg> + </bean> + <bean id="jetspeed-pipeline" class="org.apache.jetspeed.pipeline.JetspeedPipeline" init-method="initialize" @@ -639,6 +745,17 @@ </constructor-arg> </bean> + <bean id="healthcheck-pipeline" class="org.apache.jetspeed.pipeline.JetspeedPipeline" init-method="initialize"> + <constructor-arg> + <value>HealthCheckPipeline</value> + </constructor-arg> + <constructor-arg> + <list> + <ref bean="healthCheckValve" /> + </list> + </constructor-arg> + </bean> + <bean id='pipeline-map' class='java.util.HashMap'> @@ -682,6 +799,9 @@ <entry key='/dtconfigure'> <value>dtconfigure-pipeline</value> </entry> + <entry key='/healthcheck'> + <value>healthcheck-pipeline</value> + </entry> </map> </constructor-arg> </bean> Modified: pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/src/webapp/WEB-INF/web.xml =================================================================== --- pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/src/webapp/WEB-INF/web.xml 2008-07-02 01:15:31 UTC (rev 1003) +++ pal-portal/branches/pal-portal-1.x/portal/jetspeed-2/src/webapp/WEB-INF/web.xml 2008-07-02 04:21:31 UTC (rev 1004) @@ -219,6 +219,13 @@ <url-pattern>/dtconfigure/*</url-pattern> </servlet-mapping> --> + <servlet-mapping> + <servlet-name> + jetspeed + </servlet-name> + <url-pattern>/healthcheck/*</url-pattern> + </servlet-mapping> + <!-- Map *.vm files to Velocity --> <servlet-mapping>