/*******************************************************************************
 * Copyright (c) 2012, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.osgi.storage;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.eclipse.osgi.container.Module;
import org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent;
import org.eclipse.osgi.container.ModuleRevision;
import org.eclipse.osgi.container.ModuleRevisionBuilder;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.framework.util.CaseInsensitiveDictionaryMap;
import org.eclipse.osgi.framework.util.ThreadInfoReport;
import org.eclipse.osgi.internal.container.LockSet;
import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.hookregistry.StorageHookFactory;
import org.eclipse.osgi.internal.hookregistry.StorageHookFactory.StorageHook;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.storage.Storage.StorageException;
import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.storage.url.BundleResourceHandler;
import org.eclipse.osgi.storage.url.bundleentry.Handler;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;

public final class BundleInfo {
	public static final String OSGI_BUNDLE_MANIFEST = "META-INF/MANIFEST.MF"; //$NON-NLS-1$
	public static final String MULTI_RELEASE_HEADER = "Multi-Release"; //$NON-NLS-1$
	public static final String MULTI_RELEASE_VERSIONS = "META-INF/versions/"; //$NON-NLS-1$
	public static final Collection<String> MULTI_RELEASE_FILTER_PREFIXES = Collections.singleton("META-INF/"); //$NON-NLS-1$

	public final class Generation {
		private final long generationId;
		private final Object genMonitor = new Object();
		private final Dictionary<String, String> cachedHeaders;
		private File content;
		private boolean isDirectory;
		private boolean isReference;
		private boolean hasPackageInfo;
		private BundleFile bundleFile;
		private Map<String, String> rawHeaders;
		private ModuleRevision revision;
		private ManifestLocalization headerLocalization;
		private ProtectionDomain domain;
		private NativeCodeFinder nativeCodeFinder;
		private List<StorageHook<?, ?>> storageHooks;
		private long lastModified;
		private boolean isMRJar;

		Generation(long generationId) {
			this.generationId = generationId;
			this.cachedHeaders = new CachedManifest(this, Collections.<String, String> emptyMap());
		}

		Generation(long generationId, File content, boolean isDirectory, boolean isReference, boolean hasPackageInfo, Map<String, String> cached, long lastModified, boolean isMRJar) {
			this.generationId = generationId;
			this.content = content;
			this.isDirectory = isDirectory;
			this.isReference = isReference;
			this.hasPackageInfo = hasPackageInfo;
			this.cachedHeaders = new CachedManifest(this, cached);
			this.lastModified = lastModified;
			this.isMRJar = isMRJar;
		}

		public BundleFile getBundleFile() {
			synchronized (genMonitor) {
				if (bundleFile == null) {
					if (getBundleId() == 0 && content == null) {
						bundleFile = new SystemBundleFile();
					} else {
						bundleFile = getStorage().createBundleFile(content, this, isDirectory, true);
					}
				}
				return bundleFile;
			}
		}

		public void close() {
			synchronized (genMonitor) {
				if (bundleFile != null) {
					try {
						bundleFile.close();
					} catch (IOException e) {
						// ignore
					}
				}
			}
		}

		public Dictionary<String, String> getHeaders() {
			return cachedHeaders;
		}

		Map<String, String> getRawHeaders() {
			synchronized (genMonitor) {
				if (rawHeaders == null) {
					BundleEntry manifest = getBundleFile().getEntry(OSGI_BUNDLE_MANIFEST);
					if (manifest == null) {
						rawHeaders = Collections.emptyMap();
					} else {
						try {
							Map<String, String> merged = ManifestElement.parseBundleManifest(manifest.getInputStream(), new CaseInsensitiveDictionaryMap<String, String>());
							// For MRJARs only replace Import-Package and Require-Capability if the versioned values are non-null
							if (Boolean.parseBoolean(merged.get(MULTI_RELEASE_HEADER))) {
								for (int i = getStorage().getRuntimeVersion().getMajor(); i > 8; i--) {
									String versionManifest = "META-INF/versions/" + i + "/OSGI-INF/MANIFEST.MF"; //$NON-NLS-1$ //$NON-NLS-2$
									BundleEntry versionEntry = getBundleFile().getEntry(versionManifest);
									if (versionEntry != null) {
										Map<String, String> versioned = ManifestElement.parseBundleManifest(versionEntry.getInputStream(), new CaseInsensitiveDictionaryMap<String, String>());
										String versionedImport = versioned.get(Constants.IMPORT_PACKAGE);
										String versionedRequireCap = versioned.get(Constants.REQUIRE_CAPABILITY);
										if (versionedImport != null) {
											merged.put(Constants.IMPORT_PACKAGE, versionedImport);
										}
										if (versionedRequireCap != null) {
											merged.put(Constants.REQUIRE_CAPABILITY, versionedRequireCap);
										}
										// found a versioned entry; stop searching for more versions
										break;
									}
								}
							}
							rawHeaders = Collections.unmodifiableMap(merged);
						} catch (Exception e) {
							if (e instanceof RuntimeException) {
								throw (RuntimeException) e;
							}
							throw new RuntimeException("Error occurred getting the bundle manifest.", e); //$NON-NLS-1$
						}
					}
				}
				return rawHeaders;
			}
		}

		public Dictionary<String, String> getHeaders(String locale) {
			ManifestLocalization current = getManifestLocalization();
			return current.getHeaders(locale);
		}

		public ResourceBundle getResourceBundle(String locale) {
			ManifestLocalization current = getManifestLocalization();
			String defaultLocale = Locale.getDefault().toString();
			if (locale == null) {
				locale = defaultLocale;
			}
			return current.getResourceBundle(locale, defaultLocale.equals(locale));
		}

		private ManifestLocalization getManifestLocalization() {
			synchronized (genMonitor) {
				if (headerLocalization == null) {
					headerLocalization = new ManifestLocalization(this, getHeaders(), getStorage().getConfiguration().getConfiguration(EquinoxConfiguration.PROP_ROOT_LOCALE, "en")); //$NON-NLS-1$
				}
				return headerLocalization;
			}
		}

		public void clearManifestCache() {
			synchronized (genMonitor) {
				if (headerLocalization != null) {
					headerLocalization.clearCache();
				}
			}
		}

		public long getGenerationId() {
			return this.generationId;
		}

		public long getLastModified() {
			return lastModified;
		}

		public boolean isDirectory() {
			synchronized (this.genMonitor) {
				return this.isDirectory;
			}
		}

		public boolean isReference() {
			synchronized (this.genMonitor) {
				return this.isReference;
			}
		}

		public boolean hasPackageInfo() {
			synchronized (this.genMonitor) {
				return this.hasPackageInfo;
			}
		}

		public boolean isMRJar() {
			synchronized (this.genMonitor) {
				return this.isMRJar;
			}
		}

		public File getContent() {
			synchronized (this.genMonitor) {
				return this.content;
			}
		}

		void setContent(File content, boolean isReference) {
			synchronized (this.genMonitor) {
				this.content = content;
				this.isDirectory = content == null ? false : Storage.secureAction.isDirectory(content);
				this.isReference = isReference;
				setLastModified(content);
			}
		}

		private void setLastModified(File content) {
			if (content == null) {
				// Bug 477787: content will be null when the osgi.framework configuration property contains an invalid value.
				lastModified = 0;
				return;
			}
			if (isDirectory)
				content = new File(content, "META-INF/MANIFEST.MF"); //$NON-NLS-1$
			lastModified = Storage.secureAction.lastModified(content);
		}

		void setStorageHooks(List<StorageHook<?, ?>> storageHooks, boolean install) {
			synchronized (this.genMonitor) {
				this.storageHooks = storageHooks;
				if (install) {
					this.hasPackageInfo = BundleInfo.hasPackageInfo(getBundleFile());
					this.isMRJar = Boolean.parseBoolean(getRawHeaders().get(MULTI_RELEASE_HEADER));
				}
			}
		}

		@SuppressWarnings("unchecked")
		public <S, L, H extends StorageHook<S, L>> H getStorageHook(Class<? extends StorageHookFactory<S, L, H>> factoryClass) {
			synchronized (this.genMonitor) {
				if (this.storageHooks == null)
					return null;
				for (StorageHook<?, ?> hook : storageHooks) {
					if (hook.getFactoryClass().equals(factoryClass)) {
						return (H) hook;
					}
				}
			}
			return null;
		}

		public ModuleRevision getRevision() {
			synchronized (this.genMonitor) {
				return this.revision;
			}
		}

		public void setRevision(ModuleRevision revision) {
			synchronized (this.genMonitor) {
				this.revision = revision;
			}
		}

		public ProtectionDomain getDomain() {
			if (getBundleId() == 0 || System.getSecurityManager() == null) {
				return null;
			}
			synchronized (this.genMonitor) {
				if (domain == null) {
					if (revision == null) {
						throw new IllegalStateException("The revision is not yet set for this generation."); //$NON-NLS-1$
					}
					domain = getStorage().getSecurityAdmin().createProtectionDomain(revision.getBundle());
				}
				return domain;
			}
		}

		/**
		 * Gets called by BundleFile during {@link BundleFile#getFile(String, boolean)}.  This method
		 * will allocate a File object where content of the specified path may be
		 * stored for this generation.  The returned File object may
		 * not exist if the content has not previously been stored.
		 * @param path the path to the content to extract from the generation
		 * @return a file object where content of the specified path may be stored.
		 * @throws StorageException if the path will escape the persistent storage of the generation
		 */
		public File getExtractFile(String path) {
			return getExtractFile(null, path);
		}

		/**
		 * Gets called by BundleFile during {@link BundleFile#getFile(String, boolean)}.  This method
		 * will allocate a File object where content of the specified path may be
		 * stored for this generation.  The returned File object may
		 * not exist if the content has not previously been stored.
		 * @param path the path to the content to extract from the generation
		 * @param base the base path that is prepended to the path, may be null
		 * @return a file object where content of the specified path may be stored.
		 * @throws StorageException if the path will escape the persistent storage of
		 * the generation starting at the specified base
		 */
		public File getExtractFile(String base, String path) {
			StringBuilder baseBuilder = new StringBuilder();
			baseBuilder.append(getBundleId()).append('/').append(getGenerationId());
			if (base != null) {
				baseBuilder.append('/').append(base);
			}

			return getStorage().getFile(baseBuilder.toString(), path, true);
		}

		public void storeContent(File destination, InputStream in, boolean nativeCode) throws IOException {
			/* the entry has not been cached */
			if (getStorage().getConfiguration().getDebug().DEBUG_STORAGE)
				Debug.println("Creating file: " + destination.getPath()); //$NON-NLS-1$
			/* create the necessary directories */
			File dir = new File(destination.getParent());
			if (!dir.mkdirs() && !dir.isDirectory()) {
				if (getStorage().getConfiguration().getDebug().DEBUG_STORAGE)
					Debug.println("Unable to create directory: " + dir.getPath()); //$NON-NLS-1$
				throw new IOException(NLS.bind(Msg.ADAPTOR_DIRECTORY_CREATE_EXCEPTION, dir.getAbsolutePath()));
			}
			/* copy the entry to the cache */
			File tempDest = File.createTempFile("staged", ".tmp", dir); //$NON-NLS-1$ //$NON-NLS-2$
			StorageUtil.readFile(in, tempDest);
			if (destination.exists()) {
				// maybe because some other thread already beat us there.
				// just delete our staged copy
				tempDest.delete();
			} else {
				StorageUtil.move(tempDest, destination, getStorage().getConfiguration().getDebug().DEBUG_STORAGE);
			}
			if (nativeCode) {
				getBundleInfo().getStorage().setPermissions(destination);
			}
		}

		public BundleInfo getBundleInfo() {
			return BundleInfo.this;
		}

		public void delete() {
			List<StorageHook<?, ?>> hooks = getStorageHooks();
			if (hooks != null) {
				for (StorageHook<?, ?> hook : hooks) {
					hook.deletingGeneration();
				}
			}
			synchronized (this.genMonitor) {
				// make sure the bundle file is closed
				if (bundleFile != null) {
					try {
						bundleFile.close();
					} catch (IOException e) {
						// ignore
					}
				}
			}
			getBundleInfo().delete(this);
		}

		public URL getEntry(String path) {
			BundleEntry entry = getBundleFile().getEntry(path);
			if (entry == null)
				return null;
			path = BundleFile.fixTrailingSlash(path, entry);
			try {
				//use the constant string for the protocol to prevent duplication
				return Storage.secureAction.getURL(BundleResourceHandler.OSGI_ENTRY_URL_PROTOCOL, Long.toString(getBundleId()) + BundleResourceHandler.BID_FWKID_SEPARATOR + Integer.toString(getStorage().getModuleContainer().hashCode()), 0, path, new Handler(getStorage().getModuleContainer(), entry));
			} catch (MalformedURLException e) {
				return null;
			}
		}

		public String findLibrary(String libname) {
			NativeCodeFinder currentFinder;
			synchronized (this.genMonitor) {
				if (nativeCodeFinder == null) {
					nativeCodeFinder = new NativeCodeFinder(this);
				}
				currentFinder = nativeCodeFinder;
			}
			return currentFinder.findLibrary(libname);
		}

		List<StorageHook<?, ?>> getStorageHooks() {
			synchronized (this.genMonitor) {
				return this.storageHooks;
			}
		}

		public ModuleRevisionBuilder adaptModuleRevisionBuilder(ModuleEvent operation, Module origin, ModuleRevisionBuilder builder) {
			List<StorageHook<?, ?>> hooks = getStorageHooks();
			if (hooks != null) {
				for (StorageHook<?, ?> hook : hooks) {
					ModuleRevisionBuilder hookResult = hook.adaptModuleRevisionBuilder(operation, origin, builder);
					if (hookResult != null) {
						builder = hookResult;
					}
				}
			}
			return builder;
		}
	}

	private final Storage storage;
	private final long bundleId;
	private final String location;
	private long nextGenerationId;
	private final Object infoMonitor = new Object();
	private LockSet<Long> generationLocks;

	public BundleInfo(Storage storage, long bundleId, String location, long nextGenerationId) {
		this.storage = storage;
		this.bundleId = bundleId;
		this.location = location;
		this.nextGenerationId = nextGenerationId;
	}

	public long getBundleId() {
		return bundleId;
	}

	public String getLocation() {
		return location;
	}

	Generation createGeneration() throws BundleException {
		synchronized (this.infoMonitor) {
			if (generationLocks == null) {
				generationLocks = new LockSet<>();
			}
			boolean lockedID;
			try {
				lockedID = generationLocks.tryLock(nextGenerationId, 5, TimeUnit.SECONDS);
			} catch (InterruptedException e) {
				Thread.currentThread().interrupt();
				throw new BundleException("Failed to obtain id locks for generation.", BundleException.STATECHANGE_ERROR, e); //$NON-NLS-1$
			}
			if (!lockedID) {
				throw new BundleException("Failed to obtain id locks for generation.", BundleException.STATECHANGE_ERROR, new ThreadInfoReport(generationLocks.getLockInfo(nextGenerationId))); //$NON-NLS-1$
			}
			Generation newGeneration = new Generation(nextGenerationId++);
			return newGeneration;
		}
	}

	void unlockGeneration(Generation generation) {
		synchronized (this.infoMonitor) {
			if (generationLocks == null) {
				throw new IllegalStateException("The generation id was not locked."); //$NON-NLS-1$
			}
			generationLocks.unlock(generation.getGenerationId());
		}
	}

	Generation restoreGeneration(long generationId, File content, boolean isDirectory, boolean isReference, boolean hasPackageInfo, Map<String, String> cached, long lastModified, boolean isMRJar) {
		synchronized (this.infoMonitor) {
			Generation restoredGeneration = new Generation(generationId, content, isDirectory, isReference, hasPackageInfo, cached, lastModified, isMRJar);
			return restoredGeneration;
		}
	}

	public Storage getStorage() {
		return storage;
	}

	public void delete() {
		try {
			getStorage().delete(getStorage().getFile(Long.toString(getBundleId()), false));
		} catch (IOException e) {
			storage.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, "Error deleting bunlde info.", e); //$NON-NLS-1$
		}
	}

	void delete(Generation generation) {
		try {
			getStorage().delete(getStorage().getFile(getBundleId() + "/" + generation.getGenerationId(), false)); //$NON-NLS-1$
		} catch (IOException e) {
			storage.getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, "Error deleting generation.", e); //$NON-NLS-1$
		}
	}

	public long getNextGenerationId() {
		synchronized (this.infoMonitor) {
			return nextGenerationId;
		}
	}

	public File getDataFile(String path) {
		File dataRoot = getStorage().getFile(getBundleId() + "/" + Storage.BUNDLE_DATA_DIR, false); //$NON-NLS-1$
		if (!Storage.secureAction.isDirectory(dataRoot) && (storage.isReadOnly() || !(Storage.secureAction.mkdirs(dataRoot) || Storage.secureAction.isDirectory(dataRoot)))) {
			if (getStorage().getConfiguration().getDebug().DEBUG_STORAGE)
				Debug.println("Unable to create bundle data directory: " + dataRoot.getAbsolutePath()); //$NON-NLS-1$
			return null;
		}
		return path == null ? dataRoot : new File(dataRoot, path);
	}

	// Used to check the bundle manifest file for any package information.
	// This is used when '.' is on the Bundle-ClassPath to prevent reading
	// the bundle manifest for package information when loading classes.
	static boolean hasPackageInfo(BundleFile bundleFile) {
		if (bundleFile == null) {
			return false;
		}
		BundleEntry manifest = bundleFile.getEntry(OSGI_BUNDLE_MANIFEST);
		if (manifest == null) {
			return false;
		}
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(manifest.getInputStream()));
			String line;
			while ((line = br.readLine()) != null) {
				if (line.length() < 20)
					continue;
				switch (line.charAt(0)) {
					case 'S' :
						if (line.charAt(1) == 'p')
							if (line.startsWith("Specification-Title: ") || line.startsWith("Specification-Version: ") || line.startsWith("Specification-Vendor: ")) //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
								return true;
						break;
					case 'I' :
						if (line.startsWith("Implementation-Title: ") || line.startsWith("Implementation-Version: ") || line.startsWith("Implementation-Vendor: ")) //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
							return true;
						break;
				}
			}
		} catch (IOException ioe) {
			// do nothing
		} finally {
			if (br != null)
				try {
					br.close();
				} catch (IOException e) {
					// do nothing
				}
		}
		return false;
	}

	static class CachedManifest extends Dictionary<String, String> implements Map<String, String> {
		private final Map<String, String> cached;
		private final Generation generation;

		CachedManifest(Generation generation, Map<String, String> cached) {
			this.generation = generation;
			this.cached = cached;
		}

		@Override
		public Enumeration<String> elements() {
			return Collections.enumeration(generation.getRawHeaders().values());
		}

		@Override
		public String get(Object key) {
			if (cached.containsKey(key)) {
				return cached.get(key);
			}
			if (!cached.isEmpty() && generation.getBundleInfo().getStorage().getConfiguration().getDebug().DEBUG_CACHED_MANIFEST) {
				Debug.println("Header key is not cached: " + key + "; for bundle: " + generation.getBundleInfo().getBundleId()); //$NON-NLS-1$ //$NON-NLS-2$
			}
			return generation.getRawHeaders().get(key);
		}

		@Override
		public boolean isEmpty() {
			return generation.getRawHeaders().isEmpty();
		}

		@Override
		public Enumeration<String> keys() {
			return Collections.enumeration(generation.getRawHeaders().keySet());
		}

		@Override
		public String put(String key, String value) {
			return generation.getRawHeaders().put(key, value);
		}

		@Override
		public String remove(Object key) {
			return generation.getRawHeaders().remove(key);
		}

		@Override
		public int size() {
			return generation.getRawHeaders().size();
		}

		@Override
		public boolean containsKey(Object key) {
			return cached.containsKey(key) || generation.getRawHeaders().containsKey(key);
		}

		@Override
		public boolean containsValue(Object value) {
			return cached.containsValue(value) || generation.getRawHeaders().containsValue(value);
		}

		@Override
		public void putAll(Map<? extends String, ? extends String> m) {
			generation.getRawHeaders().putAll(m);
		}

		@Override
		public void clear() {
			generation.getRawHeaders().clear();
		}

		@Override
		public Set<String> keySet() {
			return generation.getRawHeaders().keySet();
		}

		@Override
		public Collection<String> values() {
			return generation.getRawHeaders().values();
		}

		@Override
		public Set<java.util.Map.Entry<String, String>> entrySet() {
			return generation.getRawHeaders().entrySet();
		}
	}

}
