/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.core.internal.boot;

/**
 * Platform URL support
 */

import java.net.*;
import java.io.*;
import java.util.*;
 
public abstract class PlatformURLConnection extends URLConnection {

	// URL access
	private boolean isInCache = false;
	private boolean isJar = false;
	
//	protected URL url;				// declared in super (platform: URL)
	private URL resolvedURL = null;	// resolved file URL (eg. http: URL)
	private URL cachedURL = null;	// file URL in cache (file: URL)

	private URLConnection connection = null; // actual connection

	// local cache
	private static Properties cacheIndex = new Properties();
	private static String cacheLocation;
	private static String indexName;
	private static String filePrefix;

	// constants	
	private static final int BUF_SIZE = 32768;
	private static final Object NOT_FOUND = new Object();	// marker
	private static final String CACHE_PROP = ".cache.properties"; //$NON-NLS-1$
	private static final String CACHE_LOCATION_PROP = "location"; //$NON-NLS-1$
	private static final String CACHE_INDEX_PROP = "index"; //$NON-NLS-1$
	private static final String CACHE_PREFIX_PROP = "prefix"; //$NON-NLS-1$
	private static final String CACHE_INDEX = ".index.properties"; //$NON-NLS-1$
	private static final String CACHE_DIR = PlatformURLHandler.PROTOCOL + File.separator;

