use of net.morimekta.providence.reflect.util.ProgramTypeRegistry in project providence by morimekta.
the class BaseGenerateSourcesMojo method executeInternal.
boolean executeInternal(IncludeExcludeFileSelector includeDirs, File outputDir, IncludeExcludeFileSelector inputSelector, String defaultInputIncludes, boolean testCompile) throws MojoExecutionException, MojoFailureException {
Set<File> inputFiles = ProvidenceInput.getInputFiles(project, inputSelector, defaultInputIncludes, print_debug, getLog());
if (inputFiles.isEmpty()) {
return false;
}
if (!outputDir.exists()) {
if (!outputDir.mkdirs()) {
throw new MojoExecutionException("Unable to create target directory " + outputDir);
}
}
TreeSet<File> includes = new TreeSet<>();
File workingDir = new File(buildDir, testCompile ? "providence-test" : "providence");
File[] deleteFiles = workingDir.listFiles();
if (!workingDir.exists()) {
if (!workingDir.mkdirs()) {
throw new MojoExecutionException("Unable to create working directory " + workingDir);
}
} else if (deleteFiles != null) {
StreamSupport.<File>stream(Spliterators.spliterator(deleteFiles, Spliterator.DISTINCT | Spliterator.IMMUTABLE), false).forEach(File::delete);
}
Set<Artifact> resolvedArtifacts = new HashSet<>();
for (Dependency dep : dependencies) {
if (testCompile || !TEST.equalsIgnoreCase(dep.getScope())) {
resolveDependency(dep, includes, workingDir, resolvedArtifacts);
}
}
if (includeDirs != null) {
DirectoryScanner includeScanner = new DirectoryScanner();
includeScanner.setIncludes(includeDirs.getIncludes());
if (includeDirs.getExcludes() != null) {
includeScanner.setExcludes(includeDirs.getExcludes());
}
includeScanner.setBasedir(project.getBasedir());
includeScanner.scan();
for (String dir : includeScanner.getIncludedDirectories()) {
includes.add(new File(project.getBasedir(), dir));
}
for (String dir : includeScanner.getExcludedDirectories()) {
includes.remove(new File(project.getBasedir(), dir));
}
}
FileManager fileManager = new FileManager(outputDir);
ProgramParser parser = new ThriftProgramParser(require_field_id, require_enum_value, allow_language_reserved_names);
TypeLoader loader = new TypeLoader(includes, parser);
if (print_debug) {
inputFiles.stream().filter(Objects::nonNull).map(file -> {
try {
return file.getAbsoluteFile().getCanonicalPath();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}).sorted().forEach(f -> getLog().info("Compiling: " + f));
}
JavaOptions javaOptions = new JavaOptions();
javaOptions.android = android;
javaOptions.jackson = jackson;
javaOptions.rw_binary = rw_binary;
javaOptions.hazelcast_portable = hazelcast_portable;
javaOptions.generated_annotation_version = generated_annotation_version;
javaOptions.public_constructors = public_constructors;
GeneratorOptions generatorOptions = new GeneratorOptions();
generatorOptions.generator_program_name = "providence-maven-plugin";
generatorOptions.program_version = getVersionString();
GeneratorFactory factory = new JavaGeneratorFactory();
Generator generator = new JavaGenerator(fileManager, generatorOptions, javaOptions);
Path base = project.getBasedir().toPath().toAbsolutePath();
if (project.getParent() != null && project.getParent().getBasedir() != null) {
// Only replace with parent if parent is a parent directory of this.
Path parentBase = project.getParent().getBasedir().toPath().toAbsolutePath();
if (base.toString().startsWith(parentBase.toString())) {
base = parentBase;
}
}
for (File in : inputFiles) {
ProgramTypeRegistry registry;
try {
registry = loader.load(in);
} catch (SerializerException e) {
// ParseException is a SerializerException. And serialize exceptions can come from
// failing to make sense of constant definitions.
getLog().error(" ============ >> PROVIDENCE << ============");
getLog().error("");
Arrays.stream(e.asString().split("\r?\n")).forEach(l -> getLog().error(l));
getLog().error("");
getLog().error(" ============ << PROVIDENCE >> ============");
throw new MojoFailureException("Failed to parse thrift file: " + in.getName(), e);
} catch (IOException e) {
throw new MojoExecutionException("Failed to read thrift file: " + in.getName(), e);
}
try {
if (skipIfMissingNamespace && registry.getProgram().getNamespaceForLanguage(factory.generatorName()) == null) {
getLog().warn("Skipping (no " + factory.generatorName() + " namespace) " + base.relativize(in.toPath()));
continue;
}
generator.generate(registry);
} catch (GeneratorException e) {
throw new MojoFailureException("Failed to generate program: " + registry.getProgram().getProgramName(), e);
} catch (IOException e) {
throw new MojoExecutionException("Failed to write program file: " + registry.getProgram().getProgramName(), e);
}
}
try {
generator.generateGlobal(loader.getProgramRegistry(), inputFiles);
} catch (GeneratorException e) {
throw new MojoFailureException("Failed to generate global", e);
} catch (IOException e) {
throw new MojoExecutionException("Failed to write global file", e);
}
return compileOutput;
}
use of net.morimekta.providence.reflect.util.ProgramTypeRegistry in project providence by morimekta.
the class TypeLoader method loadInternal.
private ProgramTypeRegistry loadInternal(File file, List<String> loadStack) throws IOException {
loadStack = new ArrayList<>(loadStack);
file = file.getCanonicalFile();
if (!file.exists()) {
throw new IllegalArgumentException("No such file " + file);
}
if (!file.isFile()) {
throw new IllegalArgumentException("Unable to load thrift program: " + file + " is not a file.");
}
file = file.getAbsoluteFile();
String path = file.getPath();
if (loadStack.contains(path)) {
// Only show the circular includes, not the path to get there.
while (!loadStack.get(0).equals(path)) {
loadStack.remove(0);
}
loadStack.add(path);
String prefix = longestCommonPrefixPath(loadStack);
if (prefix.length() > 0) {
loadStack = stripCommonPrefix(loadStack);
throw new IllegalArgumentException("Circular includes detected: " + prefix + "... " + String.join(" -> ", loadStack));
}
throw new IllegalArgumentException("Circular includes detected: " + String.join(" -> ", loadStack));
}
loadStack.add(path);
ProgramTypeRegistry registry = this.programRegistry.registryForPath(path);
if (programRegistry.containsProgramPath(path)) {
return registry;
}
InputStream in = new BufferedInputStream(new FileInputStream(file));
ProgramType doc = parser.parse(in, file, includes);
ArrayList<File> queue = new ArrayList<>();
if (doc.hasIncludes()) {
for (String include : doc.getIncludes()) {
File location = new File(file.getParent(), include).getCanonicalFile();
if (!location.exists()) {
if (include.startsWith(".") || include.startsWith(File.separator)) {
throw new ParseException("No such file \"" + include + "\" to include from " + file.getName());
}
for (File inc : includes) {
File i = new File(inc, include);
if (i.exists()) {
location = i.getCanonicalFile();
break;
}
}
}
if (location.exists() && !queue.contains(location)) {
queue.add(location.getAbsoluteFile());
}
}
}
// Load includes in reverse order, in case of serial dependencies.
Collections.reverse(queue);
loadedDocuments.put(path, doc);
for (File include : queue) {
registry.registerInclude(programNameFromPath(include.getPath()), loadInternal(include, ImmutableList.copyOf(loadStack)));
}
// Now everything it depends on is loaded.
CProgram program = converter.convert(path, doc);
programRegistry.putProgram(path, program);
programRegistry.putProgramType(path, doc);
return registry;
}
use of net.morimekta.providence.reflect.util.ProgramTypeRegistry in project providence by morimekta.
the class JavaGenerator method generate.
@Override
@SuppressWarnings("resource")
public void generate(@Nonnull ProgramTypeRegistry registry) throws IOException, GeneratorException {
CProgram program = registry.getProgram();
String javaPackage = JUtils.getJavaPackage(program);
JHelper helper = new JHelper(registry);
String path = JUtils.getPackageClassPath(javaPackage);
if (program.getConstants().size() > 0) {
String file = helper.getConstantsClassName(program) + ".java";
OutputStream out = new BufferedOutputStream(getFileManager().create(path, file));
try {
IndentedPrintWriter writer = new IndentedPrintWriter(out);
appendFileHeader(writer, helper, program);
constFomatter(writer, helper).appendProgramClass(program);
writer.flush();
} finally {
try {
getFileManager().finalize(out);
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (javaOptions.hazelcast_portable && program.getConstants().stream().anyMatch(t -> t.getName().equals("FACTORY_ID"))) {
String file = helper.getHazelcastFactoryClassName(program) + ".java";
OutputStream out = new BufferedOutputStream(getFileManager().create(path, file));
try {
IndentedPrintWriter writer = new IndentedPrintWriter(out);
appendFileHeader(writer, helper, program);
hazelcastFomatter(writer, helper).appendProgramClass(program);
writer.flush();
} finally {
try {
getFileManager().finalize(out);
} catch (IOException e) {
e.printStackTrace();
}
}
}
for (PDeclaredDescriptor<?> type : program.getDeclaredTypes()) {
String file = JUtils.getClassName(type) + ".java";
OutputStream out = new BufferedOutputStream(getFileManager().create(path, file));
try {
IndentedPrintWriter writer = new IndentedPrintWriter(out);
appendFileHeader(writer, helper, program);
switch(type.getType()) {
case MESSAGE:
messageFormatter(writer, helper).appendMessageClass((PMessageDescriptor<?, ?>) type);
break;
case ENUM:
enumFormatter(writer).appendEnumClass((CEnumDescriptor) type);
break;
default:
throw new GeneratorException("Unhandled declaration type.");
}
writer.flush();
} finally {
try {
getFileManager().finalize(out);
} catch (IOException e) {
e.printStackTrace();
}
}
}
for (CService service : program.getServices()) {
String file = JUtils.getClassName(service) + ".java";
OutputStream out = new BufferedOutputStream(getFileManager().create(path, file));
try {
IndentedPrintWriter writer = new IndentedPrintWriter(out);
appendFileHeader(writer, helper, program);
serviceFormatter(writer, helper).appendServiceClass(service);
writer.flush();
} finally {
try {
getFileManager().finalize(out);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
use of net.morimekta.providence.reflect.util.ProgramTypeRegistry in project providence by morimekta.
the class Convert method run.
@SuppressWarnings("unchecked")
void run(String... args) {
try {
ArgumentParser cli = options.getArgumentParser("pvd", "Providence Converter");
try {
cli.parse(args);
if (options.showHelp()) {
System.out.println(cli.getProgramDescription());
System.out.println("Usage: " + cli.getSingleLineUsage());
System.out.println();
System.out.println("Example code to run:");
System.out.println("$ cat call.json | pvd -I thrift/ -S cal.Calculator");
System.out.println("$ pvd -i binary,file:my.data -o json_protocol -I thrift/ cal.Operation");
System.out.println();
System.out.println("Note that when handling service calls, only 1 call can be converted.");
System.out.println();
cli.printUsage(System.out);
System.out.println();
System.out.println("Available formats are:");
for (Format format : Format.values()) {
System.out.println(String.format(" - %-20s : %s", format.name(), format.desc));
}
return;
}
if (options.showVersion()) {
System.out.println(cli.getProgramDescription());
return;
}
if (options.listTypes) {
ProgramRegistry registry = options.getProgramRegistry();
for (ProgramTypeRegistry pr : registry.getLoadedRegistries()) {
CProgram program = pr.getProgram();
System.out.println(program.getProgramFilePath() + ":");
for (PDeclaredDescriptor dd : program.getDeclaredTypes()) {
if (dd instanceof CStructDescriptor) {
System.out.println(" struct " + dd.getQualifiedName());
} else if (dd instanceof CUnionDescriptor) {
System.out.println(" union " + dd.getQualifiedName());
} else if (dd instanceof CExceptionDescriptor) {
System.out.println(" exception " + dd.getQualifiedName());
}
}
for (PService s : program.getServices()) {
System.out.println(" service " + s.getQualifiedName());
}
}
return;
}
cli.validate();
if (options.getDefinition() == null) {
MessageReader in = options.getServiceInput();
MessageWriter out = options.getServiceOutput();
PService service = options.getServiceDefinition();
PServiceCall call = in.read(service);
in.close();
out.write(call);
out.separator();
out.close();
// TODO: Validate we don't have garbage data after call.
if (options.out.base64mime && options.out.file == null) {
System.out.println();
}
} else {
AtomicInteger num = new AtomicInteger(0);
int size = options.getInput().peek(m -> num.incrementAndGet()).collect(options.getOutput());
if (num.get() == 0 || size == 0) {
throw new IOException("No data");
}
if (options.out.base64mime && options.out.file == null) {
System.out.println();
}
}
return;
} catch (ArgumentException e) {
System.err.println(e.getMessage());
System.out.println("Usage: " + cli.getSingleLineUsage());
System.err.println();
System.err.println("Run $ pvd --help # for available options.");
if (options.verbose()) {
System.err.println();
e.printStackTrace();
}
} catch (SerializerException e) {
System.out.flush();
System.err.println();
System.err.println(e.asString());
if (options.verbose()) {
System.err.println();
e.printStackTrace();
}
} catch (UncheckedIOException | IOException e) {
System.out.flush();
System.err.println();
System.err.println("I/O error: " + e.getMessage());
if (options.verbose()) {
System.err.println();
e.printStackTrace();
}
}
} catch (Exception e) {
System.out.flush();
System.err.println();
System.err.println("Unchecked exception: " + e.getMessage());
if (options.verbose()) {
System.err.println();
e.printStackTrace();
}
}
exit(1);
}
use of net.morimekta.providence.reflect.util.ProgramTypeRegistry in project providence by morimekta.
the class GeneratorMain method run.
public void run(String... args) {
try {
ArgumentParser cli = options.getArgumentParser("pvdgen", "Providence generator");
cli.parse(args);
if (options.isHelp()) {
System.out.println("Providence generator - " + Utils.getVersionString());
System.out.println("Usage: pvdgen [-I dir] [-o dir] -g generator[:opt[,opt]*] file...");
System.out.println();
if (options.help.factory != null) {
System.out.format("%s : %s%n", options.help.factory.generatorName(), options.help.factory.generatorDescription());
System.out.println();
System.out.println("Available options");
System.out.println();
options.help.factory.printGeneratorOptionsHelp(System.out);
} else {
System.out.println("Example code to run:");
System.out.println("$ pvdgen -I thrift/ --out target/ --gen java:android thrift/the-one.thrift");
System.out.println();
cli.printUsage(System.out);
System.out.println();
System.out.println("Available generators:");
Map<String, GeneratorFactory> factories = options.getFactories();
for (GeneratorFactory lang : factories.values()) {
System.out.format(" - %-10s : %s%n", lang.generatorName(), lang.generatorDescription());
}
}
return;
} else if (options.version) {
System.out.println("Providence generator - " + Utils.getVersionString());
return;
}
cli.validate();
ProgramParser parser = options.getParser();
List<File> includes = options.getIncludes();
List<File> input = options.getInputFiles();
TypeLoader loader = new TypeLoader(includes, parser);
Generator generator = options.getGenerator(loader);
for (File f : input) {
ProgramTypeRegistry registry = loader.load(f);
if (options.skipIfMissingNamespace && registry.getProgram().getNamespaceForLanguage(options.gen.factory.generatorName()) == null) {
System.out.println("Skipping (no " + options.gen.factory.generatorName() + " namespace) " + f.getCanonicalFile().getAbsolutePath());
}
generator.generate(loader.load(f));
}
generator.generateGlobal(loader.getProgramRegistry(), input);
return;
} catch (ArgumentException e) {
System.err.println("Usage: pvdgen [-I dir] [-o dir] -g generator[:opt[,opt]*] file...");
System.err.println(e.getLocalizedMessage());
System.err.println();
System.err.println("Run $ pvdgen --help # for available options.");
if (options.verbose) {
e.printStackTrace();
}
} catch (ParseException e) {
System.err.println(e.asString());
if (options.verbose) {
e.printStackTrace();
}
} catch (IllegalArgumentException e) {
System.err.println(e.getMessage());
if (options.verbose) {
e.printStackTrace();
}
} catch (GeneratorException e) {
System.err.println("Generator error: " + e.getMessage());
if (options.verbose) {
e.printStackTrace();
}
} catch (IOException e) {
System.err.println("I/O error: " + e.getMessage());
if (options.verbose) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
exit(1);
}
Aggregations