org.openmicroscopy.shoola.env.data.model.appdata.WindowsApplicationDataExtractor.java Source code

Java tutorial

Introduction

Here is the source code for org.openmicroscopy.shoola.env.data.model.appdata.WindowsApplicationDataExtractor.java

Source

/*
 * org.openmicroscopy.shoola.env.data.model.appdata.WindowsApplicationDataExtractor 
 *
 *------------------------------------------------------------------------------
 *  Copyright (C) 2006-2012 University of Dundee & Open Microscopy Environment.
 *  All rights reserved.
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *------------------------------------------------------------------------------
 */
package org.openmicroscopy.shoola.env.data.model.appdata;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.URL;

import javax.swing.Icon;
import javax.swing.filechooser.FileSystemView;

import org.apache.commons.io.FilenameUtils;
import org.openmicroscopy.shoola.env.data.model.ApplicationData;

import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Version;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;

/**
 * Provides the Windows implementation to extract application properties using
 * the {@link LANGANDCODEPAGE} class with the <a
 * href="https://github.com/twall/jna">JNA</a> library.
 * 
 * @author Scott Littlewood, <a
 *         href="mailto:sylittlewood@dundee.ac.uk">sylittlewood@dundee.ac.uk</a>
 * @since Beta4.4
 */
public class WindowsApplicationDataExtractor implements ApplicationDataExtractor {

    /**
     * Windows specific keys for accessing application properties @see
     * http://msdn
     * .microsoft.com/en-us/library/windows/desktop/ms647464(v=vs.85).aspx
     */
    private static final String APPLICATION_PROPERTY_KEY_COMMENTS = "Comments";
    private static final String APPLICATION_PROPERTY_KEY_COMPANY_NAME = "CompanyName";
    private static final String APPLICATION_PROPERTY_KEY_FILE_DESCRIPTION = "FileDescription";
    private static final String APPLICATION_PROPERTY_KEY_FILE_VERSION = "FileVersion";
    private static final String APPLICATION_PROPERTY_KEY_INTERNAL_NAME = "InternalName";
    private static final String APPLICATION_PROPERTY_KEY_LEGAL_COPYRIGHT = "LegalCopyright";
    private static final String APPLICATION_PROPERTY_KEY_LEGAL_TRADEMARK = "LegalTrademark";
    private static final String APPLICATION_PROPERTY_KEY_ORIGINAL_FILE_NAME = "OriginalFileName";
    private static final String APPLICATION_PROPERTY_KEY_PRODUCT_NAME = "ProductName";
    private static final String APPLICATION_PROPERTY_KEY_PRODUCT_VERSION = "ProductVersion";
    private static final String APPLICATION_PROPERTY_KEY_PRIVATE_BUILD = "PrivateBuild";
    private static final String APPLICATION_PROPERTY_KEY_SPECIAL_BUILD = "SpecialBuild";

    private static final String WINDOWS_QUERYPATH_TRANSLATION = "\\VarFileInfo\\Translation";

    /** The default application location on <code>Windows</code> platform. */
    private static final String LOCATION_WINDOWS = "C:\\Program Files\\";

    /**
     * Gets the system icon for the application
     * 
     * @param file
     *            the file location of the application to retrieve the icon for
     * @return the icon associated with this application
     */
    private Icon getSystemIconFor(File file) {
        Icon icon = FileSystemView.getFileSystemView().getSystemIcon(file);

        return icon;
    }

    /**
     * Allocates a portion of memory for use by JNA
     * 
     * @param size
     *            the size of the memory to allocate
     * @return a pointer to the memory location
     */
    private Pointer allocateBuffer(int size) {
        byte[] bufferarray = new byte[size];
        Pointer buffer = new Memory(bufferarray.length);

        return buffer;
    }

