| package org.apache.maven.index.packer; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.text.SimpleDateFormat; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Properties; |
| import java.util.TimeZone; |
| |
| import javax.inject.Inject; |
| import javax.inject.Named; |
| import javax.inject.Singleton; |
| |
| import org.apache.maven.index.context.IndexingContext; |
| import org.apache.maven.index.incremental.IncrementalHandler; |
| import org.apache.maven.index.updater.IndexDataWriter; |
| import org.codehaus.plexus.util.FileUtils; |
| import org.codehaus.plexus.util.IOUtil; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * A default {@link IndexPacker} implementation. Creates the properties, legacy index zip and new gz files. |
| * |
| * @author Tamas Cservenak |
| * @author Eugene Kuleshov |
| */ |
| @Singleton |
| @Named |
| public class DefaultIndexPacker |
| implements IndexPacker |
| { |
| |
| private final Logger logger = LoggerFactory.getLogger( getClass() ); |
| |
| protected Logger getLogger() |
| { |
| return logger; |
| } |
| |
| private final IncrementalHandler incrementalHandler; |
| |
| |
| @Inject |
| public DefaultIndexPacker( IncrementalHandler incrementalHandler ) |
| { |
| this.incrementalHandler = incrementalHandler; |
| } |
| |
| public void packIndex( IndexPackingRequest request ) |
| throws IOException, IllegalArgumentException |
| { |
| if ( request.getTargetDir() == null ) |
| { |
| throw new IllegalArgumentException( "The target dir is null" ); |
| } |
| |
| if ( request.getTargetDir().exists() ) |
| { |
| if ( !request.getTargetDir().isDirectory() ) |
| { |
| throw new IllegalArgumentException( // |
| String.format( "Specified target path %s is not a directory", |
| request.getTargetDir().getAbsolutePath() ) ); |
| } |
| if ( !request.getTargetDir().canWrite() ) |
| { |
| throw new IllegalArgumentException( String.format( "Specified target path %s is not writtable", |
| request.getTargetDir().getAbsolutePath() ) ); |
| } |
| } |
| else |
| { |
| if ( !request.getTargetDir().mkdirs() ) |
| { |
| throw new IllegalArgumentException( "Can't create " + request.getTargetDir().getAbsolutePath() ); |
| } |
| } |
| |
| // These are all of the files we'll be dealing with (except for the incremental chunks of course) |
| File v1File = new File( request.getTargetDir(), IndexingContext.INDEX_FILE_PREFIX + ".gz" ); |
| |
| Properties info = null; |
| |
| try |
| { |
| // Note that for incremental indexes to work properly, a valid index.properties file |
| // must be present |
| info = readIndexProperties( request ); |
| |
| if ( request.isCreateIncrementalChunks() ) |
| { |
| List<Integer> chunk = incrementalHandler.getIncrementalUpdates( request, info ); |
| |
| if ( chunk == null ) |
| { |
| getLogger().debug( "Problem with Chunks, forcing regeneration of whole index" ); |
| incrementalHandler.initializeProperties( info ); |
| } |
| else if ( chunk.isEmpty() ) |
| { |
| getLogger().debug( "No incremental changes, not writing new incremental chunk" ); |
| } |
| else |
| { |
| File file = new File( request.getTargetDir(), // |
| IndexingContext.INDEX_FILE_PREFIX + "." + info.getProperty( |
| IndexingContext.INDEX_CHUNK_COUNTER ) + ".gz" ); |
| |
| writeIndexData( request, chunk, file ); |
| |
| if ( request.isCreateChecksumFiles() ) |
| { |
| FileUtils.fileWrite( |
| new File( file.getParentFile(), file.getName() + ".sha1" ).getAbsolutePath(), |
| DigesterUtils.getSha1Digest( file ) ); |
| |
| FileUtils.fileWrite( |
| new File( file.getParentFile(), file.getName() + ".md5" ).getAbsolutePath(), |
| DigesterUtils.getMd5Digest( file ) ); |
| } |
| } |
| } |
| } |
| catch ( IOException e ) |
| { |
| getLogger().info( "Unable to read properties file, will force index regeneration" ); |
| info = new Properties(); |
| incrementalHandler.initializeProperties( info ); |
| } |
| |
| Date timestamp = request.getContext().getTimestamp(); |
| |
| if ( timestamp == null ) |
| { |
| timestamp = new Date( 0 ); // never updated |
| } |
| |
| if ( request.getFormats().contains( IndexPackingRequest.IndexFormat.FORMAT_V1 ) ) |
| { |
| info.setProperty( IndexingContext.INDEX_TIMESTAMP, format( timestamp ) ); |
| |
| writeIndexData( request, null, v1File ); |
| |
| if ( request.isCreateChecksumFiles() ) |
| { |
| FileUtils.fileWrite( new File( v1File.getParentFile(), v1File.getName() + ".sha1" ).getAbsolutePath(), |
| DigesterUtils.getSha1Digest( v1File ) ); |
| |
| FileUtils.fileWrite( new File( v1File.getParentFile(), v1File.getName() + ".md5" ).getAbsolutePath(), |
| DigesterUtils.getMd5Digest( v1File ) ); |
| } |
| } |
| |
| writeIndexProperties( request, info ); |
| } |
| |
| private Properties readIndexProperties( IndexPackingRequest request ) |
| throws IOException |
| { |
| File file = null; |
| |
| if ( request.isUseTargetProperties() || request.getContext().getIndexDirectoryFile() == null ) |
| { |
| file = new File( request.getTargetDir(), IndexingContext.INDEX_REMOTE_PROPERTIES_FILE ); |
| } |
| else |
| { |
| file = |
| new File( request.getContext().getIndexDirectoryFile(), IndexingContext.INDEX_PACKER_PROPERTIES_FILE ); |
| } |
| |
| Properties properties = new Properties(); |
| |
| FileInputStream fos = null; |
| |
| try |
| { |
| fos = new FileInputStream( file ); |
| properties.load( fos ); |
| } |
| finally |
| { |
| if ( fos != null ) |
| { |
| fos.close(); |
| } |
| } |
| |
| return properties; |
| } |
| |
| void writeIndexData( IndexPackingRequest request, List<Integer> docIndexes, File targetArchive ) |
| throws IOException |
| { |
| if ( targetArchive.exists() ) |
| { |
| targetArchive.delete(); |
| } |
| |
| try( OutputStream os = new FileOutputStream( targetArchive ) ) |
| { |
| IndexDataWriter dw = new IndexDataWriter( os ); |
| dw.write( request.getContext(), request.getIndexReader(), docIndexes ); |
| |
| os.flush(); |
| } |
| } |
| |
| void writeIndexProperties( IndexPackingRequest request, Properties info ) |
| throws IOException |
| { |
| File propertyFile = |
| new File( request.getContext().getIndexDirectoryFile(), IndexingContext.INDEX_PACKER_PROPERTIES_FILE ); |
| File targetPropertyFile = new File( request.getTargetDir(), IndexingContext.INDEX_REMOTE_PROPERTIES_FILE ); |
| |
| info.setProperty( IndexingContext.INDEX_ID, request.getContext().getId() ); |
| |
| try (OutputStream os = new FileOutputStream( propertyFile )) |
| { |
| info.store( os, null ); |
| } |
| |
| try (OutputStream os = new FileOutputStream( targetPropertyFile )) |
| { |
| info.store( os, null ); |
| } |
| |
| if ( request.isCreateChecksumFiles() ) |
| { |
| FileUtils.fileWrite( new File( targetPropertyFile.getParentFile(), |
| targetPropertyFile.getName() + ".sha1" ).getAbsolutePath(), |
| DigesterUtils.getSha1Digest( targetPropertyFile ) ); |
| |
| FileUtils.fileWrite( |
| new File( targetPropertyFile.getParentFile(), targetPropertyFile.getName() + ".md5" ).getAbsolutePath(), |
| DigesterUtils.getMd5Digest( targetPropertyFile ) ); |
| } |
| } |
| |
| private String format( Date d ) |
| { |
| SimpleDateFormat df = new SimpleDateFormat( IndexingContext.INDEX_TIME_FORMAT ); |
| df.setTimeZone( TimeZone.getTimeZone( "GMT" ) ); |
| return df.format( d ); |
| } |
| } |