/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/util/org/apache/slide/util/launcher/Generator.java,v 1.1 2004/03/25 16:18:12 juergen Exp $
 * $Revision: 1.1 $
 * $Date: 2004/03/25 16:18:12 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.slide.util.launcher;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.apache.slide.util.Files;
import org.apache.slide.util.IO;
import org.apache.slide.util.Properties;
import org.apache.slide.util.Strings;
import org.apache.slide.util.XAssertionFailed;
import org.apache.slide.util.os.Platform;

/**
 * Generates a launch script
 */
public class Generator {
    private static final String BASEDIR = "BASEDIR";
    
    private final File dir;
    private final String name; /** of the script, without extension */
    private final File props;
    private final File jar;
    /** Environment to be turnd into -D stuff by the launch script. variable -> property mapping. */
    private final Properties env;
    private final String vmargs;
    /** always slashes; relative to script locations (not properties location!); may be null */
    private final String nativeLib;

    private final IO io;
    
    public Generator(File dir, String name, File props, File jar, Properties env, String vmargs, String nativeLib) {
        this.dir = dir;
        this.name = name;
        this.props = props;
        this.env = env;
        this.jar = jar;
        this.nativeLib = nativeLib;
        this.io = new IO();
        this.vmargs = vmargs;
    }
    
    public void run() throws IOException {
        run(Platform.UNIX);
        run(Platform.WINDOWS);
    }
    
    private void run(Platform platform) throws IOException {
        String script;
        
        script = getTemplate(platform.scriptSuffix);
        script = replace(script, platform);
        script = Strings.replace(script, Platform.CURRENT.lineSeparator, platform.lineSeparator);
        io.write(new File(dir, name + platform.scriptSuffix), script);
    }
    
    private String getTemplate(String extension) throws IOException {
        String name;
        InputStream src;
        
        // use a suffix that part of the resources we include in the file
        name = "template" + extension + ".properties";
        src = getClass().getResourceAsStream(name);
        if (src == null) {
            throw new XAssertionFailed("resource not found: " + name);
        }
        return io.readString(src);
    }
    
    public String replace(String template, Platform platform) throws IOException {
        Properties p;
        
        p = new Properties();
        p.add("vmargs", vmargs);
        p.add("file", Files.getRelative(dir, props, platform.fileSeparator));
        p.add("env", getEnvironment(platform));
        p.add("jar", Files.getRelative(dir, jar, platform.fileSeparator));
        p.add("fixed", setNative(platform) + checkEnvironment(platform));
        return p.replace(template);
    }
    
    private String checkEnvironment(Platform platform) {
        String[] keys;
        StringBuffer result;
        int i;
        
        result = new StringBuffer();
        if (platform == Platform.WINDOWS) {
            keys = env.getAll();
            for (i = 0; i < keys.length; i++) {
                checkQuotes(env.get(keys[i]), result);
            }
        }
        return result.toString();
    }
    
    private void checkQuotes(String name, StringBuffer result) {
        result.append("if %" + name + "%x == %" + name + ":\"=%x goto :" + name + "_OK");
        result.append(Platform.WINDOWS.lineSeparator);
        result.append("echo Environment variable " + name + " must not contain quotes: %" + name + "%");
        result.append(Platform.WINDOWS.lineSeparator);
        result.append("echo Please removes the quotes an try again");
        result.append(Platform.WINDOWS.lineSeparator);
        result.append("goto :end");
        result.append(Platform.WINDOWS.lineSeparator);
        result.append(":" + name + "_OK");
        result.append(Platform.WINDOWS.lineSeparator);
    }
    
    private String setNative(Platform platform) {
        String str;
        
        if (nativeLib == null) {
            return "";
        }
        str = platform.variableRef(BASEDIR) + nativeLib.replace('/', platform.fileSeparator);
        return platform.variableSet(platform.nativePathVariable,
                                    str + platform.pathSeparator + platform.variableRef(platform.nativePathVariable))
            + platform.lineSeparator;
    }
    
    private String getEnvironment(Platform platform) {
        StringBuffer buffer;
        String[] keys;
        String key;
        String value;
        int i;
        
        keys = env.getAll();
        buffer = new StringBuffer();
        for (i = 0; i < keys.length; i++) {
            key = keys[i];
            value = env.get(key);
            if (i > 0) {
                buffer.append(' ');
            }
            buffer.append("\"-D");
            buffer.append(key);
            buffer.append('=');
            buffer.append(platform.variableRef(value));
            buffer.append('"');
        }
        return buffer.toString();
    }
}
