001: /*******************************************************************************
002: * Copyright (c) 2005, 2007 BEA Systems, Inc.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * tyeung@bea.com - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.apt.core.internal.util;
011:
012: import java.io.BufferedOutputStream;
013: import java.io.ByteArrayInputStream;
014: import java.io.ByteArrayOutputStream;
015: import java.io.File;
016: import java.io.FileInputStream;
017: import java.io.FileOutputStream;
018: import java.io.IOException;
019: import java.io.InputStream;
020: import java.io.OutputStream;
021:
022: import org.eclipse.core.resources.IContainer;
023: import org.eclipse.core.resources.IFile;
024: import org.eclipse.core.resources.IFolder;
025: import org.eclipse.core.resources.IResource;
026: import org.eclipse.core.resources.ResourcesPlugin;
027: import org.eclipse.core.runtime.CoreException;
028: import org.eclipse.jdt.apt.core.internal.AptPlugin;
029:
030: /**
031: * Simple utility class to encapsulate an mkdirs() that avoids a timing issue
032: * in the jdk.
033: */
034: public final class FileSystemUtil {
035: private FileSystemUtil() {
036: }
037:
038: /**
039: * If the given resource is a folder, then recursively deleted all derived
040: * files and folders contained within it. Delete the folder if it becomes empty
041: * and if itself is also a derived resource.
042: * If the given resource is a file, delete it iff it is a derived resource.
043: * The resource is left untouched if it is no a folder or a file.
044: * @param resource
045: * @return <code>true</code> iff the resource has been deleted.
046: * @throws CoreException
047: */
048: public static boolean deleteDerivedResources(
049: final IResource resource) throws CoreException {
050: if (null == resource) {
051: return false;
052: }
053: if (resource.getType() == IResource.FOLDER) {
054: boolean deleteFolder = resource.isDerived();
055: IResource[] members = ((IFolder) resource).members();
056: for (int i = 0, len = members.length; i < len; i++) {
057: deleteFolder &= deleteDerivedResources(members[i]);
058: }
059: if (deleteFolder) {
060: deleteResource(resource);
061: return true;
062: }
063: return false;
064: } else if (resource.getType() == IResource.FILE) {
065: if (resource.isDerived()) {
066: deleteResource(resource);
067: return true;
068: }
069: return false;
070: }
071: // will skip pass everything else.
072: else
073: return false;
074: }
075:
076: /**
077: * Delete a resource without throwing an exception.
078: */
079: private static void deleteResource(IResource resource) {
080: try {
081: resource.delete(true, null);
082: } catch (CoreException e) {
083: // might have been concurrently deleted
084: if (resource.exists()) {
085: AptPlugin
086: .log(
087: e,
088: "Unable to delete derived resource " + resource); //$NON-NLS-1$
089: }
090: }
091: }
092:
093: public static void mkdirs(File parent) {
094: if (parent == null)
095: return;
096:
097: // It is necessary to synchronize to prevent timing issues while creating the parent directories
098: // We can be codegening multiple files that go into the same directory at the same time.
099: synchronized (FileSystemUtil.class) {
100: if (!parent.exists()) {
101: boolean succeed = false;
102: for (int i = 0; !succeed && i < 5; i++)
103: succeed = parent.mkdirs();
104: }
105: }
106: }
107:
108: public static void makeDerivedParentFolders(IContainer container)
109: throws CoreException {
110: // synchronize the "does it exist - if not, create it" sequence.
111: if ((container instanceof IFolder) && !container.exists()) {
112: makeDerivedParentFolders(container.getParent());
113: try {
114: ((IFolder) container).create(true, true, null);
115: } catch (CoreException e) {
116: // Ignore race condition where another thread created the folder at the
117: // same time, causing checkDoesNotExist() to throw within create().
118: if (!container.exists()) {
119: throw e;
120: }
121: }
122: container.setDerived(true);
123: }
124: }
125:
126: /**
127: * Returns the contents of a file as a string in UTF8 format
128: */
129: public static String getContentsOfIFile(IFile file)
130: throws IOException, CoreException {
131: return getContents(file.getContents(true));
132: }
133:
134: public static String getContentsOfFile(File file)
135: throws IOException {
136: return getContents(new FileInputStream(file));
137: }
138:
139: private static String getContents(InputStream in)
140: throws IOException {
141: try {
142: ByteArrayOutputStream out = new ByteArrayOutputStream();
143: byte[] buffer = new byte[512];
144: int len;
145: while ((len = in.read(buffer)) > 0) {
146: out.write(buffer, 0, len);
147: }
148: out.close();
149: String s = new String(out.toByteArray(), "UTF8"); //$NON-NLS-1$
150: return s;
151: } finally {
152: try {
153: in.close();
154: } catch (IOException ioe) {
155: }
156: }
157: }
158:
159: /**
160: * Stores a string into an Eclipse file in UTF8 format. The file
161: * will be created if it does not already exist.
162: * @throws IOException, CoreException
163: */
164: public static void writeStringToIFile(IFile file, String contents)
165: throws IOException, CoreException {
166: byte[] data = contents.getBytes("UTF8"); //$NON-NLS-1$
167: ByteArrayInputStream input = new ByteArrayInputStream(data);
168: if (file.exists()) {
169: if (file.isReadOnly()) {
170: // provide opportunity to checkout read-only .factorypath file
171: ResourcesPlugin.getWorkspace().validateEdit(
172: new IFile[] { file }, null);
173: }
174: file.setContents(input, true, false, null);
175: } else {
176: // Even with FORCE, create() will still throw if the file already exists.
177: file.create(input, IResource.FORCE, null);
178: }
179: }
180:
181: /**
182: * Stores a string into an ordinary workspace file in UTF8 format.
183: * The file will be created if it does not already exist.
184: * @throws IOException
185: */
186: public static void writeStringToFile(File file, String contents)
187: throws IOException {
188: byte[] data = contents.getBytes("UTF8"); //$NON-NLS-1$
189: OutputStream out = new BufferedOutputStream(
190: new FileOutputStream(file));
191: try {
192: for (byte b : data) {
193: out.write(b);
194: }
195: } finally {
196: try {
197: out.close();
198: } catch (IOException ioe) {
199: }
200: }
201: }
202:
203: /**
204: * Return true if the content of the streams is identical,
205: * false if not.
206: */
207: public static boolean compareStreams(InputStream is1,
208: InputStream is2) {
209: try {
210: int b1 = is1.read();
211: while (b1 != -1) {
212: int b2 = is2.read();
213: if (b1 != b2) {
214: return false;
215: }
216: b1 = is1.read();
217: }
218:
219: int b2 = is2.read();
220: if (-1 != b2) {
221: return false;
222: }
223: return true;
224: } catch (IOException ioe) {
225: return false;
226: }
227: }
228: }
|