Package org.apache.harmony.tools.javah

Source Code of org.apache.harmony.tools.javah.Main

/*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You 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.harmony.tools.javah;

import java.io.File;
import java.io.FileWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.harmony.tools.ClassProvider;
import org.apache.harmony.tools.Mangler;

/**
* This is a tool that allows you to create JNI-style header files.
*/
public class Main {

    /**
     * Prints the usage information.
     */
    public static void usage() {
        System.out.println("JNI-style header files generator.");
        System.out.println();
        System.out.println("Usage: " + Main.class.getName()
                + " [options] <class names>\n");
        System.out.println("[options]");
        System.out.println("  -bootclasspath <path> The given path will be prepended to");
        System.out.println("                        the default class path.\n");
        System.out.println("  -classpath <path>     The given path will be appended to");
        System.out.println("                        the default class path.\n");
        System.out.println("  -o <file>             All the output will be redirected into");
        System.out.println("                        the specified file.\n");
        System.out.println("  -d <directory>        All the header files will be created in the specified");
        System.out.println("                        directory which will be created if it is necessary.\n");
        System.out.println("  -inner                Inner classes will be processed automatically.\n");
        System.out.println("  -verbose              Allows running commentary.\n");
        System.out.println("<class names>           A list of the fully qualified class names");
        System.out.println("                        separated by a space.");
    }

    /**
     * A convenient way to run this tool from a command line.
     */
    public static void main(String args[]) {
        if (args.length < 1) {
            usage();
            System.exit(1);
        }

        String pathSep = null;
        try {
            pathSep = System.getProperty("path.separator");
        } catch (SecurityException e) {
            // ignore
        }
       
        Set names = new HashSet();
        Map options = new HashMap();
        int i = 0;
        while (i < args.length) {
            if (args[i].equals("-bootclasspath") || args[i].equals("-classpath")) {
                String path = (String) args[i + 1];

                // We can concatenate several options, if there is no
                // security restriction; otherwise, the new option replaces
                // the old one.
                if (pathSep != null) {
                    String prevPath = (String) options.get(args[i]);
                    if (prevPath != null) {
                        path = prevPath + pathSep + path;
                    }
                }

                options.put(args[i], path);
                i++;
            } else if (args[i].equals("-d") || args[i].equals("-o")) {
                options.put(args[i], new File(args[i + 1]));
                i++;
            } else if (args[i].equals("-inner") || args[i].equals("-verbose")) {
                options.put(args[i], Boolean.valueOf(true));
            } else {
                names.add(args[i]);
            }
            i++;
        }
        System.exit(run(options, names));
    }

