blob: 933dd1b5b208ac1497949ade2b6758c21b5a8b7d [file] [log] [blame]
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 );
}
}