/*
 * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.net.www;
import java.net.URL;
import java.io.*;
import java.util.StringTokenizer;
import sun.security.action.GetPropertyAction;

class MimeLauncher extends Thread {
    java.net.URLConnection uc;
    MimeEntry m;
    String genericTempFileTemplate;
    InputStream is;
    String execPath;

    MimeLauncher (MimeEntry M, java.net.URLConnection uc,
                  InputStream is, String tempFileTemplate, String threadName) throws ApplicationLaunchException {
        super(null, null, threadName, 0, false);
        m = M;
        this.uc = uc;
        this.is = is;
        genericTempFileTemplate = tempFileTemplate;

        /* get the application to launch */
        String launchString = m.getLaunchString();

        /* get a valid path to launch application - sets
           the execPath instance variable with the correct path.
         */
        if (!findExecutablePath(launchString)) {
            /* strip off parameters i.e %s */
            String appName;
            int index = launchString.indexOf(' ');
            if (index != -1) {
                appName = launchString.substring(0, index);
            }
            else {
                appName = launchString;
            }
            throw new ApplicationLaunchException(appName);
        }
    }

    protected String getTempFileName(URL url, String template) {
        String tempFilename = template;

        // Replace all but last occurrance of "%s" with timestamp to insure
        // uniqueness.  There's a subtle behavior here: if there is anything
        // _after_ the last "%s" we need to append it so that unusual launch
        // strings that have the datafile in the middle can still be used.
        int wildcard = tempFilename.lastIndexOf("%s");
        String prefix = tempFilename.substring(0, wildcard);

        String suffix = "";
        if (wildcard < tempFilename.length() - 2) {
            suffix = tempFilename.substring(wildcard + 2);
        }

        long timestamp = System.currentTimeMillis()/1000;
        int argIndex = 0;
        while ((argIndex = prefix.indexOf("%s")) >= 0) {
            prefix = prefix.substring(0, argIndex)
                + timestamp
                + prefix.substring(argIndex + 2);
        }

        // Add a file name and file-extension if known
        String filename = url.getFile();

        String extension = "";
        int dot = filename.lastIndexOf('.');

        // BugId 4084826:  Temp MIME file names not always valid.
        // Fix:  don't allow slashes in the file name or extension.
        if (dot >= 0 && dot > filename.lastIndexOf('/')) {
            extension = filename.substring(dot);
        }

        filename = "HJ" + url.hashCode();

        tempFilename = prefix + filename + timestamp + extension + suffix;

        return tempFilename;
    }

    public void run() {
        try {
            String ofn = m.getTempFileTemplate();
            if (ofn == null) {
                ofn = genericTempFileTemplate;
            }

            ofn = getTempFileName(uc.getURL(), ofn);
            try {
                OutputStream os = new FileOutputStream(ofn);
                byte buf[] = new byte[2048];
                int i = 0;
                try {
                    while ((i = is.read(buf)) >= 0) {
                        os.write(buf, 0, i);
                    }
                } catch(IOException e) {
                  //System.err.println("Exception in write loop " + i);
                  //e.printStackTrace();
                } finally {
                    os.close();
                    is.close();
                }
            } catch(IOException e) {
              //System.err.println("Exception in input or output stream");
              //e.printStackTrace();
            }

            int inx = 0;
            String c = execPath;
            while ((inx = c.indexOf("%t")) >= 0) {
                c = c.substring(0, inx) + uc.getContentType()
                    + c.substring(inx + 2);
            }

            boolean substituted = false;
            while ((inx = c.indexOf("%s")) >= 0) {
                c = c.substring(0, inx) + ofn + c.substring(inx + 2);
                substituted = true;
            }
            if (!substituted)
                c = c + " <" + ofn;

            // System.out.println("Execing " +c);

            Runtime.getRuntime().exec(c);
        } catch(IOException e) {
        }
    }

    /* This method determines the path for the launcher application
       and sets the execPath instance variable.  It uses the exec.path
       property to obtain a list of paths that is in turn used to
       location the application.  If a valid path is not found, it
       returns false else true.  */
    private boolean findExecutablePath(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }

        String command;
        int index = str.indexOf(' ');
        if (index != -1) {
            command = str.substring(0, index);
        }
        else {
            command = str;
        }

        File f = new File(command);
        if (f.isFile()) {
            // Already executable as it is
            execPath = str;
            return true;
        }

        String execPathList;
        execPathList = GetPropertyAction.privilegedGetProperty("exec.path");
        if (execPathList == null) {
            // exec.path property not set
            return false;
        }

        StringTokenizer iter = new StringTokenizer(execPathList, "|");
        while (iter.hasMoreElements()) {
            String prefix = (String)iter.nextElement();
            String fullCmd = prefix + File.separator + command;
            f = new File(fullCmd);
            if (f.isFile()) {
                execPath = prefix + File.separator + str;
                return true;
            }
        }

        return false; // application not found in exec.path
    }
}