blob: e72f450caa0c792bd9ad8fa787a523ab465afd8b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 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
* Walter Harley - Patch for ensuring the parent folders are created
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.apt.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.net.URI;
import java.nio.charset.Charset;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.NestingKind;
import javax.tools.SimpleJavaFileObject;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
/**
* Implementation of a Java file object that corresponds to a file on the file system
*/
public class EclipseFileObject extends SimpleJavaFileObject {
private File f;
private Charset charset;
private boolean parentsExist; // parent directories exist
public EclipseFileObject(String className, URI uri, Kind kind, Charset charset) {
super(uri, kind);
this.f = new File(this.uri);
this.charset = charset;
this.parentsExist = false;
}
/* (non-Javadoc)
* @see javax.tools.JavaFileObject#getAccessLevel()
*/
public Modifier getAccessLevel() {
// cannot express multiple modifier
if (getKind() != Kind.CLASS) {
return null;
}
ClassFileReader reader = null;
try {
reader = ClassFileReader.read(this.f);
} catch (ClassFormatException e) {
// ignore
} catch (IOException e) {
// ignore
}
if (reader == null) {
return null;
}
final int accessFlags = reader.accessFlags();
if ((accessFlags & ClassFileConstants.AccPublic) != 0) {
return Modifier.PUBLIC;
}
if ((accessFlags & ClassFileConstants.AccAbstract) != 0) {
return Modifier.ABSTRACT;
}
if ((accessFlags & ClassFileConstants.AccFinal) != 0) {
return Modifier.FINAL;
}
return null;
}
/* (non-Javadoc)
* @see javax.tools.JavaFileObject#getNestingKind()
*/
public NestingKind getNestingKind() {
switch(kind) {
case SOURCE :
return NestingKind.TOP_LEVEL;
case CLASS :
ClassFileReader reader = null;
try {
reader = ClassFileReader.read(this.f);
} catch (ClassFormatException e) {
// ignore
} catch (IOException e) {
// ignore
}
if (reader == null) {
return null;
}
if (reader.isAnonymous()) {
return NestingKind.ANONYMOUS;
}
if (reader.isLocal()) {
return NestingKind.LOCAL;
}
if (reader.isMember()) {
return NestingKind.MEMBER;
}
return NestingKind.TOP_LEVEL;
default:
return null;
}
}
/* (non-Javadoc)
* @see javax.tools.FileObject#delete()
*/
public boolean delete() {
return this.f.delete();
}
public boolean equals(Object o) {
if (!(o instanceof EclipseFileObject)) {
return false;
}
EclipseFileObject eclipseFileObject = (EclipseFileObject) o;
return eclipseFileObject.toUri().equals(this.uri);
}
/* (non-Javadoc)
* @see javax.tools.FileObject#getCharContent(boolean)
*/
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return Util.getCharContents(this, ignoreEncodingErrors, org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(this.f), this.charset.name());
}
/* (non-Javadoc)
* @see javax.tools.FileObject#getLastModified()
*/
public long getLastModified() {
return this.f.lastModified();
}
public String getName() {
return this.f.getPath();
}
public int hashCode() {
return f.hashCode();
}
/* (non-Javadoc)
* @see javax.tools.FileObject#openInputStream()
*/
public InputStream openInputStream() throws IOException {
// TODO (olivier) should be used buffered input stream
return new FileInputStream(this.f);
}
/* (non-Javadoc)
* @see javax.tools.FileObject#openOutputStream()
*/
public OutputStream openOutputStream() throws IOException {
ensureParentDirectoriesExist();
return new FileOutputStream(this.f);
}
/* (non-Javadoc)
* @see javax.tools.FileObject#openReader(boolean)
*/
public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
return new FileReader(this.f);
}
/* (non-Javadoc)
* @see javax.tools.FileObject#openWriter()
*/
public Writer openWriter() throws IOException {
ensureParentDirectoriesExist();
return new FileWriter(this.f);
}
@Override
public String toString() {
return this.f.getAbsolutePath();
}
private void ensureParentDirectoriesExist() throws IOException {
if (!this.parentsExist) {
File parent = f.getParentFile();
if (parent != null && !parent.exists()) {
if (!parent.mkdirs()) {
// could have been concurrently created
if (!parent.exists() || !parent.isDirectory())
throw new IOException("Unable to create parent directories for " + f); //$NON-NLS-1$
}
}
this.parentsExist = true;
}
}
}