![JAR search and dependency download from the Maven repository](/logo.png)
net.roydesign.io.ApplicationFile Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mrjadapter Show documentation
Show all versions of mrjadapter Show documentation
MRJ Adapter is a wrapper around built in Java Virtual Machine APIs provided by Apple.
The newest version!
/*******************************************************************************
File: ApplicationFile.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/20/03 Created this file - Steve
03/31/03 Added instantiation of osName, which was otherwise undefined,
implemented the two getMacBundleResource() methods, provided
a better implementation of open() and openDocuments() - Steve
06/17/03 Use net.roydesign.mac.MRJAdapter - Steve
*******************************************************************************/
package net.roydesign.io;
import net.roydesign.mac.MRJAdapter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
/**
* An application file is the executable file on disk for an application. This
* class defines methods to locate, inspect and launch such applications and
* integrates a few methods to handle traits specific to the Mac OS platform.
* Due to the intrinsic platform-dependant nature of some of this functionality,
* this is always work in progress. Support for classic Mac OS, Mac OS X, and
* Windows is currently implemented.
*
* @version MRJ Adapter 1.2
*/
public class ApplicationFile
{
/**
* The name of the OS, from the os.name system property.
*/
private static final String osName = System.getProperty("os.name");
/**
* The executable file on disk.
*/
private final File executable;
/**
* Construct an application file with a path. This is identical
* to the {@code java.io.File} constructor.
* @param path the executable path
*/
public ApplicationFile(String path)
{
this.executable = new File(path);
}
/**
* Construct an application file with a parent directory and the
* name or subpath of a child executable 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 ApplicationFile(String parent, String child)
{
this.executable = new File(parent, child);
}
/**
* Construct an application file with a parent directory and the
* name or subpath of a child executable 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 ApplicationFile(File parent, String child)
{
this.executable = new File(parent, child);
}
/**
* Construct an application file with a {@code java.io.File}
* object. Note that the given file object is not used internally.
* @param executable the executable file object
*/
public ApplicationFile(File executable)
{
// We don't use the passed File object, because
// we want to have full control over it
this(executable.getPath());
}
/**
* Utility method to read and parse the content of the given Mac OS
* MRJApp.properties file, trying to extract the value of the given key.
* The keys that can be found in the Info.plist are defined by Apple.
* If the given key is not found, the value {@code null} is returned.
* @param file the MRJApp.properties file
* @param key the key to look for
* @return the value of the key, or null
* @exception IOException when an I/O error occurs
*/
public static String parseMRJAppProperties(File file, String key) throws IOException
{
FileInputStream in = new FileInputStream(file);
Properties props = new Properties();
props.load(in);
in.close();
return props.getProperty(key);
}
/**
* Launch the application.
* @return whether the file was opened successfully or not
* @exception IOException when any error occurs
*/
public boolean open() throws IOException
{
try
{
Process p = Runtime.getRuntime().exec(new String[]
{"open", "-a", executable.getAbsolutePath()});
if (p.waitFor() != 0)
return false;
}
catch (InterruptedException e)
{
return false;
}
// We get here when the application was opened successfully,
// so be happy and let the user know
return true;
}
/**
* Launch the application with the given arguments.
* @param args the arguments to pass to the application
* @return the application process
* @exception IOException when any error occurs
*/
public Process open(String... args) throws IOException
{
/** @todo Need to provide a better way to start processes */
String[] nargs = new String[args.length + 1];
nargs[0] = executable.getAbsolutePath();
System.arraycopy(args, 0, nargs, 1, args.length);
return Runtime.getRuntime().exec(nargs);
}
/**
* Open the given document. Note that the behavior of this method
* is platform specific. Some platforms allow multiple instances of
* an application to execute simultaneously, some others don't, and
* some others have mixed behaviors. For example, on Mac OS X,
* double-clickable applications are not allowed to have multiple
* instances but command line tools can.
* @param documentFile the document to be opened
* @return whether the document was opened successfully or not
* @exception IOException when any error occurs
*/
public boolean openDocument(DocumentFile documentFile) throws IOException
{
return openDocument(documentFile.getFile());
}
/**
* Open the given file. Note that the behavior of this method
* is platform specific. Some platforms allow multiple instances of
* an application to execute simultaneously, some others don't, and
* some others have mixed behaviors. For example, on Mac OS X,
* double-clickable applications are not allowed to have multiple
* instances but command line tools can.
* @param file the file to be opened
* @return whether the file was opened successfully or not
* @exception IOException when any error occurs
*/
public boolean openDocument(File file) throws IOException
{
return openDocuments(file);
}
/**
* Open the given documents. Note that the behavior of this method
* is platform specific. Some platforms allow multiple instances of
* an application to execute simultaneously, some others don't, and
* some others have mixed behaviors. For example, on Mac OS X,
* double-clickable applications are not allowed to have multiple
* instances but command line tools can.
* @param documentFiles the documents to be opened
* @return whether the documents were opened successfully or not
* @exception IOException when any error occurs
*/
public boolean openDocuments(DocumentFile... documentFiles) throws IOException
{
int numFiles = documentFiles.length;
File[] files = new File[numFiles];
for (int i = 0; i < numFiles; i++)
files[i] = documentFiles[i].getFile();
return openDocuments(files);
}
/**
* Open the given files. Note that the behavior of this method
* is platform specific. Some platforms allow multiple instances of
* an application to execute simultaneously, some others don't, and
* some others have mixed behaviors. For example, on Mac OS X,
* double-clickable applications are not allowed to have multiple
* instances but command line tools can.
* @param files the files to be opened
* @return whether the files were opened successfully or not
* @exception IOException when any error occurs
*/
public boolean openDocuments(File... files) throws IOException
{
int numFiles = files.length;
try
{
// On Mac OS X, use 'open' on the command line
String[] strs = new String[3 + numFiles];
strs[0] = "open";
strs[1] = "-a";
strs[2] = executable.getAbsolutePath();
for (int i = 0; i < numFiles; i++)
strs[3 + i] = files[i].getAbsolutePath();
Process p = Runtime.getRuntime().exec(strs);
if (p.waitFor() != 0)
return false;
}
catch (InterruptedException e)
{
return false;
}
// We get here when the documents were opened successfully,
// so be happy and let the user know
return true;
}
/**
* Get the path to the application file on disk.
* @return the path to the application
* @see File#getPath
*/
public String getPath()
{
return executable.getPath();
}
/**
* Get the absolute path to the application file on disk.
* @return the absolute path to the application
* @see File#getAbsolutePath
*/
public String getAbsolutePath()
{
return executable.getAbsolutePath();
}
/**
* Get the canonical path to the application file on disk.
* @return the canonical path to the application
* @see File#getCanonicalPath
*/
public String getCanonicalPath() throws IOException
{
return executable.getCanonicalPath();
}
// exists() ?
// canExecute() ?
// getLocalizedName() ?
// getParent() ?
// getParentFile() ?
// isMacBundle() ?
// isCFM() ?
// isMachO() ?
// isBoth() ?
/**
* Get the name of the executable file on disk.
* @return the name of the executable
*/
public String getExecutableName()
{
return executable.getName();
}
/**
* Get the name displayed by the application to the user.
* @return the name displayed to the user
* @exception IOException when an I/O error occurs
*/
public String getDisplayedName() throws IOException
{
if (executable.isDirectory())
{
// Try to extract it out of the bundle
File mrjAppProperties = new File(executable, "Contents/MRJApp.properties");
if (mrjAppProperties.exists())
{
String name =
parseMRJAppProperties(mrjAppProperties, "com.apple.mrj.application.apple.menu.about.name");
if (name != null)
return name;
}
/** @todo Add support for InfoPlist.strings */
File infoPlist = new File(executable, "Contents/Info.plist");
if (infoPlist.exists())
{
String name = MRJAdapter.parseInfoPlist(infoPlist, "com.apple.mrj.application.apple.menu.about.name");
if (name == null)
{
name = MRJAdapter.parseInfoPlist(infoPlist, "CFBundleName");
if (name == null)
name = MRJAdapter.parseInfoPlist(infoPlist, "CFBundleExecutable");
}
return name;
}
}
return getExecutableName();
}
/**
* Get the Mac OS creator code of the application. On the Mac OS and
* Mac OS X, this method will return the assigned case-sensitive four
* character type string. On all other platforms, the behavior depends
* whether the application is a Mac OS bundled application that is
* temporarily sitting on another platform, or not. When this is the
* case, this method will recognize the bundled app and will extract
* the Mac OS creator code from it. This will only work for correctly
* bundled applications. Otherwise, an empty string will be returned
* to provide a consistent cross-platform behavior.
* @return the Mac OS creator code, or an empty string
* @exception IOException when an I/O error occurs
* @see MRJAdapter#getFileCreator
*/
public String getMacCreator() throws IOException
{
return MRJAdapter.getFileCreator(executable);
}
/**
* Get a Mac OS resource file from the application bundle. Resource files
* are stored in the folder Contents/Resources inside the bundle. This
* method will locate the requested resource only if it's located at the
* top level of the Resources folder. It returns a {@code File}
* object that can be used to read the resource.
* @param resource the name of the resource file
* @return the resource file
* @exception FileNotFoundException when the resource can't be found
* @see MRJAdapter#getBundleResource
*/
public File getMacBundleResource(String resource) throws FileNotFoundException
{
return MRJAdapter.getBundleResource(resource);
}
/**
* Get a Mac OS resource file from the application bundle. Resource files
* are stored in the folder Contents/Resources inside the bundle. This
* method will locate the requested resource only if it's located in the
* specified subfolder of the Resources folder. It returns a {@code File}
* object that can be used to read the resource.
* @param resource the name of the resource file
* @param subFolder the name of the subfolder of Resources
* @return the resource file
* @exception FileNotFoundException when the resource can't be found
* @see MRJAdapter#getBundleResource
*/
public File getMacBundleResource(String resource, String subFolder)
throws FileNotFoundException
{
return MRJAdapter.getBundleResource(resource, subFolder);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy