org.jcurl.core.jnlp.FileDialogWebstart.java Source code

Java tutorial

Introduction

Here is the source code for org.jcurl.core.jnlp.FileDialogWebstart.java

Source

/*
 * jcurl java curling software framework http://www.jcurl.org
 * Copyright (C) 2005-2009 M. Rohrmoser
 * 
 * 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.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package org.jcurl.core.jnlp;

import java.awt.Component;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.apache.commons.logging.Log;
import org.jcurl.core.jnlp.FileDialogService.Contents;
import org.jcurl.core.jnlp.FileDialogService.OpenService;
import org.jcurl.core.jnlp.FileDialogService.SaveService;
import org.jcurl.core.log.JCLoggerFactory;

/**
 * Fully reflection based implementation for use in untrusted environments to
 * avoid compile-time dependency.
 * 
 * https://java.sun.com/products/javawebstart/1.0.1/javadoc/javax/jnlp/FileOpenService.html
 * https://java.sun.com/products/javawebstart/1.0.1/javadoc/javax/jnlp/FileSaveService.html
 * 
 * @author <a href="mailto:m@jcurl.org">M. Rohrmoser </a>
 * @version $Id$
 */
class FileDialogWebstart implements OpenService, SaveService {

    private static final Log log = JCLoggerFactory.getLogger(FileDialogWebstart.class);

    /**
     * Dynamic Interface Wrapper (or dynamic Delegate) using
     * {@link Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)}
     * mapping only identical methods.
     * <p>
     * The two interfaces must have identical methods!
     * </p>
     * 
     * @param src
     *            the source instance (the one to wrap)
     * @param dstT
     *            destination interface type
     * @return target interface instance.
     */
    static Object wrap(final Object src, final Class<?> dstT) {
        if (log.isDebugEnabled())
            log.debug("wrap(" + src + ", " + dstT + ")");
        if (src == null)
            return null;
        return Proxy.newProxyInstance(FileDialogWebstart.class.getClassLoader(), new Class[] { dstT },
                new InvocationHandler() {
                    public Object invoke(final Object proxy, final Method method, final Object[] args)
                            throws Throwable {
                        final Class<?> srcT = src.getClass();
                        // Wrap ALL Methods (also getClass, equals, toString,
                        // ...)
                        final Method dstM = srcT.getMethod(method.getName(), method.getParameterTypes());
                        if (log.isDebugEnabled()) {
                            log.debug("proxy: " + proxy.getClass());
                            log.debug("method: " + method);
                            log.debug("args: " + args);
                            log.debug("srcT: " + srcT);
                            log.debug("dstM: " + dstM);
                        }
                        final Object ret = dstM.invoke(src, args);
                        if (log.isDebugEnabled())
                            log.debug("ret: " + ret);
                        return ret;
                    }
                });
    }

    private final Object fos;

    private final Object fss;

    private final Method open;

    private final Method save;

    private final Method saveAs;

    private final Class<?> tco;

    FileDialogWebstart() {
        try {
            tco = Class.forName("javax.jnlp.FileContents");
            if (log.isDebugEnabled()) {
                final Method[] ms = tco.getMethods();
                for (int i = ms.length - 1; i >= 0; i--)
                    log.debug(ms[i]);
            }
            // FileOpenService
            fos = Class.forName("javax.jnlp.ServiceManager").getMethod("lookup", new Class[] { String.class })
                    .invoke(null, new Object[] { "javax.jnlp.FileOpenService" });
            log.debug(fos);
            if (log.isDebugEnabled()) {
                final Method[] ms = fos.getClass().getMethods();
                for (int i = ms.length - 1; i >= 0; i--)
                    log.debug(ms[i]);
            }
            open = fos.getClass().getMethod("openFileDialog", new Class[] { String.class, String[].class });
            log.debug(open);
            // FileSaveService
            fss = Class.forName("javax.jnlp.ServiceManager").getMethod("lookup", new Class[] { String.class })
                    .invoke(null, new Object[] { "javax.jnlp.FileSaveService" });
            log.debug(fss);
            if (log.isDebugEnabled()) {
                final Method[] ms = fss.getClass().getMethods();
                for (int i = ms.length - 1; i >= 0; i--)
                    log.debug(ms[i]);
            }
            saveAs = fss.getClass().getMethod("saveAsFileDialog",
                    new Class[] { String.class, String[].class, tco });
            log.debug(saveAs);
            save = fss.getClass().getMethod("saveFileDialog",
                    new Class[] { String.class, String[].class, InputStream.class, String.class });
            log.debug(save);
        } catch (final Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Contents openFileDialog(final String pathHint, final String[] extensions, final Component parent) {
        try {
            if (log.isDebugEnabled())
                log.debug("openFileDialog(" + pathHint + ", " + to(extensions) + ", " + parent + ")");
            return (Contents) wrap(open.invoke(fos, new Object[] { pathHint, extensions }), Contents.class);
        } catch (final Exception e) {
            throw new RuntimeException("Unhandled", e);
        }
    }

    public Contents saveAsFileDialog(final String pathHint, final String[] extensions, final Contents contents,
            final Component parent) {
        try {
            if (log.isDebugEnabled())
                log.debug(pathHint + ", " + to(extensions) + ", " + contents + ", " + parent);
            return (Contents) wrap(saveAs.invoke(fss, new Object[] { pathHint, extensions, wrap(contents, tco) }),
                    Contents.class);
        } catch (final Exception e) {
            throw new RuntimeException("Unhandled", e);
        }
    }

    public Contents saveFileDialog(final String pathHint, final String[] extensions, final InputStream stream,
            final String name, final Component parent) {
        try {
            if (log.isDebugEnabled())
                log.debug(pathHint + ", " + to(extensions) + ", " + stream + ", " + name + ", " + parent);
            return (Contents) wrap(save.invoke(fss, new Object[] { pathHint, extensions, stream, name }),
                    Contents.class);
        } catch (final Exception e) {
            throw new RuntimeException("Unhandled", e);
        }
    }

    private String to(final String[] a) {
        final StringBuilder b = new StringBuilder();
        for (final String element : a)
            b.append(element).append(" ");
        return b.toString().trim();
    }
}