This is an automated email from the ASF dual-hosted git repository.

ghenzler pushed a commit to branch 
feature/FELIX-6245-condition-service-interfaces-FELIX-6250-healthcheck-monitor
in repository https://gitbox.apache.org/repos/asf/felix-dev.git

commit a90b002ec5c4b9a3a5fe5117b373420b01f3f40c
Author: georg.henzler <[email protected]>
AuthorDate: Sat Mar 28 01:43:50 2020 +0100

    FELIX-6250 Refactored interval/quartz jobs of async HCs
    
    in order to make them reusable for HealthCheckMonitor
---
 .gitignore                                         |  1 +
 .../executor/async/AsyncHealthCheckExecutor.java   | 84 +++++++++++++---------
 .../impl/executor/async/AsyncHealthCheckJob.java   | 68 ------------------
 .../AsyncIntervalJob.java}                         | 28 ++++----
 .../felix/hc/core/impl/scheduling/AsyncJob.java    | 33 +++++++++
 .../AsyncQuartzCronJob.java}                       | 42 ++++++-----
 .../async => scheduling}/QuartzCronScheduler.java  |  2 +-
 .../scheduling/QuartzCronSchedulerProvider.java    | 68 ++++++++++++++++++
 8 files changed, 193 insertions(+), 133 deletions(-)

diff --git a/.gitignore b/.gitignore
index ee18842..a03bc09 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,4 @@ maven-eclipse.xml
 .idea/
 *~
 dependency-reduced-pom.xml
+.DS_Store
\ No newline at end of file
diff --git 
a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckExecutor.java
 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckExecutor.java
index ac96df5..e3ecc43 100644
--- 
a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckExecutor.java
+++ 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckExecutor.java
@@ -35,7 +35,14 @@ import org.apache.felix.hc.api.execution.HealthCheckMetadata;
 import org.apache.felix.hc.api.execution.HealthCheckSelector;
 import org.apache.felix.hc.core.impl.executor.ExecutionResult;
 import org.apache.felix.hc.core.impl.executor.HealthCheckExecutorThreadPool;
+import org.apache.felix.hc.core.impl.executor.HealthCheckFuture;
+import org.apache.felix.hc.core.impl.executor.HealthCheckFuture.Callback;
 import org.apache.felix.hc.core.impl.executor.HealthCheckResultCache;
+import org.apache.felix.hc.core.impl.scheduling.AsyncQuartzCronJob;
+import org.apache.felix.hc.core.impl.scheduling.AsyncIntervalJob;
+import org.apache.felix.hc.core.impl.scheduling.AsyncJob;
+import org.apache.felix.hc.core.impl.scheduling.QuartzCronScheduler;
+import org.apache.felix.hc.core.impl.scheduling.QuartzCronSchedulerProvider;
 import org.apache.felix.hc.core.impl.util.HealthCheckFilter;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
