All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.roydesign.io.DocumentFile Maven / Gradle / Ivy

Go to download

MRJ Adapter is a wrapper around built in Java Virtual Machine APIs provided by Apple.

The newest version!
/*******************************************************************************

	File:		DocumentFile.java
	Author:		Steve Roy 
				
	Part of MRJ Adapter, a unified API for easy integration of Mac OS specific
	functionality within your cross-platform Java application.
	
	This library is open source and can be modified and/or distributed under
	the terms of the Artistic License.
	

	Change History:
	02/12/03	Created this file - Steve
	03/31/03	Modified openWith() to call into ApplicationFile instead - Steve
	06/17/03	Use net.roydesign.mac.MRJAdapter - Steve

*******************************************************************************/

package net.roydesign.io;

import com.apple.eio.FileManager;
import com.apple.mrj.MRJFileUtils;
import com.apple.mrj.MRJOSType;
import net.roydesign.mac.MRJAdapter;

import java.io.File;
import java.io.IOException;

/**
 * 

A document file is a file meant to be opened in an application. Most * platforms have their own way of binding a document to an application, * and this class attempts to incorporate the smarts for those varied * mechanisms. Of interest is the fact that all methods in this class * are cross-platform, even the methods specific to a particular OS. Those * methods will simply not do anything, or will act on an internal member * variable. In any case, this allows your code to be free of ugly platform * checks.

* *

In particular, this class supports the Mac OS type/creator binding * mechanism. Even though the methods are specific to the Mac OS, they can * be called on any platform. For example, calling {@code setMacCreator("ABCD")} * won't put this information in the file system as it would on Mac OS, but * it will still be tracked internally, so that a subsequent call to * {@code getMacCreator()} will return the set value. This ensures that * your code runs unchanged on all platforms.

* *

This class also exposes methods to easily change the filename extension * of the document on disk. This is meant as an equivalent to the Mac specific * type/creator facility so that the type and binding of a document can be * set on platforms other that Mac OS.

* *

The document can be renamed, and this translates into the file * on disk to be renamed as well. This is a convenience over having to use * the {@code File.renameTo(File)} method and its associated pitfalls.

* *

Finally this class also makes it easy to open a document, either as * though the user had double-clicked it in the file system, using its default * binding, or with a given application of your choice. This functionality is * typically highly platform dependent and error prone. Using this class makes * it simple. All you have to do is {@code new DocumentFile(myFile).open()}.

* * @version MRJ Adapter 1.2 */ public class DocumentFile { /** * The name of the OS, from the os.name system property. */ private static final String osName = System.getProperty("os.name"); /** * The file represented by this document. */ private File file; /** * The Mac OS creator code of the file. */ private String macCreator = ""; /** * The Mac OS type code of the file. */ private String macType = ""; /** * Construct a document file with a path. This is identical * to the {@code java.io.File} constructor. * @param path the document path */ public DocumentFile(String path) { this.file = new File(path); } /** * Construct a document file with a parent directory and the * name or subpath of a child document file. This is identical * to the {@code java.io.File} constructor. * @param parent the parent directory * @param child the child directory path or file name */ public DocumentFile(String parent, String child) { this.file = new File(parent, child); } /** * Construct a document file with a parent directory and the * name or subpath of a child document file. This is identical * to the {@code java.io.File} constructor. * @param parent the parent directory * @param child the child directory path or file name */ public DocumentFile(File parent, String child) { this.file = new File(parent, child); } /** * Construct a document file with a {@code java.io.File} * object. Note that the given file object is not used internally. * @param file the file object */ public DocumentFile(File file) { // We don't use the passed File object, because // we want to have full control over it this(file.getPath()); } /** * Set the Mac OS type code of the given file. This method does nothing * on other platforms. The type code is a case-sensitive four character * string. Any exceeding character will be ignored and the string will be * padded with spaces if shorter, with the exception of the case where * the string length is zero, in which case the file type will be set * to nothing. * @param file the file to set the type of * @param type the type code * @exception IOException when an I/O error occurs */ public static void setFileType(File file, String type) throws IOException { FileManager.setFileType(file.getAbsolutePath(), MRJAdapter.fourCharCodeToInt(type)); } /** * Set the Mac OS creator code of the given file. This method does * nothing on other platforms. The creator code is a case-sensitive * four character string. Any exceeding character will be ignored * and the string will be padded with spaces if shorter, with the * exception of the case where the string length is zero, in which * case the file creator will be set to nothing. * @param file the file to set the creator of * @param creator the creator code * @exception IOException when an I/O error occurs */ public static void setFileCreator(File file, String creator) throws IOException { FileManager.setFileCreator(file.getAbsolutePath(), MRJAdapter.fourCharCodeToInt(creator)); } /** * Set the Mac OS creator and type codes of the given file. This method * does nothing on other platforms. The creator and type codes are * case-sensitive four character strings. Any exceeding character will * be ignored and the string will be padded with spaces if shorter, with * the exception of the case where the string length is zero, in which * case the file creator will be set to nothing. * @param file the file to set the creator and type of * @param creator the creator code * @param type the type code * @exception IOException when an I/O error occurs */ public static void setFileCreatorAndType(File file, String creator, String type) throws IOException { FileManager.setFileTypeAndCreator(file.getAbsolutePath(), MRJAdapter.fourCharCodeToInt(type), MRJAdapter.fourCharCodeToInt(creator)); } /** * Get the Mac OS type code of the given file. On other platforms, * this method returns an empty string, which is the same as if * the file type was not set on the Mac platform. A Mac type is * a four character string, unless the file has no type, in which * case an empty string is returned. Note that this method supports * Mac OS style bundles on all platforms, which is useful in the * case where such a bundle is temporarily located on a non-Mac * file system. When this is detected, the method will extract the * type code from the bundle just like Mac OS does natively. * @param file the file to get to type from * @return the type code * @exception IOException when an I/O error occurs */ public static String getFileType(File file) throws IOException { int t = FileManager.getFileType(file.getAbsolutePath()); return MRJAdapter.intToFourCharCode(t); } /** * Open the document in its native application. If the application * can't be identified or found, this method will return false. * You should handle this by bringing up a file dialog for the * user to locate an application to use for opening the file. You * can use the class {@code ApplicationDialog} for this. * Currently, this method supports all flavors of Mac OS and Windows. * On all other platforms, the value {@code false} is returned * so you can take appropriate action, which should actually be the * same action that you would take if you were on Mac OS/Windows and * the method returned {@code false}. * @return whether the file was opened successfully or not * @exception IOException when an I/O error occurs */ public boolean open() throws IOException { try { // On Mac OS X, use 'open' on the command line Process p = Runtime.getRuntime().exec(new String[] {"open", file.getAbsolutePath()}); if (p.waitFor() != 0) return false; } catch (InterruptedException e) { return false; } // We get here when the document was opened successfully, // so be happy and let the user know return true; } /** * Open the document with the given application file. If the operation * fails or an error occurs, this method will return false. * @param application the application file to use to open the document * @return whether the file was opened successfully or not * @exception IOException when an I/O error occurs */ public boolean openWith(ApplicationFile application) throws IOException { return application.openDocument(this); } /** * Open the document with the given application. If the operation * fails or an error occurs, this method will return false. * @param application the application to use to open the document * @return whether the file was opened successfully or not * @exception IOException when an I/O error occurs */ public boolean openWith(File application) throws IOException { return openWith(new ApplicationFile(application)); } /** * Set the type code of the file as used on Mac OS and Mac OS X. * On all other platforms, this method does nothing to the file * on disk but still keeps track of the assigned type internally * so that {@code getMacType()} returns the assigned value. * @param type the Mac type code to assign * @exception IOException when an I/O error occurs * @see DocumentFile#setFileType */ public void setMacType(String type) throws IOException { this.macType = type; setFileType(file, type); } /** * Get the type code of a file as used on Mac OS and Mac OS X. * On all other platforms, this method will returned the value set * in a previous call to {@code setMacType()}. Otherwise an * empty string is returned. * @return the Mac type code of the file * @exception IOException when an I/O error occurs * @see DocumentFile#getFileType */ public String getMacType() throws IOException { String t = getFileType(file); if (t.isEmpty() && macType != null) return macType; return t; } /** * Set the creator code of the file as used on Mac OS and Mac OS X. * On all other platforms, this method does nothing to the file * on disk but still keeps track of the assigned creator internally * so that {@code getMacCreator()} returns the assigned value. * @param creator the Mac creator code to assign * @exception IOException when an I/O error occurs * @see DocumentFile#setFileCreator */ public void setMacCreator(String creator) throws IOException { this.macCreator = creator; setFileCreator(file, creator); } /** * Get the creator code of a file as used on Mac OS and Mac OS X. * On all other platforms, this method will returned the value set * in a previous call to {@code setMacCreator()}. Otherwise an * empty string is returned. * @return the Mac creator code of the file * @exception IOException when an I/O error occurs * @see MRJAdapter#getFileCreator */ public String getMacCreator() throws IOException { String c = MRJAdapter.getFileCreator(file); if (c.isEmpty() && macCreator != null) return macCreator; return c; } /** * Set the creator code of the file as used on Mac OS and Mac OS X. * On all other platforms, this method does nothing to the file * on disk but still keeps track of the assigned creator internally * so that {@code getMacCreator()} returns the assigned value. * @param creator the Mac creator code to assign * @param type the Mac type code to assign * @exception IOException when an I/O error occurs * @see DocumentFile#setFileCreatorAndType */ public void setMacCreatorAndType(String creator, String type) throws IOException { this.macCreator = creator; this.macType = type; setFileCreatorAndType(file, creator, type); } /** * Set the name extension of the file as used on many platforms to * designate the file type and the application binding. The * extension must not start with a period. Since the file will * be renamed on disk, it's up to you to verify if a file * with the new title and extension already exists prior to calling * this method. An I/O exception will be thrown if the document * can't be renamed for whatever reason. * @param extension the new extension of the document * @exception IOException if the method fails to rename the document */ public void setExtension(String extension) throws IOException { StringBuilder b = new StringBuilder(); b.append(getTitle()); if (extension != null && !extension.isEmpty()) { b.append('.'); b.append(extension); } File f = new File(file.getParent(), b.toString()); if (!file.renameTo(f)) throw new IOException("failed to rename file"); this.file = f; } /** * Get the name extension of a file as used on many platforms to * designate the file type and the application binding. The extension * is the name of the document on disk, minus the title and not * including the period. * @return the name extension of the document * @exception IOException when an I/O error occurs */ public String getExtension() { String n = file.getName(); int pos = n.lastIndexOf('.'); if (pos != -1 && pos + 1 != n.length()) return n.substring(pos + 1); return ""; } /** * Set the title of the document file. This method sets the title * of the document, which corresponds to the name of the document * file minus its filename extension. Since the file will be * renamed on disk, it's up to you to verify if a file with the * new title (and extension) already exists prior to calling this * method. An I/O exception will be thrown if the document * can't be renamed for whatever reason. * @param title the new title of the document * @exception IOException if the method fails to rename the document */ public void setTitle(String title) throws IOException { if (title == null || title.isEmpty()) throw new IllegalArgumentException("title can't be null or zero length"); StringBuilder b = new StringBuilder(); b.append(title); String ext = getExtension(); if (ext != null && !ext.isEmpty()) { b.append('.'); b.append(ext); } File f = new File(file.getParent(), b.toString()); if (!file.renameTo(f)) throw new IOException("failed to rename file"); this.file = f; } /** * Get the title of the document file. The title of the document * is the name of the file on disk minus the filename extension. * @return the title of the document * @exception IOException when an I/O error occurs */ public String getTitle() { String n = file.getName(); int pos = n.lastIndexOf('.'); if (pos != -1 && pos != 0 && pos + 1 != n.length()) return n.substring(0, pos); return n; } /** * Set the title and extension of the document file. Since the * file will be renamed on disk, it's up to you to verify if a file * with the new title and extension already exists prior to calling * this method. An I/O exception will be thrown if the document * can't be renamed for whatever reason. * @param title the new title of the document * @param extension the new extension of the document * @exception IOException if the method fails to rename the document */ public void setTitleAndExtension(String title, String extension) throws IOException { if (title == null || title.isEmpty()) throw new IllegalArgumentException("title can't be null or zero length"); StringBuilder b = new StringBuilder(); b.append(title); if (extension != null && !extension.isEmpty()) { b.append('.'); b.append(extension); } File f = new File(file.getParent(), b.toString()); if (!file.renameTo(f)) throw new IOException("failed to rename file"); this.file = f; } /** * Get the file object representing this document on disk. * @return the file object for this document */ public File getFile() { return file; } /** * Get the path to the document file on disk. * @return the path to the document * @see File#getPath */ public String getPath() { return file.getPath(); } /** * Get the absolute path to the document file on disk. * @return the absolute path to the document * @see File#getAbsolutePath */ public String getAbsolutePath() { return file.getAbsolutePath(); } /** * Get the canonical path to the document file on disk. * @return the canonical path to the document * @see File#getCanonicalPath */ public String getCanonicalPath() throws IOException { return file.getCanonicalPath(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy