/*******************************************************************************
 * Copyright (c) 2006, 2009 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:
 *   David Knibb               initial implementation      
 *   Matthew Webster           Eclipse 3.2 changes
 *   Martin Lippert            caching optimizations     
 *   Martin Lippert            caching of generated classes
 *******************************************************************************/

package org.eclipse.equinox.weaving.hooks;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import org.eclipse.equinox.service.weaving.CacheEntry;
import org.eclipse.equinox.weaving.adaptors.Debug;
import org.eclipse.equinox.weaving.adaptors.IWeavingAdaptor;
import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.eclipse.osgi.storage.bundlefile.BundleFile;

/**
 * This is a wrapper for bundle files that allows the weaving runtime to create
 * wrapped instances of bundle entry objects.
 * 
 * Those bundle entry objects are used to return class bytes from the cache
 * instead of the bundle itself.
 */
@SuppressWarnings("nls")
public class WeavingBundleFile extends AbstractWeavingBundleFile {

	private final URL url;

	/**
	 * Create a new wrapper for a bundle file
	 * 
	 * @param adaptorProvider A provider that allows this wrapper to gain access to
	 *                        the adaptor of this bundle
	 * @param bundleFile      The wrapped bundle file
	 * @throws IOException
	 */
	public WeavingBundleFile(final BundleAdaptorProvider adaptorProvider, final BundleFile bundleFile) {
		super(adaptorProvider, bundleFile);
		try {
			this.url = delegate.getBaseFile().toURL();
		} catch (final MalformedURLException e) {
			throw new RuntimeException("Unexpected error getting bundle file URL.", e);
		}
	}

	@Override
	public BundleEntry getEntry(final String path) {
		if (Debug.DEBUG_BUNDLE)
			Debug.println("> AspectJBundleFile.getEntry() path=" + path + ", url=" + url);
		BundleEntry entry = delegate.getEntry(path);

		if (path.endsWith(".class") && entry != null) {
			final int offset = path.lastIndexOf('.');
			final String name = path.substring(0, offset).replace('/', '.');
			final IWeavingAdaptor adaptor = getAdaptor();
			if (adaptor != null) {
				final CacheEntry cacheEntry = adaptor.findClass(name, url);
				if (cacheEntry == null) {
					entry = new WeavingBundleEntry(adaptor, entry, url, false);
					if (Debug.DEBUG_BUNDLE)
						Debug.println("- AspectJBundleFile.getEntry() path=" + path + ", entry=" + entry);
				} else if (cacheEntry.getCachedBytes() != null) {
					entry = new CachedClassBundleEntry(adaptor, entry, path, cacheEntry.getCachedBytes(), url);
				} else {
					entry = new WeavingBundleEntry(adaptor, entry, url, cacheEntry.dontWeave());
				}
			}
		} else if (path.endsWith(".class") && entry == null) {
			final int offset = path.lastIndexOf('.');
			final String name = path.substring(0, offset).replace('/', '.');
			final IWeavingAdaptor adaptor = getAdaptor();
			if (adaptor != null) {
				final CacheEntry cacheEntry = adaptor.findClass(name, url);
				if (cacheEntry != null && cacheEntry.getCachedBytes() != null) {
					entry = new CachedGeneratedClassBundleEntry(adaptor, path, cacheEntry.getCachedBytes(), url);
				}
			}
		}

		if (Debug.DEBUG_BUNDLE)
			Debug.println("< AspectJBundleFile.getEntry() entry=" + entry);
		return entry;
	}

}
