org.eclipse.swt.program.Program Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.swt.gtk.linux.x86 Show documentation
Show all versions of org.eclipse.swt.gtk.linux.x86 Show documentation
Standard Widget Toolkit for GTK
The newest version!
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.program;
import java.io.*;
import java.nio.file.*;
import java.nio.file.Path;
import java.util.*;
import java.util.List;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gtk.*;
import org.eclipse.swt.widgets.*;
/**
* Instances of this class represent programs and
* their associated file extensions in the operating
* system.
*
* @see Program snippets
* @see Sample code and further information
*/
public final class Program {
String name = ""; //$NON-NLS-1$
String command;
String iconPath;
Display display;
/* GIO specific
* true if command expects a URI
* false if expects a path
*/
boolean gioExpectUri;
static long modTime;
static Map> mimeTable;
static final String PREFIX_HTTP = "http://"; //$NON-NLS-1$
static final String PREFIX_HTTPS = "https://"; //$NON-NLS-1$
/**
* Prevents uninitialized instances from being created outside the package.
*/
Program() {
}
static String[] parseCommand(String cmd) {
List args = new ArrayList<>();
int sIndex = 0;
int eIndex;
while (sIndex < cmd.length()) {
/* Trim initial white space of argument. */
while (sIndex < cmd.length() && Character.isWhitespace(cmd.charAt(sIndex))) {
sIndex++;
}
if (sIndex < cmd.length()) {
/* If the command is a quoted string */
if (cmd.charAt(sIndex) == '"' || cmd.charAt(sIndex) == '\'') {
/* Find the terminating quote (or end of line).
* This code currently does not handle escaped characters (e.g., " a\"b").
*/
eIndex = sIndex + 1;
while (eIndex < cmd.length() && cmd.charAt(eIndex) != cmd.charAt(sIndex)) eIndex++;
if (eIndex >= cmd.length()) {
/* The terminating quote was not found
* Add the argument as is with only one initial quote.
*/
args.add(cmd.substring(sIndex, eIndex));
} else {
/* Add the argument, trimming off the quotes. */
args.add(cmd.substring(sIndex + 1, eIndex));
}
sIndex = eIndex + 1;
}
else {
/* Use white space for the delimiters. */
eIndex = sIndex;
while (eIndex < cmd.length() && !Character.isWhitespace(cmd.charAt(eIndex))) eIndex++;
args.add(cmd.substring(sIndex, eIndex));
sIndex = eIndex + 1;
}
}
}
return args.toArray(new String[args.size()]);
}
/**
* Finds the program that is associated with an extension.
* The extension may or may not begin with a '.'. Note that
* a Display
must already exist to guarantee that
* this method returns an appropriate result.
*
* @param extension the program extension
* @return the program or null
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT when extension is null
*
*/
public static Program findProgram(String extension) {
return findProgram(Display.getCurrent(), extension);
}
/*
* API: When support for multiple displays is added, this method will
* become public and the original method above can be deprecated.
*/
static Program findProgram(Display display, String extension) {
if (extension == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (extension.length() == 0) return null;
if (extension.charAt(0) != '.') extension = "." + extension;
String mimeType = gio_getMimeType(extension);
if (mimeType == null) return null;
return gio_getProgram(display, mimeType);
}
/**
* Answers all available programs in the operating system. Note
* that a Display
must already exist to guarantee
* that this method returns an appropriate result.
*
* @return an array of programs
*/
public static Program[] getPrograms() {
return getPrograms(Display.getCurrent());
}
/**
* Returns the receiver's image data. This is the icon
* that is associated with the receiver in the operating
* system.
*
* @return the image data for the program, may be null
*/
public ImageData getImageData() {
if (iconPath == null) return null;
ImageData data = null;
int /*long*/ icon_theme =GTK.gtk_icon_theme_get_default();
byte[] icon = Converter.wcsToMbcs (iconPath, true);
int /*long*/ gicon = OS.g_icon_new_for_string(icon, null);
if (gicon != 0) {
int /*long*/ gicon_info = GTK.gtk_icon_theme_lookup_by_gicon (icon_theme, gicon, 16/*size*/, 0);
if (gicon_info != 0) {
int /*long*/ pixbuf = GTK.gtk_icon_info_load_icon(gicon_info, null);
if (pixbuf != 0) {
int stride = GDK.gdk_pixbuf_get_rowstride(pixbuf);
int /*long*/ pixels = GDK.gdk_pixbuf_get_pixels(pixbuf);
int height = GDK.gdk_pixbuf_get_height(pixbuf);
int width = GDK.gdk_pixbuf_get_width(pixbuf);
boolean hasAlpha = GDK.gdk_pixbuf_get_has_alpha(pixbuf);
byte[] srcData = new byte[stride * height];
C.memmove(srcData, pixels, srcData.length);
OS.g_object_unref(pixbuf);
if (hasAlpha) {
PaletteData palette = new PaletteData(0xFF000000, 0xFF0000, 0xFF00);
data = new ImageData(width, height, 32, palette, 4, srcData);
data.bytesPerLine = stride;
int s = 3, a = 0;
byte[] alphaData = new byte[width*height];
for (int y=0; y= OS.VERSION(3, 8, 0)) {
OS.g_object_unref(gicon_info);
} else {
GTK.gtk_icon_info_free(gicon_info);
}
}
OS.g_object_unref(gicon);
}
return data;
}
static Map> gio_getMimeInfo() {
/*
* The file 'globs' contain the file extensions associated to the
* mime-types. Each line that has to be parsed corresponds to a
* different extension of a mime-type. The template of such line is -
* application/pdf:*.pdf
*/
Path path = Paths.get("/usr/share/mime/globs");
long lastModified = 0;
try {
lastModified = Files.getLastModifiedTime(path).toMillis();
} catch (IOException e) {
// ignore and reparse the file
}
if (modTime != 0 && modTime == lastModified) {
return mimeTable;
} else {
try {
mimeTable = new HashMap<>();
modTime = lastModified;
for (String line : Files.readAllLines(path)) {
int separatorIndex = line.indexOf(':');
if (separatorIndex > 0) {
List mimeTypes = new ArrayList<>();
String mimeType = line.substring(0, separatorIndex);
String extensionFormat = line.substring(separatorIndex + 1);
int extensionIndex = extensionFormat.indexOf(".");
if (extensionIndex > 0) {
String extension = extensionFormat.substring(extensionIndex);
if (mimeTable.containsKey(extension)) {
/*
* If mimeType already exists, it is required to
* update the existing key (mime-type) with the
* new extension.
*/
List value = mimeTable.get(extension);
mimeTypes.addAll(value);
}
mimeTypes.add(mimeType);
mimeTable.put(extension, mimeTypes);
}
}
}
return mimeTable;
} catch (IOException e) {
}
}
return null;
}
static String gio_getMimeType(String extension) {
String mimeType = null;
Map> h = gio_getMimeInfo();
if (h != null && h.containsKey(extension)) {
List mimeTypes = h.get(extension);
mimeType = mimeTypes.get(0);
}
return mimeType;
}
static Program gio_getProgram(Display display, String mimeType) {
Program program = null;
byte[] mimeTypeBuffer = Converter.wcsToMbcs (mimeType, true);
int /*long*/ application = OS.g_app_info_get_default_for_type (mimeTypeBuffer, false);
if (application != 0) {
program = gio_getProgram(display, application);
}
return program;
}
static Program gio_getProgram (Display display, int /*long*/ application) {
Program program = new Program();
program.display = display;
int length;
byte[] buffer;
int /*long*/ applicationName = OS.g_app_info_get_name (application);
if (applicationName != 0) {
length = C.strlen (applicationName);
if (length > 0) {
buffer = new byte [length];
C.memmove (buffer, applicationName, length);
program.name = new String (Converter.mbcsToWcs (buffer));
}
}
int /*long*/ applicationCommand = OS.g_app_info_get_executable (application);
if (applicationCommand != 0) {
length = C.strlen (applicationCommand);
if (length > 0) {
buffer = new byte [length];
C.memmove (buffer, applicationCommand, length);
program.command = new String (Converter.mbcsToWcs (buffer));
}
}
program.gioExpectUri = OS.g_app_info_supports_uris(application);
int /*long*/ icon = OS.g_app_info_get_icon(application);
if (icon != 0) {
int /*long*/ icon_name = OS.g_icon_to_string(icon);
if (icon_name != 0) {
length = C.strlen(icon_name);
if (length > 0) {
buffer = new byte[length];
C.memmove(buffer, icon_name, length);
program.iconPath = new String(Converter.mbcsToWcs(buffer));
}
OS.g_free(icon_name);
}
OS.g_object_unref(icon);
}
return program.command != null ? program : null;
}
/*
* API: When support for multiple displays is added, this method will
* become public and the original method above can be deprecated.
*/
static Program[] getPrograms(Display display) {
int /*long*/ applicationList = OS.g_app_info_get_all ();
int /*long*/ list = applicationList;
Program program;
LinkedHashSet programs = new LinkedHashSet<>();
while (list != 0) {
int /*long*/ application = OS.g_list_data(list);
if (application != 0) {
//TODO: Should the list be filtered or not?
// if (OS.g_app_info_should_show(application)) {
program = gio_getProgram(display, application);
if (program != null) programs.add(program);
// }
}
list = OS.g_list_next(list);
}
if (applicationList != 0) OS.g_list_free(applicationList);
return programs.toArray(new Program[programs.size()]);
}
static boolean isExecutable(String fileName) {
byte[] fileNameBuffer = Converter.wcsToMbcs (fileName, true);
if (OS.g_file_test(fileNameBuffer, OS.G_FILE_TEST_IS_DIR)) return false;
if (!OS.g_file_test(fileNameBuffer, OS.G_FILE_TEST_IS_EXECUTABLE)) return false;
int /*long*/ file = OS.g_file_new_for_path (fileNameBuffer);
boolean result = false;
if (file != 0) {
byte[] buffer = Converter.wcsToMbcs ("*", true); //$NON-NLS-1$
int /*long*/ fileInfo = OS.g_file_query_info(file, buffer, 0, 0, 0);
if (fileInfo != 0) {
int /*long*/ contentType = OS.g_file_info_get_content_type(fileInfo);
if (contentType != 0) {
byte[] exeType = Converter.wcsToMbcs ("application/x-executable", true); //$NON-NLS-1$
result = OS.g_content_type_is_a(contentType, exeType);
if (!result) {
byte [] shellType = Converter.wcsToMbcs ("application/x-shellscript", true); //$NON-NLS-1$
result = OS.g_content_type_equals(contentType, shellType);
}
}
OS.g_object_unref(fileInfo);
}
OS.g_object_unref (file);
}
return result;
}
/**
* GIO - Launch the default program for the given file.
*/
static boolean gio_launch(String fileName) {
boolean result = false;
byte[] fileNameBuffer = Converter.wcsToMbcs (fileName, true);
int /*long*/ file = OS.g_file_new_for_commandline_arg (fileNameBuffer);
if (file != 0) {
int /*long*/ uri = OS.g_file_get_uri (file);
if (uri != 0) {
result = OS.g_app_info_launch_default_for_uri (uri, 0, 0);
OS.g_free(uri);
}
OS.g_object_unref (file);
}
return result;
}
/**
* GIO - Execute the program for the given file.
*/
boolean gio_execute(String fileName) {
boolean result = false;
byte[] commandBuffer = Converter.wcsToMbcs (command, true);
byte[] nameBuffer = Converter.wcsToMbcs (name, true);
int /*long*/ application = OS.g_app_info_create_from_commandline(commandBuffer, nameBuffer, gioExpectUri
? OS.G_APP_INFO_CREATE_SUPPORTS_URIS : OS.G_APP_INFO_CREATE_NONE, 0);
if (application != 0) {
byte[] fileNameBuffer = Converter.wcsToMbcs (fileName, true);
int /*long*/ file = 0;
if (fileName.length() > 0) {
if (OS.g_app_info_supports_uris (application)) {
file = OS.g_file_new_for_uri (fileNameBuffer);
} else {
file = OS.g_file_new_for_path (fileNameBuffer);
}
}
int /*long*/ list = 0;
if (file != 0) list = OS.g_list_append (0, file);
result = OS.g_app_info_launch (application, list, 0, 0);
if (list != 0) {
OS.g_list_free (list);
OS.g_object_unref (file);
}
OS.g_object_unref (application);
}
return result;
}
/**
* Answer all program extensions in the operating system. Note
* that a Display
must already exist to guarantee
* that this method returns an appropriate result.
*
* @return an array of extensions
*/
public static String[] getExtensions() {
Map> mimeInfo = gio_getMimeInfo();
if (mimeInfo == null) return new String[0];
/* Create a unique set of the file extensions. */
List extensions = new ArrayList<>(mimeInfo.keySet());
/* Return the list of extensions. */
return extensions.toArray(new String[extensions.size()]);
}
/**
* Launches the operating system executable associated with the file or
* URL (http:// or https://). If the file is an executable then the
* executable is launched. Note that a Display
must already
* exist to guarantee that this method returns an appropriate result.
*
* @param fileName the file or program name or URL (http:// or https://)
* @return true
if the file is launched, otherwise false
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT when fileName is null
*
*/
public static boolean launch(String fileName) {
return launch(Display.getCurrent(), fileName, null);
}
/**
* Launches the operating system executable associated with the file or
* URL (http:// or https://). If the file is an executable then the
* executable is launched. The program is launched with the specified
* working directory only when the workingDir
exists and
* fileName
is an executable.
* Note that a Display
must already exist to guarantee
* that this method returns an appropriate result.
*
* @param fileName the file name or program name or URL (http:// or https://)
* @param workingDir the name of the working directory or null
* @return true
if the file is launched, otherwise false
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT when fileName is null
*
*
* @since 3.6
*/
public static boolean launch (String fileName, String workingDir) {
return launch(Display.getCurrent(), fileName, workingDir);
}
/*
* API: When support for multiple displays is added, this method will
* become public and the original method above can be deprecated.
*/
static boolean launch (Display display, String fileName, String workingDir) {
if (fileName == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
if (workingDir != null && isExecutable(fileName)) {
try {
Compatibility.exec (new String [] {fileName}, null, workingDir);
return true;
} catch (IOException e) {
return false;
}
}
if (gio_launch (fileName)) return true;
int index = fileName.lastIndexOf ('.');
if (index != -1) {
String extension = fileName.substring (index);
Program program = Program.findProgram (display, extension);
if (program != null && program.execute (fileName)) return true;
}
String lowercaseName = fileName.toLowerCase ();
if (lowercaseName.startsWith (PREFIX_HTTP) || lowercaseName.startsWith (PREFIX_HTTPS)) {
Program program = Program.findProgram (display, ".html"); //$NON-NLS-1$
if (program == null) {
program = Program.findProgram (display, ".htm"); //$NON-NLS-1$
}
if (program != null && program.execute (fileName)) return true;
}
/* If the above launch attempts didn't launch the file, then try with exec().*/
try {
Compatibility.exec (new String [] {fileName}, null, workingDir);
return true;
} catch (IOException e) {
return false;
}
}
/**
* Compares the argument to the receiver, and returns true
* if they represent the same object using a class
* specific comparison.
*
* @param other the object to compare with this object
* @return true
if the object is the same as this object and false
otherwise
*
* @see #hashCode()
*/
@Override
public boolean equals(Object other) {
if (this == other) return true;
if (!(other instanceof Program)) return false;
Program program = (Program)other;
return display == program.display && name.equals(program.name) && command.equals(program.command)
&& gioExpectUri == program.gioExpectUri;
}
/**
* Executes the program with the file as the single argument
* in the operating system. It is the responsibility of the
* programmer to ensure that the file contains valid data for
* this program.
*
* @param fileName the file or program name
* @return true
if the file is launched, otherwise false
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT when fileName is null
*
*/
public boolean execute(String fileName) {
if (fileName == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
return gio_execute(fileName);
}
/**
* Returns the receiver's name. This is as short and
* descriptive a name as possible for the program. If
* the program has no descriptive name, this string may
* be the executable name, path or empty.
*
* @return the name of the program
*/
public String getName() {
return name;
}
/**
* Returns an integer hash code for the receiver. Any two
* objects that return true
when passed to
* equals
must return the same value for this
* method.
*
* @return the receiver's hash
*
* @see #equals(Object)
*/
@Override
public int hashCode() {
return name.hashCode() ^ command.hashCode();
}
/**
* Returns a string containing a concise, human-readable
* description of the receiver.
*
* @return a string representation of the program
*/
@Override
public String toString() {
return "Program {" + name + "}";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy