Package org.eclipse.jdt.internal.core

Source Code of org.eclipse.jdt.internal.core.JarPackageFragmentRoot

/*******************************************************************************
* Copyright (c) 2000, 2011 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
*******************************************************************************/
package org.eclipse.jdt.internal.core;

import java.net.URL;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
import org.eclipse.jdt.internal.core.util.Util;

/**
* 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 org.eclipse.jdt.core.IPackageFragmentRoot
* @see org.eclipse.jdt.internal.core.JarPackageFragmentRootInfo
*/
public class JarPackageFragmentRoot extends PackageFragmentRoot {

  private final static ArrayList EMPTY_LIST = new ArrayList();

  /**
   * The path to the jar file
   * (a workspace relative path if the jar is internal,
   * or an OS path if the jar is external)
   */
  protected final IPath jarPath;

  /**
   * 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(IPath externalJarPath, JavaProject project) {
    super(null, project);
    this.jarPath = externalJarPath;
  }
  /**
   * Constructs a package fragment root which is the root of the Java package directory hierarchy
   * based on a JAR file.
   */
  protected JarPackageFragmentRoot(IResource resource, JavaProject project) {
    super(resource, project);
    this.jarPath = resource.getFullPath();
  }

  /**
   * 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.
   */
  protected boolean computeChildren(OpenableElementInfo info, IResource underlyingResource) throws JavaModelException {
    HashtableOfArrayToObject rawPackageInfo = new HashtableOfArrayToObject();
    IJavaElement[] children;
    ZipFile jar = null;
    try {
      IJavaProject project = getJavaProject();
      String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
      String compliance = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
      jar = getJar();

      // always create the default package
      rawPackageInfo.put(CharOperation.NO_STRINGS, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });

      for (Enumeration e= jar.entries(); e.hasMoreElements();) {
        ZipEntry member= (ZipEntry) e.nextElement();
        initRawPackageInfo(rawPackageInfo, member.getName(), member.isDirectory(), sourceLevel, compliance);
      }

      // loop through all of referenced packages, creating package fragments if necessary
      // and cache the entry names in the rawPackageInfo table
      children = new IJavaElement[rawPackageInfo.size()];
      int index = 0;
      for (int i = 0, length = rawPackageInfo.keyTable.length; i < length; i++) {
        String[] pkgName = (String[]) rawPackageInfo.keyTable[i];
        if (pkgName == null) continue;
        children[index++] = getPackageFragment(pkgName);
      }
    } catch (CoreException e) {
      if (e.getCause() instanceof ZipException) {
        // not a ZIP archive, leave the children empty
        Util.log(IStatus.ERROR, "Invalid ZIP archive: " + toStringWithAncestors()); //$NON-NLS-1$
        children = NO_ELEMENTS;
      } else if (e instanceof JavaModelException) {
        throw (JavaModelException)e;
      } else {
        throw new JavaModelException(e);
      }
    } finally {
      JavaModelManager.getJavaModelManager().closeZipFile(jar);
    }

