1package org.apache.archiva.metadata.repository.stats;
23/*4 * Licensed to the Apache Software Foundation (ASF) under one5 * or more contributor license agreements. See the NOTICE file6 * distributed with this work for additional information7 * regarding copyright ownership. The ASF licenses this file8 * to you under the Apache License, Version 2.0 (the9 * "License"); you may not use this file except in compliance10 * with the License. You may obtain a copy of the License at11 *12 * http://www.apache.org/licenses/LICENSE-2.013 *14 * Unless required by applicable law or agreed to in writing,15 * software distributed under the License is distributed on an16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY17 * KIND, either express or implied. See the License for the18 * specific language governing permissions and limitations19 * under the License.20 */2122import org.apache.archiva.metadata.repository.MetadataRepository;
23import org.apache.archiva.metadata.repository.MetadataRepositoryException;
24import org.apache.archiva.metadata.repository.RepositorySession;
25import org.apache.archiva.metadata.repository.RepositorySessionFactory;
26import org.apache.archiva.metadata.repository.stats.model.DefaultRepositoryStatistics;
27import org.apache.archiva.metadata.repository.stats.model.RepositoryStatistics;
28import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsManager;
29import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsProvider;
30import org.apache.archiva.metadata.repository.stats.model.RepositoryWalkingStatisticsProvider;
31import org.apache.commons.lang3.time.StopWatch;
32import org.slf4j.Logger;
33import org.slf4j.LoggerFactory;
34import org.springframework.stereotype.Service;
3536import javax.inject.Inject;
37import java.text.ParseException;
38import java.text.SimpleDateFormat;
39import java.util.ArrayList;
40import java.util.Collections;
41import java.util.Date;
42import java.util.List;
43import java.util.TimeZone;
4445/**46 *47 */48 @Service("repositoryStatisticsManager#default")
49publicclassDefaultRepositoryStatisticsManager50implementsRepositoryStatisticsManager51 {
52privatestaticfinal Logger log = LoggerFactory.getLogger( DefaultRepositoryStatisticsManager.class );
5354privatestaticfinal TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" );
5556privateRepositoryWalkingStatisticsProvideryWalkingStatisticsProvider.html#RepositoryWalkingStatisticsProvider">RepositoryWalkingStatisticsProvider walkingProvider = newRepositoryWalkingStatisticsProvider();
57585960 @Inject
61RepositorySessionFactory repositorySessionFactory;
6263 @Override
64publicboolean hasStatistics( String repositoryId )
65throwsMetadataRepositoryException66 {
67try(RepositorySession session = repositorySessionFactory.createSession()) {
68finalMetadataRepository metadataRepository = session.getRepository( );
69return metadataRepository.hasMetadataFacet(session, repositoryId, DefaultRepositoryStatistics.FACET_ID);
70 }
71 }
7273 @Override
74publicRepositoryStatistics getLastStatistics( String repositoryId )
75throwsMetadataRepositoryException76 {
77 StopWatch stopWatch = new StopWatch();
78 stopWatch.start();
79try(RepositorySession session = repositorySessionFactory.createSession()) {
80finalMetadataRepository metadataRepository = session.getRepository( );
8182// TODO: consider a more efficient implementation that directly gets the last one from the content repository83 List<String> scans = metadataRepository.getMetadataFacets(session, repositoryId, DefaultRepositoryStatistics.FACET_ID);
84if (scans == null) {
85returnnull;
86 }
87 Collections.sort(scans);
88if (!scans.isEmpty()) {
89 String name = scans.get(scans.size() - 1);
90RepositoryStatistics repositoryStatistics =
91 RepositoryStatistics.class.cast(metadataRepository.getMetadataFacet(session, repositoryId,
92 RepositoryStatistics.FACET_ID, name));
93 stopWatch.stop();
94 log.debug("time to find last RepositoryStatistics: {} ms", stopWatch.getTime());
95return repositoryStatistics;
96 } else {
97returnnull;
98 }
99 }
100 }
101102 @Override
103publicvoid addStatisticsAfterScan( String repositoryId, Date startTime,
104 Date endTime, long totalFiles, long newFiles )
105throwsMetadataRepositoryException106 {
107try(RepositorySession session = repositorySessionFactory.createSession()) {
108finalMetadataRepository metadataRepository = session.getRepository( );
109110DefaultRepositoryStatisticstRepositoryStatistics.html#DefaultRepositoryStatistics">DefaultRepositoryStatistics repositoryStatistics = newDefaultRepositoryStatistics();
111 repositoryStatistics.setRepositoryId(repositoryId);
112 repositoryStatistics.setScanStartTime(startTime);
113 repositoryStatistics.setScanEndTime(endTime);
114 repositoryStatistics.setTotalFileCount(totalFiles);
115 repositoryStatistics.setNewFileCount(newFiles);
116117// TODO118// In the future, instead of being tied to a scan we might want to record information in the fly based on119// events that are occurring. Even without these totals we could query much of the information on demand based120// on information from the metadata content repository. In the mean time, we lock information in at scan time.121// Note that if new types are later discoverable due to a code change or new plugin, historical stats will not122// be updated and the repository will need to be rescanned.123124long startGather = System.currentTimeMillis();
125126if (metadataRepository instanceof RepositoryStatisticsProvider) {
127 ((RepositoryStatisticsProvider) metadataRepository).populateStatistics(session,
128 metadataRepository, repositoryId, repositoryStatistics);
129 } else {
130 walkingProvider.populateStatistics(session, metadataRepository, repositoryId, repositoryStatistics);
131 }
132133 log.info("Gathering statistics executed in {} ms", (System.currentTimeMillis() - startGather));
134135 metadataRepository.addMetadataFacet(session, repositoryId, repositoryStatistics);
136 }
137 }
138139 @Override
140publicvoid deleteStatistics( String repositoryId )
141throwsMetadataRepositoryException142 {
143try(RepositorySession session = repositorySessionFactory.createSession()) {
144finalMetadataRepository metadataRepository = session.getRepository( );
145 metadataRepository.removeMetadataFacets(session, repositoryId, DefaultRepositoryStatistics.FACET_ID);
146 }
147 }
148149 @Override
150public List<RepositoryStatistics> getStatisticsInRange( String repositoryId,
151 Date startTime, Date endTime )
152throwsMetadataRepositoryException153 {
154try(RepositorySession session = repositorySessionFactory.createSession()) {
155finalMetadataRepository metadataRepository = session.getRepository( );
156 List<RepositoryStatistics> results = new ArrayList<>();
157 List<String> list = metadataRepository.getMetadataFacets(session, repositoryId, DefaultRepositoryStatistics.FACET_ID);
158 Collections.sort(list, Collections.reverseOrder());
159for (String name : list) {
160try {
161 Date date = createNameFormat().parse(name);
162if ((startTime == null || !date.before(startTime)) && (endTime == null || !date.after(
163 endTime))) {
164RepositoryStatistics stats =
165 (RepositoryStatistics) metadataRepository.getMetadataFacet(session,
166 repositoryId,
167 DefaultRepositoryStatistics.FACET_ID, name);
168 results.add(stats);
169 }
170 } catch (ParseException e) {
171 log.error("Invalid scan result found in the metadata repository: {}", e.getMessage());
172// continue and ignore this one173 }
174 }
175return results;
176 }
177 }
178179privatestatic SimpleDateFormat createNameFormat()
180 {
181 SimpleDateFormat fmt = new SimpleDateFormat( DefaultRepositoryStatistics.SCAN_TIMESTAMP_FORMAT );
182 fmt.setTimeZone( UTC_TIME_ZONE );
183return fmt;
184 }
185186publicRepositorySessionFactory getRepositorySessionFactory( )
187 {
188return repositorySessionFactory;
189 }
190191publicvoid setRepositorySessionFactory( RepositorySessionFactory repositorySessionFactory )
192 {
193this.repositorySessionFactory = repositorySessionFactory;
194 }
195 }