package org.eclipse.jdt.internal.core;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
import org.eclipse.core.runtime.*;
import org.eclipse.core.resources.*;
import org.eclipse.jdt.core.*;

import java.io.*;
import java.util.*;
import java.util.zip.*;

/**
 * A package fragment root that corresponds to a .jar or .zip.
 *
 * <p>NOTE: The only visible entries from a .jar or .zip package fragment root
 * are .class files.
 * <p>NOTE: A jar package fragment root may or may not have an associated resource.
 *
 * @see IPackageFragmentRoot
 * @see JarPackageFragmentRootInfo
 */
public class JarPackageFragmentRoot extends PackageFragmentRoot {
	/**
	 * The absolute path to the jar file.
	 */
	protected IPath fJarPath= null;

	/**
	 * The delimiter between the zip path and source path in the
	 * attachment server property.
	 */
	protected final static char ATTACHMENT_PROPERTY_DELIMITER= '*';

	/**
	 * The name of the meta-inf directory not to be included as a 
	 * jar package fragment.
	 * @see #computeJarChildren
	 */
	//protected final static String META_INF_NAME = "META-INF/";
	/**
	 * Constructs a package fragment root which is the root of the Java package directory hierarchy 
	 * based on a JAR file that is not contained in a <code>IJavaProject</code> and
	 * does not have an associated <code>IResource</code>.
	 */
	protected JarPackageFragmentRoot(String jarPath, IJavaProject project) {
		super(null, project, jarPath);
		fJarPath= new Path(jarPath);
	}
	/**
	 * Constructs a package fragment root which is the root of the Java package directory hierarchy 
	 * based on a JAR file.
	 */
	protected JarPackageFragmentRoot(IResource resource, IJavaProject project) {
		super(resource, project);
		fJarPath= resource.getFullPath();
	}
	/**
	 * @see IPackageFragmentRoot
	 */
	public void attachSource(IPath zipPath, IPath rootPath, IProgressMonitor monitor) throws JavaModelException {
		QualifiedName qName= getSourceAttachmentPropertyName();
		try {
			verifyAttachSource(zipPath);
			if (monitor != null) {
				monitor.beginTask(Util.bind("element.attachingSource"/*nonNLS*/), 2);
			}
			SourceMapper mapper= null;
			SourceMapper oldMapper= getSourceMapper();
			IWorkspace workspace= getJavaModel().getWorkspace();
			boolean rootNeedsToBeClosed= false;

			if (zipPath == null) {
				//source being detached
				rootNeedsToBeClosed= true;
			/* Disable deltas (see 1GDTUSD)
				// fire a delta to notify the UI about the source detachement.
				JavaModelManager manager = (JavaModelManager) JavaModelManager.getJavaModelManager();
				JavaModel model = (JavaModel) getJavaModel();
				JavaElementDelta attachedSourceDelta = new JavaElementDelta(model);
				attachedSourceDelta .sourceDetached(this); // this would be a JarPackageFragmentRoot
				manager.registerResourceDelta(attachedSourceDelta );
				manager.fire(); // maybe you want to fire the change later. Let us know about it.
			*/
			} else {
			/*
				// fire a delta to notify the UI about the source attachement.
				JavaModelManager manager = (JavaModelManager) JavaModelManager.getJavaModelManager();
				JavaModel model = (JavaModel) getJavaModel();
				JavaElementDelta attachedSourceDelta = new JavaElementDelta(model);
				attachedSourceDelta .sourceAttached(this); // this would be a JarPackageFragmentRoot
				manager.registerResourceDelta(attachedSourceDelta );
				manager.fire(); // maybe you want to fire the change later. Let us know about it.
			 */
				String rootPathString= null;
				if (rootPath == null) {
					rootPath= new Path(IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH);
				}

				//check if different from the current attachment
				IPath storedZipPath= getSourceAttachmentPath();
				IPath storedRootPath= getSourceAttachmentRootPath();
				if (monitor != null) {
					monitor.worked(1);
				}
				if (storedZipPath != null) {
					if (!(storedZipPath.equals(zipPath) && rootPath.equals(storedRootPath))) {
						rootNeedsToBeClosed= true;
					}
				}
				if ((zipPath.isAbsolute() && workspace.getRoot().findMember(zipPath) != null) || !zipPath.isAbsolute()) {
					// internal to the workbench
					// a resource
					IResource zipFile= workspace.getRoot().findMember(zipPath);
					if (zipFile == null) {
						if (monitor != null) {
							monitor.done();
						}
						throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, zipPath));
					}
					if (!(zipFile.getType() == IResource.FILE)) {
						if (monitor != null) {
							monitor.done();
						}
						throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, zipPath));
					}
				}
				mapper= new SourceMapper(zipPath, rootPath.toOSString(), (JavaModel) getJavaModel());
			}
			setSourceMapper(mapper);
			if (zipPath == null) {
				//remove the property
				getWorkspace().getRoot().setPersistentProperty(qName, null);
			} else {
				//set the property to the path of the mapped zip
				getWorkspace().getRoot().setPersistentProperty(qName, zipPath.toString() + ATTACHMENT_PROPERTY_DELIMITER + rootPath.toString());
			}
			if (rootNeedsToBeClosed) {
				if (oldMapper != null) {
					oldMapper.close();
				}
				IBufferManager manager= BufferManager.getDefaultBufferManager();
				Enumeration openBuffers= manager.getOpenBuffers();
				while (openBuffers.hasMoreElements()) {
					IBuffer buffer= (IBuffer) openBuffers.nextElement();
					IOpenable possibleJarMember= buffer.getOwner();
					if (isAncestorOf((IJavaElement) possibleJarMember)) {
						buffer.close();
					}
				}
				if (monitor != null) {
					monitor.worked(1);
				}
			}
		} catch (JavaModelException e) {
			try {
				getWorkspace().getRoot().setPersistentProperty(qName, null); // loose info - will be recomputed
			} catch(CoreException ce){
			}
			throw e;
		} catch (CoreException rae) {
			try {
				getWorkspace().getRoot().setPersistentProperty(qName, null); // loose info - will be recomputed
			} catch(CoreException ce){
			}
			throw new JavaModelException(rae);
		} finally {
			if (monitor != null) {
				monitor.done();
			}
		}
	}
	/**
	 * Close the associated JAR file stored in the info of this element. If
	 * this jar has an associated ZIP source attachment, close it too.
	 *
	 * @see IOpenable
	 */
	protected void closing(Object info) throws JavaModelException {
		SourceMapper mapper= getSourceMapper();
		if (mapper != null) {
			mapper.close();
		}
		super.closing(info);
	}
	/**
	 * Compute the package fragment children of this package fragment root.
	 * These are all of the directory zip entries, and any directories implied
	 * by the path of class files contained in the jar of this package fragment root.
	 * Has the side effect of opening the package fragment children.
	 */
	protected boolean computeChildren(OpenableElementInfo info) throws JavaModelException {
		Vector vChildren= new Vector();
		computeJarChildren((JarPackageFragmentRootInfo) info, vChildren);
		IJavaElement[] children= new IJavaElement[vChildren.size()];
		vChildren.copyInto(children);
		info.setChildren(children);
		return true;
	}
