001package org.apache.archiva.rest.services;
002/*
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 */
020
021import org.apache.archiva.redback.components.cache.Cache;
022import org.apache.archiva.redback.components.cache.CacheStatistics;
023import org.apache.archiva.redback.components.taskqueue.TaskQueue;
024import org.apache.archiva.redback.components.taskqueue.TaskQueueException;
025import org.apache.archiva.repository.scanner.RepositoryScanner;
026import org.apache.archiva.repository.scanner.RepositoryScannerInstance;
027import org.apache.archiva.rest.api.model.CacheEntry;
028import org.apache.archiva.rest.api.model.ConsumerScanningStatistics;
029import org.apache.archiva.rest.api.model.QueueEntry;
030import org.apache.archiva.rest.api.model.RepositoryScannerStatistics;
031import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
032import org.apache.archiva.rest.api.services.SystemStatusService;
033import org.apache.archiva.rest.services.utils.ConsumerScanningStatisticsComparator;
034import org.springframework.context.ApplicationContext;
035import org.springframework.stereotype.Service;
036
037import javax.inject.Inject;
038import javax.ws.rs.core.Response;
039import java.text.DecimalFormat;
040import java.text.SimpleDateFormat;
041import java.util.ArrayList;
042import java.util.Collections;
043import java.util.Date;
044import java.util.List;
045import java.util.Locale;
046import java.util.Map;
047import java.util.Set;
048
049/**
050 * @author Olivier Lamy
051 * @since 1.4-M3
052 */
053@Service( "systemStatusService#rest" )
054public class DefaultSystemStatusService
055    extends AbstractRestService
056    implements SystemStatusService
057{
058
059
060    private Map<String, TaskQueue> queues = null;
061
062    private Map<String, Cache> caches = null;
063
064    private RepositoryScanner scanner;
065
066    // display spring scheduled
067    //@Inject @Named (value="springScheduler");
068
069
070    @Inject
071    public DefaultSystemStatusService( ApplicationContext applicationContext, RepositoryScanner scanner )
072    {
073        this.scanner = scanner;
074
075        queues = getBeansOfType( applicationContext, TaskQueue.class );
076
077        caches = getBeansOfType( applicationContext, Cache.class );
078    }
079
080    @Override
081    public String getMemoryStatus()
082        throws ArchivaRestServiceException
083    {
084        Runtime runtime = Runtime.getRuntime();
085
086        long total = runtime.totalMemory();
087        long used = total - runtime.freeMemory();
088        long max = runtime.maxMemory();
089        return formatMemory( used ) + "/" + formatMemory( total ) + " (Max: " + formatMemory( max ) + ")";
090    }
091
092    private static String formatMemory( long l )
093    {
094        return l / ( 1024 * 1024 ) + "M";
095    }
096
097    @Override
098    public String getCurrentServerTime( String locale )
099        throws ArchivaRestServiceException
100    {
101        SimpleDateFormat sdf = new SimpleDateFormat( "EEE, d MMM yyyy HH:mm:ss Z", new Locale( locale ) );
102        return sdf.format( new Date() );
103    }
104
105    @Override
106    public List<QueueEntry> getQueueEntries()
107        throws ArchivaRestServiceException
108    {
109        try
110        {
111            List<QueueEntry> queueEntries = new ArrayList<QueueEntry>( queues.size() );
112            for ( Map.Entry<String, TaskQueue> entry : queues.entrySet() )
113            {
114                queueEntries.add( new QueueEntry( entry.getKey(), entry.getValue().getQueueSnapshot().size() ) );
115            }
116
117            return queueEntries;
118        }
119        catch ( TaskQueueException e )
120        {
121            log.error( e.getMessage(), e );
122            throw new ArchivaRestServiceException( e.getMessage(),
123                                                   Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e );
124        }
125    }
126
127    @Override
128    public List<CacheEntry> getCacheEntries()
129        throws ArchivaRestServiceException
130    {
131        List<CacheEntry> cacheEntries = new ArrayList<CacheEntry>( caches.size() );
132        DecimalFormat decimalFormat = new DecimalFormat( "#%" );
133
134        for ( Map.Entry<String, Cache> entry : caches.entrySet() )
135        {
136            CacheStatistics cacheStatistics = entry.getValue().getStatistics();
137
138            cacheEntries.add( new CacheEntry( entry.getKey(), cacheStatistics.getSize(), cacheStatistics.getCacheHits(),
139                                              cacheStatistics.getCacheMiss(),
140                                              decimalFormat.format( cacheStatistics.getCacheHitRate() ).toString(),
141                                              cacheStatistics.getInMemorySize() ) );
142        }
143
144        Collections.sort( cacheEntries );
145
146        return cacheEntries;
147    }
148
149    @Override
150    public Boolean clearCache( String cacheKey )
151        throws ArchivaRestServiceException
152    {
153        Cache cache = caches.get( cacheKey );
154        if ( cache == null )
155        {
156            throw new ArchivaRestServiceException( "no cache for key: " + cacheKey,
157                                                   Response.Status.BAD_REQUEST.getStatusCode(), null );
158        }
159
160        cache.clear();
161        return Boolean.TRUE;
162    }
163
164    @Override
165    public Boolean clearAllCaches()
166        throws ArchivaRestServiceException
167    {
168        for ( Cache cache : caches.values() )
169        {
170            cache.clear();
171        }
172        return Boolean.TRUE;
173    }
174
175    @Override
176    public List<RepositoryScannerStatistics> getRepositoryScannerStatistics()
177        throws ArchivaRestServiceException
178    {
179        Set<RepositoryScannerInstance> repositoryScannerInstances = scanner.getInProgressScans();
180        if ( repositoryScannerInstances.isEmpty() )
181        {
182            return Collections.emptyList();
183        }
184        List<RepositoryScannerStatistics> repositoryScannerStatisticsList =
185            new ArrayList<RepositoryScannerStatistics>( repositoryScannerInstances.size() );
186
187        for ( RepositoryScannerInstance instance : repositoryScannerInstances )
188        {
189            RepositoryScannerStatistics repositoryScannerStatistics = new RepositoryScannerStatistics();
190            repositoryScannerStatisticsList.add( repositoryScannerStatistics );
191            repositoryScannerStatistics.setManagedRepository( instance.getRepository() );
192            repositoryScannerStatistics.setNewFileCount( instance.getStats().getNewFileCount() );
193            repositoryScannerStatistics.setTotalFileCount( instance.getStats().getTotalFileCount() );
194            repositoryScannerStatistics.setConsumerScanningStatistics( mapConsumerScanningStatistics( instance ) );
195        }
196
197        return repositoryScannerStatisticsList;
198    }
199
200    private List<ConsumerScanningStatistics> mapConsumerScanningStatistics( RepositoryScannerInstance instance )
201    {
202        DecimalFormat decimalFormat = new DecimalFormat( "###.##" );
203        if ( instance.getConsumerCounts() == null )
204        {
205            return Collections.emptyList();
206        }
207        List<ConsumerScanningStatistics> ret =
208            new ArrayList<ConsumerScanningStatistics>( instance.getConsumerCounts().size() );
209        for ( Map.Entry<String, Long> entry : instance.getConsumerCounts().entrySet() )
210        {
211            ConsumerScanningStatistics consumerScanningStatistics = new ConsumerScanningStatistics();
212            consumerScanningStatistics.setConsumerKey( entry.getKey() );
213            consumerScanningStatistics.setCount( entry.getValue() );
214            consumerScanningStatistics.setTime( instance.getConsumerTimings().get( entry.getKey() ) );
215            if ( consumerScanningStatistics.getCount() > 0 )
216            {
217                consumerScanningStatistics.setAverage( decimalFormat.format(
218                    consumerScanningStatistics.getTime() / consumerScanningStatistics.getCount() ) );
219            }
220            ret.add( consumerScanningStatistics );
221        }
222        Collections.sort( ret, ConsumerScanningStatisticsComparator.INSTANCE );
223        return ret;
224    }
225}