This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.metadata.repository.stats;
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
022import org.apache.archiva.metadata.repository.MetadataRepository;
023import org.apache.archiva.metadata.repository.MetadataRepositoryException;
024import org.apache.archiva.metadata.repository.RepositorySession;
025import org.apache.archiva.metadata.repository.RepositorySessionFactory;
026import org.apache.archiva.metadata.repository.stats.model.DefaultRepositoryStatistics;
027import org.apache.archiva.metadata.repository.stats.model.RepositoryStatistics;
028import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsManager;
029import org.apache.archiva.metadata.repository.stats.model.RepositoryStatisticsProvider;
030import org.apache.archiva.metadata.repository.stats.model.RepositoryWalkingStatisticsProvider;
031import org.apache.commons.lang3.time.StopWatch;
032import org.slf4j.Logger;
033import org.slf4j.LoggerFactory;
034import org.springframework.stereotype.Service;
035
036import javax.inject.Inject;
037import java.text.ParseException;
038import java.text.SimpleDateFormat;
039import java.util.ArrayList;
040import java.util.Collections;
041import java.util.Date;
042import java.util.List;
043import java.util.TimeZone;
044
045/**
046 *
047 */
048@Service("repositoryStatisticsManager#default")
049public class DefaultRepositoryStatisticsManager
050    implements RepositoryStatisticsManager
051{
052    private static final Logger log = LoggerFactory.getLogger( DefaultRepositoryStatisticsManager.class );
053
054    private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" );
055
056    private RepositoryWalkingStatisticsProvider walkingProvider = new RepositoryWalkingStatisticsProvider();
057
058
059
060    @Inject
061    RepositorySessionFactory repositorySessionFactory;
062
063    @Override
064    public boolean hasStatistics( String repositoryId )
065        throws MetadataRepositoryException
066    {
067        try(RepositorySession session = repositorySessionFactory.createSession()) {
068            final MetadataRepository metadataRepository = session.getRepository( );
069            return metadataRepository.hasMetadataFacet(session, repositoryId, DefaultRepositoryStatistics.FACET_ID);
070        }
071    }
072
073    @Override
074    public RepositoryStatistics getLastStatistics( String repositoryId )
075        throws MetadataRepositoryException
076    {
077        StopWatch stopWatch = new StopWatch();
078        stopWatch.start();
079        try(RepositorySession session = repositorySessionFactory.createSession()) {
080            final MetadataRepository metadataRepository = session.getRepository( );
081
082            // TODO: consider a more efficient implementation that directly gets the last one from the content repository
083            List<String> scans = metadataRepository.getMetadataFacets(session, repositoryId, DefaultRepositoryStatistics.FACET_ID);
084            if (scans == null) {
085                return null;
086            }
087            Collections.sort(scans);
088            if (!scans.isEmpty()) {
089                String name = scans.get(scans.size() - 1);
090                RepositoryStatistics repositoryStatistics =
091                        RepositoryStatistics.class.cast(metadataRepository.getMetadataFacet(session, repositoryId,
092                                RepositoryStatistics.FACET_ID, name));
093                stopWatch.stop();
094                log.debug("time to find last RepositoryStatistics: {} ms", stopWatch.getTime());
095                return repositoryStatistics;
096            } else {
097                return null;
098            }
099        }
100    }
101
102    @Override
103    public void addStatisticsAfterScan( String repositoryId, Date startTime,
104                                        Date endTime, long totalFiles, long newFiles )
105        throws MetadataRepositoryException
106    {
107        try(RepositorySession session = repositorySessionFactory.createSession()) {
108            final MetadataRepository metadataRepository = session.getRepository( );
109
110            DefaultRepositoryStatistics repositoryStatistics = new DefaultRepositoryStatistics();
111            repositoryStatistics.setRepositoryId(repositoryId);
112            repositoryStatistics.setScanStartTime(startTime);
113            repositoryStatistics.setScanEndTime(endTime);
114            repositoryStatistics.setTotalFileCount(totalFiles);
115            repositoryStatistics.setNewFileCount(newFiles);
116
117            // TODO
118            // In the future, instead of being tied to a scan we might want to record information in the fly based on
119            // events that are occurring. Even without these totals we could query much of the information on demand based
120            // 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 not
122            // be updated and the repository will need to be rescanned.
123
124            long startGather = System.currentTimeMillis();
125
126            if (metadataRepository instanceof RepositoryStatisticsProvider) {
127                ((RepositoryStatisticsProvider) metadataRepository).populateStatistics(session,
128                        metadataRepository, repositoryId, repositoryStatistics);
129            } else {
130                walkingProvider.populateStatistics(session, metadataRepository, repositoryId, repositoryStatistics);
131            }
132
133            log.info("Gathering statistics executed in {} ms", (System.currentTimeMillis() - startGather));
134
135            metadataRepository.addMetadataFacet(session, repositoryId, repositoryStatistics);
136        }
137    }
138
139    @Override
140    public void deleteStatistics( String repositoryId )
141        throws MetadataRepositoryException
142    {
143        try(RepositorySession session = repositorySessionFactory.createSession()) {
144            final MetadataRepository metadataRepository = session.getRepository( );
145            metadataRepository.removeMetadataFacets(session, repositoryId, DefaultRepositoryStatistics.FACET_ID);
146        }
147    }
148
149    @Override
150    public List<RepositoryStatistics> getStatisticsInRange( String repositoryId,
151                                                            Date startTime, Date endTime )
152        throws MetadataRepositoryException
153    {
154        try(RepositorySession session = repositorySessionFactory.createSession()) {
155            final MetadataRepository 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());
159            for (String name : list) {
160                try {
161                    Date date = createNameFormat().parse(name);
162                    if ((startTime == null || !date.before(startTime)) && (endTime == null || !date.after(
163                            endTime))) {
164                        RepositoryStatistics 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 one
173                }
174            }
175            return results;
176        }
177    }
178
179    private static SimpleDateFormat createNameFormat()
180    {
181        SimpleDateFormat fmt = new SimpleDateFormat( DefaultRepositoryStatistics.SCAN_TIMESTAMP_FORMAT );
182        fmt.setTimeZone( UTC_TIME_ZONE );
183        return fmt;
184    }
185
186    public RepositorySessionFactory getRepositorySessionFactory( )
187    {
188        return repositorySessionFactory;
189    }
190
191    public void setRepositorySessionFactory( RepositorySessionFactory repositorySessionFactory )
192    {
193        this.repositorySessionFactory = repositorySessionFactory;
194    }
195}