/**
 * Determine all of the package fragments associated with this package fragment root.
 * Cache the zip entries for each package fragment in the info for the package fragment.
 * The package fragment children are all opened.
 * Add all of the package fragments to vChildren.
 *
 * @exception JavaModelException The resource (the jar) associated with this package fragment root does not exist
 */
protected void computeJarChildren(JarPackageFragmentRootInfo info, Vector vChildren) throws JavaModelException {
	ZipFile jar= null;
	try {
		jar= getJar();
		Hashtable packageFragToTypes= new Hashtable();

		// always create the default package
		packageFragToTypes.put(IPackageFragment.DEFAULT_PACKAGE_NAME, new Vector[] { new Vector(), new Vector()
		});

		Vector[] temp;
		for (Enumeration e= jar.entries(); e.hasMoreElements();) {
			ZipEntry member= (ZipEntry) e.nextElement();
			String eName= member.getName();
			if (member.isDirectory()) {
				eName= eName.substring(0, eName.length() - 1);
				eName= eName.replace('/', '.');
				temp= (Vector[]) packageFragToTypes.get(eName);
				if (temp == null) {
					temp= new Vector[] { new Vector(), new Vector()
				 };
					packageFragToTypes.put(eName, temp);
				}
			} else {
				if (Util.isClassFileName(eName)) {
					//only interested in class files
					//store the class file entry name to be cached in the appropriate package fragment
					//zip entries only use '/'
					Vector classTemp;
					int lastSeparator= eName.lastIndexOf('/');
					String key= IPackageFragment.DEFAULT_PACKAGE_NAME;
					String value= eName;
					if (lastSeparator != -1) {
						//not in the default package
						eName= eName.replace('/', '.');
						value= eName.substring(lastSeparator + 1);
						key= eName.substring(0, lastSeparator);
					}
					temp= (Vector[]) packageFragToTypes.get(key);
					if (temp == null) {
						// build all package fragments in the key
						lastSeparator= key.indexOf('.');
						while (lastSeparator > 0) {
							String prefix= key.substring(0, lastSeparator);
							if (packageFragToTypes.get(prefix) == null) {
								packageFragToTypes.put(prefix, new Vector[] { new Vector(), new Vector()
							 });
							}
							lastSeparator= key.indexOf('.', lastSeparator + 1);
						}
						classTemp= new Vector();
						classTemp.addElement(value);
						packageFragToTypes.put(key, new Vector[] {classTemp, new Vector()
					 });
					} else {
						classTemp= temp[0];
						classTemp.addElement(value);
					}
				} else {
					Vector resTemp;
					int lastSeparator= eName.lastIndexOf('/');
					String key= IPackageFragment.DEFAULT_PACKAGE_NAME;
					String value= eName;
					if (lastSeparator != -1) {
						//not in the default package
						eName= eName.replace('/', '.');
						key= eName.substring(0, lastSeparator);
					}
					temp= (Vector[]) packageFragToTypes.get(key);
					if (temp == null) {
						// build all package fragments in the key
						lastSeparator= key.indexOf('.');
						while (lastSeparator > 0) {
							String prefix= key.substring(0, lastSeparator);
							if (packageFragToTypes.get(prefix) == null) {
								packageFragToTypes.put(prefix, new Vector[] { new Vector(), new Vector()
							 });
							}
							lastSeparator= key.indexOf('.', lastSeparator + 1);
						}
						resTemp= new Vector();
						resTemp.addElement(value);
						packageFragToTypes.put(key, new Vector[] { new Vector(), resTemp });
					} else {
						resTemp= temp[1];
						resTemp.addElement(value);
					}
				}
			}
		}
		//loop through all of referenced packages, creating package fragments if necessary
		// and cache the entry names in the infos created for those package fragments
		Enumeration packages= packageFragToTypes.keys();
		while (packages.hasMoreElements()) {
			String packName= (String) packages.nextElement();
			Vector[] entries= (Vector[]) packageFragToTypes.get(packName);
			JarPackageFragment packFrag= (JarPackageFragment) getPackageFragment(packName);
			JarPackageFragmentInfo fragInfo= (JarPackageFragmentInfo) packFrag.createElementInfo();
			fragInfo.setEntryNames(entries[0]);
			int resLength= entries[1].size();
			if (resLength == 0) {
				packFrag.computeNonJavaResources(new String[] {}, fragInfo, jar.getName());
			} else {
				String[] resNames= new String[resLength];
				entries[1].copyInto(resNames);
				packFrag.computeNonJavaResources(resNames, fragInfo, jar.getName());
			}
			packFrag.computeChildren(fragInfo);
			fgJavaModelManager.putInfo(packFrag, fragInfo);
			vChildren.addElement(packFrag);
		}
	} catch (CoreException e) {
		throw new JavaModelException(e);
	} finally {
		if (jar != null) {
			try {
				jar.close();
			} catch (IOException e) {
				// ignore 
			}
		}
	}
}
	/**
	 * Returns a new element info for this element.
	 */
	protected OpenableElementInfo createElementInfo() {
		return new JarPackageFragmentRootInfo();
	}
	/**
	 * A Jar is always K_BINARY.
	 *
	 * @exception NotPresentException if the project and root do
	 *      not exist.
	 */
	protected int determineKind(IResource underlyingResource) throws JavaModelException {
		return IPackageFragmentRoot.K_BINARY;
	}
	/**
	 * Returns true if this handle represents the same jar
	 * as the given handle. Two jars are equal if they share
	 * the same zip file.
	 *
	 * @see Object#equals
	 */
	public boolean equals(Object o) {
		if (this == o)
			return true;
		if (o instanceof JarPackageFragmentRoot) {
			JarPackageFragmentRoot other= (JarPackageFragmentRoot) o;
			return fJarPath.equals(other.fJarPath);
		}
		return false;
	}
