blob: ab6ffd5fefe4b6863f6c4bf6f5c4dfa29b7248fa [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2007 BEA Systems, Inc.
* 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:
* tyeung@bea.com - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.apt.core.internal.util;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.apt.core.internal.AptPlugin;
/**
* Simple utility class to encapsulate an mkdirs() that avoids a timing issue
* in the jdk.
*/
public final class FileSystemUtil
{
private FileSystemUtil() {}
/**
* If the given resource is a folder, then recursively deleted all derived
* files and folders contained within it. Delete the folder if it becomes empty
* and if itself is also a derived resource.
* If the given resource is a file, delete it iff it is a derived resource.
* The resource is left untouched if it is no a folder or a file.
* @param resource
* @return <code>true</code> iff the resource has been deleted.
* @throws CoreException
*/
public static boolean deleteDerivedResources(final IResource resource)
throws CoreException
{
if (null == resource) {
return false;
}
if( resource.getType() == IResource.FOLDER ){
boolean deleteFolder = resource.isDerived();
IResource[] members = ((IFolder)resource).members();
for( int i=0, len=members.length; i<len; i++ ){
deleteFolder &= deleteDerivedResources(members[i]);
}
if( deleteFolder ){
deleteResource(resource);
return true;
}
return false;
}
else if( resource.getType() == IResource.FILE ){
if( resource.isDerived() ){
deleteResource(resource);
return true;
}
return false;
}
// will skip pass everything else.
else
return false;
}
/**
* Delete a resource without throwing an exception.
*/
private static void deleteResource(IResource resource) {
try {
resource.delete(true, null);
} catch (CoreException e) {
// might have been concurrently deleted
if (resource.exists()) {
AptPlugin.log(e, "Unable to delete derived resource " + resource); //$NON-NLS-1$
}
}
}
public static void mkdirs( File parent )
{
if ( parent == null )
return;
// It is necessary to synchronize to prevent timing issues while creating the parent directories
// We can be codegening multiple files that go into the same directory at the same time.
synchronized (FileSystemUtil.class) {
if (!parent.exists()) {
boolean succeed = false;
for (int i = 0 ; !succeed && i < 5 ; i++)
succeed = parent.mkdirs();
}
}
}
public static void makeDerivedParentFolders (IContainer container) throws CoreException {
// synchronize the "does it exist - if not, create it" sequence.
if ((container instanceof IFolder) && !container.exists()) {
makeDerivedParentFolders(container.getParent());
try {
((IFolder)container).create(true, true, null);
}
catch (CoreException e) {
// Ignore race condition where another thread created the folder at the
// same time, causing checkDoesNotExist() to throw within create().
if (!container.exists()) {
throw e;
}
}
container.setDerived(true);
}
}
/**
* Returns the contents of a file as a string in UTF8 format
*/
public static String getContentsOfIFile(IFile file) throws IOException, CoreException {
return getContents(file.getContents(true));
}
public static String getContentsOfFile(File file) throws IOException {
return getContents(new FileInputStream(file));
}
private static String getContents(InputStream in) throws IOException {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[512];
int len;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.close();
String s = new String(out.toByteArray(), "UTF8"); //$NON-NLS-1$
return s;
}
finally {
try {in.close();} catch (IOException ioe) {}
}
}
/**
* Stores a string into an Eclipse file in UTF8 format. The file
* will be created if it does not already exist.
* @throws IOException, CoreException
*/
public static void writeStringToIFile(IFile file, String contents) throws IOException, CoreException {
byte[] data = contents.getBytes("UTF8"); //$NON-NLS-1$
ByteArrayInputStream input = new ByteArrayInputStream(data);
if (file.exists()) {
if (file.isReadOnly()) {
// provide opportunity to checkout read-only .factorypath file
ResourcesPlugin.getWorkspace().validateEdit(new IFile[]{file}, null);
}
file.setContents(input, true, false, null);
}
else {
// Even with FORCE, create() will still throw if the file already exists.
file.create(input, IResource.FORCE, null);
}
}
/**
* Stores a string into an ordinary workspace file in UTF8 format.
* The file will be created if it does not already exist.
* @throws IOException
*/
public static void writeStringToFile(File file, String contents) throws IOException {
byte[] data = contents.getBytes("UTF8"); //$NON-NLS-1$
OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
try {
for (byte b : data) {
out.write(b);
}
}
finally {
try {out.close();} catch (IOException ioe) {}
}
}
/**
* Return true if the content of the streams is identical,
* false if not.
*/
public static boolean compareStreams(InputStream is1, InputStream is2) {
try {
int b1 = is1.read();
while(b1 != -1) {
int b2 = is2.read();
if(b1 != b2) {
return false;
}
b1 = is1.read();
}
int b2 = is2.read();
if(-1 != b2) {
return false;
}
return true;
}
catch (IOException ioe) {
return false;
}
}
}