package org.apache.archiva.audit; /* * 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. */ import org.apache.archiva.metadata.model.facets.AuditEvent; import org.apache.archiva.metadata.repository.MetadataRepository; import org.apache.archiva.metadata.repository.MetadataRepositoryException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.TimeZone; /** * */ @Service("auditManager#default") public class DefaultAuditManager implements AuditManager { private static final int NUM_RECENT_EVENTS = 10; private static final Logger log = LoggerFactory.getLogger( DefaultAuditManager.class ); private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" ); @Override public List<AuditEvent> getMostRecentAuditEvents( MetadataRepository metadataRepository, List<String> repositoryIds ) throws MetadataRepositoryException { // TODO: consider a more efficient implementation that directly gets the last ten from the content repository List<AuditRecord> records = new ArrayList<>(); for ( String repositoryId : repositoryIds ) { List<String> names = metadataRepository.getMetadataFacets( repositoryId, AuditEvent.FACET_ID ); for ( String name : names ) { records.add( new AuditRecord( repositoryId, name ) ); } } Collections.sort( records ); records = records.subList( 0, records.size() < NUM_RECENT_EVENTS ? records.size() : NUM_RECENT_EVENTS ); List<AuditEvent> events = new ArrayList<>( records.size() ); for ( AuditRecord record : records ) { AuditEvent auditEvent = (AuditEvent) metadataRepository.getMetadataFacet( record.repositoryId, AuditEvent.FACET_ID, record.name ); events.add( auditEvent ); } return events; } @Override public void addAuditEvent( MetadataRepository repository, AuditEvent event ) throws MetadataRepositoryException { // ignore those with no repository - they will still be logged to the textual audit log if ( event.getRepositoryId() != null ) { repository.addMetadataFacet( event.getRepositoryId(), event ); } } @Override public void deleteAuditEvents( MetadataRepository metadataRepository, String repositoryId ) throws MetadataRepositoryException { metadataRepository.removeMetadataFacets( repositoryId, AuditEvent.FACET_ID ); } @Override public List<AuditEvent> getAuditEventsInRange( MetadataRepository metadataRepository, Collection<String> repositoryIds, Date startTime, Date endTime ) throws MetadataRepositoryException { return getAuditEventsInRange( metadataRepository, repositoryIds, null, startTime, endTime ); } @Override public List<AuditEvent> getAuditEventsInRange( MetadataRepository metadataRepository, Collection<String> repositoryIds, String resource, Date startTime, Date endTime ) throws MetadataRepositoryException { List<AuditEvent> results = new ArrayList<>(); for ( String repositoryId : repositoryIds ) { List<String> list = metadataRepository.getMetadataFacets( repositoryId, AuditEvent.FACET_ID ); for ( String name : list ) { try { Date date = createNameFormat().parse( name ); if ( ( startTime == null || !date.before( startTime ) ) && ( endTime == null || !date.after( endTime ) ) ) { AuditEvent event = (AuditEvent) metadataRepository.getMetadataFacet( repositoryId, AuditEvent.FACET_ID, name ); if ( resource == null || event.getResource().startsWith( resource ) ) { results.add( event ); } } } catch ( ParseException e ) { log.error( "Invalid audit event found in the metadata repository: " + e.getMessage() ); // continue and ignore this one } } } Collections.sort( results, new Comparator<AuditEvent>() { @Override public int compare( AuditEvent o1, AuditEvent o2 ) { return o2.getTimestamp().compareTo( o1.getTimestamp() ); } } ); return results; } private static SimpleDateFormat createNameFormat() { SimpleDateFormat fmt = new SimpleDateFormat( AuditEvent.TIMESTAMP_FORMAT ); fmt.setTimeZone( UTC_TIME_ZONE ); return fmt; } private static final class AuditRecord implements Comparable<AuditRecord> { private String repositoryId; private String name; public AuditRecord( String repositoryId, String name ) { this.repositoryId = repositoryId; this.name = name; } @Override public int compareTo( AuditRecord other ) { // reverse ordering return other.name.compareTo( name ); } } }