[SYNCOPE-1103] Option to put Quartz scheduler in standby, from provisioning.properties
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/67ecbea3 Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/67ecbea3 Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/67ecbea3 Branch: refs/heads/2_0_X Commit: 67ecbea39eb9d54f73ab6fcd79fdbe57de399e3b Parents: 69a0fe4 Author: Francesco Chicchiriccò <ilgro...@apache.org> Authored: Tue Jun 6 15:01:54 2017 +0200 Committer: Francesco Chicchiriccò <ilgro...@apache.org> Committed: Tue Jun 6 15:02:14 2017 +0200 ---------------------------------------------------------------------- core/logic/pom.xml | 4 - .../syncope/core/logic/AnyObjectLogic.java | 1 + .../apache/syncope/core/logic/GroupLogic.java | 4 + .../core/logic/LogicInvocationHandler.java | 37 +- .../syncope/core/logic/NotificationLogic.java | 2 +- .../apache/syncope/core/logic/ReportLogic.java | 20 +- .../apache/syncope/core/logic/SyncopeLogic.java | 7 +- .../core/logic/SystemLoadReporterJob.java | 57 -- .../apache/syncope/core/logic/TaskLogic.java | 2 +- .../apache/syncope/core/logic/UserLogic.java | 2 + .../core/logic/cocoon/FopSerializer.java | 82 +++ .../core/logic/cocoon/TextSerializer.java | 83 +++ .../core/logic/cocoon/XSLTTransformer.java | 193 +++++++ .../syncope/core/logic/init/JobManagerImpl.java | 379 -------------- .../logic/notification/NotificationJob.java | 86 --- .../notification/NotificationJobDelegate.java | 259 --------- .../core/logic/report/AbstractReportlet.java | 52 -- .../core/logic/report/AuditReportlet.java | 141 ----- .../core/logic/report/FopSerializer.java | 82 --- .../core/logic/report/GroupReportlet.java | 316 ----------- .../logic/report/ReconciliationReportlet.java | 519 ------------------- .../core/logic/report/ReportException.java | 32 -- .../syncope/core/logic/report/ReportJob.java | 80 --- .../core/logic/report/ReportJobDelegate.java | 198 ------- .../core/logic/report/ReportXMLConst.java | 44 -- .../core/logic/report/StaticReportlet.java | 128 ----- .../core/logic/report/TextSerializer.java | 83 --- .../core/logic/report/UserReportlet.java | 383 -------------- .../core/logic/report/XSLTTransformer.java | 193 ------- .../persistence/jpa/dao/JPAAnyObjectDAO.java | 9 +- .../core/persistence/jpa/dao/JPAGroupDAO.java | 25 +- .../core/persistence/jpa/dao/JPARoleDAO.java | 7 +- .../core/persistence/jpa/dao/JPAUserDAO.java | 9 +- .../test/resources/domains/MasterContent.xml | 20 +- core/provisioning-api/pom.xml | 5 + .../core/provisioning/api/AuditManager.java | 10 +- .../api/event/AfterHandlingEvent.java | 115 ++++ .../api/event/AnyCreatedUpdatedEvent.java | 46 ++ .../provisioning/api/event/AnyDeletedEvent.java | 57 ++ .../api/notification/NotificationManager.java | 8 + core/provisioning-java/pom.xml | 6 +- .../provisioning/java/AuditManagerImpl.java | 20 + .../provisioning/java/ConnectorFacadeProxy.java | 5 + .../provisioning/java/job/JobManagerImpl.java | 393 ++++++++++++++ .../java/job/SystemLoadReporterJob.java | 57 ++ .../java/job/notification/NotificationJob.java | 86 +++ .../notification/NotificationJobDelegate.java | 268 ++++++++++ .../java/job/report/AbstractReportlet.java | 52 ++ .../java/job/report/AuditReportlet.java | 141 +++++ .../java/job/report/GroupReportlet.java | 316 +++++++++++ .../job/report/ReconciliationReportlet.java | 519 +++++++++++++++++++ .../java/job/report/ReportException.java | 32 ++ .../provisioning/java/job/report/ReportJob.java | 80 +++ .../java/job/report/ReportJobDelegate.java | 198 +++++++ .../java/job/report/ReportXMLConst.java | 44 ++ .../java/job/report/StaticReportlet.java | 128 +++++ .../java/job/report/UserReportlet.java | 383 ++++++++++++++ .../notification/NotificationManagerImpl.java | 20 + .../pushpull/AbstractPullResultHandler.java | 20 +- .../pushpull/AbstractPushResultHandler.java | 20 +- .../pushpull/AbstractRealmResultHandler.java | 2 +- .../pushpull/AbstractSyncopeResultHandler.java | 33 -- .../AnyObjectPullResultHandlerImpl.java | 5 + .../pushpull/GroupPullResultHandlerImpl.java | 7 +- .../pushpull/RealmPushResultHandlerImpl.java | 21 +- .../pushpull/UserPullResultHandlerImpl.java | 5 + .../src/main/resources/provisioning.properties | 1 + .../src/main/resources/provisioningContext.xml | 3 + .../spring/event/AnyCreatedUpdatedEvent.java | 47 -- .../core/spring/event/AnyDeletedEvent.java | 53 -- .../src/main/resources/provisioning.properties | 1 + .../client/ElasticsearchIndexManager.java | 4 +- .../core/reference/ITImplementationLookup.java | 10 +- .../main/resources/all/provisioning.properties | 1 + .../resources/mariadb/provisioning.properties | 1 + .../resources/mysql/provisioning.properties | 1 + .../resources/oracle/provisioning.properties | 1 + .../resources/postgres/provisioning.properties | 1 + .../src/main/resources/provisioning.properties | 1 + .../resources/sqlserver/provisioning.properties | 1 + .../syncope/fit/core/AbstractTaskITCase.java | 2 +- .../syncope/fit/core/ConnectorITCase.java | 2 - .../fit/core/NotificationTaskITCase.java | 2 +- .../systemadministration/highavailability.adoc | 26 + 84 files changed, 3523 insertions(+), 3276 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/pom.xml ---------------------------------------------------------------------- diff --git a/core/logic/pom.xml b/core/logic/pom.xml index 7baa863..0ab849f 100644 --- a/core/logic/pom.xml +++ b/core/logic/pom.xml @@ -51,10 +51,6 @@ under the License. <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> - <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-jdbc</artifactId> - </dependency> <dependency> <groupId>org.aspectj</groupId> http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java index c4ee237..b4779df 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java @@ -136,6 +136,7 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectPatch effectiveRealms, searchCond, page, size, orderBy, AnyTypeKind.ANY_OBJECT); return CollectionUtils.collect(matchingAnyObjects, new Transformer<AnyObject, AnyObjectTO>() { + @Transactional(readOnly = true) @Override public AnyObjectTO transform(final AnyObject input) { return binder.getAnyObjectTO(input, details); http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java index c59907c..b93142d 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java @@ -155,6 +155,7 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupPatch> { userDAO.findAllGroups(userDAO.findByUsername(AuthContextUtils.getUsername())), new Transformer<Group, GroupTO>() { + @Transactional(readOnly = true) @Override public GroupTO transform(final Group input) { return binder.getGroupTO(input, true); @@ -193,6 +194,7 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupPatch> { page, size, orderBy), new Transformer<Group, GroupTO>() { + @Transactional(readOnly = true) @Override public GroupTO transform(final Group input) { return binder.getGroupTO(input, details); @@ -220,6 +222,7 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupPatch> { searchCondition, page, size, orderBy, AnyTypeKind.GROUP); return CollectionUtils.collect(matchingGroups, new Transformer<Group, GroupTO>() { + @Transactional(readOnly = true) @Override public GroupTO transform(final Group input) { return binder.getGroupTO(input, details); @@ -281,6 +284,7 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupPatch> { SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.GroupOwnership); sce.getElements().addAll(CollectionUtils.collect(ownedGroups, new Transformer<Group, String>() { + @Transactional(readOnly = true) @Override public String transform(final Group group) { return group.getKey() + " " + group.getName(); http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java b/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java index 87eda20..2d12682 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java @@ -24,6 +24,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.syncope.common.lib.types.AuditElements; import org.apache.syncope.core.provisioning.api.AuditManager; import org.apache.syncope.core.provisioning.api.notification.NotificationManager; +import org.apache.syncope.core.provisioning.api.event.AfterHandlingEvent; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @@ -31,6 +32,7 @@ import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; @Aspect public class LogicInvocationHandler { @@ -43,6 +45,9 @@ public class LogicInvocationHandler { @Autowired private AuditManager auditManager; + @Autowired + private ApplicationEventPublisher publisher; + @Around("execution(* org.apache.syncope.core.logic.AbstractLogic+.*(..))") public Object around(final ProceedingJoinPoint joinPoint) throws Throwable { Class<?> clazz = joinPoint.getTarget().getClass(); @@ -89,27 +94,17 @@ public class LogicInvocationHandler { LOG.debug("After throwing {}.{}", clazz.getSimpleName(), event); throw t; } finally { - if (notificationsAvailable) { - notificationManager.createTasks(AuditElements.EventCategoryType.LOGIC, - category, - null, - event, - condition, - before, - output, - input); - } - - if (auditRequested) { - auditManager.audit(AuditElements.EventCategoryType.LOGIC, - category, - null, - event, - condition, - before, - output, - input); - } + publisher.publishEvent(new AfterHandlingEvent(this, + notificationsAvailable, + auditRequested, + AuditElements.EventCategoryType.LOGIC, + category, + null, + event, + condition, + before, + output, + input)); } } } http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/NotificationLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/NotificationLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/NotificationLogic.java index aa54c0d..3b867b4 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/NotificationLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/NotificationLogic.java @@ -30,12 +30,12 @@ import org.apache.syncope.common.lib.to.NotificationTO; import org.apache.syncope.common.lib.types.JobAction; import org.apache.syncope.common.lib.types.JobType; import org.apache.syncope.common.lib.types.StandardEntitlement; -import org.apache.syncope.core.logic.notification.NotificationJob; import org.apache.syncope.core.persistence.api.dao.NotFoundException; import org.apache.syncope.core.persistence.api.dao.NotificationDAO; import org.apache.syncope.core.persistence.api.entity.Notification; import org.apache.syncope.core.provisioning.api.data.NotificationDataBinder; import org.apache.syncope.core.provisioning.api.job.JobManager; +import org.apache.syncope.core.provisioning.java.job.notification.NotificationJob; import org.quartz.JobKey; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java index 5a27343..1f232ad 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ReportLogic.java @@ -40,29 +40,29 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Triple; import org.apache.syncope.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.to.BulkActionResult; import org.apache.syncope.common.lib.to.ExecTO; +import org.apache.syncope.common.lib.to.JobTO; import org.apache.syncope.common.lib.to.ReportTO; import org.apache.syncope.common.lib.types.ClientExceptionType; +import org.apache.syncope.common.lib.types.JobAction; +import org.apache.syncope.common.lib.types.JobType; import org.apache.syncope.common.lib.types.ReportExecExportFormat; import org.apache.syncope.common.lib.types.ReportExecStatus; +import org.apache.syncope.common.lib.types.StandardEntitlement; +import org.apache.syncope.core.logic.cocoon.FopSerializer; +import org.apache.syncope.core.logic.cocoon.TextSerializer; +import org.apache.syncope.core.logic.cocoon.XSLTTransformer; +import org.apache.syncope.core.persistence.api.dao.ConfDAO; import org.apache.syncope.core.persistence.api.dao.NotFoundException; import org.apache.syncope.core.persistence.api.dao.ReportDAO; import org.apache.syncope.core.persistence.api.dao.ReportExecDAO; +import org.apache.syncope.core.persistence.api.dao.search.OrderByClause; import org.apache.syncope.core.persistence.api.entity.EntityFactory; import org.apache.syncope.core.persistence.api.entity.Report; import org.apache.syncope.core.persistence.api.entity.ReportExec; import org.apache.syncope.core.provisioning.api.data.ReportDataBinder; import org.apache.syncope.core.provisioning.api.job.JobNamer; -import org.apache.syncope.core.logic.report.TextSerializer; -import org.apache.syncope.common.lib.to.BulkActionResult; -import org.apache.syncope.common.lib.to.JobTO; -import org.apache.syncope.common.lib.types.JobAction; -import org.apache.syncope.common.lib.types.JobType; -import org.apache.syncope.common.lib.types.StandardEntitlement; -import org.apache.syncope.core.logic.report.FopSerializer; -import org.apache.syncope.core.logic.report.XSLTTransformer; -import org.apache.syncope.core.persistence.api.dao.ConfDAO; -import org.apache.syncope.core.persistence.api.dao.search.OrderByClause; import org.apache.xmlgraphics.util.MimeConstants; import org.quartz.JobKey; import org.springframework.beans.factory.annotation.Autowired; http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java index bce3c09..149ddea 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java @@ -62,6 +62,8 @@ import org.apache.syncope.core.workflow.api.GroupWorkflowAdapter; import org.apache.syncope.core.workflow.api.UserWorkflowAdapter; import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.PayloadApplicationEvent; +import org.springframework.context.event.EventListener; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -237,10 +239,11 @@ public class SyncopeLogic extends AbstractLogic<AbstractBaseBean> { } } - public void addLoadInstant(final SystemInfo.LoadInstant instant) { + @EventListener + public void addLoadInstant(final PayloadApplicationEvent<SystemInfo.LoadInstant> event) { synchronized (MONITOR) { initSystemInfo(); - SYSTEM_INFO.getLoad().add(instant); + SYSTEM_INFO.getLoad().add(event.getPayload()); } } http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/SystemLoadReporterJob.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/SystemLoadReporterJob.java b/core/logic/src/main/java/org/apache/syncope/core/logic/SystemLoadReporterJob.java deleted file mode 100644 index bb419bc..0000000 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/SystemLoadReporterJob.java +++ /dev/null @@ -1,57 +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 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.syncope.core.logic; - -import java.lang.management.ManagementFactory; -import org.apache.syncope.common.lib.info.SystemInfo; -import org.apache.syncope.core.provisioning.java.job.AbstractInterruptableJob; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** - * Reports about system load. - */ -@Component -public class SystemLoadReporterJob extends AbstractInterruptableJob { - - private static final Integer MB = 1024 * 1024; - - @Autowired - private SyncopeLogic logic; - - @Override - public void execute(final JobExecutionContext context) throws JobExecutionException { - super.execute(context); - - SystemInfo.LoadInstant instant = new SystemInfo.LoadInstant(); - - instant.setSystemLoadAverage(ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage()); - - instant.setUptime(ManagementFactory.getRuntimeMXBean().getUptime()); - - Runtime runtime = Runtime.getRuntime(); - instant.setTotalMemory(runtime.totalMemory() / MB); - instant.setMaxMemory(runtime.maxMemory() / MB); - instant.setFreeMemory(runtime.freeMemory() / MB); - - logic.addLoadInstant(instant); - } -} http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java index 21cb4ee..a310e47 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/TaskLogic.java @@ -53,11 +53,11 @@ import org.apache.syncope.core.persistence.api.entity.task.TaskUtilsFactory; import org.apache.syncope.core.provisioning.api.data.TaskDataBinder; import org.apache.syncope.core.provisioning.api.job.JobNamer; import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor; -import org.apache.syncope.core.logic.notification.NotificationJobDelegate; import org.apache.syncope.core.persistence.api.dao.ConfDAO; import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO; import org.apache.syncope.core.persistence.api.dao.NotificationDAO; import org.apache.syncope.core.provisioning.java.job.TaskJob; +import org.apache.syncope.core.provisioning.java.job.notification.NotificationJobDelegate; import org.quartz.JobDataMap; import org.quartz.JobKey; import org.springframework.beans.factory.annotation.Autowired; http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java index 1672cfd..7cc5414 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java @@ -118,6 +118,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> { page, size, orderBy), new Transformer<User, UserTO>() { + @Transactional(readOnly = true) @Override public UserTO transform(final User input) { return binder.returnUserTO(binder.getUserTO(input, details)); @@ -160,6 +161,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> { searchCondition, page, size, orderBy, AnyTypeKind.USER); return CollectionUtils.collect(matchingUsers, new Transformer<User, UserTO>() { + @Transactional(readOnly = true) @Override public UserTO transform(final User input) { return binder.returnUserTO(binder.getUserTO(input, details)); http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/cocoon/FopSerializer.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/cocoon/FopSerializer.java b/core/logic/src/main/java/org/apache/syncope/core/logic/cocoon/FopSerializer.java new file mode 100644 index 0000000..bacec1f --- /dev/null +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/cocoon/FopSerializer.java @@ -0,0 +1,82 @@ +/* + * 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.syncope.core.logic.cocoon; + +import java.io.File; +import java.io.OutputStream; + +import org.apache.cocoon.pipeline.ProcessingException; +import org.apache.cocoon.pipeline.caching.CacheKey; +import org.apache.cocoon.pipeline.caching.SimpleCacheKey; +import org.apache.cocoon.pipeline.component.CachingPipelineComponent; +import org.apache.cocoon.pipeline.util.StringRepresentation; +import org.apache.cocoon.sax.AbstractSAXSerializer; +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.Fop; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.apps.FopFactoryBuilder; +import org.apache.xmlgraphics.util.MimeConstants; +import org.xml.sax.ContentHandler; + +public class FopSerializer extends AbstractSAXSerializer implements CachingPipelineComponent { + + private static final FopFactory FOP_FACTORY = new FopFactoryBuilder(new File(".").toURI()).build(); + + private String outputFormat; + + /** + * Create a new FOP serializer that produces a PDF in output + */ + public FopSerializer() { + this(MimeConstants.MIME_PDF); + } + + /** + * Create a new FOP serializer that produces the specified mime + * + * @param outputFormat the output's mime type + */ + public FopSerializer(final String outputFormat) { + if (outputFormat == null) { + throw new IllegalArgumentException("The parameter 'outputFormat' mustn't be null."); + } + + this.outputFormat = outputFormat; + } + + @Override + public CacheKey constructCacheKey() { + return new SimpleCacheKey(); + } + + @Override + public void setOutputStream(final OutputStream outputStream) { + try { + Fop fop = FOP_FACTORY.newFop(this.outputFormat, outputStream); + ContentHandler fopContentHandler = fop.getDefaultHandler(); + + this.setContentHandler(fopContentHandler); + } catch (FOPException e) { + throw new ProcessingException("Impossible to initialize FOPSerializer", e); + } + } + + @Override + public String toString() { + return StringRepresentation.buildString(this, "outputFormat=" + this.outputFormat); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/cocoon/TextSerializer.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/cocoon/TextSerializer.java b/core/logic/src/main/java/org/apache/syncope/core/logic/cocoon/TextSerializer.java new file mode 100644 index 0000000..ce4ffb4 --- /dev/null +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/cocoon/TextSerializer.java @@ -0,0 +1,83 @@ +/* + * 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.syncope.core.logic.cocoon; + +import org.apache.cocoon.sax.component.XMLSerializer; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; + +/** + * Converts XML into plain text. It omits all XML tags and writes only character events to the output. Input document + * must have at least one element - root element - which should wrap all the text inside it. + * + */ +public class TextSerializer extends XMLSerializer { + + private static final String UTF_8 = "UTF-8"; + + private static final String TXT = "text"; + + public TextSerializer() { + super(); + super.setOmitXmlDeclaration(true); + } + + @Override + public void setDocumentLocator(final Locator locator) { + // nothing + } + + @Override + public void processingInstruction(final String target, final String data) + throws SAXException { + // nothing + } + + @Override + public void startDTD(final String name, final String publicId, final String systemId) + throws SAXException { + // nothing + } + + @Override + public void endDTD() throws SAXException { + // nothing + } + + @Override + public void startElement(final String uri, final String loc, final String raw, final Attributes atts) + throws SAXException { + // nothing + } + + @Override + public void endElement(final String uri, final String name, final String raw) + throws SAXException { + // nothing + } + + public static TextSerializer createPlainSerializer() { + final TextSerializer serializer = new TextSerializer(); + serializer.setContentType("text/plain; charset=" + UTF_8); + serializer.setEncoding(UTF_8); + serializer.setMethod(TXT); + return serializer; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/cocoon/XSLTTransformer.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/cocoon/XSLTTransformer.java b/core/logic/src/main/java/org/apache/syncope/core/logic/cocoon/XSLTTransformer.java new file mode 100644 index 0000000..1d8c6e2 --- /dev/null +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/cocoon/XSLTTransformer.java @@ -0,0 +1,193 @@ +/* + * 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.syncope.core.logic.cocoon; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; +import javax.xml.transform.Source; +import javax.xml.transform.Templates; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import org.apache.cocoon.pipeline.SetupException; +import org.apache.cocoon.pipeline.caching.CacheKey; +import org.apache.cocoon.pipeline.component.CachingPipelineComponent; +import org.apache.cocoon.pipeline.util.StringRepresentation; +import org.apache.cocoon.sax.AbstractSAXTransformer; +import org.apache.cocoon.sax.SAXConsumer; +import org.apache.cocoon.sax.util.SAXConsumerAdapter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class XSLTTransformer extends AbstractSAXTransformer implements CachingPipelineComponent { + + private static final Logger LOG = LoggerFactory.getLogger(XSLTTransformer.class); + + /** + * A generic transformer factory to parse XSLTs. + */ + private static final SAXTransformerFactory TRAX_FACTORY = createNewSAXTransformerFactory(); + + /** + * The XSLT parameters name pattern. + */ + private static final Pattern XSLT_PARAMETER_NAME_PATTERN = Pattern.compile("[a-zA-Z_][\\w\\-\\.]*"); + + /** + * The XSLT parameters reference. + */ + private Map<String, Object> parameters; + + /** + * The XSLT Template reference. + */ + private Templates templates; + + private Source source; + + public XSLTTransformer(final Source source) { + super(); + this.load(source, null); + } + + /** + * Creates a new transformer reading the XSLT from the Source source and setting the TransformerFactory attributes. + * + * This constructor is useful when users want to perform XSLT transformation using <a + * href="http://xml.apache.org/xalan-j/xsltc_usage.html">xsltc</a>. + * + * @param source the XSLT source + * @param attributes the Transformer Factory attributes + */ + public XSLTTransformer(final Source source, final Map<String, Object> attributes) { + super(); + this.load(source, attributes); + } + + /** + * Method useful to create a new transformer reading the XSLT from the URL source and setting the Transformer + * Factory attributes. + * + * This method is useful when users want to perform XSLT transformation using <a + * href="http://xml.apache.org/xalan-j/xsltc_usage.html">xsltc</a>. + * + * @param source the XSLT source + * @param attributes the Transformer Factory attributes + */ + private void load(final Source source, final Map<String, Object> attributes) { + if (source == null) { + throw new IllegalArgumentException("The parameter 'source' mustn't be null."); + } + + this.source = source; + + this.load(this.source, this.source.toString(), attributes); + } + + private void load(final Source source, final String localCacheKey, final Map<String, Object> attributes) { + LOG.debug("{} local cache miss: {}", getClass().getSimpleName(), localCacheKey); + + // XSLT has to be parsed + final SAXTransformerFactory transformerFactory; + if (attributes == null || attributes.isEmpty()) { + transformerFactory = TRAX_FACTORY; + } else { + transformerFactory = createNewSAXTransformerFactory(); + for (Map.Entry<String, Object> attribute : attributes.entrySet()) { + transformerFactory.setAttribute(attribute.getKey(), attribute.getValue()); + } + } + + try { + this.templates = transformerFactory.newTemplates(source); + } catch (TransformerConfigurationException e) { + throw new SetupException("Impossible to read XSLT from '" + source + "', see nested exception", e); + } + } + + /** + * Sets the XSLT parameters to be applied to XSLT stylesheet. + * + * @param parameters the XSLT parameters to be applied to XSLT stylesheet + */ + public void setParameters(final Map<String, ? extends Object> parameters) { + if (parameters == null) { + this.parameters = null; + } else { + this.parameters = new HashMap<String, Object>(parameters); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected void setSAXConsumer(final SAXConsumer consumer) { + TransformerHandler transformerHandler; + try { + transformerHandler = TRAX_FACTORY.newTransformerHandler(this.templates); + } catch (Exception e) { + throw new SetupException("Could not initialize transformer handler.", e); + } + + if (this.parameters != null) { + final Transformer transformer = transformerHandler.getTransformer(); + + for (Map.Entry<String, Object> entry : this.parameters.entrySet()) { + final String name = entry.getKey(); + + // is valid XSLT parameter name + if (XSLT_PARAMETER_NAME_PATTERN.matcher(name).matches()) { + transformer.setParameter(name, entry.getValue()); + } + } + } + + final SAXResult result = new SAXResult(); + result.setHandler(consumer); + // According to TrAX specs, all TransformerHandlers are LexicalHandlers + result.setLexicalHandler(consumer); + transformerHandler.setResult(result); + + final SAXConsumerAdapter saxConsumerAdapter = new SAXConsumerAdapter(); + saxConsumerAdapter.setContentHandler(transformerHandler); + super.setSAXConsumer(saxConsumerAdapter); + } + + @Override + public CacheKey constructCacheKey() { + return null; + } + + /** + * Utility method to create a new transformer factory. + * + * @return a new transformer factory + */ + private static SAXTransformerFactory createNewSAXTransformerFactory() { + return (SAXTransformerFactory) TransformerFactory.newInstance(); + } + + @Override + public String toString() { + return StringRepresentation.buildString(this, "src=<" + this.source + ">"); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobManagerImpl.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobManagerImpl.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobManagerImpl.java deleted file mode 100644 index d8b08f1..0000000 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobManagerImpl.java +++ /dev/null @@ -1,379 +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 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.syncope.core.logic.init; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import org.apache.commons.collections4.IterableUtils; -import org.apache.commons.collections4.Predicate; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.syncope.common.lib.SyncopeConstants; -import org.apache.syncope.common.lib.types.TaskType; -import org.apache.syncope.core.logic.SystemLoadReporterJob; -import org.apache.syncope.core.persistence.api.dao.ConfDAO; -import org.apache.syncope.core.persistence.api.dao.NotFoundException; -import org.apache.syncope.core.persistence.api.dao.ReportDAO; -import org.apache.syncope.core.persistence.api.dao.TaskDAO; -import org.apache.syncope.core.persistence.api.entity.Report; -import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr; -import org.apache.syncope.core.persistence.api.entity.task.PushTask; -import org.apache.syncope.core.persistence.api.entity.task.SchedTask; -import org.apache.syncope.core.persistence.api.entity.task.Task; -import org.apache.syncope.core.provisioning.api.job.JobNamer; -import org.apache.syncope.core.logic.notification.NotificationJob; -import org.apache.syncope.core.logic.report.ReportJob; -import org.apache.syncope.core.spring.security.AuthContextUtils; -import org.apache.syncope.core.spring.ApplicationContextProvider; -import org.apache.syncope.core.persistence.api.SyncopeLoader; -import org.apache.syncope.core.persistence.api.DomainsHolder; -import org.apache.syncope.core.provisioning.java.job.TaskJob; -import org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate; -import org.apache.syncope.core.provisioning.java.pushpull.PullJobDelegate; -import org.quartz.CronScheduleBuilder; -import org.quartz.Job; -import org.quartz.JobBuilder; -import org.quartz.JobDataMap; -import org.quartz.JobExecutionContext; -import org.quartz.JobKey; -import org.quartz.Scheduler; -import org.quartz.SchedulerException; -import org.quartz.TriggerBuilder; -import org.quartz.TriggerKey; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.scheduling.quartz.SchedulerFactoryBean; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; -import org.apache.syncope.core.provisioning.api.job.JobManager; -import org.identityconnectors.common.IOUtil; -import org.quartz.impl.jdbcjobstore.Constants; -import org.springframework.jdbc.datasource.DataSourceUtils; -import org.apache.syncope.core.persistence.api.entity.task.PullTask; - -@Component -public class JobManagerImpl implements JobManager, SyncopeLoader { - - private static final Logger LOG = LoggerFactory.getLogger(JobManager.class); - - @Autowired - private DomainsHolder domainsHolder; - - @Autowired - private SchedulerFactoryBean scheduler; - - @Autowired - private TaskDAO taskDAO; - - @Autowired - private ReportDAO reportDAO; - - @Autowired - private ConfDAO confDAO; - - private boolean isRunningHere(final JobKey jobKey) throws SchedulerException { - return IterableUtils.matchesAny(scheduler.getScheduler().getCurrentlyExecutingJobs(), - new Predicate<JobExecutionContext>() { - - @Override - public boolean evaluate(final JobExecutionContext jec) { - return jobKey.equals(jec.getJobDetail().getKey()); - } - }); - } - - private boolean isRunningElsewhere(final JobKey jobKey) throws SchedulerException { - if (!scheduler.getScheduler().getMetaData().isJobStoreClustered()) { - return false; - } - - Connection conn = DataSourceUtils.getConnection(domainsHolder.getDomains().get(SyncopeConstants.MASTER_DOMAIN)); - PreparedStatement stmt = null; - ResultSet resultSet = null; - try { - stmt = conn.prepareStatement( - "SELECT 1 FROM " + Constants.DEFAULT_TABLE_PREFIX + "FIRED_TRIGGERS " - + "WHERE JOB_NAME = ? AND JOB_GROUP = ?"); - stmt.setString(1, jobKey.getName()); - stmt.setString(2, jobKey.getGroup()); - - resultSet = stmt.executeQuery(); - return resultSet.next(); - } catch (SQLException e) { - throw new SchedulerException(e); - } finally { - IOUtil.quietClose(resultSet); - IOUtil.quietClose(stmt); - IOUtil.quietClose(conn); - } - } - - @Override - public boolean isRunning(final JobKey jobKey) throws SchedulerException { - return isRunningHere(jobKey) || isRunningElsewhere(jobKey); - } - - private void registerJob( - final String jobName, final Job jobInstance, - final String cronExpression, final Date startAt, - final Map<String, Object> jobMap) - throws SchedulerException { - - if (isRunningHere(new JobKey(jobName, Scheduler.DEFAULT_GROUP))) { - LOG.debug("Job {} already running, cancel", jobName); - return; - } - - // 0. unregister job - unregisterJob(jobName); - - // 1. Job bean - ApplicationContextProvider.getBeanFactory().registerSingleton(jobName, jobInstance); - - // 2. JobDetail bean - JobBuilder jobDetailBuilder = JobBuilder.newJob(jobInstance.getClass()). - withIdentity(jobName). - usingJobData(new JobDataMap(jobMap)); - - // 3. Trigger - if (cronExpression == null && startAt == null) { - // Jobs added with no trigger must be durable - scheduler.getScheduler().addJob(jobDetailBuilder.storeDurably().build(), true); - } else { - TriggerBuilder<?> triggerBuilder; - - if (cronExpression == null) { - triggerBuilder = TriggerBuilder.newTrigger(). - withIdentity(JobNamer.getTriggerName(jobName)). - startAt(startAt); - } else { - triggerBuilder = TriggerBuilder.newTrigger(). - withIdentity(JobNamer.getTriggerName(jobName)). - withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)); - - if (startAt == null) { - triggerBuilder = triggerBuilder.startNow(); - } else { - triggerBuilder = triggerBuilder.startAt(startAt); - } - } - - scheduler.getScheduler().scheduleJob(jobDetailBuilder.build(), triggerBuilder.build()); - } - } - - @SuppressWarnings("unchecked") - private <T> T createSpringBean(final Class<T> jobClass) { - T jobInstance = null; - for (int i = 0; i < 5 && jobInstance == null; i++) { - LOG.debug("{} attempt to create Spring bean for {}", i, jobClass); - try { - jobInstance = (T) ApplicationContextProvider.getBeanFactory(). - createBean(jobClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false); - LOG.debug("{} attempt to create Spring bean for {} succeeded", i, jobClass); - } catch (BeanCreationException e) { - LOG.error("Could not create Spring bean for {}", jobClass, e); - try { - Thread.sleep(1000); - } catch (final InterruptedException ex) { - // ignore - } - } - } - if (jobInstance == null) { - throw new NotFoundException("Spring bean for " + jobClass); - } - - return jobInstance; - } - - @Override - public Map<String, Object> register(final SchedTask task, final Date startAt, final long interruptMaxRetries) - throws SchedulerException { - - TaskJob job = createSpringBean(TaskJob.class); - job.setTaskKey(task.getKey()); - - String jobDelegateClassName = task instanceof PullTask - ? PullJobDelegate.class.getName() - : task instanceof PushTask - ? PushJobDelegate.class.getName() - : task.getJobDelegateClassName(); - - Map<String, Object> jobMap = new HashMap<>(); - jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain()); - jobMap.put(TaskJob.DELEGATE_CLASS_KEY, jobDelegateClassName); - jobMap.put(INTERRUPT_MAX_RETRIES_KEY, interruptMaxRetries); - - registerJob( - JobNamer.getJobKey(task).getName(), - job, - task.getCronExpression(), - startAt, - jobMap); - return jobMap; - } - - @Override - public void register(final Report report, final Date startAt, final long interruptMaxRetries) - throws SchedulerException { - - ReportJob job = createSpringBean(ReportJob.class); - job.setReportKey(report.getKey()); - - Map<String, Object> jobMap = new HashMap<>(); - jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain()); - jobMap.put(INTERRUPT_MAX_RETRIES_KEY, interruptMaxRetries); - - registerJob(JobNamer.getJobKey(report).getName(), job, report.getCronExpression(), startAt, jobMap); - } - - private void unregisterJob(final String jobName) { - try { - scheduler.getScheduler().unscheduleJob(new TriggerKey(jobName, Scheduler.DEFAULT_GROUP)); - scheduler.getScheduler().deleteJob(new JobKey(jobName, Scheduler.DEFAULT_GROUP)); - } catch (SchedulerException e) { - LOG.error("Could not remove job " + jobName, e); - } - - if (ApplicationContextProvider.getBeanFactory().containsSingleton(jobName)) { - ApplicationContextProvider.getBeanFactory().destroySingleton(jobName); - } - } - - @Override - public void unregister(final Task task) { - unregisterJob(JobNamer.getJobKey(task).getName()); - } - - @Override - public void unregister(final Report report) { - unregisterJob(JobNamer.getJobKey(report).getName()); - } - - @Override - public Integer getPriority() { - return 200; - } - - @Transactional - @Override - public void load() { - final Pair<String, Long> conf = AuthContextUtils.execWithAuthContext( - SyncopeConstants.MASTER_DOMAIN, new AuthContextUtils.Executable<Pair<String, Long>>() { - - @Override - public Pair<String, Long> exec() { - String notificationJobCronExpression = StringUtils.EMPTY; - - CPlainAttr notificationJobCronExp = - confDAO.find("notificationjob.cronExpression", NotificationJob.DEFAULT_CRON_EXP); - if (!notificationJobCronExp.getValuesAsStrings().isEmpty()) { - notificationJobCronExpression = notificationJobCronExp.getValuesAsStrings().get(0); - } - - long interruptMaxRetries = - confDAO.find("tasks.interruptMaxRetries", "1").getValues().get(0).getLongValue(); - - return ImmutablePair.of(notificationJobCronExpression, interruptMaxRetries); - } - }); - - for (String domain : domainsHolder.getDomains().keySet()) { - AuthContextUtils.execWithAuthContext(domain, new AuthContextUtils.Executable<Void>() { - - @Override - public Void exec() { - // 1. jobs for SchedTasks - Set<SchedTask> tasks = new HashSet<>(taskDAO.<SchedTask>findAll(TaskType.SCHEDULED)); - tasks.addAll(taskDAO.<PullTask>findAll(TaskType.PULL)); - tasks.addAll(taskDAO.<PushTask>findAll(TaskType.PUSH)); - for (SchedTask task : tasks) { - try { - register(task, task.getStartAt(), conf.getRight()); - } catch (Exception e) { - LOG.error("While loading job instance for task " + task.getKey(), e); - } - } - - // 2. jobs for Reports - for (Report report : reportDAO.findAll()) { - try { - register(report, null, conf.getRight()); - } catch (Exception e) { - LOG.error("While loading job instance for report " + report.getName(), e); - } - } - - return null; - } - }); - } - - Map<String, Object> jobMap = new HashMap<>(); - jobMap.put(JobManager.DOMAIN_KEY, AuthContextUtils.getDomain()); - jobMap.put(INTERRUPT_MAX_RETRIES_KEY, conf.getRight()); - - // 3. NotificationJob - if (StringUtils.isBlank(conf.getLeft())) { - LOG.debug("Empty value provided for {}'s cron, not registering anything on Quartz", - NotificationJob.class.getSimpleName()); - } else { - LOG.debug("{}'s cron expression: {} - registering Quartz job and trigger", - NotificationJob.class.getSimpleName(), conf.getLeft()); - - try { - NotificationJob job = createSpringBean(NotificationJob.class); - registerJob( - NOTIFICATION_JOB.getName(), - job, - conf.getLeft(), - null, - jobMap); - } catch (Exception e) { - LOG.error("While loading {} instance", NotificationJob.class.getSimpleName(), e); - } - } - - // 4. SystemLoadReporterJob (fixed schedule, every minute) - LOG.debug("Registering {}", SystemLoadReporterJob.class); - try { - SystemLoadReporterJob job = createSpringBean(SystemLoadReporterJob.class); - registerJob( - "systemLoadReporterJob", - job, - "0 * * * * ?", - null, - jobMap); - } catch (Exception e) { - LOG.error("While loading {} instance", SystemLoadReporterJob.class.getSimpleName(), e); - } - } -} http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java b/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java deleted file mode 100644 index 7a0270f..0000000 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJob.java +++ /dev/null @@ -1,86 +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 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.syncope.core.logic.notification; - -import org.apache.syncope.core.spring.security.AuthContextUtils; -import org.apache.syncope.core.persistence.api.DomainsHolder; -import org.apache.syncope.core.provisioning.java.job.AbstractInterruptableJob; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** - * Periodically checks for notification to send. - * - * @see org.apache.syncope.core.persistence.api.entity.task.NotificationTask - */ -@Component -public class NotificationJob extends AbstractInterruptableJob { - - public enum Status { - - SENT, - NOT_SENT - - } - - public static final String DEFAULT_CRON_EXP = "0 0/5 * * * ?"; - - private static final Logger LOG = LoggerFactory.getLogger(NotificationJob.class); - - @Autowired - private DomainsHolder domainsHolder; - - @Autowired - private NotificationJobDelegate delegate; - - @Override - public void execute(final JobExecutionContext context) throws JobExecutionException { - super.execute(context); - - LOG.debug("Waking up..."); - - for (String domain : domainsHolder.getDomains().keySet()) { - try { - AuthContextUtils.execWithAuthContext(domain, new AuthContextUtils.Executable<Void>() { - - @Override - public Void exec() { - try { - delegate.execute(); - } catch (Exception e) { - LOG.error("While sending out notifications", e); - throw new RuntimeException(e); - } - - return null; - } - }); - } catch (RuntimeException e) { - LOG.error("While sending out notifications", e); - throw new JobExecutionException("While sending out notifications", e); - } - } - - LOG.debug("Sleeping again..."); - } -} http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJobDelegate.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJobDelegate.java b/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJobDelegate.java deleted file mode 100644 index ea9b1da..0000000 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/notification/NotificationJobDelegate.java +++ /dev/null @@ -1,259 +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 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.syncope.core.logic.notification; - -import java.util.Date; -import java.util.Properties; -import javax.mail.internet.MimeMessage; -import org.apache.commons.lang3.StringUtils; -import org.apache.syncope.common.lib.types.AuditElements; -import org.apache.syncope.common.lib.types.TaskType; -import org.apache.syncope.common.lib.types.TraceLevel; -import org.apache.syncope.core.provisioning.api.utils.ExceptionUtils2; -import org.apache.syncope.core.persistence.api.dao.TaskDAO; -import org.apache.syncope.core.persistence.api.entity.EntityFactory; -import org.apache.syncope.core.persistence.api.entity.task.NotificationTask; -import org.apache.syncope.core.persistence.api.entity.task.TaskExec; -import org.apache.syncope.core.provisioning.api.AuditManager; -import org.apache.syncope.core.provisioning.api.notification.NotificationManager; -import org.quartz.JobExecutionException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.JavaMailSenderImpl; -import org.springframework.mail.javamail.MimeMessageHelper; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -@Component -public class NotificationJobDelegate { - - private static final Logger LOG = LoggerFactory.getLogger(NotificationJobDelegate.class); - - /** - * Task DAO. - */ - @Autowired - private TaskDAO taskDAO; - - @Autowired - private JavaMailSender mailSender; - - @Autowired - private EntityFactory entityFactory; - - @Autowired - private AuditManager auditManager; - - @Autowired - private NotificationManager notificationManager; - - private long maxRetries; - - private void init() { - maxRetries = notificationManager.getMaxRetries(); - - if (mailSender instanceof JavaMailSenderImpl - && StringUtils.isNotBlank(((JavaMailSenderImpl) mailSender).getUsername())) { - - Properties javaMailProperties = ((JavaMailSenderImpl) mailSender).getJavaMailProperties(); - javaMailProperties.setProperty("mail.smtp.auth", "true"); - ((JavaMailSenderImpl) mailSender).setJavaMailProperties(javaMailProperties); - } - } - - @Transactional - public TaskExec executeSingle(final NotificationTask task) { - init(); - - TaskExec execution = entityFactory.newEntity(TaskExec.class); - execution.setTask(task); - execution.setStart(new Date()); - - boolean retryPossible = true; - - if (StringUtils.isBlank(task.getSubject()) || task.getRecipients().isEmpty() - || StringUtils.isBlank(task.getHtmlBody()) || StringUtils.isBlank(task.getTextBody())) { - - String message = "Could not fetch all required information for sending e-mails:\n" - + task.getRecipients() + "\n" - + task.getSender() + "\n" - + task.getSubject() + "\n" - + task.getHtmlBody() + "\n" - + task.getTextBody(); - LOG.error(message); - - execution.setStatus(NotificationJob.Status.NOT_SENT.name()); - retryPossible = false; - - if (task.getTraceLevel().ordinal() >= TraceLevel.FAILURES.ordinal()) { - execution.setMessage(message); - } - } else { - if (LOG.isDebugEnabled()) { - LOG.debug("About to send e-mails:\n" - + task.getRecipients() + "\n" - + task.getSender() + "\n" - + task.getSubject() + "\n" - + task.getHtmlBody() + "\n" - + task.getTextBody() + "\n"); - } - - for (String to : task.getRecipients()) { - try { - MimeMessage message = mailSender.createMimeMessage(); - MimeMessageHelper helper = new MimeMessageHelper(message, true); - helper.setTo(to); - helper.setFrom(task.getSender()); - helper.setSubject(task.getSubject()); - helper.setText(task.getTextBody(), task.getHtmlBody()); - - mailSender.send(message); - - execution.setStatus(NotificationJob.Status.SENT.name()); - - StringBuilder report = new StringBuilder(); - switch (task.getTraceLevel()) { - case ALL: - report.append("FROM: ").append(task.getSender()).append('\n'). - append("TO: ").append(to).append('\n'). - append("SUBJECT: ").append(task.getSubject()).append('\n').append('\n'). - append(task.getTextBody()).append('\n').append('\n'). - append(task.getHtmlBody()).append('\n'); - break; - - case SUMMARY: - report.append("E-mail sent to ").append(to).append('\n'); - break; - - case FAILURES: - case NONE: - default: - } - if (report.length() > 0) { - execution.setMessage(report.toString()); - } - - auditManager.audit( - AuditElements.EventCategoryType.TASK, - "notification", - null, - "send", - AuditElements.Result.SUCCESS, - null, - null, - task, - "Successfully sent notification to " + to); - } catch (Exception e) { - LOG.error("Could not send e-mail", e); - - execution.setStatus(NotificationJob.Status.NOT_SENT.name()); - if (task.getTraceLevel().ordinal() >= TraceLevel.FAILURES.ordinal()) { - execution.setMessage(ExceptionUtils2.getFullStackTrace(e)); - } - - auditManager.audit( - AuditElements.EventCategoryType.TASK, - "notification", - null, - "send", - AuditElements.Result.FAILURE, - null, - null, - task, - "Could not send notification to " + to, e); - } - - execution.setEnd(new Date()); - } - } - - if (hasToBeRegistered(execution)) { - execution = notificationManager.storeExec(execution); - if (retryPossible - && (NotificationJob.Status.valueOf(execution.getStatus()) == NotificationJob.Status.NOT_SENT)) { - - handleRetries(execution); - } - } else { - notificationManager.setTaskExecuted(execution.getTask().getKey(), true); - } - - return execution; - } - - @Transactional - public void execute() throws JobExecutionException { - for (NotificationTask task : taskDAO.<NotificationTask>findToExec(TaskType.NOTIFICATION)) { - LOG.debug("Found notification task {} to be executed: starting...", task); - executeSingle(task); - LOG.debug("Notification task {} executed", task); - } - } - - private boolean hasToBeRegistered(final TaskExec execution) { - NotificationTask task = (NotificationTask) execution.getTask(); - - // True if either failed and failures have to be registered, or if ALL - // has to be registered. - return (NotificationJob.Status.valueOf(execution.getStatus()) == NotificationJob.Status.NOT_SENT - && task.getTraceLevel().ordinal() >= TraceLevel.FAILURES.ordinal()) - || task.getTraceLevel() == TraceLevel.ALL; - } - - private void handleRetries(final TaskExec execution) { - if (maxRetries <= 0) { - return; - } - - long failedExecutionsCount = notificationManager.countExecutionsWithStatus( - execution.getTask().getKey(), NotificationJob.Status.NOT_SENT.name()); - - if (failedExecutionsCount <= maxRetries) { - LOG.debug("Execution of notification task {} will be retried [{}/{}]", - execution.getTask(), failedExecutionsCount, maxRetries); - notificationManager.setTaskExecuted(execution.getTask().getKey(), false); - - auditManager.audit( - AuditElements.EventCategoryType.TASK, - "notification", - null, - "retry", - AuditElements.Result.SUCCESS, - null, - null, - execution, - "Notification task " + execution.getTask().getKey() + " will be retried"); - } else { - LOG.error("Maximum number of retries reached for task {} - giving up", execution.getTask()); - - auditManager.audit( - AuditElements.EventCategoryType.TASK, - "notification", - null, - "retry", - AuditElements.Result.FAILURE, - null, - null, - execution, - "Giving up retries on notification task " + execution.getTask().getKey()); - } - } -} http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/report/AbstractReportlet.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/AbstractReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/AbstractReportlet.java deleted file mode 100644 index 69e6b4f..0000000 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/AbstractReportlet.java +++ /dev/null @@ -1,52 +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 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.syncope.core.logic.report; - -import org.apache.syncope.core.persistence.api.dao.Reportlet; -import org.apache.syncope.common.lib.report.ReportletConf; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.transaction.annotation.Transactional; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; - -public abstract class AbstractReportlet implements Reportlet { - - protected static final Logger LOG = LoggerFactory.getLogger(AbstractReportlet.class); - - protected abstract void doExtract(ReportletConf conf, ContentHandler handler) throws SAXException; - - @Override - @Transactional(readOnly = true) - public void extract(final ReportletConf conf, final ContentHandler handler) throws SAXException { - if (conf == null) { - throw new ReportException(new IllegalArgumentException("No configuration provided")); - } - - AttributesImpl atts = new AttributesImpl(); - atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, conf.getName()); - atts.addAttribute("", "", ReportXMLConst.ATTR_CLASS, ReportXMLConst.XSD_STRING, getClass().getName()); - handler.startElement("", "", ReportXMLConst.ELEMENT_REPORTLET, atts); - - doExtract(conf, handler); - - handler.endElement("", "", ReportXMLConst.ELEMENT_REPORTLET); - } -} http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/report/AuditReportlet.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/AuditReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/AuditReportlet.java deleted file mode 100644 index ffd94a4..0000000 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/AuditReportlet.java +++ /dev/null @@ -1,141 +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 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.syncope.core.logic.report; - -import java.util.List; -import java.util.Map; -import javax.sql.DataSource; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; -import org.apache.syncope.common.lib.report.AuditReportletConf; -import org.apache.syncope.common.lib.report.ReportletConf; -import org.apache.syncope.core.provisioning.java.AuditEntry; -import org.apache.syncope.core.spring.security.AuthContextUtils; -import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.apache.syncope.core.persistence.api.DomainsHolder; -import org.apache.syncope.core.persistence.api.dao.ReportletConfClass; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.core.JdbcTemplate; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; - -@ReportletConfClass(AuditReportletConf.class) -public class AuditReportlet extends AbstractReportlet { - - @Autowired - private DomainsHolder domainsHolder; - - private AuditReportletConf conf; - - private DataSource datasource; - - private void doExtractConf(final ContentHandler handler) throws SAXException { - JdbcTemplate jdbcTemplate = new JdbcTemplate(datasource); - jdbcTemplate.setMaxRows(conf.getSize()); - List<Map<String, Object>> rows = jdbcTemplate. - queryForList("SELECT * FROM SYNCOPEAUDIT ORDER BY EVENT_DATE DESC"); - - handler.startElement("", "", "events", null); - AttributesImpl atts = new AttributesImpl(); - for (Map<String, Object> row : rows) { - AuditEntry auditEntry = POJOHelper.deserialize(row.get("MESSAGE").toString(), AuditEntry.class); - - atts.clear(); - if (StringUtils.isNotBlank(auditEntry.getWho())) { - atts.addAttribute("", "", "who", ReportXMLConst.XSD_STRING, auditEntry.getWho()); - } - handler.startElement("", "", "event", atts); - - atts.clear(); - if (StringUtils.isNotBlank(auditEntry.getLogger().getCategory())) { - atts.addAttribute("", "", "category", - ReportXMLConst.XSD_STRING, auditEntry.getLogger().getCategory()); - } - if (StringUtils.isNotBlank(auditEntry.getLogger().getSubcategory())) { - atts.addAttribute("", "", "subcategory", - ReportXMLConst.XSD_STRING, auditEntry.getLogger().getSubcategory()); - } - if (StringUtils.isNotBlank(auditEntry.getLogger().getEvent())) { - atts.addAttribute("", "", "event", - ReportXMLConst.XSD_STRING, auditEntry.getLogger().getEvent()); - } - if (auditEntry.getLogger().getResult() != null) { - atts.addAttribute("", "", "result", - ReportXMLConst.XSD_STRING, auditEntry.getLogger().getResult().name()); - } - handler.startElement("", "", "logger", atts); - handler.endElement("", "", "logger"); - - if (auditEntry.getBefore() != null) { - char[] before = ToStringBuilder.reflectionToString( - auditEntry.getBefore(), ToStringStyle.MULTI_LINE_STYLE).toCharArray(); - handler.startElement("", "", "before", null); - handler.characters(before, 0, before.length); - handler.endElement("", "", "before"); - } - - if (auditEntry.getInput() != null) { - handler.startElement("", "", "inputs", null); - for (Object inputObj : auditEntry.getInput()) { - char[] input = ToStringBuilder.reflectionToString( - inputObj, ToStringStyle.MULTI_LINE_STYLE).toCharArray(); - handler.startElement("", "", "input", null); - handler.characters(input, 0, input.length); - handler.endElement("", "", "input"); - } - handler.endElement("", "", "inputs"); - } - - if (auditEntry.getOutput() != null) { - char[] output = ToStringBuilder.reflectionToString( - auditEntry.getOutput(), ToStringStyle.MULTI_LINE_STYLE).toCharArray(); - handler.startElement("", "", "output", null); - handler.characters(output, 0, output.length); - handler.endElement("", "", "output"); - } - - handler.startElement("", "", "throwable", null); - char[] throwable = row.get("THROWABLE").toString().toCharArray(); - handler.characters(throwable, 0, throwable.length); - handler.endElement("", "", "throwable"); - - handler.endElement("", "", "event"); - } - handler.endElement("", "", "events"); - } - - @Override - protected void doExtract(final ReportletConf conf, final ContentHandler handler) throws SAXException { - if (conf instanceof AuditReportletConf) { - this.conf = AuditReportletConf.class.cast(conf); - } else { - throw new ReportException(new IllegalArgumentException("Invalid configuration provided")); - } - - datasource = domainsHolder.getDomains().get(AuthContextUtils.getDomain()); - if (datasource == null) { - throw new ReportException(new IllegalArgumentException("Could not get to DataSource")); - } - - doExtractConf(handler); - } - -} http://git-wip-us.apache.org/repos/asf/syncope/blob/67ecbea3/core/logic/src/main/java/org/apache/syncope/core/logic/report/FopSerializer.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/FopSerializer.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/FopSerializer.java deleted file mode 100644 index d90a619..0000000 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/FopSerializer.java +++ /dev/null @@ -1,82 +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 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.syncope.core.logic.report; - -import java.io.File; -import java.io.OutputStream; - -import org.apache.cocoon.pipeline.ProcessingException; -import org.apache.cocoon.pipeline.caching.CacheKey; -import org.apache.cocoon.pipeline.caching.SimpleCacheKey; -import org.apache.cocoon.pipeline.component.CachingPipelineComponent; -import org.apache.cocoon.pipeline.util.StringRepresentation; -import org.apache.cocoon.sax.AbstractSAXSerializer; -import org.apache.fop.apps.FOPException; -import org.apache.fop.apps.Fop; -import org.apache.fop.apps.FopFactory; -import org.apache.fop.apps.FopFactoryBuilder; -import org.apache.xmlgraphics.util.MimeConstants; -import org.xml.sax.ContentHandler; - -public class FopSerializer extends AbstractSAXSerializer implements CachingPipelineComponent { - - private static final FopFactory FOP_FACTORY = new FopFactoryBuilder(new File(".").toURI()).build(); - - private String outputFormat; - - /** - * Create a new FOP serializer that produces a PDF in output - */ - public FopSerializer() { - this(MimeConstants.MIME_PDF); - } - - /** - * Create a new FOP serializer that produces the specified mime - * - * @param outputFormat the output's mime type - */ - public FopSerializer(final String outputFormat) { - if (outputFormat == null) { - throw new IllegalArgumentException("The parameter 'outputFormat' mustn't be null."); - } - - this.outputFormat = outputFormat; - } - - @Override - public CacheKey constructCacheKey() { - return new SimpleCacheKey(); - } - - @Override - public void setOutputStream(final OutputStream outputStream) { - try { - Fop fop = FOP_FACTORY.newFop(this.outputFormat, outputStream); - ContentHandler fopContentHandler = fop.getDefaultHandler(); - - this.setContentHandler(fopContentHandler); - } catch (FOPException e) { - throw new ProcessingException("Impossible to initialize FOPSerializer", e); - } - } - - @Override - public String toString() { - return StringRepresentation.buildString(this, "outputFormat=" + this.outputFormat); - } -}