/* * 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.isis.core.runtime.services.auditing; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import org.apache.isis.applib.annotation.DomainService; import org.apache.isis.applib.annotation.NatureOfService; import org.apache.isis.applib.annotation.Programmatic; import org.apache.isis.applib.services.audit.AuditerService; import org.apache.isis.applib.services.audit.AuditingService3; import org.apache.isis.applib.services.bookmark.Bookmark; import org.apache.isis.applib.services.clock.ClockService; import org.apache.isis.applib.services.iactn.InteractionContext; import org.apache.isis.applib.services.user.UserService; import org.apache.isis.applib.services.xactn.Transaction; import org.apache.isis.applib.services.xactn.TransactionService; import org.apache.isis.core.metamodel.adapter.ObjectAdapter; import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil; import org.apache.isis.core.metamodel.facets.object.audit.AuditableFacet; import org.apache.isis.core.runtime.services.changes.AdapterAndProperty; import org.apache.isis.core.runtime.services.changes.ChangedObjectsServiceInternal; import org.apache.isis.core.runtime.services.changes.PreAndPostValues; /** * Wrapper around {@link org.apache.isis.applib.services.audit.AuditingService3}. Is a no-op if there is no injected service. */ @DomainService( nature = NatureOfService.DOMAIN, menuOrder = "" + Integer.MAX_VALUE ) public class AuditingServiceInternal { Boolean whetherCanAudit; private boolean canAudit() { if(whetherCanAudit == null) { whetherCanAudit = determineWhetherCanAudit(); } return whetherCanAudit; } private boolean determineWhetherCanAudit() { if (auditingServiceIfAny != null) { return true; } for (final AuditerService auditerService : auditerServices) { if (auditerService.isEnabled()) { return true; } } return false; } @Programmatic public void audit() { if(!canAudit()) { return; } final Set<Map.Entry<AdapterAndProperty, PreAndPostValues>> changedObjectProperties = changedObjectsServiceInternal.getChangedObjectProperties(); final String currentUser = userService.getUser().getName(); final java.sql.Timestamp currentTime = clockService.nowAsJavaSqlTimestamp(); for (Map.Entry<AdapterAndProperty, PreAndPostValues> auditEntry : changedObjectProperties) { auditChangedProperty(currentTime, currentUser, auditEntry); } } private void auditChangedProperty( final java.sql.Timestamp timestamp, final String user, final Map.Entry<AdapterAndProperty, PreAndPostValues> auditEntry) { final AdapterAndProperty aap = auditEntry.getKey(); final ObjectAdapter adapter = aap.getAdapter(); final AuditableFacet auditableFacet = adapter.getSpecification().getFacet(AuditableFacet.class); if(auditableFacet == null || auditableFacet.isDisabled()) { return; } final Bookmark target = aap.getBookmark(); final String propertyId = aap.getPropertyId(); final String memberId = aap.getMemberId(); final PreAndPostValues papv = auditEntry.getValue(); final String preValue = papv.getPreString(); final String postValue = papv.getPostString(); final String targetClass = CommandUtil.targetClassNameFor(adapter); Transaction transaction = transactionService.currentTransaction(); final UUID transactionId = transaction.getTransactionId(); final int sequence = transaction.getSequence(); if(auditingServiceIfAny != null) { auditingServiceIfAny .audit(transactionId, targetClass, target, memberId, propertyId, preValue, postValue, user, timestamp); } for (AuditerService auditerService : auditerServices) { if (auditerService.isEnabled()) { auditerService .audit(transactionId, sequence, targetClass, target, memberId, propertyId, preValue, postValue, user, timestamp); } } } /** * could be null if none has been registered. */ @javax.inject.Inject private AuditingService3 auditingServiceIfAny; @javax.inject.Inject private List<AuditerService> auditerServices; @javax.inject.Inject private ChangedObjectsServiceInternal changedObjectsServiceInternal; @javax.inject.Inject UserService userService; @javax.inject.Inject ClockService clockService; @javax.inject.Inject InteractionContext interactionContext; @javax.inject.Inject TransactionService transactionService; }