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    }