001/*
002 * (C) Copyright 2006-2015 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 */
018package org.nuxeo.ecm.platform.pictures.tiles.gimp;
019
020import java.io.BufferedReader;
021import java.io.IOException;
022import java.io.InputStreamReader;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026
027import org.apache.commons.lang3.SystemUtils;
028
029import org.nuxeo.ecm.platform.pictures.tiles.service.PictureTilingComponent;
030
031/**
032 * Helper class to execute a Gimp procedure
033 *
034 * @author tiry
035 */
036public class GimpExecutor {
037
038    private static String gimpOpts = "--no-interface --batch ";
039
040    private static String gimpQuit = " --batch '(gimp-quit 1)'";
041
042    private static String GIMPLOG_PREFIX = "*NXGIMPLOG*";
043
044    protected static boolean useQuickExec = false;
045
046    private static String gimpPath;
047
048    public static void setUseQuickExec(boolean quickExec) {
049        useQuickExec = quickExec;
050    }
051
052    protected static Map<String, String> execCmd(String[] cmd) throws IOException {
053        long t0 = System.currentTimeMillis();
054        Process p1 = Runtime.getRuntime().exec(cmd);
055        int exitValue;
056        try {
057            exitValue = p1.waitFor();
058        } catch (InterruptedException e) {
059            // reset interrupted status
060            Thread.currentThread().interrupt();
061            // continue interrupt
062            throw new RuntimeException(e);
063        }
064
065        Map<String, String> result = new HashMap<>();
066
067        if (exitValue == 0) {
068            BufferedReader stdInput = new BufferedReader(new InputStreamReader(p1.getInputStream()));
069            String strLine;
070
071            while ((strLine = stdInput.readLine()) != null) {
072
073                if (strLine.startsWith(GIMPLOG_PREFIX)) {
074                    String resLine = strLine.substring(GIMPLOG_PREFIX.length());
075                    String[] res = resLine.split(":");
076                    result.put(res[0].trim(), res[1].trim());
077                }
078            }
079        }
080        long t1 = System.currentTimeMillis();
081        result.put("JavaProcessExecTime", t1 - t0 + "ms");
082
083        return result;
084    }
085
086    protected static Map<String, String> quickExecCmd(String[] cmd) throws IOException {
087        long t0 = System.currentTimeMillis();
088        Process p1 = Runtime.getRuntime().exec(cmd);
089
090        boolean execTerminated = false;
091        Map<String, String> result = new HashMap<>();
092
093        while (!execTerminated) {
094            BufferedReader stdInput = new BufferedReader(new InputStreamReader(p1.getInputStream()));
095            String strLine;
096
097            while ((strLine = stdInput.readLine()) != null) {
098
099                if (strLine.startsWith(GIMPLOG_PREFIX)) {
100                    String resLine = strLine.substring(GIMPLOG_PREFIX.length());
101                    String[] res = resLine.split(":");
102                    result.put(res[0].trim(), res[1].trim());
103                }
104            }
105
106            // check if we can exit
107            if (result.containsKey("ReturnCode")) {
108                execTerminated = true;
109            }
110
111            try {
112                int exitCode = p1.exitValue();
113                execTerminated = true;
114            } catch (IllegalThreadStateException e) {
115                // process not yet terminated
116            }
117        }
118        long t1 = System.currentTimeMillis();
119        result.put("JavaProcessExecTime", t1 - t0 + "ms");
120        return result;
121    }
122
123    public static Map<String, String> exec(String procName, List<Object> params) throws IOException {
124        StringBuffer procStringBuf = new StringBuffer();
125
126        procStringBuf.append("'(");
127        procStringBuf.append(procName);
128        procStringBuf.append(" RUN-NONINTERACTIVE ");
129
130        for (Object p : params) {
131            if (p instanceof String) {
132                String pStr = (String) p;
133                procStringBuf.append(" \"");
134                procStringBuf.append(pStr);
135                procStringBuf.append("\"");
136            } else if (p instanceof Integer) {
137                Integer pInt = (Integer) p;
138                procStringBuf.append(" ");
139                procStringBuf.append(pInt.toString());
140            }
141        }
142
143        procStringBuf.append(")'");
144        String procString = procStringBuf.toString();
145
146        // init command script
147        String[] cmd = { "/bin/sh", "-c", getGimpPath() + " " + gimpOpts + procString + gimpQuit + " 2>&1" };
148
149        if (SystemUtils.IS_OS_WINDOWS) {
150            cmd[0] = "cmd";
151            cmd[1] = "/C";
152        }
153
154        if (useQuickExec) {
155            return quickExecCmd(cmd);
156        } else {
157            return execCmd(cmd);
158        }
159    }
160
161    protected static String getGimpPath() {
162        if ((gimpPath == null) || ("".equals(gimpPath))) {
163            if (SystemUtils.IS_OS_WINDOWS) {
164                gimpPath = PictureTilingComponent.getEnvValue("GimpExecutable", "gimp.exe");
165                // gimpPath="gimp.exe";
166            } else {
167                gimpPath = PictureTilingComponent.getEnvValue("GimpExecutable", "gimp");
168                // gimpPath="gimp";
169            }
170        }
171        return gimpPath;
172    }
173
174}