Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
rymsha committed Jan 7, 2025
1 parent 5a403cf commit 6b2ac78
Show file tree
Hide file tree
Showing 14 changed files with 128 additions and 68 deletions.
26 changes: 7 additions & 19 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ repositories {
xp.enonicRepo()
}

sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = sourceCompatibility

configurations {
includeLib { transitive = false }
}
Expand All @@ -32,38 +35,23 @@ dependencies {
testImplementation "com.enonic.xp:testing:${xpVersion}"
}

task copyPropertyFiles(type: Copy) {
def libFile = file(configurations.includeLib.singleFile)
def libFiles = zipTree(libFile)

def propertySpec = copySpec {
from libFiles
include "CronUtilsI18N*.properties"

}

into "${buildDir}/resources/main/properties" with propertySpec

}

task copyClassFiles(type: Copy) {
task copyLibFiles(type: Copy) {
def libFile = file(configurations.includeLib.singleFile)
def libFiles = zipTree(libFile)

def classSpec = copySpec {
from libFiles
include "**/*.class"
include "**/*.**"
exclude "META-INF/**"
}

into "${buildDir}/classes/java/main" with classSpec
}

jar {
from 'CronUtilsI18N_*.properties'
from '*.class'
}

processResources.dependsOn copyPropertyFiles, copyClassFiles
processResources.dependsOn copyLibFiles

jacocoTestReport {
reports {
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
3 changes: 2 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
26 changes: 16 additions & 10 deletions gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

##############################################################################
#
Expand Down Expand Up @@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
Expand Down Expand Up @@ -83,7 +85,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Expand Down Expand Up @@ -130,26 +133,29 @@ location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi

# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
Expand Down Expand Up @@ -198,11 +204,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.

set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
Expand Down
22 changes: 12 additions & 10 deletions gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem

@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
Expand Down Expand Up @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

Expand All @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto execute

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

Expand Down
6 changes: 4 additions & 2 deletions src/main/java/com/enonic/lib/cron/handler/LibCronHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.enonic.lib.cron.model.params.ListJobsParams;
import com.enonic.lib.cron.model.params.ScheduleParams;
import com.enonic.lib.cron.provider.CronJobProvider;
import com.enonic.lib.cron.scheduler.JobExecutorService;
import com.enonic.xp.context.Context;
import com.enonic.xp.script.bean.BeanContext;
import com.enonic.xp.script.bean.ScriptBean;
Expand All @@ -18,8 +19,9 @@ public final class LibCronHandler
@Override
public void initialize( final BeanContext context )
{
this.cronJobProvider = new CronJobProvider( context.getApplicationKey(), context.getBinding( Context.class ).get(),
context.getService( SecurityService.class ).get() );
this.cronJobProvider =
new CronJobProvider( context.getBinding( Context.class ).get(), context.getService( SecurityService.class ).get(),
context.getService( JobExecutorService.class ).get() );
}

public void schedule( final ScheduleParams params )
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/enonic/lib/cron/model/CronTrigger.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final class CronTrigger
private static final CronParser PARSER = new CronParser( DEFINITION );

private static final CronDescriptor DESCRIPTOR =
new CronDescriptor( ResourceBundle.getBundle( "properties/CronUtilsI18N", Locale.UK ) );
new CronDescriptor( ResourceBundle.getBundle( "com/cronutils/CronUtilsI18N", Locale.ROOT ) );

private final Cron cron;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import com.enonic.lib.cron.model.JobDescriptorFactory;
import com.enonic.lib.cron.model.params.ListJobsParams;
import com.enonic.lib.cron.model.params.ScheduleParams;
import com.enonic.lib.cron.scheduler.JobExecutorService;
import com.enonic.lib.cron.scheduler.JobScheduler;
import com.enonic.xp.app.ApplicationKey;
import com.enonic.xp.context.Context;
import com.enonic.xp.security.SecurityService;

Expand All @@ -19,10 +19,10 @@ public class CronJobProvider

private final JobScheduler jobScheduler;

public CronJobProvider( final ApplicationKey applicationKey, final Context context, final SecurityService securityService )
public CronJobProvider( final Context context, final SecurityService securityService, final JobExecutorService jobExecutorService )
{
this.jobDescriptorFactory = new JobDescriptorFactory( securityService, context );
this.jobScheduler = new JobScheduler( applicationKey );
this.jobScheduler = new JobScheduler( jobExecutorService );
}

public void schedule( final ScheduleParams params )
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.enonic.lib.cron.scheduler;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;

@Component(immediate = true, service = JobExecutorService.class)
public class JobExecutorService
{
private ScheduledExecutorService scheduledExecutorService;

@Activate
public void activate( final BundleContext context )
{
final String applicationKey = context.getBundle().getSymbolicName();
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor( new ThreadFactoryImpl( applicationKey + "-job-thread" ) );
}

@Deactivate
public void deactivate()
{
this.scheduledExecutorService.shutdownNow();
}

Check warning on line 29 in src/main/java/com/enonic/lib/cron/scheduler/JobExecutorService.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/enonic/lib/cron/scheduler/JobExecutorService.java#L28-L29

Added lines #L28 - L29 were not covered by tests

public ScheduledFuture<?> scheduleWithFixedDelay( Runnable command, long initialDelay, long delay, TimeUnit unit )
{
return this.scheduledExecutorService.scheduleWithFixedDelay( command, initialDelay, delay, unit );
}

public ScheduledFuture<?> schedule( Runnable command, long delay, TimeUnit unit )
{
return this.scheduledExecutorService.schedule( command, delay, unit );
}
}
17 changes: 6 additions & 11 deletions src/main/java/com/enonic/lib/cron/scheduler/JobScheduler.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
Expand All @@ -16,26 +14,23 @@
import org.slf4j.LoggerFactory;

import com.enonic.lib.cron.model.JobDescriptor;
import com.enonic.xp.app.ApplicationKey;

public final class JobScheduler
{
private static final Logger LOG = LoggerFactory.getLogger( JobScheduler.class );

private final ScheduledExecutorService scheduledExecutorService;
private final JobExecutorService jobExecutorService;

private final Map<String, RecurringJob> tasks = new LinkedHashMap<>();

public JobScheduler( final ApplicationKey applicationKey )
public JobScheduler( final JobExecutorService executorService )
{
this.scheduledExecutorService =
Executors.newSingleThreadScheduledExecutor( new ThreadFactoryImpl( applicationKey + "-job-thread" ) );
this.jobExecutorService = executorService;
}

public synchronized void deactivate()
{
this.tasks.clear();
this.scheduledExecutorService.shutdownNow();
}

public synchronized void unschedule( final String jobName )
Expand All @@ -60,8 +55,8 @@ public synchronized void schedule( final JobDescriptor job )
final JobExecutionCommand command = new JobExecutionCommand( job, rerunCommandCallback, runCheckFunction );

final ScheduledFuture<?> scheduledFuture = cron
? this.scheduledExecutorService.schedule( command, job.nextExecution().toMillis(), TimeUnit.MILLISECONDS )
: this.scheduledExecutorService.scheduleWithFixedDelay( command, job.getDelay(), job.getFixedDelay(), TimeUnit.MILLISECONDS );
? this.jobExecutorService.schedule( command, job.nextExecution().toMillis(), TimeUnit.MILLISECONDS )
: this.jobExecutorService.scheduleWithFixedDelay( command, job.getDelay(), job.getFixedDelay(), TimeUnit.MILLISECONDS );

final RecurringJob existed = this.tasks.put( job.getName(), new RecurringJob( scheduledFuture, job ) );
if ( existed != null )
Expand Down Expand Up @@ -120,7 +115,7 @@ private synchronized void rerunCommandCallback( final JobExecutionCommand comman
{
// Our job is still in the map, so we can reschedule it
final ScheduledFuture<?> scheduledFuture =
this.scheduledExecutorService.schedule( command, descriptor.nextExecution().toMillis(), TimeUnit.MILLISECONDS );
this.jobExecutorService.schedule( command, descriptor.nextExecution().toMillis(), TimeUnit.MILLISECONDS );
return new RecurringJob( scheduledFuture, descriptor );
}
else
Expand Down
4 changes: 0 additions & 4 deletions src/main/resources/lib/cron.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
const service = __.newBean('com.enonic.lib.cron.handler.LibCronHandler');

__.disposer(function () {
service.deactivate();
});

function required(params, name) {
const value = params[name];
if (value === undefined) {
Expand Down
17 changes: 15 additions & 2 deletions src/test/java/com/enonic/lib/cron/handler/LibCronHandlerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;

import com.enonic.lib.cron.scheduler.JobExecutorService;
import com.enonic.xp.security.PrincipalKey;
import com.enonic.xp.security.SecurityService;
import com.enonic.xp.security.User;
import com.enonic.xp.security.auth.AuthenticationInfo;
import com.enonic.xp.security.auth.AuthenticationToken;
import com.enonic.xp.testing.ScriptTestSupport;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class LibCronHandlerTest
extends ScriptTestSupport
{
Expand All @@ -22,8 +29,14 @@ public void initialize()
{
super.initialize();

this.securityService = Mockito.mock( SecurityService.class );
this.securityService = mock( SecurityService.class );
addService( SecurityService.class, this.securityService );

JobExecutorService jobExecutorService = mock( JobExecutorService.class );

when( jobExecutorService.scheduleWithFixedDelay( any(), anyLong(), anyLong(), any() ) ).thenReturn( mock() );
when( jobExecutorService.schedule( any(), anyLong(), any() ) ).thenReturn( mock() );
addService( JobExecutorService.class, jobExecutorService );
}

@Test
Expand All @@ -41,7 +54,7 @@ public void testScheduleWithCron()
@Test
public void testScheduleWithContext()
{
Mockito.when( this.securityService.authenticate( Mockito.isA( AuthenticationToken.class ) ) ).
when( this.securityService.authenticate( Mockito.isA( AuthenticationToken.class ) ) ).
thenReturn( AuthenticationInfo.create().
user( User.create().
login( "test-user" ).
Expand Down
Loading

0 comments on commit 6b2ac78

Please sign in to comment.