/*
* Copyright 2009 Alin Dreghiciu.
*
* Licensed 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.
*/
package org.ops4j.pax.url.cache.internal;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Properties;
import org.ops4j.io.StreamUtils;
import org.ops4j.lang.NullArgumentException;
/**
* TODO Add JavaDoc.
*
* @author Alin Dreghiciu (adreghiciu@gmail.com)
* @since 06 02, 2009
*/
public class Connection
extends URLConnection
{
/**
* Parsed url.
*/
private final Parser m_parser;
/**
* Service configuration.
*/
private final Configuration m_configuration;
/**
* Name corresponding to url (base64 encoding).
*/
private final String m_cacheName;
/**
* Url property name.
*/
private static final String META_URL = "url";
/**
* Cached time property name.
*/
private static final String META_CACHED_ON = "cachedOn";
/**
* Meta file extension.
*/
private static final String EXT_META = ".meta";
/**
* Data file extension.
*/
private static final String EXT_DATA = ".data";
/**
* Creates a new connection.
*
* @param url url to be handled; cannot be null.
* @param configuration protocol configuration; cannot be null
*
* @throws MalformedURLException - If url path is empty
* @throws IOException - If cache name cannot be generated
* @throws NullArgumentException - If url or configuration is null
*/
protected Connection( final URL url,
final Configuration configuration )
throws IOException
{
super( url );
NullArgumentException.validateNotNull( url, "URL" );
NullArgumentException.validateNotNull( configuration, "Configuration" );
m_parser = new Parser( url.getPath() );
m_configuration = configuration;
m_cacheName = generateCacheName( m_parser.getUrl() );
}
/**
* Generate caching name out of url.
*
* @param url url to be cached
*
* @return cache name
*
* @throws IOException - If cache name cannot be generated
*/
private static String generateCacheName( final URL url )
throws IOException
{
final MessageDigest md5;
try
{
md5 = MessageDigest.getInstance( "MD5" );
}
catch( NoSuchAlgorithmException e )
{
throw new IOException( "Cannot generate caching name (MD5 not supported)" );
}
String encoded = new BigInteger( 1, md5.digest( url.toExternalForm().getBytes() ) ).toString( 16 );
if( encoded.length() == 31 )
{
encoded = "0" + encoded;
}
return encoded;
}
/**
* Does nothing.
*/
@Override
public void connect()
{
//do nothing
}
/**
* Returns the input stream denoted by the url.
*
* @return the input stream for the resource denoted by url
*
* @throws java.io.IOException in case of an exception during accessing the resource
* @see java.net.URLConnection#getInputStream()
*/
@Override
public InputStream getInputStream()
throws IOException
{
connect();
final File workingDir = m_configuration.getWorkingDirectory();
final File cacheMetaFile = new File( workingDir, m_cacheName + EXT_META );
final File cacheDateFile = new File( workingDir, m_cacheName + EXT_DATA );
final Properties cacheMeta = new Properties();
try
{
InputStream in = new FileInputStream( cacheMetaFile );
try
{
cacheMeta.load( in );
}
finally
{
in.close();
}
}
catch( FileNotFoundException ignore )
{
//ignore
}
final String cacheUrl = cacheMeta.getProperty( META_URL );
if( cacheUrl == null )
{
cacheMeta.setProperty( META_URL, url.getPath() );
}
final String cacheTime = cacheMeta.getProperty( META_CACHED_ON );
if( cacheTime == null || !cacheDateFile.exists() )
{
StreamUtils.copyStream(
m_parser.getUrl().openStream(),
new BufferedOutputStream( new FileOutputStream( cacheDateFile ) ),
true
);
cacheMeta.setProperty( META_CACHED_ON, String.valueOf( System.currentTimeMillis() ) );
}
OutputStream out = new FileOutputStream( cacheMetaFile );
try
{
cacheMeta.store( out, null );
}
finally
{
out.close();
}
return new BufferedInputStream( new FileInputStream( cacheDateFile ) );
}
}