You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by at...@apache.org on 2008/06/13 14:02:11 UTC

svn commit: r667492 - in /portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE: components/portal/src/java/org/apache/jetspeed/healthcheck/ components/portal/src/java/org/apache/jetspeed/healthcheck/validators/ components/portal/src/java/org/a...

Author: ate
Date: Fri Jun 13 05:02:11 2008
New Revision: 667492

URL: http://svn.apache.org/viewvc?rev=667492&view=rev
Log:
JS2-888: New HealthCheck feature contributed by Ruben Carvalho
See: http://issues.apache.org/jira/browse/JS2-888

Great new feature, thanks Ruben!

Added:
    portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/
    portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/
    portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DataSourcesValidationBean.java   (with props)
    portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DatasourceAvailableHealthCheckValidator.java   (with props)
    portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidator.java   (with props)
    portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidatorResult.java   (with props)
    portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/PortletApplicationAvailableHeathCheckValidator.java   (with props)
    portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/pipeline/valve/HealthCheckValve.java   (with props)
Modified:
    portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/src/webapp/WEB-INF/assembly/pipelines.xml
    portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/src/webapp/WEB-INF/web.xml

Added: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DataSourcesValidationBean.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DataSourcesValidationBean.java?rev=667492&view=auto
==============================================================================
--- portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DataSourcesValidationBean.java (added)
+++ portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DataSourcesValidationBean.java Fri Jun 13 05:02:11 2008
@@ -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.carvalho@fmr.com">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

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DataSourcesValidationBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DataSourcesValidationBean.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DataSourcesValidationBean.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DatasourceAvailableHealthCheckValidator.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DatasourceAvailableHealthCheckValidator.java?rev=667492&view=auto
==============================================================================
--- portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DatasourceAvailableHealthCheckValidator.java (added)
+++ portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DatasourceAvailableHealthCheckValidator.java Fri Jun 13 05:02:11 2008
@@ -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.carvalho@fmr.com">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

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DatasourceAvailableHealthCheckValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DatasourceAvailableHealthCheckValidator.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/DatasourceAvailableHealthCheckValidator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidator.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidator.java?rev=667492&view=auto
==============================================================================
--- portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidator.java (added)
+++ portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidator.java Fri Jun 13 05:02:11 2008
@@ -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.carvalho@fmr.com">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

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidator.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidatorResult.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidatorResult.java?rev=667492&view=auto
==============================================================================
--- portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidatorResult.java (added)
+++ portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidatorResult.java Fri Jun 13 05:02:11 2008
@@ -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.carvalho@fmr.com">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

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidatorResult.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidatorResult.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/HealthCheckValidatorResult.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/PortletApplicationAvailableHeathCheckValidator.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/PortletApplicationAvailableHeathCheckValidator.java?rev=667492&view=auto
==============================================================================
--- portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/PortletApplicationAvailableHeathCheckValidator.java (added)
+++ portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/PortletApplicationAvailableHeathCheckValidator.java Fri Jun 13 05:02:11 2008
@@ -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.carvalho@fmr.com">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

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/PortletApplicationAvailableHeathCheckValidator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/PortletApplicationAvailableHeathCheckValidator.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/healthcheck/validators/PortletApplicationAvailableHeathCheckValidator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/pipeline/valve/HealthCheckValve.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/pipeline/valve/HealthCheckValve.java?rev=667492&view=auto
==============================================================================
--- portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/pipeline/valve/HealthCheckValve.java (added)
+++ portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/pipeline/valve/HealthCheckValve.java Fri Jun 13 05:02:11 2008
@@ -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.carvalho@fmr.com">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

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/pipeline/valve/HealthCheckValve.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/pipeline/valve/HealthCheckValve.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/portal/src/java/org/apache/jetspeed/pipeline/valve/HealthCheckValve.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/src/webapp/WEB-INF/assembly/pipelines.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/src/webapp/WEB-INF/assembly/pipelines.xml?rev=667492&r1=667491&r2=667492&view=diff
==============================================================================
--- portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/src/webapp/WEB-INF/assembly/pipelines.xml (original)
+++ portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/src/webapp/WEB-INF/assembly/pipelines.xml Fri Jun 13 05:02:11 2008
@@ -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"
@@ -638,6 +744,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'>
@@ -681,6 +798,9 @@
             <entry key='/dtconfigure'>
                 <value>dtconfigure-pipeline</value>
             </entry>                        
+            <entry key='/healthcheck'>
+                <value>healthcheck-pipeline</value>
+            </entry>
         </map>        
     </constructor-arg>        
   </bean>

Modified: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/src/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/src/webapp/WEB-INF/web.xml?rev=667492&r1=667491&r2=667492&view=diff
==============================================================================
--- portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/src/webapp/WEB-INF/web.xml (original)
+++ portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/src/webapp/WEB-INF/web.xml Fri Jun 13 05:02:11 2008
@@ -215,6 +215,12 @@
        </servlet-name>
        <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>



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org