@@ -56,16 +63,17 @@ public class AsyncHealthCheckExecutor implements 
ServiceListener {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(AsyncHealthCheckExecutor.class);
 
-    @Reference
-    HealthCheckExecutorThreadPool healthCheckExecutorThreadPool;
-
-    private Map<HealthCheckMetadata, ExecutionResult> asyncResultsByDescriptor 
= new ConcurrentHashMap<HealthCheckMetadata, ExecutionResult>();
+    private Map<HealthCheckMetadata, ExecutionResult> asyncResultsByDescriptor 
= new ConcurrentHashMap<>();
 
-    private Map<HealthCheckMetadata, AsyncHealthCheckJob> registeredJobs = new 
HashMap<HealthCheckMetadata, AsyncHealthCheckJob>();
+    private Map<HealthCheckMetadata, AsyncJob> registeredJobs = new 
HashMap<>();
 
     private BundleContext bundleContext;
 
-    private QuartzCronScheduler quartzCronScheduler = null;
+    @Reference
+    HealthCheckExecutorThreadPool healthCheckExecutorThreadPool;
+    
+    @Reference
+    QuartzCronSchedulerProvider quartzCronSchedulerProvider;
 
     @Activate
     protected final void activate(final ComponentContext componentContext) 
throws InvalidSyntaxException {
@@ -95,10 +103,6 @@ public class AsyncHealthCheckExecutor implements 
ServiceListener {
         for (HealthCheckMetadata healthCheckDescriptor : new 
LinkedList<HealthCheckMetadata>(registeredJobs.keySet())) {
             unscheduleHealthCheck(healthCheckDescriptor);
         }
-
-        if (quartzCronScheduler != null) {
-            quartzCronScheduler.shutdown();
-        }
     }
 
     @Override
@@ -131,24 +135,18 @@ public class AsyncHealthCheckExecutor implements 
ServiceListener {
     private boolean scheduleHealthCheck(HealthCheckMetadata descriptor) {
 
         try {
-            AsyncHealthCheckJob healthCheckAsyncJob = null;
-
+            AsyncJob healthCheckAsyncJob = null;
+            
             if (isAsyncCron(descriptor)) {
-
-                if (quartzCronScheduler == null) {
-                    if (classExists("org.quartz.CronTrigger")) {
-                        quartzCronScheduler = new 
QuartzCronScheduler(healthCheckExecutorThreadPool);
-                        LOG.info("Created quartz scheduler for async HC");
-                    } else {
-                        LOG.warn("Can not schedule async health check '{}' 
with cron expression '{}' since quartz library is not on classpath", 
descriptor.getName(), descriptor.getAsyncCronExpression());
-                        return false;
-                    }
+               
+                try {
+                               healthCheckAsyncJob = new 
AsyncQuartzCronJob(getAsyncJob(descriptor), quartzCronSchedulerProvider, 
"job-hc-" + descriptor.getServiceId(), "async-healthchecks", 
descriptor.getAsyncCronExpression());
+                } catch(ClassNotFoundException|NoClassDefFoundError e) {
+                    LOG.warn("Can not schedule async health check '{}' with 
cron expression '{}' since quartz library is not on classpath", 
descriptor.getName(), descriptor.getAsyncCronExpression());
+                    return false;
                 }
-
-                healthCheckAsyncJob = new 
AsyncHealthCheckQuartzCronJob(descriptor, this, bundleContext, 
quartzCronScheduler);
             } else if (isAsyncInterval(descriptor)) {
-
-                healthCheckAsyncJob = new 
AsyncHealthCheckIntervalJob(descriptor, this, bundleContext, 
healthCheckExecutorThreadPool);
+                healthCheckAsyncJob = new 
AsyncIntervalJob(getAsyncJob(descriptor), healthCheckExecutorThreadPool, 
descriptor.getAsyncIntervalInSec());
             }
 
             if (healthCheckAsyncJob != null) {
@@ -166,13 +164,38 @@ public class AsyncHealthCheckExecutor implements 
ServiceListener {
 
     }
 
+       private Runnable getAsyncJob(HealthCheckMetadata descriptor) {
+               
+               return new Runnable() {
+                       @Override
+                       public void run() {
+                       LOG.debug("Running job {}", this);
+                       HealthCheckFuture healthCheckFuture = new 
HealthCheckFuture(descriptor, bundleContext, new Callback() {
+
+                           @Override
+                           public void finished(HealthCheckExecutionResult 
result) {
+                               updateWith(result);
+                           }
+                       });
+
+                       // run future in same thread (as we are already async 
via scheduler)
+                       healthCheckFuture.run();
+                       }
+                       
+                       @Override
+                       public String toString() {
+                               return descriptor.toString();
+                       }
+               };
+       }
+
     private boolean unscheduleHealthCheck(HealthCheckMetadata descriptor) {
 
         // here no check for isAsync must be used to ensure previously
         // scheduled async checks are correctly unscheduled if they have
         // changed from async to sync.
 
-        AsyncHealthCheckJob job = registeredJobs.remove(descriptor);
+        AsyncJob job = registeredJobs.remove(descriptor);
         if (job != null) {
             return job.unschedule();
         } else {
@@ -250,13 +273,4 @@ public class AsyncHealthCheckExecutor implements 
ServiceListener {
         return healthCheckMetadata.getAsyncIntervalInSec() != null && 
healthCheckMetadata.getAsyncIntervalInSec() > 0L;
     }
 
-    private boolean classExists(String className) {
-        try {
-            Class.forName(className);
-            return true;
-        } catch (ClassNotFoundException e) {
-            return false;
-        }
-    }
-
 }
diff --git 
a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckJob.java
 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckJob.java
deleted file mode 100644
index 161d7d4..0000000
--- 
a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckJob.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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 SF 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.felix.hc.core.impl.executor.async;
-
-import org.apache.felix.hc.api.execution.HealthCheckExecutionResult;
-import org.apache.felix.hc.api.execution.HealthCheckMetadata;
-import org.apache.felix.hc.core.impl.executor.HealthCheckFuture;
-import org.apache.felix.hc.core.impl.executor.HealthCheckFuture.Callback;
-import org.osgi.framework.BundleContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/** Abstract class for async execution variants cron/interval. */
-public abstract class AsyncHealthCheckJob implements Runnable {
-    private static final Logger LOG = 
LoggerFactory.getLogger(AsyncHealthCheckJob.class);
-
-    protected final HealthCheckMetadata healthCheckDescriptor;
-    protected final AsyncHealthCheckExecutor asyncHealthCheckExecutor;
-    protected final BundleContext bundleContext;
-
-    public AsyncHealthCheckJob(HealthCheckMetadata healthCheckDescriptor, 
AsyncHealthCheckExecutor asyncHealthCheckExecutor,
-            BundleContext bundleContext) {
-        this.healthCheckDescriptor = healthCheckDescriptor;
-        this.asyncHealthCheckExecutor = asyncHealthCheckExecutor;
-        this.bundleContext = bundleContext;
-    }
-
-    @Override
-    public void run() {
-
-        LOG.debug("Running job {}", this);
-        HealthCheckFuture healthCheckFuture = new 
HealthCheckFuture(healthCheckDescriptor, bundleContext, new Callback() {
-
-            @Override
-            public void finished(HealthCheckExecutionResult result) {
-                asyncHealthCheckExecutor.updateWith(result);
-            }
-        });
-
-        // run future in same thread (as we are already async via scheduler)
-        healthCheckFuture.run();
-
-    }
-
-    public abstract boolean schedule();
-
-    public abstract boolean unschedule();
-
-    @Override
-    public String toString() {
-        return "[Async job for " + this.healthCheckDescriptor + "]";
-    }
-}
\ No newline at end of file
diff --git 
a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckIntervalJob.java
 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncIntervalJob.java
similarity index 67%
rename from 
healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckIntervalJob.java
rename to 
healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncIntervalJob.java
index 3561382..a5758b4 100644
--- 
a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckIntervalJob.java
+++ 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncIntervalJob.java
@@ -15,32 +15,31 @@
  * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations under the License.
  */
-package org.apache.felix.hc.core.impl.executor.async;
+package org.apache.felix.hc.core.impl.scheduling;
 
 import java.util.concurrent.ScheduledFuture;
 
-import org.apache.felix.hc.api.execution.HealthCheckMetadata;
 import org.apache.felix.hc.core.impl.executor.HealthCheckExecutorThreadPool;
-import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /** Runs health checks that are configured with an interval 
(ScheduledThreadPoolExecutor.scheduleAtFixedRate()) for asynchronous execution. 
 */
-public class AsyncHealthCheckIntervalJob extends AsyncHealthCheckJob 
implements Runnable {
-    private static final Logger LOG = 
LoggerFactory.getLogger(AsyncHealthCheckExecutor.class);
+public class AsyncIntervalJob extends AsyncJob {
+    private static final Logger LOG = 
LoggerFactory.getLogger(AsyncIntervalJob.class);
 
     private final HealthCheckExecutorThreadPool healthCheckExecutorThreadPool;
+    private final Long asyncIntervalInSec;
+    
     private ScheduledFuture<?> scheduleFuture = null;
 
-    public AsyncHealthCheckIntervalJob(HealthCheckMetadata 
healthCheckDescriptor, AsyncHealthCheckExecutor asyncHealthCheckExecutor,
-            BundleContext bundleContext, HealthCheckExecutorThreadPool 
healthCheckExecutorThreadPool) {
-        super(healthCheckDescriptor, asyncHealthCheckExecutor, bundleContext);
+    public AsyncIntervalJob(Runnable runnable, HealthCheckExecutorThreadPool 
healthCheckExecutorThreadPool, Long asyncIntervalInSec) {
+        super(runnable);
         this.healthCheckExecutorThreadPool = healthCheckExecutorThreadPool;
+        this.asyncIntervalInSec = asyncIntervalInSec;
     }
 
     public boolean schedule() {
-        Long asyncIntervalInSec = 
healthCheckDescriptor.getAsyncIntervalInSec();
-        scheduleFuture = 
healthCheckExecutorThreadPool.scheduleAtFixedRate(this, asyncIntervalInSec);
+        scheduleFuture = 
healthCheckExecutorThreadPool.scheduleAtFixedRate(runnable, asyncIntervalInSec);
         LOG.info("Scheduled job {} for execution every {}sec", this, 
asyncIntervalInSec);
         return true;
     }
@@ -49,12 +48,17 @@ public class AsyncHealthCheckIntervalJob extends 
AsyncHealthCheckJob implements
     public boolean unschedule() {
 
         if (scheduleFuture != null) {
-            LOG.debug("Unscheduling async job for {}", healthCheckDescriptor);
+            LOG.debug("Unscheduling async job for {}", runnable);
             return scheduleFuture.cancel(false);
         } else {
-            LOG.debug("No scheduled future for {} exists", 
healthCheckDescriptor);
+            LOG.debug("No scheduled future for {} exists", runnable);
             return false;
         }
     }
+    
+    @Override
+    public String toString() {
+        return "[Async interval job for " + runnable + "]";
+    }
 
 }
\ No newline at end of file
diff --git 
a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncJob.java
 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncJob.java
new file mode 100644
index 0000000..18d5c68
--- /dev/null
+++ 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncJob.java
@@ -0,0 +1,33 @@
+/*
+ * 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 SF 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.felix.hc.core.impl.scheduling;
+
+/** Abstract class for async scheduling variants cron/interval. */
+public abstract class AsyncJob  {
+
+    protected final Runnable runnable;
+
+    public AsyncJob(Runnable runnable) {
+        this.runnable = runnable;
+    }
+
+    public abstract boolean schedule();
+
+    public abstract boolean unschedule();
+
+}
\ No newline at end of file
diff --git 
a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckQuartzCronJob.java
 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncQuartzCronJob.java
similarity index 72%
rename from 
healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckQuartzCronJob.java
rename to 
healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncQuartzCronJob.java
index fed885c..15317e0 100644
--- 
a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/AsyncHealthCheckQuartzCronJob.java
+++ 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/AsyncQuartzCronJob.java
@@ -15,14 +15,12 @@
  * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations under the License.
  */
-package org.apache.felix.hc.core.impl.executor.async;
+package org.apache.felix.hc.core.impl.scheduling;
 
 import static org.quartz.CronScheduleBuilder.cronSchedule;
 import static org.quartz.JobBuilder.newJob;
 import static org.quartz.TriggerBuilder.newTrigger;
 
-import org.apache.felix.hc.api.execution.HealthCheckMetadata;
-import org.osgi.framework.BundleContext;
 import org.quartz.CronTrigger;
 import org.quartz.Job;
 import org.quartz.JobDataMap;
@@ -39,18 +37,24 @@ import org.slf4j.LoggerFactory;
  * 
  * This implementation uses quartz to support the cron syntax (which is not 
supported by executors from standard java java.util.concurrent
  * package) */
-public class AsyncHealthCheckQuartzCronJob extends AsyncHealthCheckJob 
implements Runnable {
-    private static final Logger LOG = 
LoggerFactory.getLogger(AsyncHealthCheckExecutor.class);
+public class AsyncQuartzCronJob extends AsyncJob {
+    private static final Logger LOG = 
LoggerFactory.getLogger(AsyncQuartzCronJob.class);
 
     private static final String JOB_DATA_KEY_JOB = "asyncHcJob";
 
     protected final QuartzCronScheduler quartzCronScheduler;
+    private final String id;
+    private final String group;
+    private final String cronExpression;
+
     private JobKey jobKey = null;
 
-    public AsyncHealthCheckQuartzCronJob(HealthCheckMetadata 
healthCheckDescriptor, AsyncHealthCheckExecutor asyncHealthCheckExecutor,
-            BundleContext bundleContext, QuartzCronScheduler quartzScheduler) {
-        super(healthCheckDescriptor, asyncHealthCheckExecutor, bundleContext);
-        this.quartzCronScheduler = quartzScheduler;
+    public AsyncQuartzCronJob(Runnable runnable, QuartzCronSchedulerProvider 
quartzCronSchedulerProvider, String id, String group, String cronExpression) 
throws ClassNotFoundException {
+        super(runnable);
+        this.quartzCronScheduler = 
quartzCronSchedulerProvider.getQuartzCronScheduler();
+        this.id = id;
+        this.group = group;
+        this.cronExpression = cronExpression;
     }
 
     public JobKey getJobKey() {
@@ -59,10 +63,10 @@ public class AsyncHealthCheckQuartzCronJob extends 
AsyncHealthCheckJob implement
 
     private JobDetail getQuartzJobDetail() {
         JobDataMap jobData = new JobDataMap();
-        jobData.put(JOB_DATA_KEY_JOB, this);
+        jobData.put(JOB_DATA_KEY_JOB, runnable);
 
-        JobDetail job = 
newJob(AsyncHealthCheckQuartzCronJob.QuartzJob.class).setJobData(jobData)
-                .withIdentity("job-hc-" + 
healthCheckDescriptor.getServiceId(), "async-healthchecks")
+        JobDetail job = 
newJob(AsyncQuartzCronJob.QuartzJob.class).setJobData(jobData)
+                .withIdentity(id, group)
                 .build();
 
         jobKey = job.getKey();
@@ -76,14 +80,14 @@ public class AsyncHealthCheckQuartzCronJob extends 
AsyncHealthCheckJob implement
             Scheduler scheduler = quartzCronScheduler.getScheduler();
 
             JobDetail job = getQuartzJobDetail();
-            CronTrigger cronTrigger = 
newTrigger().withSchedule(cronSchedule(healthCheckDescriptor.getAsyncCronExpression())).forJob(job)
+            CronTrigger cronTrigger = 
newTrigger().withSchedule(cronSchedule(cronExpression)).forJob(job)
                     .build();
 
             scheduler.scheduleJob(job, cronTrigger);
             LOG.info("Scheduled job {} with trigger {}", job, cronTrigger);
             return true;
         } catch (SchedulerException e) {
-            LOG.error("Could not schedule job for " + healthCheckDescriptor + 
": " + e, e);
+            LOG.error("Could not schedule job for " + runnable + ": " + e, e);
             return false;
         }
 
@@ -102,15 +106,19 @@ public class AsyncHealthCheckQuartzCronJob extends 
AsyncHealthCheckJob implement
         }
     }
 
+    @Override
+    public String toString() {
+        return "[Async quartz job for " + runnable + "]";
+    }
+    
     // quartz forces to pass in a class object (and not an instance), hence 
this helper class is needed
     public static class QuartzJob implements Job {
 
         @Override
         public void execute(JobExecutionContext context) throws 
JobExecutionException {
-            AsyncHealthCheckQuartzCronJob hc = (AsyncHealthCheckQuartzCronJob) 
context.getJobDetail().getJobDataMap().get(JOB_DATA_KEY_JOB);
-            hc.run();
+               Runnable ayncJob = (Runnable) 
context.getJobDetail().getJobDataMap().get(JOB_DATA_KEY_JOB);
+               ayncJob.run();
         }
-
     }
 
 }
\ No newline at end of file
diff --git 
a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/QuartzCronScheduler.java
 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronScheduler.java
similarity index 98%
rename from 
healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/QuartzCronScheduler.java
rename to 
healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronScheduler.java
index c43b97e..8fc6cb7 100644
--- 
a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/executor/async/QuartzCronScheduler.java
+++ 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronScheduler.java
@@ -15,7 +15,7 @@
  * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations under the License.
  */
-package org.apache.felix.hc.core.impl.executor.async;
+package org.apache.felix.hc.core.impl.scheduling;
 
 import org.apache.felix.hc.core.impl.executor.HealthCheckExecutorThreadPool;
 import org.quartz.Scheduler;
diff --git 
a/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronSchedulerProvider.java
 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronSchedulerProvider.java
new file mode 100644
index 0000000..70b4f8e
--- /dev/null
+++ 
b/healthcheck/core/src/main/java/org/apache/felix/hc/core/impl/scheduling/QuartzCronSchedulerProvider.java
@@ -0,0 +1,68 @@
+/*
+ * 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 SF 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.felix.hc.core.impl.scheduling;
+
+import org.apache.felix.hc.core.impl.executor.HealthCheckExecutorThreadPool;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Component without direct quartz imports (can always start) that will 
provide a QuartzCronScheduler on demand. */
+@Component(service = QuartzCronSchedulerProvider.class)
+public class QuartzCronSchedulerProvider {
+
+       private static final Logger LOG = 
LoggerFactory.getLogger(QuartzCronSchedulerProvider.class);
+    private static final String CLASS_FROM_QUARTZ_FRAMEWORK = 
"org.quartz.CronTrigger";
+
+       private QuartzCronScheduler quartzCronScheduler = null;
+       
+    @Reference
+    HealthCheckExecutorThreadPool healthCheckExecutorThreadPool;
+       
+       public synchronized QuartzCronScheduler getQuartzCronScheduler() throws 
ClassNotFoundException {
+        if (quartzCronScheduler == null) {
+            if (classExists(CLASS_FROM_QUARTZ_FRAMEWORK)) {
+                quartzCronScheduler = new 
QuartzCronScheduler(healthCheckExecutorThreadPool);
+                LOG.info("Created quartz scheduler health check core bundle");
+            } else {
+                throw new ClassNotFoundException("Class " + 
CLASS_FROM_QUARTZ_FRAMEWORK + " was not found (install quartz library into 
classpath)");
+            }
+        }
+        return quartzCronScheduler;
+       }
+       
+       @Deactivate
+       protected synchronized void deactivate() {
+               if (quartzCronScheduler != null) {
+                       quartzCronScheduler.shutdown();
+                       quartzCronScheduler = null;
+                       LOG.info("QuartzCronScheduler shutdown");
+               }
+       }
+       
+    private boolean classExists(String className) {
+        try {
+            Class.forName(className);
+            return true;
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+    }
+}

Reply via email to