	// debug tracing
	public static boolean DEBUG = false;
	public static boolean DEBUG_CONNECT = true;
	public static boolean DEBUG_CACHE_LOOKUP = true;
	public static boolean DEBUG_CACHE_COPY = true;
protected PlatformURLConnection(URL url) {
	super(url);
}
protected boolean allowCaching() {
	return false;
}
public void connect() throws IOException {
	connect(false);
}
private synchronized void connect(boolean asLocal) throws IOException {
	if (!connected) {
		if (shouldCache(asLocal)) {
			try {				
				URL inCache = getURLInCache();
				if (inCache!=null) connection = inCache.openConnection();
			} catch(IOException e) {
				// failed to cache ... will use resolved URL instead
			}
		}

		// use resolved URL
		if (connection==null) connection = resolvedURL.openConnection();
		connected = true;
		if (DEBUG && DEBUG_CONNECT)
			debug("Connected as "+connection.getURL()); //$NON-NLS-1$
	}
}
private void copyToCache() throws IOException {

	if (isInCache | cachedURL==null) return;
	String tmp;
	int ix;
		
	// cache entry key
	String key;
	if (isJar) {
		tmp = url.getFile();
		ix = tmp.lastIndexOf(PlatformURLHandler.JAR_SEPARATOR);
		if (ix!=-1) tmp = tmp.substring(0,ix);
		key = tmp;
	}
	else key = url.getFile();
		
	// source url
	URL src;
	if (isJar) {
		tmp = resolvedURL.getFile();
		ix = tmp.lastIndexOf(PlatformURLHandler.JAR_SEPARATOR);
		if (ix!=-1) tmp = tmp.substring(0,ix);
		src = new URL(tmp);
	}
	else src = resolvedURL;
	InputStream srcis = null;
	
	// cache target
	String tgt;
	if (isJar) {
		tmp = cachedURL.getFile();
		ix = tmp.indexOf(PlatformURLHandler.PROTOCOL_SEPARATOR);
		if (ix!=-1) tmp = tmp.substring(ix+1);
		ix = tmp.lastIndexOf(PlatformURLHandler.JAR_SEPARATOR);
		if (ix!=-1) tmp = tmp.substring(0,ix);
		tgt = tmp;
	}
	else tgt = cachedURL.getFile();	
	File tgtFile = null;
	FileOutputStream tgtos = null;
	
	boolean error = false;
	long total = 0;

	try {
		if (DEBUG && DEBUG_CACHE_COPY) {
			if (isJar) debug ("Caching jar as "+tgt); //$NON-NLS-1$
			else debug("Caching as "+tgt); //$NON-NLS-1$
		}
			
		srcis = src.openStream();
		byte[] buf = new byte[BUF_SIZE];
		int count = srcis.read(buf);

		tgtFile = new File(tgt);
		tgtos = new FileOutputStream(tgtFile);
		
		while(count!=-1) {
			total += count;
			tgtos.write(buf,0,count);
			count = srcis.read(buf);
		}

		srcis.close();
		srcis=null;
		tgtos.close();
		tgtos=null;

		// add cache entry
		cacheIndex.put(key,tgt);
		isInCache = true;
	}
	catch(IOException e) {
		error = true;
		cacheIndex.put(key,NOT_FOUND);	// mark cache entry for this execution
		if (DEBUG && DEBUG_CACHE_COPY)
			debug("Failed to cache due to "+e); //$NON-NLS-1$
		throw e;		
	}
	finally {		
		if (!error && DEBUG && DEBUG_CACHE_COPY)
			debug(total + " bytes copied"); //$NON-NLS-1$
		if (srcis!=null) srcis.close();
		if (tgtos!=null) tgtos.close();
	}
}
protected void debug(String s) {
	System.out.println("URL "+getURL().toString()+"^"+Integer.toHexString(Thread.currentThread().hashCode())+" "+s); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
private static void debugStartup(String s) {
	System.out.println("URL "+s); //$NON-NLS-1$
}
public URL[] getAuxillaryURLs () throws IOException {
	return null;
}
public synchronized InputStream getInputStream() throws IOException {
	if (!connected) connect();
	return connection.getInputStream();
}
public URL getResolvedURL() {
	return resolvedURL;
}
public URL getURLAsLocal() throws IOException {
	connect(true);	// connect and force caching if necessary
	URL u = connection.getURL();
	String up = u.getProtocol();
	if (!up.equals(PlatformURLHandler.FILE) && !up.equals(PlatformURLHandler.JAR)) {
		throw new IOException(Policy.bind("url.noaccess", url.toString())); //$NON-NLS-1$
	}
	return u;
}
private URL getURLInCache() throws IOException {

	if (!allowCaching()) return null;	// target should not be cached
	
	if (isInCache) return cachedURL;

	if (cacheLocation==null | cacheIndex==null) return null;	// not caching
	
	// check if we are dealing with a .jar/ .zip
	String file = ""; //$NON-NLS-1$
	String jarEntry = null;
	if (isJar) {
		file = url.getFile();
		int ix = file.lastIndexOf(PlatformURLHandler.JAR_SEPARATOR);
		if (ix!=-1) {
			jarEntry = file.substring(ix+PlatformURLHandler.JAR_SEPARATOR.length());
			file = file.substring(0,ix);
		}
	}
	else {
		file = url.getFile();
		jarEntry = null;
	}
	
	// check for cached entry
	String tmp = (String)cacheIndex.get(file);

	// check for "not found" marker
	if (tmp!=null && tmp==NOT_FOUND) throw new IOException();

	// validate cache entry
	if (tmp!=null && !(new File(tmp)).exists()) {
		tmp = null;
		cacheIndex.remove(url.getFile());
	}

	// found in cache
	if (tmp!=null) {
		if (isJar) {
			if (DEBUG && DEBUG_CACHE_LOOKUP)
				debug("Jar located in cache as "+tmp); //$NON-NLS-1$
			tmp = PlatformURLHandler.FILE + PlatformURLHandler.PROTOCOL_SEPARATOR + tmp + PlatformURLHandler.JAR_SEPARATOR + jarEntry;
			cachedURL = new URL(PlatformURLHandler.JAR,null,-1,tmp);
		}
		else {
			if (DEBUG && DEBUG_CACHE_LOOKUP)
				debug("Located in cache as "+tmp); //$NON-NLS-1$
			cachedURL = new URL(PlatformURLHandler.FILE,null,-1,tmp);
		}
		isInCache = true;
	}
	else {
		// attemp to cache
		int ix = file.lastIndexOf("/"); //$NON-NLS-1$
		tmp = file.substring(ix+1);
		tmp = cacheLocation + filePrefix + Long.toString((new java.util.Date()).getTime()) + "_" + tmp; //$NON-NLS-1$
		tmp = tmp.replace(File.separatorChar,'/');
		if (isJar) {
			tmp = PlatformURLHandler.FILE + PlatformURLHandler.PROTOCOL_SEPARATOR + tmp + PlatformURLHandler.JAR_SEPARATOR + jarEntry;
			cachedURL = new URL(PlatformURLHandler.JAR,null,-1,tmp);
		}
		else cachedURL = new URL(PlatformURLHandler.FILE,null,-1,tmp);
		copyToCache();
	}
	
	return cachedURL;
}
/*
 * to be implemented by subclass
 * @return URL resolved URL
 */
 
protected URL resolve() throws IOException {
	throw new IOException();
}

private String resolvePath(String spec) {
	if (spec.length() == 0 || spec.charAt(0) != '$')
		return spec;
	int i = spec.indexOf('/', 1);
	String first = ""; //$NON-NLS-1$
	String rest = ""; //$NON-NLS-1$
	if (i == -1)
		first = spec;
	else {	
		first = spec.substring(0, i);
		rest = spec.substring(i);
	}
	if (first.equalsIgnoreCase("$ws$")) //$NON-NLS-1$
		return "ws/" + InternalBootLoader.getWS() + rest; //$NON-NLS-1$
	if (first.equalsIgnoreCase("$os$")) //$NON-NLS-1$
		return "os/" + InternalBootLoader.getOS() + rest; //$NON-NLS-1$
	if (first.equalsIgnoreCase("$nl$")) { //$NON-NLS-1$
		String nl = InternalBootLoader.getNL();
		nl = nl.replace('_', '/');
		return "nl/" + nl + rest; //$NON-NLS-1$
	}
	return spec;
}

protected String getId(String spec) {
	int i = spec.lastIndexOf('_');
	return i >= 0 ? spec.substring(0, i) : spec;
}

protected String getVersion(String spec) {
	int i = spec.lastIndexOf('_');
	return i >= 0 ? spec.substring(i + 1, spec.length()) : ""; //$NON-NLS-1$
}

void setResolvedURL(URL url) throws IOException {
	if (resolvedURL==null) {
		int ix = url.getFile().lastIndexOf(PlatformURLHandler.JAR_SEPARATOR);
		isJar = -1 != ix;
		// Resolved URLs containing !/ separator are assumed to be jar URLs.
		// If the resolved protocol is not jar, new jar URL is created.
		if (isJar && !url.getProtocol().equals(PlatformURLHandler.JAR)) 
			url = new URL(PlatformURLHandler.JAR,"",-1,url.toExternalForm()); //$NON-NLS-1$
		resolvedURL=url;
	}
}
private boolean shouldCache(boolean asLocal) {
	
	// don't cache files that are known to be local
	String rp = resolvedURL.getProtocol();
	String rf = resolvedURL.getFile();
	if (rp.equals(PlatformURLHandler.FILE)) return false;
	if (rp.equals(PlatformURLHandler.JAR) && (rf.startsWith(PlatformURLHandler.FILE))) return false;

	// for other files force caching if local connection was requested
	if (asLocal) return true;
	
	// for now cache all files
	// XXX: add cache policy support
	return true;
}
static void shutdown() {
	if (indexName!=null && cacheLocation!=null) {
		// weed out "not found" entries
		Enumeration keys = cacheIndex.keys();
		String key;
		Object value;
		while (keys.hasMoreElements()) {
			key = (String) keys.nextElement();
			value = cacheIndex.get(key);
			if (value==NOT_FOUND) cacheIndex.remove(key);
		}
		//if the cache index is empty we don't need to save it
		if (cacheIndex.size() == 0)
			return;
		try {
			// try to save cache index
			FileOutputStream fos = null;
			fos = new FileOutputStream(cacheLocation+indexName);
			try {
				cacheIndex.store(fos,null);
			} finally {
				fos.close();
			}
		}
		catch(IOException e) {
			// failed to store cache index ... ignore
		}
	}	
}
static void startup(String location) {

	
	verifyLocation(location); // check for platform location, ignore errors
	String cacheProps = location.trim();
	if (!cacheProps.endsWith(File.separator)) cacheProps += File.separator;
	cacheProps += CACHE_PROP;
	File cachePropFile = new File(cacheProps);
	Properties props = null;	
	FileInputStream fis;
	
	if (cachePropFile.exists()) {
		// load existing properties	
		try {
			props = new Properties();
			fis = new FileInputStream(cachePropFile);
			try {
				props.load(fis);
			}
			finally {
				fis.close();
			}
		}
		catch(IOException e) {
			props = null;
		}
	}

	if (props==null) {
		// first time up, or failed to load previous settings
		props = new Properties();
		String tmp = System.getProperty("java.io.tmpdir"); //$NON-NLS-1$
		if (!tmp.endsWith(File.separator)) tmp += File.separator;
		tmp += CACHE_DIR;
		props.put(CACHE_LOCATION_PROP,tmp);
		
		tmp = Long.toString((new java.util.Date()).getTime());
		props.put(CACHE_PREFIX_PROP,tmp);
			
		tmp += CACHE_INDEX;
		props.put(CACHE_INDEX_PROP,tmp);

		// save for next time around
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(cachePropFile);
			try {
				props.store(fos,null);
			}
			finally {
				fos.close();
			}
		}
		catch(IOException e) {
			// failed to store cache location metadata ... ignore
		}
	}

	// remember settings for shutdown processing
	filePrefix = (String)props.get(CACHE_PREFIX_PROP);
	indexName = (String)props.get(CACHE_INDEX_PROP);
	cacheLocation = (String)props.get(CACHE_LOCATION_PROP);
	
	if (DEBUG) {
		debugStartup("Cache location: " + cacheLocation); //$NON-NLS-1$
		debugStartup("Cache index: " + indexName); //$NON-NLS-1$
		debugStartup("Cache file prefix: " + filePrefix); //$NON-NLS-1$
	}

	// create cache directory structure if needed
	if (!verifyLocation(cacheLocation)) {
		indexName = null;
		cacheLocation = null;	
		if (DEBUG)
			debugStartup("Failed to create cache directory structure. Caching suspended"); //$NON-NLS-1$
		return;
	}

	// attempt to initialize cache index
	if (cacheLocation!=null && indexName!=null) {
		try {
			fis = new FileInputStream(cacheLocation+indexName);
			try {
				cacheIndex.load(fis);
			}
			finally {
				fis.close();
			}
		}
		catch(IOException e) {				
			if (DEBUG) 
				debugStartup("Failed to initialize cache"); //$NON-NLS-1$
		}
	}
}
private static boolean verifyLocation(String location) {
	// verify cache directory exists. Create if needed
	File cacheDir = new File(location);
	if (cacheDir.exists())
		return true;
	return cacheDir.mkdirs();
}
}
