/****************************************************************************** * Copyright (C) 2012-2013 Fabio Zadrozny * * 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: * Fabio Zadrozny <fabiofz@gmail.com> - initial API and implementation ******************************************************************************/ package org.python.pydev.core; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; import java.nio.charset.IllegalCharsetNameException; import java.util.zip.ZipFile; import org.eclipse.core.filebuffers.ITextFileBuffer; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jface.text.IDocument; import org.python.pydev.core.log.Log; import org.python.pydev.shared_core.callbacks.ICallback0; import org.python.pydev.shared_core.io.FileUtils; import org.python.pydev.shared_core.string.FastStringBuffer; /** * File utilities that need access to: * - ITextFileBufferManager * - IProject/IResource * * Also, the functions to load documents may suppose they're dealing with Python files (i.e.: * to get the encoding to open the stream properly if we weren't able to get the stream from * the ITextFileBufferManager). */ public class FileUtilsFileBuffer { /** * Characters that files in the filesystem cannot have. */ public static char[] INVALID_FILESYSTEM_CHARS = { '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '[', ']', '{', '}', '=', '+', '.', ' ', '`', '~', '\'', '"', ',', ';' }; /** * @return a valid name for a project so that the returned name can be used to create a file in the filesystem */ public static String getValidProjectName(IProject project) { String name = project.getName(); for (char c : INVALID_FILESYSTEM_CHARS) { name = name.replace(c, '_'); } return name; } public static IDocument getDocFromFile(java.io.File f) throws IOException { return getDocFromFile(f, true); } /** * @return a string with the contents from a path within a zip file. */ public static String getStringFromZip(File f, String pathInZip) throws Exception { return (String) getCustomReturnFromZip(f, pathInZip, String.class); } /** * @return a document with the contents from a path within a zip file. */ public static IDocument getDocFromZip(File f, String pathInZip) throws Exception { return (IDocument) getCustomReturnFromZip(f, pathInZip, IDocument.class); } /** * @param f the zip file that should be opened * @param pathInZip the path within the zip file that should be gotten * @param returnType the class that specifies the return type of this method. * If null, it'll return in the fastest possible way available. * Valid options are: * String.class * IDocument.class * FastStringBuffer.class * * @return an object with the contents from a path within a zip file, having the return type * of the object specified by the parameter returnType. */ public static Object getCustomReturnFromZip(File f, String pathInZip, Class<? extends Object> returnType) throws Exception { try (ZipFile zipFile = new ZipFile(f, ZipFile.OPEN_READ);) { try (InputStream inputStream = zipFile.getInputStream(zipFile.getEntry(pathInZip));) { return FileUtils.getStreamContents(inputStream, null, null, returnType); } } } /** * @return a string with the contents of the passed file */ public static String getStringFromFile(java.io.File f, boolean loadIfNotInWorkspace) throws IOException { return (String) getCustomReturnFromFile(f, loadIfNotInWorkspace, String.class); } /** * @return the document given its 'filesystem' file */ public static IDocument getDocFromFile(java.io.File f, boolean loadIfNotInWorkspace) throws IOException { return (IDocument) getCustomReturnFromFile(f, loadIfNotInWorkspace, IDocument.class); } /** * @param f the file from where we want to get the contents * @param returnType the class that specifies the return type of this method. * If null, it'll return in the fastest possible way available. * Valid options are: * String.class * IDocument.class * FastStringBuffer.class * * * @return an object with the contents from the file, having the return type * of the object specified by the parameter returnType. */ public static Object getCustomReturnFromFile(java.io.File f, boolean loadIfNotInWorkspace, Class<? extends Object> returnType) throws IOException { IPath path = Path.fromOSString(FileUtils.getFileAbsolutePath(f)); IDocument doc = getDocFromPath(path); if (doc != null) { if (returnType == null || returnType == IDocument.class) { return doc; } else if (returnType == String.class) { return doc.get(); } else if (returnType == FastStringBuffer.class) { return new FastStringBuffer(doc.get(), 16); } else { throw new RuntimeException("Don't know how to treat requested return type: " + returnType); } } if (doc == null && loadIfNotInWorkspace) { FileInputStream stream = new FileInputStream(f); try { String encoding = FileUtils.getPythonFileEncoding(f); return FileUtils.getStreamContents(stream, encoding, null, returnType); } finally { try { if (stream != null) { stream.close(); } } catch (Exception e) { Log.log(e); } } } return doc; } /** * @param path the path we're interested in * @return a file buffer to be used. */ public static ITextFileBuffer getBufferFromPath(IPath path) { return FileUtils.getBufferFromPath(path); } /** * @return null if it was unable to get the document from the path (this may happen if it was not refreshed). * Or the document that represents the file */ public static IDocument getDocFromPath(IPath path) { return FileUtils.getDocFromPath(path); } public static ICallback0<IDocument> getDocOnCallbackFromResource(final IResource resource) { return new ICallback0<IDocument>() { private IDocument cache; private boolean calledOnce = false; @Override public IDocument call() { if (!calledOnce) { calledOnce = true; cache = getDocFromResource(resource); } return cache; } }; } /** * Returns a document, created with the contents of a resource (first tries to get from the 'FileBuffers', * and if that fails, it creates one reading the file. */ public static IDocument getDocFromResource(IResource resource) { return FileUtils.getDocFromResource(resource); } /** * The encoding declared in the document is returned (according to the PEP: http://www.python.org/doc/peps/pep-0263/) */ public static String getPythonFileEncoding(IDocument doc, String fileLocation) throws IllegalCharsetNameException { Reader inputStreamReader = new StringReader(doc.get()); return FileUtils.getPythonFileEncoding(inputStreamReader, fileLocation); } }