    info.setChildren(children);
    ((JarPackageFragmentRootInfo) info).rawPackageInfo = rawPackageInfo;
    return true;
  }
  /**
   * Returns a new element info for this element.
   */
  protected Object createElementInfo() {
    return new JarPackageFragmentRootInfo();
  }
  /**
   * A Jar is always K_BINARY.
   */
  protected int determineKind(IResource underlyingResource) {
    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 this.jarPath.equals(other.jarPath);
    }
    return false;
  }
  public String getElementName() {
    return this.jarPath.lastSegment();
  }
  /**
   * 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 JavaModelManager.getJavaModelManager().getZipFile(getPath());
  }
  /**
   * @see IPackageFragmentRoot
   */
  public int getKind() {
    return IPackageFragmentRoot.K_BINARY;
  }
  int internalKind() throws JavaModelException {
    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)
    Object[] defaultPkgResources =  ((JarPackageFragment) getPackageFragment(CharOperation.NO_STRINGS)).storedNonJavaResources();
    int length = defaultPkgResources.length;
    if (length == 0)
      return defaultPkgResources;
    Object[] nonJavaResources = new Object[length];
    for (int i = 0; i < length; i++) {
      JarEntryResource nonJavaResource = (JarEntryResource) defaultPkgResources[i];
      nonJavaResources[i] = nonJavaResource.clone(this);
    }
    return nonJavaResources;
  }
  public PackageFragment getPackageFragment(String[] pkgName) {
    return new JarPackageFragment(this, pkgName);
  }
  public IPath internalPath() {
    if (isExternal()) {
      return this.jarPath;
    } else {
      return super.internalPath();
    }
  }
  public IResource resource(PackageFragmentRoot root) {
    if (this.resource == null) {
      // external jar
      return null;
    }
    return super.resource(root);
  }


  /**
   * @see IJavaElement
   */
  public IResource getUnderlyingResource() throws JavaModelException {
    if (isExternal()) {
      if (!exists()) throw newNotPresentException();
      return null;
    } else {
      return super.getUnderlyingResource();
    }
  }
  public int hashCode() {
    return this.jarPath.hashCode();
  }
  private void initRawPackageInfo(HashtableOfArrayToObject rawPackageInfo, String entryName, boolean isDirectory, String sourceLevel, String compliance) {
    int lastSeparator = isDirectory ? entryName.length()-1 : entryName.lastIndexOf('/');
    String[] pkgName = Util.splitOn('/', entryName, 0, lastSeparator);
    String[] existing = null;
    int length = pkgName.length;
    int existingLength = length;
    while (existingLength >= 0) {
      existing = (String[]) rawPackageInfo.getKey(pkgName, existingLength);
      if (existing != null) break;
      existingLength--;
    }
    JavaModelManager manager = JavaModelManager.getJavaModelManager();
    for (int i = existingLength; i < length; i++) {
      if (Util.isValidFolderNameForPackage(pkgName[i], sourceLevel, compliance)) {
        System.arraycopy(existing, 0, existing = new String[i+1], 0, i);
        existing[i] = manager.intern(pkgName[i]);
        rawPackageInfo.put(existing, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
      } else {
        // non-Java resource folder
        if (!isDirectory) {
          ArrayList[] children = (ArrayList[]) rawPackageInfo.get(existing);
          if (children[1/*NON_JAVA*/] == EMPTY_LIST) children[1/*NON_JAVA*/] = new ArrayList();
          children[1/*NON_JAVA*/].add(entryName);
        }
        return;
      }
    }
    if (isDirectory)
      return;

    // add classfile info amongst children
    ArrayList[] children = (ArrayList[]) rawPackageInfo.get(pkgName);
    if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
      if (children[0/*JAVA*/] == EMPTY_LIST) children[0/*JAVA*/] = new ArrayList();
      String nameWithoutExtension = entryName.substring(lastSeparator + 1, entryName.length() - 6);
      children[0/*JAVA*/].add(nameWithoutExtension);
    } else {
      if (children[1/*NON_JAVA*/] == EMPTY_LIST) children[1/*NON_JAVA*/] = new ArrayList();
      children[1/*NON_JAVA*/].add(entryName);
    }

  }
  /**
   * @see IPackageFragmentRoot
   */
  public boolean isArchive() {
    return true;
  }
  /**
   * @see IPackageFragmentRoot
   */
  public boolean isExternal() {
    return resource() == null;
  }
  /**
   * Jars and jar entries are all read only
   */
  public boolean isReadOnly() {
    return true;
  }

  /**
   * Returns whether the corresponding resource or associated file exists
   */
  protected boolean resourceExists(IResource underlyingResource) {
    if (underlyingResource == null) {
      return
        JavaModel.getExternalTarget(
          getPath()/*don't make the path relative as this is an external archive*/,
          true/*check existence*/) != null;
    } else {
      return super.resourceExists(underlyingResource);
    }
  }

  protected void toStringAncestors(StringBuffer buffer) {
    if (isExternal())
      // don't show project as it is irrelevant for external jar files.
      // also see https://bugs.eclipse.org/bugs/show_bug.cgi?id=146615
      return;
    super.toStringAncestors(buffer);
  }

  public URL getIndexPath() {
    try {
      IClasspathEntry entry = ((JavaProject) getParent()).getClasspathEntryFor(getPath());
      if (entry != null) return ((ClasspathEntry)entry).getLibraryIndexLocation()
    } catch (JavaModelException e) {
      // ignore exception
    }
    return null;
  }

}
TOP

Related Classes of org.eclipse.jdt.internal.core.JarPackageFragmentRoot

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.