blob: 745d9c03e4c66d65808e6807eab9f1834a1d0245 [file] [log] [blame]
package org.eclipse.jdt.internal.core.builder.impl;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.internal.core.Assert;
import org.eclipse.jdt.internal.core.builder.IState;
import org.eclipse.jdt.internal.core.builder.IType;
import org.eclipse.jdt.internal.core.Util;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
/**
* A <ProjectBinaryOutput> is a <BinaryOutput> that stores the
* binaries in a folder of an <IProject>.
*/
public class ProjectBinaryOutput extends BinaryOutput {
private IProject project;
private IPath outputPath;
private JavaDevelopmentContextImpl dc;
/**
* Creates a new ProjectBinaryOutput for the given project and output path
* in this project.
*/
public ProjectBinaryOutput(IProject project, IPath outputPath, JavaDevelopmentContextImpl dc) {
this.project = project;
this.outputPath = outputPath;
this.dc = dc;
/* create the output folder is it doesn't exist */
if (!project.getFullPath().equals(outputPath)) {
this.makeContainersIfNecessary(outputPath);
}
}
/**
* @see BinaryOutput
*/
protected void basicPutBinary(TypeStructureEntry tsEntry, byte[] binary, int crc) {
IType type;
IPath path = getPathForBinary(type = tsEntry.getType());
deleteBinary(type);
IContainer container = makeContainersIfNecessary(path.removeLastSegments(1));
PackageElement element = new PackageElement(type.getPackage(), new SourceEntry(path, null, null));
IFile file = container.getFile(new Path(path.lastSegment()));
try {
ByteArrayInputStream stream = new ByteArrayInputStream(binary);
file.create(stream, true, null);
} catch (CoreException e) {
throw this.dc.internalException(e);
}
}
/**
* Deletes everything in the given container.
*/
private void deleteAllInContainer(IContainer container) {
try {
if (!container.exists())
return;
IResource[] members = container.members();
for (int i = 0, max = members.length; i < max;i++) {
IResource resource = (IResource) members[i];
resource.delete(true, null);
}
} catch (CoreException e) {
}
}
/**
* @see BinaryOutput
*/
public void deleteBinary(IType type) {
IPath path = getPathForBinary(type);
IFile file = getFile(path);
try {
file.delete(true, null);
} catch (CoreException e) {
}
}
/**
* Deletes the classes in the given container, recursively.
* Delete any folders which become empty.
*/
private void deleteClassesInContainer(IContainer container) {
try {
if (!container.exists())
return;
IResource[] members = container.members();
for (int i = 0, max = members.length; i < max;i++) {
IResource resource = (IResource) members[i];
switch (resource.getType()) {
case IResource.FILE :
if (resource.getName().toLowerCase().endsWith(".class"/*nonNLS*/)) {
resource.delete(true, null);
}
break;
case IResource.PROJECT :
case IResource.FOLDER :
deleteClassesInContainer((IContainer) resource);
break;
}
}
//
// Don't delete empty folders, since the output may overlap with the source, and
// we don't want to delete empty folders which the user may have created.
//
// if (container.getType() == IResource.FOLDER && !container.members().hasMoreElements()) {
// container.delete(true, null);
// }
} catch (CoreException e) {
}
}
/**
* @see BinaryOutput
*/
public void garbageCollect(IState[] statesInUse) {
// Nothing to do for a Project binary output
}
/**
* @see BinaryOutput
*/
public byte[] getBinary(TypeStructureEntry tsEntry, IType type) {
IPath path = getPathForBinary(type);
IFile file = getFile(path);
try {
InputStream input = file.getContents(true);
return Util.readContentsAsBytes(input);
} catch (IOException e) {
return new byte[0];
} catch (CoreException e) {
return new byte[0];
}
}
/**
* Returns the container for a path.
*/
private IContainer getContainer(IPath path) {
if (path.isAbsolute()){
if (this.project.getFullPath().equals(path)){
return this.project;
} else {
return this.project.getWorkspace().getRoot().getFolder(path);
}
}
return this.project.getFolder(path);
}
/**
* Returns the file for a path.
*/
private IFile getFile(IPath path) {
if (path.isAbsolute()){
return this.project.getWorkspace().getRoot().getFile(path);
}
return this.project.getFile(path);
}
/**
* Returns the path for the output package fragment root.
*/
IPath getOutputPath() {
return this.outputPath;
}
/**
* Returns the path in the output folder for the given type.
*/
private IPath getPathForBinary(IType type) {
return getOutputPath().append(type.getName().replace('.', '/') + ".class"/*nonNLS*/);
}
/**
* Returns the container at the given path, creating it and any parent folders if necessary.
*/
IContainer makeContainersIfNecessary(IPath path) {
try {
IContainer container = getContainer(path);
if (container.exists())
return container;
Assert.isTrue(container instanceof IFolder);
makeContainersIfNecessary(path.removeLastSegments(1));
((IFolder) container).create(true, true, null);
return container;
} catch (CoreException e) {
throw this.dc.internalException(e);
}
}
/**
* @see BinaryOutput
*/
public void scrubOutput() {
IJavaProject projectElement = JavaCore.create(this.project);
IClasspathEntry[] entries;
try {
entries = projectElement.getResolvedClasspath(true);
} catch(JavaModelException e){
throw this.dc.internalException(e);
}
/* detect whether the binary ouput coincidates with source folder */
boolean flushAllOutput = true;
boolean hasSource = false;
for (int i = 0, length = entries.length; i < length; i++) {
IClasspathEntry entry = entries[i];
if ((entry.getEntryKind() == IClasspathEntry.CPE_SOURCE)) {
hasSource = true;
if (this.outputPath.equals(entry.getPath())){
flushAllOutput = false; // output coincidates, cannot flush
break;
}
}
}
if (hasSource) {
if (flushAllOutput){
deleteAllInContainer(getContainer(this.outputPath));
} else {
deleteClassesInContainer(getContainer(this.outputPath));
}
}
}
}