public IClasspathEntry findSourceAttachmentRecommendation() {

	try {

		IPath rootPath = this.getPath();
		IClasspathEntry entry;
		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
		
		// try on enclosing project first
		JavaProject parentProject = (JavaProject) getJavaProject();
		try {
			entry = parentProject.getClasspathEntryFor(rootPath);
			if (entry != null){
				Object target = JavaModel.getTarget(workspaceRoot, entry.getSourceAttachmentPath(), true);
				if (target instanceof IFile){
					IFile file = (IFile) target;
					if ("jar"/*nonNLS*/.equalsIgnoreCase(file.getFileExtension()) || "zip"/*nonNLS*/.equalsIgnoreCase(file.getFileExtension())){
						return entry;
					}
				}
				if (target instanceof java.io.File){
					java.io.File file = (java.io.File) target;
					String name = file.getName();
					if (Util.endsWithIgnoreCase(name, ".jar"/*nonNLS*/) || Util.endsWithIgnoreCase(name, ".zip"/*nonNLS*/)){
						return entry;
					}
				}
			}
		} catch(JavaModelException e){
		}
		
		// iterate over all projects
		IJavaModel model = getJavaModel();
		IJavaProject[] jProjects = model.getJavaProjects();
		for (int i = 0, max = jProjects.length; i < max; i++){
			JavaProject jProject = (JavaProject) jProjects[i];
			if (jProject == parentProject) continue; // already done
			try {
				entry = jProject.getClasspathEntryFor(rootPath);
				if (entry != null){
					Object target = JavaModel.getTarget(workspaceRoot, entry.getSourceAttachmentPath(), true);
					if (target instanceof IFile){
						IFile file = (IFile) target;
						String name = file.getName();
						if (Util.endsWithIgnoreCase(name, ".jar"/*nonNLS*/) || Util.endsWithIgnoreCase(name, ".zip"/*nonNLS*/)){
							return entry;
						}
					}
					if (target instanceof java.io.File){
						java.io.File file = (java.io.File) target;
						String name = file.getName();
						if (Util.endsWithIgnoreCase(name, ".jar"/*nonNLS*/) || Util.endsWithIgnoreCase(name, ".zip"/*nonNLS*/)){
							return entry;
						}
					}
				}
			} catch(JavaModelException e){
			}
		}
	} catch(JavaModelException e){
	}

	return null;
}
	/**
	 * Returns the underlying ZipFile for this Jar package fragment root.
	 *
	 * @exception CoreException if an error occurs accessing the jar
	 */
	public ZipFile getJar() throws CoreException {
		return fgJavaModelManager.getZipFile(getPath());
	}
	/**
	 * @see IJavaElement
	 */
	public IJavaProject getJavaProject() {
		IJavaElement parent= getParent();
		if (parent == null) {
			return null;
		} else {
			return parent.getJavaProject();
		}
	}
	/**
	 * @see IPackageFragmentRoot
	 */
	public int getKind() {
		return IPackageFragmentRoot.K_BINARY;
	}
	/**
	 * Returns an array of non-java resources contained in the receiver.
	 */
	public Object[] getNonJavaResources() throws JavaModelException {
		// We want to show non java resources of the default package at the root (see PR #1G58NB8)
		return ((JarPackageFragment) this.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME)).storedNonJavaResources();
	}
	/**
	 * @see IPackageFragmentRoot
	 */
	public IPackageFragment getPackageFragment(String packageName) {

		return new JarPackageFragment(this, packageName);
	}
	/**
	 * @see IPackageFragmentRoot
	 */
	public IPath getPath() {
		if (fResource == null) {
			return fJarPath;
		} else {
			return super.getPath();
		}
	}
	/**
	 * @see IPackageFragmentRoot
	 */
	public IPath getSourceAttachmentPath() throws JavaModelException {
		String serverPathString= getSourceAttachmentProperty();
		if (serverPathString == null) {
			return null;
		}
		int index= serverPathString.lastIndexOf(ATTACHMENT_PROPERTY_DELIMITER);
		if (index < 0) return null;
		String serverZipPathString= serverPathString.substring(0, index);
		return new Path(serverZipPathString);
	}
	/**
	 * Returns the server property for this package fragment root's
	 * source attachement.
	 */
	protected String getSourceAttachmentProperty() throws JavaModelException {
		String propertyString = null;
		QualifiedName qName= getSourceAttachmentPropertyName();
		try {
			propertyString = getWorkspace().getRoot().getPersistentProperty(qName);
			
			// if no existing source attachment information, then lookup a recommendation from classpath entries
			if (propertyString == null || propertyString.lastIndexOf(ATTACHMENT_PROPERTY_DELIMITER) < 0){
				IClasspathEntry recommendation = findSourceAttachmentRecommendation();
				if (recommendation != null){
					propertyString = recommendation.getSourceAttachmentPath().toString() 
										+ ATTACHMENT_PROPERTY_DELIMITER 
										+ (recommendation.getSourceAttachmentRootPath() == null ? ""/*nonNLS*/ : recommendation.getSourceAttachmentRootPath().toString());
					getWorkspace().getRoot().setPersistentProperty(qName, propertyString);
				}
			}
			return propertyString;
		} catch (CoreException ce) {
			throw new JavaModelException(ce);
		}
	}
	/**
	 * Returns the qualified name for the source attachment property
	 * of this jar.
	 */
	protected QualifiedName getSourceAttachmentPropertyName() throws JavaModelException {
		ZipFile jarFile = null;
		try {
			jarFile = getJar();
			return new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: "/*nonNLS*/ + jarFile.getName());
		} catch (CoreException e) {
			throw new JavaModelException(e);
		} finally {
			try {
				if (jarFile != null) {
					jarFile.close();
				}
			} catch(IOException e) {
				// ignore 
			}
		}
	}
	/**
	 * @see IPackageFragmentRoot
	 */
	public IPath getSourceAttachmentRootPath() throws JavaModelException {
		String serverPathString= getSourceAttachmentProperty();
		if (serverPathString == null) {
			return null;
		}
		int index= serverPathString.lastIndexOf(ATTACHMENT_PROPERTY_DELIMITER);
		String serverRootPathString= IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
		if (index != serverPathString.length() - 1) {
			serverRootPathString= serverPathString.substring(index + 1);
		}
		return new Path(serverRootPathString);
	}
	/**
	 * @see JavaElement
	 */
	public SourceMapper getSourceMapper() {
		try {
			return ((JarPackageFragmentRootInfo) getElementInfo()).getSourceMapper();
		} catch (JavaModelException e) {
			return null;
		}
	}
	/**
	 * @see IJavaElement
	 */
	public IResource getUnderlyingResource() throws JavaModelException {
		if (fResource == null) {
			return null;
		} else {
			return super.getUnderlyingResource();
		}
	}
	/**
	 * If I am not open, return true to avoid parsing.
	 *
	 * @see IParent 
	 */
	public boolean hasChildren() throws JavaModelException {
		if (isOpen()) {
			return getChildren().length > 0;
		} else {
			return true;
		}
	}
	public int hashCode() {
		return fJarPath.hashCode();
	}
	/**
	 * @see IPackageFragmentRoot
	 */
	public boolean isArchive() {
		return true;
	}
	/**
	 * @see IPackageFragmentRoot
	 */
	public boolean isExternal() {
		return fResource == null;
	}
	/**
	 * Jars and jar entries are all read only
	 */
	public boolean isReadOnly() {
		return true;
	}
	/**
	 * @see Openable#openWhenClosed()
	 */
	protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
		super.openWhenClosed(pm);
		try {
			//restore any stored attached source zip
			IPath zipPath= getSourceAttachmentPath();
			if (zipPath != null) {
				IPath rootPath= getSourceAttachmentRootPath();
				attachSource(zipPath, rootPath, pm);
			}
		} catch(JavaModelException e){ // no attached source
		}
	}
	/**
	 * An archive cannot refresh its children.
	 */
	public void refreshChildren() {
		// do nothing
	}
	/**
	 * Reset the array of non-java resources contained in the receiver to null.
	 */
	public void resetNonJavaResources() throws JavaModelException {
		((JarPackageFragmentRootInfo) getElementInfo()).setNonJavaResources(null);
	}
	/**
	 * @private - for use by <code>AttachSourceOperation</code> only.
	 * Sets the source mapper associated with this jar.
	 */
	public void setSourceMapper(SourceMapper mapper) throws JavaModelException {
		((JarPackageFragmentRootInfo) getElementInfo()).setSourceMapper(mapper);
	}
	/**
	 * Possible failures: <ul>
	 *  <li>RELATIVE_PATH - the path supplied to this operation must be
	 *      an absolute path
	 *  <li>ELEMENT_NOT_PRESENT - the jar supplied to the operation
	 *      does not exist
	 * </ul>
	 */
	protected void verifyAttachSource(IPath zipPath) throws JavaModelException {
		IJavaModelStatus status= null;
		if (!exists0()) {
			throw newNotPresentException();
		} else if (zipPath != null && !zipPath.isAbsolute()) {
			throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH, zipPath));
		}
	}

/**
 * @see JavaElement#getHandleMemento()
 */
public String getHandleMemento(){
	StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento());
	buff.append(getHandleMementoDelimiter());
	buff.append(this.fJarPath.toString()); // 1GEP51U
	return buff.toString();
}
}
