org.stanwood.media.info.MediaFileInfoFetcher.java Source code

Java tutorial

Introduction

Here is the source code for org.stanwood.media.info.MediaFileInfoFetcher.java

Source

/*
 *  Copyright (C) 2008-2011  John-Paul.Stanford <dev@stanwood.org.uk>
 *
 *  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 3 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, see <http://www.gnu.org/licenses/>.
 */
package org.stanwood.media.info;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.text.MessageFormat;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.Executor;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Level;
import org.stanwood.media.collections.LRUMapCache;
import org.stanwood.media.logging.LoggerOutputStream;
import org.stanwood.media.logging.StanwoodException;
import org.stanwood.media.util.FileHelper;
import org.stanwood.media.util.NativeHelper;
import org.stanwood.media.xml.XMLParser;
import org.stanwood.media.xml.XMLParserException;
import org.w3c.dom.Document;

/**
 * Used to find information about a media file that is containted within the
 * file.
 */
public class MediaFileInfoFetcher {

    private final static Log log = LogFactory.getLog(MediaFileInfoFetcher.class);

    private String mediaInfoCmdPath;

    private LRUMapCache<File, IMediaFileInfo> infoCache;

    /**
     * The constructor
     * @param nativeDir The native application directory
     * @throws StanwoodException Thrown if their is a problem finding the native apps
     */
    public MediaFileInfoFetcher(File nativeDir) throws StanwoodException {
        mediaInfoCmdPath = NativeHelper.getNativeApplication(nativeDir, "mediainfo"); //$NON-NLS-1$
        boolean errors = false;
        if (!checkCommand(mediaInfoCmdPath)) {
            log.error(MessageFormat.format(Messages.getString("MediaFileInfoFetcher.UNABLE_EXEC_COMMAND"), //$NON-NLS-1$
                    mediaInfoCmdPath));
            errors = true;
        }
        if (errors) {
            throw new StanwoodException(Messages.getString("MediaFileInfoFetcher.RequiredCommandNotFound")); //$NON-NLS-1$
        }

        infoCache = new LRUMapCache<File, IMediaFileInfo>(100);
    }

    /**
     * Used to get information on a media file
     * @param file The media file
     * @return The information object. If this is a video file then it will be
     *         of type {@link IVideoFileInfo}.
     * @throws StanwoodException Thrown if their are any problems
     */
    public IMediaFileInfo getInformation(File file) throws StanwoodException {
        IMediaFileInfo info = infoCache.get(file);
        if (info == null) {
            try {
                File infoFile = FileHelper.createTempFile("output", ".xml"); //$NON-NLS-1$ //$NON-NLS-2$
                if (!infoFile.delete() && infoFile.exists()) {
                    throw new IOException(MessageFormat
                            .format(Messages.getString("MediaFileInfoFetcher.UnableDeleteFile"), infoFile)); //$NON-NLS-1$
                }
                try {
                    getCommandOutput(true, true, true, mediaInfoCmdPath, "--Output=XML", "--Full", //$NON-NLS-1$//$NON-NLS-2$
                            "--LogFile=" + infoFile.getAbsolutePath(), file.getAbsolutePath()); //$NON-NLS-1$
                } catch (StanwoodException e) {
                    log.error(MessageFormat.format(Messages.getString("MediaFileInfoFetcher.UnableReadMediaInfo"), //$NON-NLS-1$
                            file), e);
                    return null;
                }
                try {
                    Document dom = XMLParser.parse(infoFile, null);
                    if (!infoFile.delete() && infoFile.exists()) {
                        throw new IOException(MessageFormat
                                .format(Messages.getString("MediaFileInfoFetcher.UnableDeleteFile"), infoFile)); //$NON-NLS-1$
                    }
                    info = MediaInfoFactory.createMediaInfo(file, dom);
                    infoCache.put(file, info);
                } catch (XMLParserException e) {
                    log.error(MessageFormat.format(Messages.getString("MediaFileInfoFetcher.UnableGetMediaInfo"), //$NON-NLS-1$
                            infoFile), e);
                    return null;
                }
            } catch (IOException e) {
                throw new StanwoodException(Messages.getString("MediaFileInfoFetcher.UnableCreateTmpFile")); //$NON-NLS-1$
            }
        }
        return info;
    }

    private boolean checkCommand(String cmd) {
        try {
            boolean capture = !log.isDebugEnabled();
            getCommandOutput(capture, capture, false, cmd);
        } catch (StanwoodException e) {
            if (log.isDebugEnabled()) {
                log.debug("Command failed", e); //$NON-NLS-1$
            }
            return false;
        }
        return true;
    }

    private String getCommandOutput(boolean captureStdout, boolean captureStderr, boolean failOnExitCode,
            String command, Object... args) throws StanwoodException {
        CommandLine cmdLine = new CommandLine(command);
        for (Object arg : args) {
            if (arg instanceof File) {
                cmdLine.addArgument(((File) arg).getAbsolutePath(), false);
            } else if (arg instanceof String) {
                cmdLine.addArgument((String) arg, false);
            }
        }
        if (log.isDebugEnabled()) {
            log.debug("About to execute: " + cmdLine.toString()); //$NON-NLS-1$
        }
        Executor exec = new DefaultExecutor();
        exec.setExitValues(new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, -1 });

        try {
            ByteArrayOutputStream capture = new ByteArrayOutputStream();
            OutputStream out;
            if (captureStdout) {
                out = capture;
            } else {
                out = new LoggerOutputStream(Level.INFO);
            }
            OutputStream err;
            ;
            if (captureStderr) {
                err = capture;
            } else {
                err = new LoggerOutputStream(Level.ERROR);
            }
            exec.setStreamHandler(new PumpStreamHandler(out, err));
            int exitCode = exec.execute(cmdLine);
            if (failOnExitCode && exitCode != 0) {
                log.error(capture.toString());
                throw new StanwoodException(MessageFormat
                        .format(Messages.getString("MediaFileInfoFetcher.NON_ZERO"), exitCode, cmdLine.toString())); //$NON-NLS-1$
            }
            return capture.toString();
        } catch (IOException e) {
            throw new StanwoodException(MessageFormat
                    .format(Messages.getString("MediaFileInfoFetcher.UnableExecuteSysCmd"), cmdLine.toString()), e); //$NON-NLS-1$
        }
    }
}