com.google.collide.dtogen.DtoGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.google.collide.dtogen.DtoGenerator.java

Source

// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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 com.google.collide.dtogen;

import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * Simple source generator that takes in a jar of interface definitions and
 * generates client and server DTO impls.
 *
 */
public class DtoGenerator {

    private static final String INVALID_PATH = "invalid path";
    private static final String SERVER = "server";
    private static final String CLIENT = "client";

    /** Flag: location of the input source dto jar. */
    static String dto_jar = null;

    /** Flag: Name of the generated java class file that contains the DTOs. */
    static String gen_file_name = "DataObjects.java";

    /** Flag: The type of impls to be generated, either CLIENT or SERVER. */
    static String impl = CLIENT;

    /**
     * Flag: A pattern we can use to search an absolute path and find the start
     * of the package definition.")
     */
    static String package_base = "java.";

    /**
     * @param args
     */
    public static void main(String[] args) {
        for (String arg : args) {
            if (arg.startsWith("--dto_jar=")) {
                dto_jar = arg.substring("--dto_jar=".length());
            } else if (arg.startsWith("--gen_file_name=")) {
                gen_file_name = arg.substring("--gen_file_name=".length());
            } else if (arg.startsWith("--impl=")) {
                impl = arg.substring("--impl=".length());
            } else if (arg.startsWith("--package_base=")) {
                package_base = arg.substring("--package_base=".length());
            } else {
                System.err.println("Unknown flag: " + arg);
                System.exit(1);
            }
        }

        String outputFilePath = gen_file_name;

        // Extract the name of the output file that will contain all the DTOs and
        // its package.
        int packageStart = outputFilePath.indexOf(package_base) + package_base.length();
        int packageEnd = outputFilePath.lastIndexOf('/');
        String fileName = outputFilePath.substring(packageEnd + 1);
        String className = fileName.substring(0, fileName.indexOf(".java"));
        String packageName = outputFilePath.substring(packageStart, packageEnd).replace('/', '.');

        File outFile = new File(outputFilePath);
        File interfaceJar = new File(dto_jar);

        try {
            DtoTemplate dtoTemplate = new DtoTemplate(packageName, className, getApiHash(interfaceJar),
                    impl.equals(SERVER));

            // Crack open the JAR that contains the class files for the DTO
            // interfaces. Collect class files to load.
            List<String> classFilePaths = new ArrayList<String>();

            JarFile jarFile = new JarFile(interfaceJar);
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                String entryFilePath = entries.nextElement().getName();
                if (entryFilePath.endsWith(".class")) {
                    classFilePaths.add(entryFilePath);
                }
            }

            // Load the classes that we found above.
            URL[] urls = { interfaceJar.toURI().toURL() };
            URLClassLoader loader = new URLClassLoader(urls);

            // We sort alphabetically to ensure deterministic order of routing types.
            Collections.sort(classFilePaths);

            for (String classFilePath : classFilePaths) {
                URL resource = loader.findResource(classFilePath);
                if (resource != null) {
                    String javaName = classFilePath.replace('/', '.').substring(0,
                            classFilePath.lastIndexOf(".class"));
                    Class<?> dtoInterface = Class.forName(javaName, false, loader);
                    if (dtoInterface.isInterface()) {
                        // Add interfaces to the DtoTemplate.
                        dtoTemplate.addInterface(dtoInterface);
                    }
                }
            }

            // Emit the generated file.
            BufferedWriter writer = new BufferedWriter(new FileWriter(outFile));
            writer.write(dtoTemplate.toString());
            writer.close();
        } catch (MalformedURLException e1) {
            e1.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    private static String getApiHash(File interfaceJar) throws IOException {
        byte[] fileBytes = Files.toByteArray(interfaceJar);
        HashCode hashCode = Hashing.sha1().hashBytes(fileBytes);
        return hashCode.toString();
    }
}