// 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();
}
}