/*******************************************************************************
* Copyright (c) 2000, 2009 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.wst.jsdt.internal.core;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.wst.jsdt.core.IClassFile;
import org.eclipse.wst.jsdt.core.IJavaScriptElement;
import org.eclipse.wst.jsdt.core.IJavaScriptModelStatusConstants;
import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import org.eclipse.wst.jsdt.core.JsGlobalScopeContainerInitializer;
import org.eclipse.wst.jsdt.internal.compiler.util.SuffixConstants;
import org.eclipse.wst.jsdt.internal.core.util.Messages;
import org.eclipse.wst.jsdt.internal.core.util.Util;
/**
* A package fragment that represents a package fragment found in a JAR.
*
* @see org.eclipse.wst.jsdt.core.IPackageFragment
*/
public class LibraryPackageFragment extends PackageFragment implements SuffixConstants {
final static String[]DEFAULT_PACKAGE={""}; //$NON-NLS-1$
/**
* Constructs a package fragment that is contained within a jar or a zip.
*/
protected LibraryPackageFragment(PackageFragmentRoot root, String[] names) {
super(root, names);
}
/**
* Compute the children of this package fragment. Children of jar package fragments
* can only be IClassFile (representing .class files).
*/
protected boolean computeChildren(OpenableElementInfo info) {
String name = this.getPackageFragmentRoot().getPath().toOSString();
ClassFile classFile = new ClassFile(this,name);
// JavaScriptUnit cu= new JavaScriptUnit(this, this.getPackageFragmentRoot().getPath().toOSString(), DefaultWorkingCopyOwner.PRIMARY);
IJavaScriptElement[] children= new IJavaScriptElement[]{classFile};
info.setChildren(children);
return true;
}
/**
* Returns true if this fragment contains at least one java resource.
* Returns false otherwise.
*/
public boolean containsJavaResources() throws JavaScriptModelException {
return true;
}
/**
* @see org.eclipse.wst.jsdt.core.IPackageFragment
*/
public IJavaScriptUnit createCompilationUnit(String cuName, String contents, boolean force, IProgressMonitor monitor) throws JavaScriptModelException {
throw new JavaScriptModelException(new JavaModelStatus(IJavaScriptModelStatusConstants.READ_ONLY, this));
}
/**
* @see JavaElement
*/
protected Object createElementInfo() {
return new LibraryPackageFragmentInfo();
}
/*
* @see JavaElement#generateInfos
*/
protected void generateInfos(Object info, HashMap newElements, IProgressMonitor pm) throws JavaScriptModelException {
// Open my jar: this creates all the pkg infos
if (!getLibraryFragmentRoot().isDirectory())
{
Openable openableParent = (Openable)this.parent;
if (!openableParent.isOpen()) {
openableParent.generateInfos(openableParent.createElementInfo(), newElements, pm);
}
}
else
super.generateInfos(info, newElements, pm);
}
protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaScriptModelException {
if (!getLibraryFragmentRoot().isDirectory())
return true; // already built
// check whether this pkg can be opened
// add compilation units/class files from resources
HashSet vChildren = new HashSet();
try {
File file = getUnderlyingFile();
File[] members = file.listFiles();
if (members != null && members.length > 0) {
for (int i = 0; i < members.length; i++) {
File child = members[i];
if (child.isFile()) {
IJavaScriptElement childElement;
if (org.eclipse.wst.jsdt.internal.compiler.util.Util.isJavaFileName(child.getName())) {
childElement = getClassFile(child.getName());
vChildren.add(childElement);
} else if (Util.isMetadataFileName(child.getName())) {
childElement = getClassFile(child.getName());
vChildren.add(childElement);
}
}
}
}
} catch (CoreException e) {
throw new JavaScriptModelException(e);
}
IJavaScriptElement[] children = new IJavaScriptElement[vChildren.size()];
vChildren.toArray(children);
info.setChildren(children);
return true;
}
/**
* @see org.eclipse.wst.jsdt.core.IPackageFragment
*/
public IClassFile[] getClassFiles() throws JavaScriptModelException {
ArrayList list = getChildrenOfType(CLASS_FILE);
IClassFile[] array= new IClassFile[list.size()];
list.toArray(array);
return array;
}
/**
* A jar package fragment never contains compilation units.
* @see org.eclipse.wst.jsdt.core.IPackageFragment
*/
public IJavaScriptUnit[] getJavaScriptUnits() {
return NO_COMPILATION_UNITS;
}
/**
* A package fragment in a jar has no corresponding resource.
*
* @see IJavaScriptElement
*/
public IResource getCorrespondingResource() {
return null;
}
/**
* Returns an array of non-java resources contained in the receiver.
*/
public Object[] getNonJavaScriptResources() throws JavaScriptModelException {
if (this.isDefaultPackage()) {
// We don't want to show non java resources of the default package (see PR #1G58NB8)
return JavaElementInfo.NO_NON_JAVA_RESOURCES;
} else {
return this.storedNonJavaResources();
}
}
/**
* Jars and jar entries are all read only
*/
public boolean isReadOnly() {
return true;
}
static final Object[] NO_OBJECTS={};
protected Object[] storedNonJavaResources() throws JavaScriptModelException {
return NO_OBJECTS;
}
protected boolean resourceExists() {
return getPackageFragmentRoot().resourceExists();
}
protected LibraryFragmentRoot getLibraryFragmentRoot()
{
return (LibraryFragmentRoot) getPackageFragmentRoot();
}
public IClassFile getClassFile(String classFileName) {
if (!org.eclipse.wst.jsdt.internal.compiler.util.Util.isClassFileName(classFileName)
&& !Util.isMetadataFileName(classFileName)) {
throw new IllegalArgumentException(Messages.element_invalidClassFileName);
}
LibraryFragmentRoot libraryFragmentRoot = getLibraryFragmentRoot();
if (!libraryFragmentRoot.isDirectory())
{
IPath path = getLibraryFragmentRoot().getPath();
// if (org.eclipse.wst.jsdt.internal.compiler.util.Util.isClassFileName(path.lastSegment().toCharArray())
// && path.lastSegment().equalsIgnoreCase(classFileName))
// {
if(path.toOSString().endsWith(classFileName)
|| path.isPrefixOf(new Path(classFileName))) {
return new ClassFile(this, path.toOSString());
}
}
else
{
String filename= "";
if (this.getFile()!=null)
filename= this.getFile().getAbsolutePath()+File.separator+classFileName;
else
filename=classFileName;
return (!Util.isMetadataFileName(classFileName)) ? (IClassFile)new ClassFile(this,filename) : (IClassFile)new MetadataFile(this,filename);
}
return super.getClassFile(classFileName);
}
public String getDisplayName() {
if(parent instanceof LibraryFragmentRoot) {
JsGlobalScopeContainerInitializer initializer = ((LibraryFragmentRoot)parent).getContainerInitializer();
if(initializer==null) return getPath().removeLastSegments(1).toString();
String name = initializer.getDescription(getPath(), getJavaScriptProject());
if(name!=null) return name;
}
return parent.getPath().lastSegment();
}
public File getUnderlyingFile() throws JavaScriptModelException {
File file = getLibraryFragmentRoot().getFile();
if (file == null) {
return null;
}
if (this.names.length == 0)
return file;
// the underlying resource may be a folder or a project (in the case that the project folder
// is atually the package fragment root)
String[] segs = this.names;
for (int i = 0; i < segs.length; ++i) {
File child = new File(file,segs[i]);
if (!child.exists() ) {
throw newNotPresentException();
}
file = child;
}
return file;
}
public File getFile() {
File file = getLibraryFragmentRoot().getFile();
int length = this.names.length;
if (length == 0) {
return file;
} else {
String[] segs = this.names;
for (int i = 0; i < segs.length; ++i) {
File child = new File(file,segs[i]);
if (!child.exists() ) {
return null;
}
file = child;
}
return file;
}
}
}