    /**
     * Returns the language code page string for the application on the current
     * windows platform
     * 
     * @param applicationPath
     * @param fileVersionInfoSize
     * @return
     * @throws Exception
     */
    private String getTranslation(String applicationPath, int fileVersionInfoSize) throws Exception {
        Pointer lpData = allocateBuffer(fileVersionInfoSize);

        boolean fileVersionInfoSuccess = Version.INSTANCE.GetFileVersionInfo(applicationPath, 0,
                fileVersionInfoSize, lpData);

        if (!fileVersionInfoSuccess)
            throw new Exception("Unable to load application information");

        PointerByReference lplpBuffer = new PointerByReference();
        IntByReference puLen = new IntByReference();

        boolean verQueryValSuccess = ExecuteQuery(lpData, WINDOWS_QUERYPATH_TRANSLATION, lplpBuffer, puLen);

        if (!verQueryValSuccess)
            throw new Exception("Unable to load application information");

        LANGANDCODEPAGE lplpBufStructure = new LANGANDCODEPAGE(lplpBuffer.getValue());
        lplpBufStructure.read();

        StringBuilder hexBuilder = new StringBuilder();

        String languageAsHex = String.format("%04x", lplpBufStructure.wLanguage);
        String codePageAsHex = String.format("%04x", lplpBufStructure.wCodePage);

        hexBuilder.append(languageAsHex);
        hexBuilder.append(codePageAsHex);

        return hexBuilder.toString();
    }

    /**
     * Performs the windows specific query related to application properties
     * 
     * @param lpData
     * @param lpSubBlock
     * @param lplpBuffer
     * @param puLen
     * @return
     */
    private boolean ExecuteQuery(Pointer lpData, String lpSubBlock, PointerByReference lplpBuffer,
            IntByReference puLen) {
        return Version.INSTANCE.VerQueryValue(lpData, lpSubBlock, lplpBuffer, puLen);
    }

    /**
     * Extracts the information item with key @propertyKey from the application
     * properties found in @applicationPath
     * 
     * @param applicationPath
     * @param fileVersionInfoSize
     * @param translation
     * @param propertyKey
     * @return
     * @throws Exception
     */
    private String getFilePropertyValue(String applicationPath, int fileVersionInfoSize, String translation,
            String propertyKey) throws Exception {

        Pointer lpData = allocateBuffer(fileVersionInfoSize);

        boolean fileInfoStatusSuccess = Version.INSTANCE.GetFileVersionInfo(applicationPath, 0, fileVersionInfoSize,
                lpData);
        if (!fileInfoStatusSuccess)
            throw new Exception("Unable to load application information");

        String queryPath = "\\StringFileInfo\\" + translation + "\\" + propertyKey;

        PointerByReference lplpBuffer = new PointerByReference();
        IntByReference puLen = new IntByReference();

        boolean verQuerySuccess = ExecuteQuery(lpData, queryPath, lplpBuffer, puLen);
        if (!verQuerySuccess)
            throw new Exception("Unable to load application information");

        int descLength = puLen.getValue();

        Pointer pointerToPropertyStringValue = lplpBuffer.getValue();
        char[] charBuffer = pointerToPropertyStringValue.getCharArray(0, descLength);

        String propertyValue = new String(charBuffer);

        return propertyValue.trim();
    }

    /**
     * @return the Windows specific directory where applications are located
     */
    public String getDefaultAppDirectory() {
        return LOCATION_WINDOWS;
    }

    /**
     * Extracts the application data for the application on a windows platform
     * 
     * @param file
     *            the file pointing to the application's location on disk
     * @return the {@link ApplicationData} object representing this applications
     *         system properties
     * @throws FileNotFoundException
     *             if the file specified is null or does not exist on disk
     */
    public ApplicationData extractAppData(File file) throws Exception {

        String absPath = file.getAbsolutePath();

        if (file == null || !file.exists())
            throw new FileNotFoundException(absPath);

        Icon icon = getSystemIconFor(file);

        IntByReference dwDummy = new IntByReference(0);
        int fileVersionInfoSize = com.sun.jna.platform.win32.Version.INSTANCE.GetFileVersionInfoSize(absPath,
                dwDummy);

        String applicationName = FilenameUtils.getBaseName(absPath);

        if (fileVersionInfoSize > 0) {
            String translation = getTranslation(absPath, fileVersionInfoSize);

            String fileDescription = getFilePropertyValue(absPath, fileVersionInfoSize, translation,
                    APPLICATION_PROPERTY_KEY_FILE_DESCRIPTION);
            String productName = getFilePropertyValue(absPath, fileVersionInfoSize, translation,
                    APPLICATION_PROPERTY_KEY_PRODUCT_NAME);

            if (fileDescription != "")
                applicationName = fileDescription;
            else if (productName != "")
                applicationName = productName;
        }

        return new ApplicationData(icon, applicationName, absPath);
    }

    /**
     * @param location
     *            the location pointing to the object to be opened
     * @returns the command string to launch the default application for the
     *          file specified by {@code location}
     */
    public String[] getDefaultOpenCommandFor(URL location) {
        return new String[] { "cmd", "/c", "start", location.toString() };
    }
}