001 package org.apache.archiva.audit; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022 import org.apache.archiva.metadata.repository.MetadataRepository; 023 import org.apache.archiva.metadata.repository.MetadataRepositoryException; 024 import org.slf4j.Logger; 025 import org.slf4j.LoggerFactory; 026 import org.springframework.stereotype.Service; 027 028 import java.text.ParseException; 029 import java.text.SimpleDateFormat; 030 import java.util.ArrayList; 031 import java.util.Collection; 032 import java.util.Collections; 033 import java.util.Comparator; 034 import java.util.Date; 035 import java.util.List; 036 import java.util.TimeZone; 037 038 /** 039 * 040 */ 041 @Service("auditManager#default") 042 public class DefaultAuditManager 043 implements AuditManager 044 { 045 private static final int NUM_RECENT_EVENTS = 10; 046 047 private static final Logger log = LoggerFactory.getLogger( DefaultAuditManager.class ); 048 049 private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" ); 050 051 public List<AuditEvent> getMostRecentAuditEvents( MetadataRepository metadataRepository, 052 List<String> repositoryIds ) 053 throws MetadataRepositoryException 054 { 055 // TODO: consider a more efficient implementation that directly gets the last ten from the content repository 056 List<AuditRecord> records = new ArrayList<AuditRecord>(); 057 for ( String repositoryId : repositoryIds ) 058 { 059 List<String> names = metadataRepository.getMetadataFacets( repositoryId, AuditEvent.FACET_ID ); 060 for ( String name : names ) 061 { 062 records.add( new AuditRecord( repositoryId, name ) ); 063 } 064 } 065 Collections.sort( records ); 066 records = records.subList( 0, records.size() < NUM_RECENT_EVENTS ? records.size() : NUM_RECENT_EVENTS ); 067 068 List<AuditEvent> events = new ArrayList<AuditEvent>( records.size() ); 069 for ( AuditRecord record : records ) 070 { 071 AuditEvent auditEvent = (AuditEvent) metadataRepository.getMetadataFacet( record.repositoryId, 072 AuditEvent.FACET_ID, 073 record.name ); 074 events.add( auditEvent ); 075 } 076 return events; 077 } 078 079 public void addAuditEvent( MetadataRepository repository, AuditEvent event ) 080 throws MetadataRepositoryException 081 { 082 // ignore those with no repository - they will still be logged to the textual audit log 083 if ( event.getRepositoryId() != null ) 084 { 085 repository.addMetadataFacet( event.getRepositoryId(), event ); 086 } 087 } 088 089 public void deleteAuditEvents( MetadataRepository metadataRepository, String repositoryId ) 090 throws MetadataRepositoryException 091 { 092 metadataRepository.removeMetadataFacets( repositoryId, AuditEvent.FACET_ID ); 093 } 094 095 public List<AuditEvent> getAuditEventsInRange( MetadataRepository metadataRepository, 096 Collection<String> repositoryIds, Date startTime, Date endTime ) 097 throws MetadataRepositoryException 098 { 099 return getAuditEventsInRange( metadataRepository, repositoryIds, null, startTime, endTime ); 100 } 101 102 public List<AuditEvent> getAuditEventsInRange( MetadataRepository metadataRepository, 103 Collection<String> repositoryIds, String resource, Date startTime, 104 Date endTime ) 105 throws MetadataRepositoryException 106 { 107 List<AuditEvent> results = new ArrayList<AuditEvent>(); 108 for ( String repositoryId : repositoryIds ) 109 { 110 List<String> list = metadataRepository.getMetadataFacets( repositoryId, AuditEvent.FACET_ID ); 111 for ( String name : list ) 112 { 113 try 114 { 115 Date date = createNameFormat().parse( name ); 116 if ( ( startTime == null || !date.before( startTime ) ) && ( endTime == null || !date.after( 117 endTime ) ) ) 118 { 119 AuditEvent event = (AuditEvent) metadataRepository.getMetadataFacet( repositoryId, 120 AuditEvent.FACET_ID, 121 name ); 122 123 if ( resource == null || event.getResource().startsWith( resource ) ) 124 { 125 results.add( event ); 126 } 127 } 128 } 129 catch ( ParseException e ) 130 { 131 log.error( "Invalid audit event found in the metadata repository: " + e.getMessage() ); 132 // continue and ignore this one 133 } 134 } 135 } 136 Collections.sort( results, new Comparator<AuditEvent>() 137 { 138 public int compare( AuditEvent o1, AuditEvent o2 ) 139 { 140 return o2.getTimestamp().compareTo( o1.getTimestamp() ); 141 } 142 } ); 143 return results; 144 } 145 146 private static SimpleDateFormat createNameFormat() 147 { 148 SimpleDateFormat fmt = new SimpleDateFormat( AuditEvent.TIMESTAMP_FORMAT ); 149 fmt.setTimeZone( UTC_TIME_ZONE ); 150 return fmt; 151 } 152 153 private static final class AuditRecord 154 implements Comparable<AuditRecord> 155 { 156 private String repositoryId; 157 158 private String name; 159 160 public AuditRecord( String repositoryId, String name ) 161 { 162 this.repositoryId = repositoryId; 163 this.name = name; 164 } 165 166 public int compareTo( AuditRecord other ) 167 { 168 // reverse ordering 169 return other.name.compareTo( name ); 170 } 171 } 172 }