View Javadoc

1   package org.apache.maven.index.updater;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0    
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.FileOutputStream;
24  import java.io.IOException;
25  import java.io.InputStream;
26  
27  import org.apache.lucene.index.Term;
28  import org.apache.lucene.search.TermQuery;
29  import org.apache.maven.index.ArtifactInfo;
30  import org.apache.maven.index.FlatSearchRequest;
31  import org.apache.maven.index.FlatSearchResponse;
32  import org.apache.maven.index.context.IndexingContext;
33  import org.apache.maven.index.context.UnsupportedExistingLuceneIndexException;
34  import org.apache.maven.index.fs.Locker;
35  import org.codehaus.plexus.util.FileUtils;
36  import org.codehaus.plexus.util.IOUtil;
37  
38  public class LocalIndexCacheTest
39      extends AbstractIndexUpdaterTest
40  {
41      private File remoteRepo;
42  
43      private File localCacheDir;
44  
45      private File indexDir;
46  
47      private IndexingContext tempContext;
48  
49      @Override
50      protected void setUp()
51          throws Exception
52      {
53          super.setUp();
54  
55          remoteRepo = new File( "target/localcache/remoterepo" ).getCanonicalFile();
56          FileUtils.deleteDirectory( remoteRepo );
57          remoteRepo.mkdirs();
58  
59          localCacheDir = new File( "target/localcache/cache" ).getCanonicalFile();
60          FileUtils.deleteDirectory( localCacheDir );
61          localCacheDir.mkdirs();
62  
63          indexDir = new File( "target/localcache/index" ).getCanonicalFile();
64          FileUtils.deleteDirectory( indexDir );
65          indexDir.mkdirs();
66      }
67  
68      @Override
69      protected void tearDown()
70          throws Exception
71      {
72          removeTempContext();
73  
74          super.tearDown();
75      }
76  
77      private IndexingContext getNewTempContext()
78          throws IOException, UnsupportedExistingLuceneIndexException
79      {
80          removeTempContext();
81  
82          tempContext =
83              indexer.addIndexingContext( repositoryId + "temp", repositoryId, repoDir, indexDir, repositoryUrl, null,
84                  MIN_CREATORS );
85  
86          return tempContext;
87      }
88  
89      private void removeTempContext()
90          throws IOException
91      {
92          if ( tempContext != null )
93          {
94              indexer.removeIndexingContext( tempContext, true );
95              tempContext = null;
96              FileUtils.cleanDirectory( indexDir );
97          }
98      }
99  
100     public void testBasic()
101         throws Exception
102     {
103         // create initial remote repo index
104         indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ),
105             context );
106         packIndex( remoteRepo, context );
107 
108         //
109         TrackingFetcher fetcher;
110         IndexUpdateRequest updateRequest;
111         IndexingContext testContext;
112 
113         // initial index download (expected: full index download)
114         testContext = getNewTempContext();
115         fetcher = new TrackingFetcher( remoteRepo );
116         updateRequest = new IndexUpdateRequest( testContext, fetcher );
117         updateRequest.setLocalIndexCacheDir( localCacheDir );
118         updater.fetchAndUpdateIndex( updateRequest );
119         assertEquals( 2, fetcher.getRetrievedResources().size() );
120         assertTrue( new File( localCacheDir, "nexus-maven-repository-index.gz" ).exists() );
121         assertTrue( new File( localCacheDir, "nexus-maven-repository-index.properties" ).exists() );
122         assertGroupCount( 1, "commons-lang", testContext );
123 
124         // update the same index (expected: no index download)
125         fetcher = new TrackingFetcher( remoteRepo );
126         updateRequest = new IndexUpdateRequest( testContext, fetcher );
127         updateRequest.setLocalIndexCacheDir( localCacheDir );
128         updater.fetchAndUpdateIndex( updateRequest );
129         assertEquals( 1, fetcher.getRetrievedResources().size() );
130         assertEquals( "nexus-maven-repository-index.properties", fetcher.getRetrievedResources().get( 0 ) );
131         assertGroupCount( 1, "commons-lang", testContext );
132 
133         // nuke index but keep the cache (expected: no index download)
134         testContext = getNewTempContext();
135         fetcher = new TrackingFetcher( remoteRepo );
136         updateRequest = new IndexUpdateRequest( testContext, fetcher );
137         updateRequest.setLocalIndexCacheDir( localCacheDir );
138         updater.fetchAndUpdateIndex( updateRequest );
139         assertEquals( 1, fetcher.getRetrievedResources().size() );
140         assertEquals( "nexus-maven-repository-index.properties", fetcher.getRetrievedResources().get( 0 ) );
141         assertGroupCount( 1, "commons-lang", testContext );
142 
143         // incremental remote update
144         indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.3", null ),
145             context );
146         packIndex( remoteRepo, context );
147 
148         // update via cache (expected: incremental chunk download)
149         fetcher = new TrackingFetcher( remoteRepo );
150         updateRequest = new IndexUpdateRequest( testContext, fetcher );
151         updateRequest.setLocalIndexCacheDir( localCacheDir );
152         updater.fetchAndUpdateIndex( updateRequest );
153         assertEquals( 2, fetcher.getRetrievedResources().size() );
154         assertEquals( "nexus-maven-repository-index.properties", fetcher.getRetrievedResources().get( 0 ) );
155         assertEquals( "nexus-maven-repository-index.1.gz", fetcher.getRetrievedResources().get( 1 ) );
156         assertGroupCount( 2, "commons-lang", testContext );
157 
158         // nuke index but keep the cache (expected: no index download, index contains both initial and delta chunks)
159         testContext = getNewTempContext();
160         fetcher = new TrackingFetcher( remoteRepo );
161         updateRequest = new IndexUpdateRequest( testContext, fetcher );
162         updateRequest.setLocalIndexCacheDir( localCacheDir );
163         updater.fetchAndUpdateIndex( updateRequest );
164         assertEquals( 1, fetcher.getRetrievedResources().size() );
165         assertEquals( "nexus-maven-repository-index.properties", fetcher.getRetrievedResources().get( 0 ) );
166         assertGroupCount( 2, "commons-lang", testContext );
167 
168         // kill the cache, but keep the index (expected: full index download)
169         // TODO how to assert if merge==false internally?
170         FileUtils.deleteDirectory( localCacheDir );
171         fetcher = new TrackingFetcher( remoteRepo );
172         updateRequest = new IndexUpdateRequest( testContext, fetcher );
173         updateRequest.setLocalIndexCacheDir( localCacheDir );
174         updater.fetchAndUpdateIndex( updateRequest );
175         assertEquals( 2, fetcher.getRetrievedResources().size() );
176         assertTrue( new File( localCacheDir, "nexus-maven-repository-index.gz" ).exists() );
177         assertTrue( new File( localCacheDir, "nexus-maven-repository-index.properties" ).exists() );
178         assertGroupCount( 2, "commons-lang", testContext );
179     }
180 
181     private void assertGroupCount( int expectedCount, String groupId, IndexingContext context )
182         throws IOException
183     {
184         TermQuery query = new TermQuery( new Term( ArtifactInfo.GROUP_ID, groupId ) );
185         FlatSearchResponse response = indexer.searchFlat( new FlatSearchRequest( query, context ) );
186         assertEquals( expectedCount, response.getTotalHits() );
187     }
188 
189     public void testForceIndexDownload()
190         throws Exception
191     {
192         indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ),
193             context );
194         packIndex( remoteRepo, context );
195 
196         //
197         TrackingFetcher fetcher;
198         IndexUpdateRequest updateRequest;
199 
200         // initial index download (expected: no index download)
201         fetcher = new TrackingFetcher( remoteRepo );
202         updateRequest = new IndexUpdateRequest( getNewTempContext(), fetcher );
203         updateRequest.setLocalIndexCacheDir( localCacheDir );
204         updater.fetchAndUpdateIndex( updateRequest );
205 
206         // corrupt local cache
207         IOUtil.copy( "corrupted", new FileOutputStream( new File( localCacheDir, "nexus-maven-repository-index.gz" ) ) );
208 
209         // try download again (it would have failed if force did not update local cache)
210         removeTempContext();
211         fetcher = new TrackingFetcher( remoteRepo );
212         updateRequest = new IndexUpdateRequest( getNewTempContext(), fetcher );
213         updateRequest.setLocalIndexCacheDir( localCacheDir );
214         updateRequest.setForceFullUpdate( true );
215         updater.fetchAndUpdateIndex( updateRequest );
216     }
217 
218     public void testInitialForcedFullDownload()
219         throws Exception
220     {
221         indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ),
222             context );
223         packIndex( remoteRepo, context );
224 
225         //
226         TrackingFetcher fetcher;
227         IndexUpdateRequest updateRequest;
228 
229         // initial forced full index download (expected: successfull download)
230         fetcher = new TrackingFetcher( remoteRepo );
231         updateRequest = new IndexUpdateRequest( getNewTempContext(), fetcher );
232         updateRequest.setLocalIndexCacheDir( localCacheDir );
233         updateRequest.setForceFullUpdate( true );
234         updater.fetchAndUpdateIndex( updateRequest );
235         assertTrue( new File( localCacheDir, "nexus-maven-repository-index.gz" ).exists() );
236         assertTrue( new File( localCacheDir, "nexus-maven-repository-index.properties" ).exists() );
237     }
238 
239     public void testFailedIndexDownload()
240         throws Exception
241     {
242         indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ),
243             context );
244         packIndex( remoteRepo, context );
245 
246         //
247         TrackingFetcher fetcher;
248         IndexUpdateRequest updateRequest;
249 
250         // failed download
251         fetcher = new TrackingFetcher( remoteRepo )
252         {
253             public InputStream retrieve( String name )
254                 throws IOException, java.io.FileNotFoundException
255             {
256                 if ( name.equals( IndexingContext.INDEX_FILE_PREFIX + ".gz" )
257                     || name.equals( IndexingContext.INDEX_FILE_PREFIX + ".zip" ) )
258                 {
259                     throw new IOException();
260                 }
261                 return super.retrieve( name );
262             };
263         };
264         updateRequest = new IndexUpdateRequest( getNewTempContext(), fetcher );
265         updateRequest.setLocalIndexCacheDir( localCacheDir );
266         try
267         {
268             updater.fetchAndUpdateIndex( updateRequest );
269             fail();
270         }
271         catch ( IOException e )
272         {
273             // expected
274         }
275 
276         // try successful download
277         fetcher = new TrackingFetcher( remoteRepo );
278         updateRequest = new IndexUpdateRequest( getNewTempContext(), fetcher );
279         updateRequest.setLocalIndexCacheDir( localCacheDir );
280         updater.fetchAndUpdateIndex( updateRequest );
281         assertTrue( new File( localCacheDir, "nexus-maven-repository-index.gz" ).exists() );
282         assertTrue( new File( localCacheDir, "nexus-maven-repository-index.properties" ).exists() );
283     }
284 
285     public void testCleanCacheDirectory()
286         throws Exception
287     {
288         indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ),
289             context );
290         packIndex( remoteRepo, context );
291 
292         //
293         TrackingFetcher fetcher;
294         IndexUpdateRequest updateRequest;
295 
296         // initial index download (expected: successfull download)
297         fetcher = new TrackingFetcher( remoteRepo );
298         updateRequest = new IndexUpdateRequest( getNewTempContext(), fetcher );
299         updateRequest.setLocalIndexCacheDir( localCacheDir );
300         updater.fetchAndUpdateIndex( updateRequest );
301 
302         // new remote index delta
303         indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.3", null ),
304             context );
305         packIndex( remoteRepo, context );
306 
307         // delta index download (expected: successfull download)
308         fetcher = new TrackingFetcher( remoteRepo );
309         updateRequest = new IndexUpdateRequest( getNewTempContext(), fetcher );
310         updateRequest.setLocalIndexCacheDir( localCacheDir );
311         updater.fetchAndUpdateIndex( updateRequest );
312 
313         // sanity check
314         assertTrue( new File( localCacheDir, "nexus-maven-repository-index.1.gz" ).canRead() );
315 
316         // .lock files are expected to be preserved
317         File lockFile = new File( localCacheDir, Locker.LOCK_FILE );
318         IOUtil.copy( "", new FileOutputStream( lockFile ) );
319         assertTrue( lockFile.canRead() );
320 
321         // all unknown files and directories are expected to be removed
322         File unknownFile = new File( localCacheDir, "unknownFile" );
323         IOUtil.copy( "", new FileOutputStream( unknownFile ) );
324         File unknownDirectory = new File( localCacheDir, "unknownDirectory" );
325         unknownDirectory.mkdirs();
326         assertTrue( unknownFile.canRead() );
327         assertTrue( unknownDirectory.isDirectory() );
328 
329         // forced full update
330         fetcher = new TrackingFetcher( remoteRepo );
331         updateRequest = new IndexUpdateRequest( getNewTempContext(), fetcher );
332         updateRequest.setLocalIndexCacheDir( localCacheDir );
333         updateRequest.setForceFullUpdate( true );
334         updater.fetchAndUpdateIndex( updateRequest );
335 
336         assertTrue( lockFile.canRead() );
337         assertFalse( new File( localCacheDir, "nexus-maven-repository-index.1.gz" ).canRead() );
338         assertFalse( unknownFile.canRead() );
339         assertFalse( unknownDirectory.isDirectory() );
340     }
341 
342     public void testOffline()
343         throws Exception
344     {
345         indexer.addArtifactToIndex( createArtifactContext( repositoryId, "commons-lang", "commons-lang", "2.2", null ),
346             context );
347         packIndex( remoteRepo, context );
348 
349         //
350         TrackingFetcher fetcher;
351         IndexUpdateRequest updateRequest;
352 
353         // initial index download (expected: successfull download)
354         fetcher = new TrackingFetcher( remoteRepo );
355         IndexingContext testContext = getNewTempContext();
356         updateRequest = new IndexUpdateRequest( testContext, fetcher );
357         updateRequest.setLocalIndexCacheDir( localCacheDir );
358         updater.fetchAndUpdateIndex( updateRequest );
359 
360         // recreate local index from the cache without remote access (and NULL fetcher)
361         // fetcher is null, so we no way to assert that
362         updateRequest = new IndexUpdateRequest( testContext, fetcher );
363         updateRequest.setLocalIndexCacheDir( localCacheDir );
364         updateRequest.setOffline( true );
365         updater.fetchAndUpdateIndex( updateRequest );
366         assertGroupCount( 1, "commons-lang", testContext );
367 
368         // recreate local index from the cache without remote access (and NOT NULL fetcher)
369         fetcher = new TrackingFetcher( remoteRepo );
370         updateRequest = new IndexUpdateRequest( testContext, fetcher );
371         updateRequest.setLocalIndexCacheDir( localCacheDir );
372         updateRequest.setOffline( true );
373         updater.fetchAndUpdateIndex( updateRequest );
374         assertEquals( 0, fetcher.getRetrievedResources().size() );
375         assertGroupCount( 1, "commons-lang", testContext );
376     }
377 
378 }