/*******************************************************************************
 * Copyright (c) 2007, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * 	IBM Corporation - initial API and implementation
 * 	Genuitec, LLC - support for multi-threaded downloads
 *  Cloudsmith Inc. - query indexes
 *  Sonatype Inc - ongoing development
 *  EclipseSource - file locking and ongoing development
 *  Red Hat Inc. - Fix compiler problems from generified IAdaptable#getAdapter
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.artifact.repository.simple;

import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.Map.Entry;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.equinox.internal.p2.artifact.processors.md5.MD5Verifier;
import org.eclipse.equinox.internal.p2.artifact.repository.*;
import org.eclipse.equinox.internal.p2.artifact.repository.Messages;
import org.eclipse.equinox.internal.p2.core.helpers.FileUtils;
import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
import org.eclipse.equinox.internal.p2.metadata.expression.CompoundIterator;
import org.eclipse.equinox.internal.p2.metadata.index.IndexProvider;
import org.eclipse.equinox.internal.p2.repository.DownloadStatus;
import org.eclipse.equinox.internal.p2.repository.Transport;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing.*;
import org.eclipse.equinox.internal.provisional.p2.repository.IStateful;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.metadata.index.IIndex;
import org.eclipse.equinox.p2.metadata.index.IIndexProvider;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.equinox.p2.repository.*;
import org.eclipse.equinox.p2.repository.artifact.*;
import org.eclipse.equinox.p2.repository.artifact.spi.AbstractArtifactRepository;
import org.eclipse.equinox.p2.repository.artifact.spi.ArtifactDescriptor;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.util.NLS;

public class SimpleArtifactRepository extends AbstractArtifactRepository implements IFileArtifactRepository, IIndexProvider<IArtifactKey> {
	/** 
	 * A boolean property controlling whether mirroring is enabled.
	 */
	public static final boolean MIRRORS_ENABLED = !"false".equals(Activator.getContext().getProperty("eclipse.p2.mirrors")); //$NON-NLS-1$//$NON-NLS-2$

	public static final boolean MD5_CHECK_ENABLED = !"false".equals(Activator.getContext().getProperty("eclipse.p2.MD5Check")); //$NON-NLS-1$//$NON-NLS-2$

	public static final boolean MD5_ARTIFACT_CHECK_ENABLED = !"false".equals(Activator.getContext().getProperty("eclipse.p2.MD5ArtifactCheck")); //$NON-NLS-1$//$NON-NLS-2$

	public static final String CONTENT_FILENAME = "artifacts"; //$NON-NLS-1$

	/** 
	 * The key for a integer property controls the maximum number
	 * of threads that should be used when optimizing downloads from a remote
	 * artifact repository.
	 */
	public static final String PROP_MAX_THREADS = "eclipse.p2.max.threads"; //$NON-NLS-1$

	/**
	 * Allows override of whether threading should be used.
	 */
	public static final String PROP_FORCE_THREADING = "eclipse.p2.force.threading"; //$NON-NLS-1$

	/**
	 * Location of the repository lock
	 */
	private Location lockLocation = null;

	/**
	 * Allows an artifact repository to set the name of its blobstore.
	 */
	public static final String PROP_BLOBSTORE_NAME = "p2.blobstore.name"; //$NON-NLS-1$

	/**
	 * Does this instance of the repository currently hold a lock
	 */
	private boolean holdsLock = false;
	/**
	 * Does this instance of the repository can be locked.
	 * It will be initialized when initializing the location for repository
	 */
	private Boolean canLock = null;

	private long cacheTimestamp = 0l;

	public class ArtifactOutputStream extends OutputStream implements IStateful {
		private boolean closed;
		private long count = 0;
		private IArtifactDescriptor descriptor;
		private OutputStream destination;
		private File file;
		private IStatus status = Status.OK_STATUS;
		private OutputStream firstLink;

		public ArtifactOutputStream(OutputStream os, IArtifactDescriptor descriptor) {
			this(os, descriptor, null);
		}

		public ArtifactOutputStream(OutputStream os, IArtifactDescriptor descriptor, File file) {
			this.destination = os;
			this.descriptor = descriptor;
			this.file = file;
		}

		public void close() throws IOException {
			if (closed)
				return;
			closed = true;

			try {
				destination.close();
			} catch (IOException e) {
				// cleanup if possible
				if (file != null)
					delete(file);
				if (getStatus().isOK())
					throw e;
				// if the stream has already been e.g. canceled, we can return - the status is already set correctly 
				return;
			}
			// if the steps ran ok and there was actual content, write the artifact descriptor
			// TODO the count check is a bit bogus but helps in some error cases (e.g., the optimizer)
			// where errors occurred in a processing step earlier in the chain.  We likely need a better
			// or more explicit way of handling this case.
			OutputStream testStream = firstLink == null ? this : firstLink;
			if (ProcessingStepHandler.checkStatus(testStream).isOK() && count > 0) {
				((ArtifactDescriptor) descriptor).setProperty(IArtifactDescriptor.DOWNLOAD_SIZE, Long.toString(count));
				addDescriptor(descriptor);
			} else if (file != null)
				// cleanup if possible
				delete(file);
		}

		public IStatus getStatus() {
			return status;
		}

		public OutputStream getDestination() {
			return destination;
		}

		public void setStatus(IStatus status) {
			this.status = status == null ? Status.OK_STATUS : status;
		}

		public void write(byte[] b) throws IOException {
			destination.write(b);
			count += b.length;
		}

		public void write(byte[] b, int off, int len) throws IOException {
			destination.write(b, off, len);
			count += len;
		}

		public void write(int b) throws IOException {
			destination.write(b);
			count++;
		}

		public void setFirstLink(OutputStream value) {
			firstLink = value;
		}
	}

	// TODO: optimize
	// we could stream right into the folder
	public static class ZippedFolderOutputStream extends OutputStream {

		private final File folder;
		private final FileOutputStream fos;
		private final File zipFile;

		public ZippedFolderOutputStream(File folder) throws IOException {
			this.folder = folder;
			zipFile = File.createTempFile(folder.getName(), JAR_EXTENSION, null);
			fos = new FileOutputStream(zipFile);
		}

		public void close() throws IOException {
			fos.close();
			try {
				FileUtils.unzipFile(zipFile, folder);
			} finally {
				zipFile.delete();
			}
		}

		public void flush() throws IOException {
			fos.flush();
		}

		public String toString() {
			return fos.toString();
		}

		public void write(byte[] b) throws IOException {
			fos.write(b);
		}

		public void write(byte[] b, int off, int len) throws IOException {
			fos.write(b, off, len);
		}

		public void write(int b) throws IOException {
			fos.write(b);
		}
	}

	private static final String ARTIFACT_FOLDER = "artifact.folder"; //$NON-NLS-1$
	private static final String ARTIFACT_UUID = "artifact.uuid"; //$NON-NLS-1$
	static final private String BLOBSTORE = ".blobstore/"; //$NON-NLS-1$
	static final private String[][] PACKED_MAPPING_RULES = {{"(& (classifier=osgi.bundle) (format=packed))", "${repoUrl}/plugins/${id}_${version}.jar.pack.gz"}, //$NON-NLS-1$//$NON-NLS-2$
			{"(& (classifier=osgi.bundle))", "${repoUrl}/plugins/${id}_${version}.jar"}, //$NON-NLS-1$//$NON-NLS-2$
			{"(& (classifier=binary))", "${repoUrl}/binary/${id}_${version}"}, //$NON-NLS-1$ //$NON-NLS-2$
			{"(& (classifier=org.eclipse.update.feature) (format=packed))", "${repoUrl}/features/${id}_${version}.jar.pack.gz"}, //$NON-NLS-1$//$NON-NLS-2$
			{"(& (classifier=org.eclipse.update.feature))", "${repoUrl}/features/${id}_${version}.jar"}}; //$NON-NLS-1$//$NON-NLS-2$

	static final private String[][] DEFAULT_MAPPING_RULES = {{"(& (classifier=osgi.bundle))", "${repoUrl}/plugins/${id}_${version}.jar"}, //$NON-NLS-1$//$NON-NLS-2$
			{"(& (classifier=binary))", "${repoUrl}/binary/${id}_${version}"}, //$NON-NLS-1$ //$NON-NLS-2$
			{"(& (classifier=org.eclipse.update.feature))", "${repoUrl}/features/${id}_${version}.jar"}}; //$NON-NLS-1$//$NON-NLS-2$
	private static final String JAR_EXTENSION = ".jar"; //$NON-NLS-1$
	static final private String REPOSITORY_TYPE = IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY;

	static final private Integer REPOSITORY_VERSION = new Integer(1);
	private static final String XML_EXTENSION = ".xml"; //$NON-NLS-1$
	protected Set<SimpleArtifactDescriptor> artifactDescriptors = new HashSet<SimpleArtifactDescriptor>();
	/**
	 * Map<IArtifactKey,List<IArtifactDescriptor>> containing the index of artifacts in the repository.
	 */
	private Map<IArtifactKey, List<IArtifactDescriptor>> artifactMap = new HashMap<IArtifactKey, List<IArtifactDescriptor>>();
	private transient BlobStore blobStore;
	transient private Mapper mapper = new Mapper();
	private KeyIndex keyIndex;
	private boolean snapshotNeeded = false;

	static final private String PUBLISH_PACK_FILES_AS_SIBLINGS = "publishPackFilesAsSiblings"; //$NON-NLS-1$

	private static final int DEFAULT_MAX_THREADS = 4;

	protected String[][] mappingRules = DEFAULT_MAPPING_RULES;

	private MirrorSelector mirrors;

	private boolean disableSave = false;

	static void delete(File toDelete) {
		if (toDelete.isDirectory()) {
			File[] children = toDelete.listFiles();
			if (children != null) {
				for (int i = 0; i < children.length; i++) {
					delete(children[i]);
				}
			}
		}
		toDelete.delete();
	}

	public static URI getActualLocation(URI base, boolean compress) {
		return getActualLocation(base, compress ? JAR_EXTENSION : XML_EXTENSION);
	}

	private static URI getActualLocation(URI base, String extension) {
		return URIUtil.append(base, CONTENT_FILENAME + extension);
	}

	public static URI getBlobStoreLocation(URI base, String suffix) {
		return URIUtil.append(base, suffix);
	}

	/*
	 * This is only called by the parser when loading a repository.
	 */
	SimpleArtifactRepository(IProvisioningAgent agent, String name, String type, String version, String description, String provider, Set<SimpleArtifactDescriptor> artifacts, String[][] mappingRules, Map<String, String> properties) {
		super(agent, name, type, version, null, description, provider, properties);
		this.artifactDescriptors.addAll(artifacts);
		this.mappingRules = mappingRules;
		for (SimpleArtifactDescriptor desc : artifactDescriptors)
			mapDescriptor(desc);
	}

	private synchronized void mapDescriptor(IArtifactDescriptor descriptor) {
		IArtifactKey key = descriptor.getArtifactKey();
		if (snapshotNeeded) {
			cloneAritfactMap();
			snapshotNeeded = false;
		}
		List<IArtifactDescriptor> descriptors = artifactMap.get(key);
		if (descriptors == null) {
			descriptors = new ArrayList<IArtifactDescriptor>();
			artifactMap.put(key, descriptors);
		}
		descriptors.add(descriptor);
		keyIndex = null;
	}

	private synchronized void unmapDescriptor(IArtifactDescriptor descriptor) {
		IArtifactKey key = descriptor.getArtifactKey();
		List<IArtifactDescriptor> descriptors = artifactMap.get(key);
		if (descriptors == null)
			return;

		if (snapshotNeeded) {
			cloneAritfactMap();
			snapshotNeeded = false;
			descriptors = artifactMap.get(key);
		}
		descriptors.remove(descriptor);
		if (descriptors.isEmpty())
			artifactMap.remove(key);
		keyIndex = null;
	}

	private void cloneAritfactMap() {
		HashMap<IArtifactKey, List<IArtifactDescriptor>> clone = new HashMap<IArtifactKey, List<IArtifactDescriptor>>(artifactMap.size());
		for (Entry<IArtifactKey, List<IArtifactDescriptor>> entry : artifactMap.entrySet())
			clone.put(entry.getKey(), new ArrayList<IArtifactDescriptor>(entry.getValue()));
		artifactMap = clone;
	}

	public SimpleArtifactRepository(IProvisioningAgent agent, String repositoryName, URI location, Map<String, String> properties) {
		super(agent, repositoryName, REPOSITORY_TYPE, REPOSITORY_VERSION.toString(), location, null, null, properties);

		boolean lockAcquired = false;
		try {
			canLock = Boolean.valueOf(canLock());
			if (canLock.booleanValue()) {
				lockAcquired = lockAndLoad(true, new NullProgressMonitor());
				if (!lockAcquired)
					throw new IllegalStateException("Cannot acquire the lock for " + location); //$NON-NLS-1$
			}

			initializeAfterLoad(location, false); // Don't update the timestamp, it will be done during save
			if (properties != null) {
				if (properties.containsKey(PUBLISH_PACK_FILES_AS_SIBLINGS)) {
					synchronized (this) {
						String newValue = properties.get(PUBLISH_PACK_FILES_AS_SIBLINGS);
						if (Boolean.TRUE.toString().equals(newValue)) {
							mappingRules = PACKED_MAPPING_RULES;
						} else {
							mappingRules = DEFAULT_MAPPING_RULES;
						}
						initializeMapper();
					}
				}
			}
			save();
		} finally {
			if (lockAcquired)
				unlock();
		}
	}

	public synchronized void addDescriptor(IArtifactDescriptor toAdd, IProgressMonitor monitor) {
		boolean lockAcquired = false;
		try {
			if (canLock()) {
				lockAcquired = lockAndLoad(false, monitor);
				if (!lockAcquired)
					return;
			}

			if (artifactDescriptors.contains(toAdd))
				return;

			SimpleArtifactDescriptor internalDescriptor = createInternalDescriptor(toAdd);
			artifactDescriptors.add(internalDescriptor);
			mapDescriptor(internalDescriptor);
			save();
		} finally {
			if (lockAcquired)
				unlock();
		}
	}

	public IArtifactDescriptor createArtifactDescriptor(IArtifactKey key) {
		return new SimpleArtifactDescriptor(key);
	}

	private SimpleArtifactDescriptor createInternalDescriptor(IArtifactDescriptor descriptor) {
		SimpleArtifactDescriptor internal = new SimpleArtifactDescriptor(descriptor);

		internal.setRepository(this);
		if (isFolderBased(descriptor))
			internal.setRepositoryProperty(ARTIFACT_FOLDER, Boolean.TRUE.toString());

		//clear out the UUID if we aren't using the blobstore.
		if (flatButPackedEnabled(descriptor) && internal.getProperty(ARTIFACT_UUID) != null) {
			internal.setProperty(ARTIFACT_UUID, null);
		}

		if (descriptor instanceof SimpleArtifactDescriptor) {
			Map<String, String> repoProperties = ((SimpleArtifactDescriptor) descriptor).getRepositoryProperties();
			for (Map.Entry<String, String> entry : repoProperties.entrySet()) {
				internal.setRepositoryProperty(entry.getKey(), entry.getValue());
			}
		}
		return internal;
	}

	public synchronized void addDescriptors(IArtifactDescriptor[] descriptors, IProgressMonitor monitor) {
		boolean lockAcquired = false;
		try {
			if (canLock()) {
				lockAcquired = lockAndLoad(false, monitor);
				if (!lockAcquired)
					return;
			}

			for (int i = 0; i < descriptors.length; i++) {
				if (artifactDescriptors.contains(descriptors[i]))
					continue;
				SimpleArtifactDescriptor internalDescriptor = createInternalDescriptor(descriptors[i]);
				artifactDescriptors.add(internalDescriptor);
				mapDescriptor(internalDescriptor);
			}
			save();
		} finally {
			if (lockAcquired)
				unlock();
		}
	}

	private synchronized OutputStream addPostSteps(ProcessingStepHandler handler, IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
		ArrayList<ProcessingStep> steps = new ArrayList<ProcessingStep>();
		steps.add(new SignatureVerifier());
		if (MD5_ARTIFACT_CHECK_ENABLED && descriptor.getProperty(IArtifactDescriptor.ARTIFACT_MD5) != null)
			steps.add(new MD5Verifier(descriptor.getProperty(IArtifactDescriptor.ARTIFACT_MD5)));
		if (steps.isEmpty())
			return destination;
		ProcessingStep[] stepArray = steps.toArray(new ProcessingStep[steps.size()]);
		// TODO should probably be using createAndLink here
		return handler.link(stepArray, destination, monitor);
	}

	private OutputStream addPreSteps(ProcessingStepHandler handler, IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
		ArrayList<ProcessingStep> steps = new ArrayList<ProcessingStep>();
		if (IArtifactDescriptor.TYPE_ZIP.equals(descriptor.getProperty(IArtifactDescriptor.DOWNLOAD_CONTENTTYPE)))
			steps.add(new ZipVerifierStep());
		if (MD5_CHECK_ENABLED && descriptor.getProperty(IArtifactDescriptor.DOWNLOAD_MD5) != null)
			steps.add(new MD5Verifier(descriptor.getProperty(IArtifactDescriptor.DOWNLOAD_MD5)));
		// Add steps here if needed
		if (steps.isEmpty())
			return destination;
		ProcessingStep[] stepArray = steps.toArray(new ProcessingStep[steps.size()]);
		// TODO should probably be using createAndLink here
		return handler.link(stepArray, destination, monitor);
	}

	private byte[] bytesFromHexString(String string) {
		byte[] bytes = new byte[UniversalUniqueIdentifier.BYTES_SIZE];
		for (int i = 0; i < string.length(); i += 2) {
			String byteString = string.substring(i, i + 2);
			bytes[i / 2] = (byte) Integer.parseInt(byteString, 16);
		}
		return bytes;
	}

	private String bytesToHexString(byte[] bytes) {
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < bytes.length; i++) {
			String hexString;
			if (bytes[i] < 0)
				hexString = Integer.toHexString(256 + bytes[i]);
			else
				hexString = Integer.toHexString(bytes[i]);
			if (hexString.length() == 1)
				buffer.append("0"); //$NON-NLS-1$
			buffer.append(hexString);
		}
		return buffer.toString();
	}

	public synchronized boolean contains(IArtifactDescriptor descriptor) {
		if (!holdsLock() && URIUtil.isFileURI(getLocation())) {
			load(new NullProgressMonitor());
		}
		SimpleArtifactDescriptor simpleDescriptor = createInternalDescriptor(descriptor);
		return artifactDescriptors.contains(simpleDescriptor);
	}

	public synchronized boolean contains(IArtifactKey key) {
		if (!holdsLock() && URIUtil.isFileURI(getLocation())) {
			load(new NullProgressMonitor());
		}
		return artifactMap.containsKey(key);
	}

	public synchronized URI createLocation(ArtifactDescriptor descriptor) {
		if (flatButPackedEnabled(descriptor)) {
			return getLocationForPackedButFlatArtifacts(descriptor);
		}
		// if the descriptor is canonical, clear out any UUID that might be set and use the Mapper
		if (descriptor.getProcessingSteps().length == 0) {
			descriptor.setProperty(ARTIFACT_UUID, null);
			IArtifactKey key = descriptor.getArtifactKey();
			URI result = mapper.map(getLocation(), key.getClassifier(), key.getId(), key.getVersion().toString(), descriptor.getProperty(IArtifactDescriptor.FORMAT));
			if (result != null) {
				if (isFolderBased(descriptor) && URIUtil.lastSegment(result).endsWith(JAR_EXTENSION)) {
					return URIUtil.removeFileExtension(result);
				}
				return result;
			}
		}

		// Otherwise generate a location by creating a UUID, remembering it in the properties 
		// and computing the location
		byte[] bytes = new UniversalUniqueIdentifier().toBytes();
		descriptor.setProperty(ARTIFACT_UUID, bytesToHexString(bytes));
		return blobStore.fileFor(bytes);
	}

	/**
	 * Removes the given descriptor, and the physical artifact corresponding
	 * to that descriptor. Returns <code>true</code> if and only if the
	 * descriptor existed in the repository, and was successfully removed.
	 */
	private boolean doRemoveArtifact(IArtifactDescriptor descriptor) {
		SimpleArtifactDescriptor simple = null;
		if (descriptor instanceof SimpleArtifactDescriptor)
			simple = (SimpleArtifactDescriptor) descriptor;
		else
			simple = createInternalDescriptor(descriptor);
		if (simple.getRepositoryProperty(SimpleArtifactDescriptor.ARTIFACT_REFERENCE) == null) {
			File file = getArtifactFile(descriptor);
			if (file != null) {
				// If the file != null remove it, otherwise just remove
				// the descriptor
				delete(file);
				if (file.exists())
					return false;
			}
		}
		boolean result = artifactDescriptors.remove(descriptor);
		if (result)
			unmapDescriptor(descriptor);

		return result;
	}

	protected IStatus downloadArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
		if (isFolderBased(descriptor)) {
			File artifactFolder = getArtifactFile(descriptor);
			if (artifactFolder == null) {
				if (getLocation(descriptor) != null && !URIUtil.isFileURI(getLocation(descriptor)))
					return reportStatus(descriptor, destination, new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.folder_artifact_not_file_repo, descriptor.getArtifactKey())));
				return reportStatus(descriptor, destination, new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.artifact_not_found, descriptor.getArtifactKey())));
			}
			// TODO: optimize and ensure manifest is written first
			File zipFile = null;
			long start = System.currentTimeMillis();
			long totalArtifactSize = 0;
			try {
				zipFile = File.createTempFile(artifactFolder.getName(), JAR_EXTENSION, null);
				FileUtils.zip(artifactFolder.listFiles(), null, zipFile, FileUtils.createRootPathComputer(artifactFolder));
				FileInputStream fis = new FileInputStream(zipFile);
				totalArtifactSize += FileUtils.copyStream(fis, true, destination, false);
			} catch (IOException e) {
				return reportStatus(descriptor, destination, new Status(IStatus.ERROR, Activator.ID, e.getMessage()));
			} finally {
				if (zipFile != null)
					zipFile.delete();
			}
			long end = System.currentTimeMillis();
			DownloadStatus statusWithDownloadSpeed = new DownloadStatus(IStatus.OK, Activator.ID, Status.OK_STATUS.getMessage());
			try {
				statusWithDownloadSpeed.setFileSize(totalArtifactSize);
				statusWithDownloadSpeed.setTransferRate(totalArtifactSize / Math.max((end - start), 1) * 1000);
			} catch (NumberFormatException e) {
				// ignore
			}
			return reportStatus(descriptor, destination, statusWithDownloadSpeed);
		}

		//download from the best available mirror
		URI baseLocation = getLocation(descriptor);
		if (baseLocation == null)
			return new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.no_location, descriptor));
		URI mirrorLocation = getMirror(baseLocation, monitor);
		IStatus status = downloadArtifact(descriptor, mirrorLocation, destination, monitor);
		IStatus result = reportStatus(descriptor, destination, status);
		// if the original download went reasonably but the reportStatus found some issues
		// (e..g, in the processing steps/validators) then mark the mirror as bad and return
		// a retry code (assuming we have more mirrors)
		if ((status.isOK() || status.matches(IStatus.INFO | IStatus.WARNING)) && result.getSeverity() == IStatus.ERROR && !artifactError(result)) {
			if (mirrors != null) {
				mirrors.reportResult(mirrorLocation.toString(), result);
				if (mirrors.hasValidMirror())
					return new MultiStatus(Activator.ID, CODE_RETRY, new IStatus[] {result}, "Retry another mirror", null); //$NON-NLS-1$
			}
		}
		// if the original status was a retry, don't lose that.
		return status.getCode() == CODE_RETRY ? status : result;
	}

	/**
	 * Return true if there is an 'artifact error'. You cannot retry when an artifact error is found.
	 * @return True if the status (or children status) have an artifact error status code. False otherwise
	 */
	private boolean artifactError(IStatus status) {
		if (status.getCode() == MirrorRequest.ARTIFACT_PROCESSING_ERROR)
			return true;
		if (status.getChildren() != null) {
			IStatus[] children = status.getChildren();
			for (IStatus child : children) {
				if (artifactError(child))
					return true;
			}
		}
		return false;
	}

	/**
	 * Copy a file to an output stream.
	 * Optionally close the streams when done.
	 * Notify the monitor about progress we make
	 * 
	 * @return the number of bytes written.
	 */
	private IStatus copyFileToStream(File in, OutputStream out, IProgressMonitor monitor) {
		// Buffer filled with contents from the stream at a time
		int bufferSize = 16 * 1024;
		byte[] buffer = new byte[bufferSize];
		// Number of passes in the below loop, convert to integer which is needed in monitor conversion below
		int expected_loops = new Double(in.length() / bufferSize).intValue() + 1; // +1: also count the initial run
		SubMonitor sub = SubMonitor.convert(monitor, Messages.downloading + in.getName(), expected_loops);
		// Be optimistic about the outcome of this...
		IStatus status = new DownloadStatus(IStatus.OK, Activator.ID, Status.OK_STATUS.getMessage());
		try {
			long start = System.currentTimeMillis();
			FileInputStream stream = new FileInputStream(in);
			try {
				int len;
				while ((len = stream.read(buffer)) != -1) {
					out.write(buffer, 0, len);
					sub.worked(1);
				}
			} finally {
				stream.close();
			}
			long end = System.currentTimeMillis();
			((DownloadStatus) status).setFileSize(in.length());
			((DownloadStatus) status).setLastModified(in.lastModified());
			((DownloadStatus) status).setTransferRate(in.length() / Math.max((end - start), 1) * 1000);
		} catch (IOException ioe) {
			status = new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.error_copying_local_file, in.getAbsolutePath()), ioe);
		}
		sub.done();
		return status;
	}

	private IStatus downloadArtifact(IArtifactDescriptor descriptor, URI mirrorLocation, OutputStream destination, IProgressMonitor monitor) {
		//Bug 340352: transport has performance overhead of 100ms and more, bypass it for local copies
		IStatus result = Status.OK_STATUS;
		if (mirrorLocation.getScheme().equals(SimpleArtifactRepositoryFactory.PROTOCOL_FILE))
			result = copyFileToStream(new File(mirrorLocation), destination, monitor);
		else
			result = getTransport().download(mirrorLocation, destination, monitor);
		if (mirrors != null)
			mirrors.reportResult(mirrorLocation.toString(), result);
		if (result.isOK() || result.getSeverity() == IStatus.CANCEL)
			return result;
		if (monitor.isCanceled())
			return Status.CANCEL_STATUS;
		// If there are more valid mirrors then return an error with a special code that tells the caller
		// to keep trying.  Note that the message in the status is largely irrelevant but the child
		// status tells the story of why we failed on this try.
		// TODO find a better way of doing this.
		if (mirrors != null && mirrors.hasValidMirror())
			return new MultiStatus(Activator.ID, CODE_RETRY, new IStatus[] {result}, "Retry another mirror", null); //$NON-NLS-1$
		return result;
	}

	/**
	 * Returns an equivalent mirror location for the given artifact location.
	 * @param baseLocation The location of the artifact in this repository
	 * @return the Location of the artifact in this repository, or an equivalent mirror
	 */
	private synchronized URI getMirror(URI baseLocation, IProgressMonitor monitor) {
		if (!MIRRORS_ENABLED || (!isForceThreading() && isLocal()))
			return baseLocation;
		if (mirrors == null)
			mirrors = new MirrorSelector(this, getTransport());
		return mirrors.getMirrorLocation(baseLocation, monitor);
	}

	public <T> T getAdapter(Class<T> adapter) {
		// if we are adapting to file or writable repositories then make sure we have a file location
		if (adapter == IFileArtifactRepository.class)
			if (!isLocal())
				return null;
		return super.getAdapter(adapter);
	}

	IStatus getArtifact(IArtifactRequest request, IProgressMonitor monitor) {
		request.perform(this, monitor);
		return request.getResult();
	}

	public IStatus getArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
		if (!holdsLock() && URIUtil.isFileURI(getLocation())) {
			load(new NullProgressMonitor());
		}
		if (monitor.isCanceled())
			return Status.CANCEL_STATUS;
		ProcessingStepHandler handler = new ProcessingStepHandler();
		destination = processDestination(handler, descriptor, destination, monitor);
		IStatus status = ProcessingStepHandler.checkStatus(destination);
		if (!status.isOK() && status.getSeverity() != IStatus.INFO)
			return status;

		return downloadArtifact(descriptor, destination, monitor);
	}

	public IStatus getRawArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
		if (!holdsLock() && URIUtil.isFileURI(getLocation())) {
			load(new NullProgressMonitor());
		}
		if (monitor.isCanceled())
			return Status.CANCEL_STATUS;
		return downloadArtifact(descriptor, destination, monitor);
	}

	public synchronized IArtifactDescriptor[] getArtifactDescriptors(IArtifactKey key) {
		if (!holdsLock() && URIUtil.isFileURI(getLocation())) {
			load(new NullProgressMonitor());
		}

		List<IArtifactDescriptor> result = artifactMap.get(key);
		if (result == null)
			return new IArtifactDescriptor[0];

		return result.toArray(new IArtifactDescriptor[result.size()]);
	}

	public File getArtifactFile(IArtifactDescriptor descriptor) {
		URI result = getLocation(descriptor);
		if (result == null || !URIUtil.isFileURI(result))
			return null;
		return URIUtil.toFile(result);
	}

	public File getArtifactFile(IArtifactKey key) {
		IArtifactDescriptor descriptor = getCompleteArtifactDescriptor(key);
		if (descriptor == null)
			return null;
		return getArtifactFile(descriptor);
	}

	public IStatus getArtifacts(IArtifactRequest[] requests, IProgressMonitor monitor) {
		if (!holdsLock() && URIUtil.isFileURI(getLocation())) {
			load(new NullProgressMonitor());
		}
		if (monitor.isCanceled())
			return Status.CANCEL_STATUS;

		final MultiStatus overallStatus = new MultiStatus(Activator.ID, IStatus.OK, NLS.bind(Messages.message_problemReadingArtifact, getLocation()), null);
		LinkedList<IArtifactRequest> requestsPending = new LinkedList<IArtifactRequest>(Arrays.asList(requests));

		int numberOfJobs = Math.min(requests.length, getMaximumThreads());
		if (numberOfJobs <= 1 || (!isForceThreading() && isLocal())) {
			SubMonitor subMonitor = SubMonitor.convert(monitor, requests.length);
			try {
				for (int i = 0; i < requests.length; i++) {
					if (monitor.isCanceled())
						return Status.CANCEL_STATUS;
					IStatus result = getArtifact(requests[i], subMonitor.newChild(1));
					if (!result.isOK())
						overallStatus.add(result);
				}
			} finally {
				subMonitor.done();
			}
		} else {
			// initialize the various jobs needed to process the get artifact requests
			monitor.beginTask(NLS.bind(Messages.sar_downloading, Integer.toString(requests.length)), requests.length);
			try {
				DownloadJob jobs[] = new DownloadJob[numberOfJobs];
				for (int i = 0; i < numberOfJobs; i++) {
					jobs[i] = new DownloadJob(Messages.sar_downloadJobName + i);
					jobs[i].initialize(this, requestsPending, monitor, overallStatus);
					jobs[i].schedule();
				}
				// wait for all the jobs to complete
				try {
					Job.getJobManager().join(DownloadJob.FAMILY, null);
				} catch (InterruptedException e) {
					//ignore
				}
			} finally {
				monitor.done();
			}
		}

		if (monitor.isCanceled())
			return Status.CANCEL_STATUS;
		else if (overallStatus.isOK())
			return Status.OK_STATUS;
		else
			return overallStatus;
	}

	public synchronized IArtifactDescriptor getCompleteArtifactDescriptor(IArtifactKey key) {
		if (!holdsLock() && URIUtil.isFileURI(getLocation())) {
			load(new NullProgressMonitor());
		}
		List<IArtifactDescriptor> descriptors = artifactMap.get(key);
		if (descriptors == null)
			return null;

		for (IArtifactDescriptor desc : descriptors) {
			// look for a descriptor that matches the key and is "complete"
			if (desc.getArtifactKey().equals(key) && desc.getProcessingSteps().length == 0)
				return desc;
		}
		return null;
	}

	public synchronized Set<SimpleArtifactDescriptor> getDescriptors() {
		if (!holdsLock() && URIUtil.isFileURI(getLocation())) {
			load(new NullProgressMonitor());
		}
		return artifactDescriptors;
	}

	/**
	 * Typically non-canonical forms of the artifact are stored in the blob store.
	 * However, we support having the pack200 files alongside the canonical artifact
	 * for compatibility with the format used in optimized update sites.  We call
	 * this arrangement "flat but packed".
	 */
	private boolean flatButPackedEnabled(IArtifactDescriptor descriptor) {
		return Boolean.TRUE.toString().equals(getProperties().get(PUBLISH_PACK_FILES_AS_SIBLINGS)) && IArtifactDescriptor.FORMAT_PACKED.equals(descriptor.getProperty(IArtifactDescriptor.FORMAT));
	}

	/**
	 * @see #flatButPackedEnabled(IArtifactDescriptor)
	 */
	private URI getLocationForPackedButFlatArtifacts(IArtifactDescriptor descriptor) {
		IArtifactKey key = descriptor.getArtifactKey();
		return mapper.map(getLocation(), key.getClassifier(), key.getId(), key.getVersion().toString(), descriptor.getProperty(IArtifactDescriptor.FORMAT));
	}

	public synchronized URI getLocation(IArtifactDescriptor descriptor) {
		// if the artifact has a uuid then use it
		String uuid = descriptor.getProperty(ARTIFACT_UUID);
		if (uuid != null)
			return blobStore.fileFor(bytesFromHexString(uuid));

		if (flatButPackedEnabled(descriptor)) {
			return getLocationForPackedButFlatArtifacts(descriptor);
		}

		try {
			// if the artifact is just a reference then return the reference location
			if (descriptor instanceof SimpleArtifactDescriptor) {
				String artifactReference = ((SimpleArtifactDescriptor) descriptor).getRepositoryProperty(SimpleArtifactDescriptor.ARTIFACT_REFERENCE);
				if (artifactReference != null) {
					try {
						return new URI(artifactReference);
					} catch (URISyntaxException e) {
						return URIUtil.fromString(artifactReference);
					}
				}
			}

			// if the descriptor is complete then use the mapping rules...
			if (descriptor.getProcessingSteps().length == 0) {
				IArtifactKey key = descriptor.getArtifactKey();
				URI result = mapper.map(getLocation(), key.getClassifier(), key.getId(), key.getVersion().toString(), descriptor.getProperty(IArtifactDescriptor.FORMAT));
				if (result != null) {
					if (isFolderBased(descriptor) && URIUtil.lastSegment(result).endsWith(JAR_EXTENSION))
						return URIUtil.removeFileExtension(result);
					if (result.getScheme() == null && "file".equals(getLocation().getScheme())) //$NON-NLS-1$
						return URIUtil.makeAbsolute(result, new File(System.getProperty("user.dir")).toURI()); //$NON-NLS-1$
					return result;
				}
			}
		} catch (URISyntaxException e) {
			return null;
		}
		// in the end there is not enough information so return null 
		return null;
	}

	/**
	 * Returns the maximum number of concurrent download threads.
	 */
	private int getMaximumThreads() {
		int repoMaxThreads = DEFAULT_MAX_THREADS;
		int userMaxThreads = DEFAULT_MAX_THREADS;
		try {
			String maxThreadString = getProperties().get(PROP_MAX_THREADS);
			if (maxThreadString != null)
				repoMaxThreads = Math.max(1, Integer.parseInt(maxThreadString));
		} catch (NumberFormatException nfe) {
			// default number of threads
		}
		try {
			String maxThreadString = Activator.getContext().getProperty(PROP_MAX_THREADS);
			if (maxThreadString != null)
				userMaxThreads = Math.max(1, Integer.parseInt(maxThreadString));
		} catch (NumberFormatException nfe) {
			// default number of threads
		}
		return Math.min(repoMaxThreads, userMaxThreads);
	}

	public OutputStream getOutputStream(IArtifactDescriptor descriptor) throws ProvisionException {
		if (!holdsLock() && URIUtil.isFileURI(getLocation())) {
			load(new NullProgressMonitor());
		}

		assertModifiable();

		// Create a copy of the original descriptor that we can manipulate and add to our repo.
		ArtifactDescriptor newDescriptor = createInternalDescriptor(descriptor);

		// Check if the artifact is already in this repository, check the newDescriptor instead of the original
		// since the implementation of hash/equals on the descriptor matters here.
		if (contains(newDescriptor)) {
			String msg = NLS.bind(Messages.available_already_in, getLocation().toString());
			throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.ARTIFACT_EXISTS, msg, null));
		}

		// Determine writing location
		URI newLocation = createLocation(newDescriptor);
		if (newLocation == null)
			throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.no_location, newDescriptor)));
		String file = URIUtil.toFile(newLocation).getAbsolutePath();

		// TODO at this point we have to assume that the repository is file-based.  Eventually 
		// we should end up with writeable URLs...
		// Make sure that the file does not exist and that the parents do
		File outputFile = new File(file);
		if (outputFile.exists()) {
			System.err.println("Artifact repository out of sync. Overwriting " + outputFile.getAbsoluteFile()); //$NON-NLS-1$
			delete(outputFile);
		}

		OutputStream target = null;
		try {
			if (isFolderBased(newDescriptor)) {
				mkdirs(outputFile);
				if (!outputFile.isDirectory())
					throw failedWrite(new IOException(NLS.bind(Messages.sar_failedMkdir, outputFile.toString())));
				target = new ZippedFolderOutputStream(outputFile);
			} else {
				// file based
				File parent = outputFile.getParentFile();
				mkdirs(parent);
				if (!parent.isDirectory())
					throw failedWrite(new IOException(NLS.bind(Messages.sar_failedMkdir, parent.toString())));
				target = new FileOutputStream(file);
			}

			// finally create and return an output stream suitably wrapped so that when it is 
			// closed the repository is updated with the descriptor
			return new ArtifactOutputStream(new BufferedOutputStream(target), newDescriptor, outputFile);
		} catch (IOException e) {
			throw failedWrite(e);
		}

	}

	/**
	 * We implement mkdirs ourselves because this code is known to run in
	 * highly concurrent scenarios, and there is a race condition in the JRE implementation
	 * of mkdirs (see bug 265654).
	 */
	private void mkdirs(File dir) {
		if (dir == null || dir.exists())
			return;
		if (dir.mkdir())
			return;
		mkdirs(dir.getParentFile());
		dir.mkdir();
	}

	private ProvisionException failedWrite(Exception e) throws ProvisionException {
		String msg = NLS.bind(Messages.repoFailedWrite, getLocation());
		throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_FAILED_WRITE, msg, e));
	}

	public synchronized String[][] getRules() {
		if (!holdsLock() && URIUtil.isFileURI(getLocation())) {
			load(new NullProgressMonitor());
		}
		return mappingRules;
	}

	private Transport getTransport() {
		return (Transport) getProvisioningAgent().getService(Transport.SERVICE_NAME);
	}

	// use this method to setup any transient fields etc after the object has been restored from a stream
	public synchronized void initializeAfterLoad(URI repoLocation) {
		this.initializeAfterLoad(repoLocation, true);
	}

	private synchronized void initializeAfterLoad(URI repoLocation, boolean updateTimestamp) {
		setLocation(repoLocation);
		String suffix = getBlobStoreName(BLOBSTORE);
		blobStore = new BlobStore(getBlobStoreLocation(repoLocation, suffix), 128);
		initializeMapper();
		for (SimpleArtifactDescriptor desc : artifactDescriptors)
			desc.setRepository(this);
		if (updateTimestamp)
			updateTimestamp();
		if (canLock == null)
			canLock = Boolean.valueOf(canLock());
	}

	private String getBlobStoreName(String defaultValue) {
		String value = getProperty(PROP_BLOBSTORE_NAME);
		if (value == null || value.length() == 0) {
			return defaultValue;
		}
		return value;
	}

	private synchronized void initializeMapper() {
		mapper = new Mapper();
		mapper.initialize(Activator.getContext(), mappingRules);
	}

	private boolean isFolderBased(IArtifactDescriptor descriptor) {
		// This is called from createInternalDescriptor, so if we aren't a
		// SimpleArtifactDescriptor then just check the descriptor properties instead 
		// of creating the internal descriptor.
		SimpleArtifactDescriptor internalDescriptor = null;
		if (descriptor instanceof SimpleArtifactDescriptor)
			internalDescriptor = (SimpleArtifactDescriptor) descriptor;
		if (internalDescriptor != null) {
			String useArtifactFolder = internalDescriptor.getRepositoryProperty(ARTIFACT_FOLDER);
			if (useArtifactFolder != null)
				return Boolean.parseBoolean(useArtifactFolder);
		}
		return Boolean.parseBoolean(descriptor.getProperty(ARTIFACT_FOLDER));
	}

	private boolean isForceThreading() {
		return "true".equals(getProperties().get(PROP_FORCE_THREADING)); //$NON-NLS-1$
	}

	private boolean isLocal() {
		return "file".equalsIgnoreCase(getLocation().getScheme()); //$NON-NLS-1$
	}

	public boolean isModifiable() {
		return isLocal();
	}

	public OutputStream processDestination(ProcessingStepHandler handler, IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
		destination = addPostSteps(handler, descriptor, destination, monitor);
		destination = handler.createAndLink(getProvisioningAgent(), descriptor.getProcessingSteps(), descriptor, destination, monitor);
		destination = addPreSteps(handler, descriptor, destination, monitor);
		return destination;
	}

	public synchronized void removeAll(IProgressMonitor monitor) {
		boolean lockAcquired = false;
		try {
			if (canLock()) {
				lockAcquired = lockAndLoad(false, monitor);
				if (!lockAcquired)
					return;
			}

			IArtifactDescriptor[] toRemove = artifactDescriptors.toArray(new IArtifactDescriptor[artifactDescriptors.size()]);
			boolean changed = false;
			for (int i = 0; i < toRemove.length; i++)
				changed |= doRemoveArtifact(toRemove[i]);
			if (changed)
				save();
		} finally {
			if (lockAcquired)
				unlock();
		}
	}

	public synchronized void removeDescriptor(IArtifactDescriptor descriptor, IProgressMonitor monitor) {
		boolean lockAcquired = false;
		try {
			if (canLock()) {
				lockAcquired = lockAndLoad(false, monitor);
				if (!lockAcquired)
					return;
			}

			if (doRemoveArtifact(descriptor))
				save();
		} finally {
			if (lockAcquired)
				unlock();
		}
	}

	public synchronized void removeDescriptors(IArtifactDescriptor[] descriptors, IProgressMonitor monitor) {
		boolean lockAcquired = false;
		try {
			if (canLock()) {
				lockAcquired = lockAndLoad(false, monitor);
				if (!lockAcquired)
					return;
			}

			boolean changed = false;
			for (IArtifactDescriptor descriptor : descriptors)
				changed |= doRemoveArtifact(descriptor);
			if (changed)
				save();
		} finally {
			if (lockAcquired)
				unlock();
		}
	}

	public synchronized void removeDescriptors(IArtifactKey[] keys, IProgressMonitor monitor) {
		boolean lockAcquired = false;
		try {
			if (canLock()) {
				lockAcquired = lockAndLoad(false, monitor);
				if (!lockAcquired)
					return;
			}

			boolean changed = false;
			for (IArtifactKey key : keys) {
				IArtifactDescriptor[] descriptors = getArtifactDescriptors(key);
				for (IArtifactDescriptor descriptor : descriptors)
					changed |= doRemoveArtifact(descriptor);
			}
			if (changed)
				save();
		} finally {
			if (lockAcquired)
				unlock();
		}
	}

	public synchronized void removeDescriptor(IArtifactKey key, IProgressMonitor monitor) {
		boolean lockAcquired = false;
		try {
			if (canLock()) {
				lockAcquired = lockAndLoad(false, monitor);
				if (!lockAcquired)
					return;
			}

			IArtifactDescriptor[] toRemove = getArtifactDescriptors(key);
			boolean changed = false;
			for (int i = 0; i < toRemove.length; i++)
				changed |= doRemoveArtifact(toRemove[i]);
			if (changed)
				save();
		} finally {
			if (lockAcquired)
				unlock();
		}
	}

	private IStatus reportStatus(IArtifactDescriptor descriptor, OutputStream destination, IStatus status) {
		// If the destination is just a normal stream then the status is simple.  Just return
		// it and do not close the destination
		if (!(destination instanceof ProcessingStep))
			return status;

		// If the destination is a processing step then close the stream to flush the data through all
		// the steps.  then collect up the status from all the steps and return
		try {
			destination.close();
		} catch (IOException e) {
			return new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.sar_reportStatus, descriptor.getArtifactKey().toExternalForm()), e);
		}

		// An error occurred obtaining the artifact, ProcessingStep errors aren't important
		if (status.matches(IStatus.ERROR))
			return status;

		IStatus stepStatus = ProcessingStepHandler.getErrorStatus(destination);
		// if the steps all ran ok and there is no interesting information, return the status from this method
		if (!stepStatus.isMultiStatus() && stepStatus.isOK())
			return status;
		// else gather up the status from the steps
		MultiStatus result = new MultiStatus(Activator.ID, IStatus.OK, new IStatus[0], NLS.bind(Messages.sar_reportStatus, descriptor.getArtifactKey().toExternalForm()), null);

		if (!status.isOK()) {
			// Transport pushes its status onto the output stream if the stream implements IStateful, to prevent
			// duplication determine if the Status is present in the ProcessingStep status. 
			boolean found = false;
			IStatus[] stepStatusChildren = stepStatus.getChildren();
			for (int i = 0; i < stepStatusChildren.length && !found; i++)
				if (stepStatusChildren[i] == status)
					found = true;
			if (!found)
				result.merge(status);
		}

		result.merge(stepStatus);
		return result;
	}

	public void save() {
		if (disableSave)
			return;
		boolean compress = "true".equalsIgnoreCase(getProperty(PROP_COMPRESSED)); //$NON-NLS-1$
		save(compress);
	}

	private void save(boolean compress) {
		assertModifiable();
		OutputStream os = null;
		try {
			try {
				URI actualLocation = getActualLocation(getLocation(), false);
				File artifactsFile = URIUtil.toFile(actualLocation);
				File jarFile = URIUtil.toFile(getActualLocation(getLocation(), true));
				if (!compress) {
					if (jarFile.exists()) {
						jarFile.delete();
					}
					if (!artifactsFile.exists()) {
						// create parent folders
						mkdirs(artifactsFile.getParentFile());
					}
					os = new FileOutputStream(artifactsFile);
				} else {
					if (artifactsFile.exists()) {
						artifactsFile.delete();
					}
					if (!jarFile.exists()) {
						mkdirs(jarFile.getParentFile());
						jarFile.createNewFile();
					}
					os = new JarOutputStream(new FileOutputStream(jarFile));
					((JarOutputStream) os).putNextEntry(new JarEntry(new Path(artifactsFile.getAbsolutePath()).lastSegment()));
				}
				super.setProperty(IRepository.PROP_TIMESTAMP, Long.toString(System.currentTimeMillis()), new NullProgressMonitor());
				new SimpleArtifactRepositoryIO(getProvisioningAgent()).write(this, os);
			} catch (IOException e) {
				// TODO proper exception handling
				e.printStackTrace();
			} finally {
				if (os != null)
					os.close();
				updateTimestamp();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private String doSetProperty(String key, String newValue, IProgressMonitor monitor, boolean save) {
		String oldValue = super.setProperty(key, newValue, new NullProgressMonitor());
		if (oldValue == newValue || (oldValue != null && oldValue.equals(newValue)))
			return oldValue;
		if (PUBLISH_PACK_FILES_AS_SIBLINGS.equals(key)) {
			synchronized (this) {
				if (Boolean.TRUE.toString().equals(newValue)) {
					mappingRules = PACKED_MAPPING_RULES;
				} else {
					mappingRules = DEFAULT_MAPPING_RULES;
				}
				initializeMapper();
			}
		}
		if (save)
			save();
		return oldValue;
	}

	public String setProperty(String key, String newValue, IProgressMonitor monitor) {
		boolean lockAcquired = false;
		try {
			if (canLock()) {
				lockAcquired = lockAndLoad(false, monitor);
				if (!lockAcquired)
					return super.getProperty(key);
			}
			return doSetProperty(key, newValue, monitor, true);
		} finally {
			if (lockAcquired)
				unlock();
		}
	}

	public synchronized void setRules(String[][] rules) {
		mappingRules = rules;
	}

	public String toString() {
		return getLocation().toString();
	}

	public IQueryable<IArtifactDescriptor> descriptorQueryable() {
		return new IQueryable<IArtifactDescriptor>() {
			public IQueryResult<IArtifactDescriptor> query(IQuery<IArtifactDescriptor> query, IProgressMonitor monitor) {
				synchronized (SimpleArtifactRepository.this) {
					snapshotNeeded = true;
					Collection<List<IArtifactDescriptor>> descs = SimpleArtifactRepository.this.artifactMap.values();
					return query.perform(new CompoundIterator<IArtifactDescriptor>(descs.iterator()));
				}
			}
		};
	}

	public IQueryResult<IArtifactKey> query(IQuery<IArtifactKey> query, IProgressMonitor monitor) {
		return IndexProvider.query(this, query, monitor);
	}

	public synchronized Iterator<IArtifactKey> everything() {
		if (!holdsLock() && URIUtil.isFileURI(getLocation())) {
			load(new NullProgressMonitor());
		}
		snapshotNeeded = true;
		return artifactMap.keySet().iterator();
	}

	public IStatus executeBatch(IRunnableWithProgress runnable, IProgressMonitor monitor) {
		IStatus result = null;

		boolean lockAcquired = false;
		synchronized (this) {
			try {
				if (canLock()) {
					lockAcquired = lockAndLoad(false, monitor);
					if (!lockAcquired)
						return new Status(IStatus.ERROR, Activator.ID, "Could not lock artifact repository for writing", null); //$NON-NLS-1$
				}

				disableSave = true;
				runnable.run(monitor);
			} catch (OperationCanceledException oce) {
				return new Status(IStatus.CANCEL, Activator.ID, oce.getMessage(), oce);
			} catch (Throwable e) {
				result = new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e);
			} finally {
				disableSave = false;
				try {
					save();
				} catch (Exception e) {
					if (result != null)
						result = new MultiStatus(Activator.ID, IStatus.ERROR, new IStatus[] {result}, e.getMessage(), e);
					else
						result = new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e);
				} finally {
					if (lockAcquired)
						unlock();
				}
			}
		}
		if (result == null)
			result = Status.OK_STATUS;
		return result;
	}

	public synchronized IIndex<IArtifactKey> getIndex(String memberName) {
		if (!holdsLock() && URIUtil.isFileURI(getLocation())) {
			load(new NullProgressMonitor());
		}
		if (ArtifactKey.MEMBER_ID.equals(memberName)) {
			snapshotNeeded = true;
			if (keyIndex == null)
				keyIndex = new KeyIndex(artifactMap.keySet());
			return keyIndex;
		}
		return null;
	}

	public Object getManagedProperty(Object client, String memberName, Object key) {
		return null;
	}

	/**
	 * Locks the location and optionally loads the repository.
	 * 
	 * @param ignoreLoad If ignoreLoad is set to true, then the location is locked
	 *                   but the repository is not loaded.  It is expected
	 *                   that the caller will load the repository manually
	 * @return Tue if the lock was acquired, false otherwise
	 */
	private synchronized boolean lockAndLoad(boolean ignoreLoad, IProgressMonitor monitor) {
		if (holdsLock) {
			throw new IllegalStateException("Locking is not reentrant"); //$NON-NLS-1$
		}
		holdsLock = false;
		boolean success = true;

		try {
			try {
				holdsLock = lock(true, monitor);
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}

			if (holdsLock) {
				if (!ignoreLoad) {
					success = false;
					doLoad(new NullProgressMonitor());
					success = true;
				}
				return true;
			}
			return false;
		} finally {
			// If we did not successfully load the repository, make sure we free the lock.
			// This will only happen if doLoad() throws an exception, otherwise
			// we will set success to true, and return above
			if (!success)
				unlock();
		}
	}

	private synchronized boolean canLock() {
		if (holdsLock())
			return false;
		if (!URIUtil.isFileURI(getLocation()))
			return false;

		try {
			lockLocation = getLockLocation();
		} catch (IOException e) {
			return false;
		}
		return !lockLocation.isReadOnly();
	}

	/**
	 * Actually lock the location.  This method should only be called
	 * from LockAndLoad. If you only want to lock the repository and not
	 * load it, see {@link SimpleArtifactRepository#lockAndLoad(boolean, IProgressMonitor)}.
	 */
	private synchronized boolean lock(boolean wait, IProgressMonitor monitor) throws IOException {
		if (!Activator.getInstance().enableArtifactLocking())
			return true;

		if (holdsLock()) {
			throw new IllegalStateException("Locking is not reentrant"); //$NON-NLS-1$
		}

		lockLocation = getLockLocation();
		boolean locked = lockLocation.lock();
		if (locked || !wait)
			return locked;

		//Someone else must have the directory locked
		while (true) {
			if (monitor.isCanceled())
				return false;
			try {
				Thread.sleep(200); // 5x per second
			} catch (InterruptedException e) {/*ignore*/
			}
			locked = lockLocation.lock();
			if (locked)
				return true;
		}
	}

	/**
	 * Returns true if this instance of SimpleArtifactRepository holds the lock or 
	 * this repository can't be locked at all due to permission, false otherwise.
	 */
	private boolean holdsLock() {
		return (canLock != null && !canLock.booleanValue()) || holdsLock;
	}

	/**URIUtil.toURI(location.toURI()
	 * Returns the location of the lock file.
	 */
	private Location getLockLocation() throws IOException {
		if (this.lockLocation != null)
			return this.lockLocation;

		URI repositoryLocation = getLocation();
		if (!URIUtil.isFileURI(repositoryLocation)) {
			throw new IOException("Cannot lock a non file based repository"); //$NON-NLS-1$
		}

		return Activator.getInstance().getLockLocation(repositoryLocation);
	}

	/**
	 * Loads the repository from disk. This method will do nothing
	 * if this instance of SimpleArtifactRepository holds the lock
	 * because it will have loaded the repo when it acquired the lock.
	 * 
	 * @param monitor
	 */
	private void load(IProgressMonitor monitor) {
		if (!holdsLock())
			doLoad(monitor);
		else
			monitor.done();
	}

	private void updateTimestamp() {
		if (!isModifiable())
			return;
		try {
			SimpleArtifactRepositoryFactory repositoryFactory = new SimpleArtifactRepositoryFactory();
			File localFile = repositoryFactory.getLocalFile(getLocation(), new NullProgressMonitor());
			long lastModified = localFile.lastModified();
			if (lastModified > 0)
				cacheTimestamp = lastModified;
		} catch (Exception e) {
			// Do nothing
		}
	}

	/**
	 * Loads the repository from disk. If the last modified timestamp on the file <=
	 * to our cache, then this method does nothing.  Otherwise the artifact repository
	 * on disk is loaded, and reconciled with this instance of the artifact repository.
	 * 
	 * @param monitor
	 */
	private void doLoad(IProgressMonitor monitor) {

		SimpleArtifactRepositoryFactory repositoryFactory = new SimpleArtifactRepositoryFactory();
		IArtifactRepository repositoryOnDisk = null;
		try {
			SubMonitor subMonitor = SubMonitor.convert(monitor, 4);
			try {
				File localFile = repositoryFactory.getLocalFile(getLocation(), subMonitor.newChild(1));
				long lastModified = localFile.lastModified();
				if (lastModified <= cacheTimestamp)
					return;
				cacheTimestamp = lastModified;
			} catch (Exception e) {
				// Dont'r worry if we can't load
				return;
			}
			try {
				repositoryOnDisk = repositoryFactory.load(getLocation(), IRepositoryManager.REPOSITORY_HINT_MODIFIABLE, subMonitor.newChild(3), false);
			} catch (Exception e) {
				// Don't worry if we can't load
				return;
			}

			if (repositoryOnDisk != null && repositoryOnDisk instanceof SimpleArtifactRepository) {
				setName(repositoryOnDisk.getName());
				setType(repositoryOnDisk.getType());
				setVersion(repositoryOnDisk.getVersion());
				setLocation(repositoryOnDisk.getLocation()); // Will this ever change, should it?
				setDescription(repositoryOnDisk.getDescription());
				setProvider(repositoryOnDisk.getProvider());
				this.mappingRules = ((SimpleArtifactRepository) repositoryOnDisk).mappingRules;

				// Clear the existing properties
				//				this.setProperties(new OrderedProperties());
				//
				Map<String, String> prop = repositoryOnDisk.getProperties();
				Set<Entry<String, String>> entrySet = prop.entrySet();
				for (Entry<String, String> entry : entrySet) {
					doSetProperty(entry.getKey(), entry.getValue(), new NullProgressMonitor(), false);
				}

				//
				this.artifactDescriptors = ((SimpleArtifactRepository) repositoryOnDisk).artifactDescriptors;
				this.artifactMap = ((SimpleArtifactRepository) repositoryOnDisk).artifactMap;
			}
		} finally {
			monitor.done();
		}
		return;
	}

	private void unlock() {
		if (!Activator.getInstance().enableArtifactLocking()) {
			holdsLock = false;
			return;
		}
		if (lockLocation != null) {
			// If we don't have the lock location, then we don't have the lock
			holdsLock = false;
			lockLocation.release();
		}
		lockLocation = null;
	}

}