    /**
     * Runs a tool.
     *
     * @param options - a <code>java.util.Map</code> of the following key-value
     * pairs.
     * <p> Note, "-d" can not be specified with "-o" at the same time.
     *
     * <li> <i>key</i> - "-d"
     * <li> <i>value</i> - a <code>java.io.File</code> object which represents
     * a directory where the generated header files will be created.
     * If this directory does not exist it will be created.
     *
     * <li> <i>key</i> - "-o"
     * <li> <i>value</i> - a <code>java.io.File</code> object where
     * the output will be directed to.
     *
     * <li> <i>key</i> - "-bootclasspath"
     * <li> <i>value</i> - a <code>java.lang.String</code> which is a path
     * where bootstrap classes are located.
     *
     * <li> <i>key</i> - "-classpath"
     * <li> <i>value</i> - a <code>java.lang.String</code> which is a path
     * where classes are located.
     *
     * <li> <i>key</i> - "-inner"
     * <li> <i>value</i> - a <code>java.lang.Boolean</code> which is equal to
     * <code>true</code>, if inner classes should be processed automatically,
     * that is, as if they are specified as elements of
     * the <code>classNames</code> parameter.
     *
     * <li> <i>key</i> - "-verbose"
     * <li> <i>value</i> - a <code>java.lang.Boolean</code> which is equal to
     * <code>true</code>, if the verbose output is needed.
     *
     * @param classNames - a set of the fully qualified class names.
     * @return <code>0</code> if there is no error; <code>1</code> otherwise.
     */
    public static int run(Map options, Set classNames) {
        File outDirectory = getFile(options, "-d");
        File outFile = getFile(options, "-o");

        if (outDirectory != null && outFile != null) {
            System.err.println("Error: You can not use both -d and -o options.");
            System.err.println();
            usage();
            return 1;
        }

        String bootClasspath = getString(options, "-bootclasspath");
        String classpath = getString(options, "-classpath");

        boolean inner = getBoolean(options, "-inner");
        boolean verbose = getBoolean(options, "-verbose");

        ClassProvider classProvider = new ClassProvider(bootClasspath,
                classpath, verbose);
        try {
            String n = System.getProperty("line.separator");
            String warning =
                  "/*" + n
                + " * THE FILE HAS BEEN AUTOGENERATED BY THE IJH TOOL." + n
                + " * Please be aware that all changes made to this file manually" + n
                + " * will be overwritten by the tool if it runs again." + n
                + " */" + n
                + n
                + "#include <jni.h>" + n
                + n;

            StringBuffer result = new StringBuffer();
            Set innerNames = new HashSet();
            File file = outFile;
            Iterator namesIter = classNames.iterator();
            while (namesIter.hasNext()) {

                // Parse the next class.
                Clazz clazz = new Clazz(classProvider, (String) namesIter.next());

                if (inner) {
                    // Get the inner class names and store them
                    // in a separate set.
                    String innerClassNames[] = clazz.getInnerClassNames();
                    for (int i = 0; i < innerClassNames.length; i++) {
                        innerNames.add(innerClassNames[i]);
                    }
                }

                if (outFile == null) {
                    // Each header should be written into the separate file.

                    String fileName = Mangler.mangleFileName(
                            clazz.getName()) + ".h";

                    if (outDirectory != null) {
                        if (!outDirectory.exists()) {
                            outDirectory.mkdir();
                        }
                        fileName = outDirectory.getPath() + File.separator
                                + fileName;
                    }

                    // Reset the output file.
                    file = new File(fileName);

                    // Reset the result buffer.
                    result = new StringBuffer();
                }

                // Append the next header.
                result.append(Main.getHeader(clazz));

                // Process the inner class names, if any.
                if (!namesIter.hasNext() && !innerNames.isEmpty()) {
                    // Remove the inner class names that have already
                    // been processed.
                    innerNames.removeAll(classNames);

                    // Reset the loop iterator.
                    classNames = new HashSet(innerNames);
                    namesIter = classNames.iterator();

                    // Clear the set of the inner class names.
                    innerNames.clear();
                }

                // Write the result into a file.
                if (outFile == null || !namesIter.hasNext()) {
                    FileWriter writer = new FileWriter(file);
                    try {
                        writer.write(warning);
                        writer.write(result.toString());
                        if (verbose) {
                            System.out.println(file.getName() + " created");
                        }
                    } finally {
                        writer.close();
                    }
                }
            }

        } catch (Exception e) {
            System.err.println("Error:");
            e.printStackTrace();
            return 1;
        }

        return 0;
    }

    /**
     * Returns a value of an option with the given name. The return type
     * is <code>java.io.File</code>.
     */
    private static File getFile(Map options, String name) {
        try {
            return (File) options.get(name);
        } catch (ClassCastException e) {
            throw new RuntimeException(
                    "'" + name + "': expected java.io.File", e);
        }
    }
   
    /**
     * Returns a value of an option with the given name. The return type
     * is <code>java.lang.String</code>.
     */
    private static String getString(Map options, String name) {
        try {
            return (String) options.get(name);
        } catch (ClassCastException e) {
            throw new RuntimeException(
                    "'" + name + "': expected java.lang.String", e);
        }
    }
   
    /**
     * Returns a value of an option with the given name. The return type
     * is <code>java.lang.Boolean</code>.
     */
    private static boolean getBoolean(Map options, String name) {
        try {
            Object value = options.get(name);
            if (value != null) {
                return ((Boolean) value).booleanValue();
            }
        } catch (ClassCastException e) {
            throw new RuntimeException(
                    "'" + name + "': expected java.lang.Boolean", e);
        }
        return false;
    }

    /**
     * Returns a string that represents a JNI-style header file.
     */
    public static String getHeader(Clazz clazz) {
        String n = System.getProperty("line.separator");
        StringBuffer result = new StringBuffer();

        result.append(n);
        result.append("/* Header for class " + clazz.getName() + " */" + n);
        result.append(n);

        String headerMacro = "_" +
                Mangler.mangleMacro(clazz.getName()).toUpperCase() + "_H";
        result.append("#ifndef " + headerMacro + n);
        result.append("#define " + headerMacro + n);
        result.append(n);

        result.append("#ifdef __cplusplus" + n);
        result.append("extern \"C\" {" + n);
        result.append("#endif" + n);
        result.append(n);

        result.append(clazz);
        result.append(n);

        result.append("#ifdef __cplusplus" + n);
        result.append("}" + n);
        result.append("#endif" + n);
        result.append(n);

        result.append("#endif /* " + headerMacro + " */" + n);
        result.append(n);

        return result.toString();
    }
}
TOP

Related Classes of org.apache.harmony.tools.javah.Main

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.