io.vertx.core.impl.verticle.JavaSourceContext Maven / Gradle / Ivy
/*
* Copyright (c) 2011-2014 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.core.impl.verticle;
import javax.tools.JavaFileObject.Kind;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
/**
*
* Resolves package name and source path based on a single Java source file.
*
* @author Janne Hietamäki
*/
public class JavaSourceContext {
private final String className;
private final File sourceRoot;
public JavaSourceContext(File file) {
String packageName = parsePackage(file);
File rootDirectory = file.getParentFile();
if (packageName != null) {
String[] pathTokens = packageName.split("\\.");
for(int i = pathTokens.length - 1; i >= 0; i--) {
String token = pathTokens[i];
if (!token.equals(rootDirectory.getName())) {
throw new RuntimeException("Package structure does not match directory structure: " + token + " != " + rootDirectory.getName());
}
rootDirectory = rootDirectory.getParentFile();
}
}
sourceRoot = rootDirectory;
String fileName = file.getName();
String className = fileName.substring(0, fileName.length() - Kind.SOURCE.extension.length());
if (packageName != null) {
className = packageName + '.' + className;
}
this.className = className;
}
public File getSourceRoot() {
return sourceRoot;
}
public String getClassName() {
return className;
}
/*
* Parse package definition from a Java source file:
* First remove all comments, split file into lines, find first non-empty line
* Then, if the line starts with keyword "package", parse the package definition from it.
*
*/
private static String parsePackage(File file) {
try {
String source = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
// http://stackoverflow.com/questions/1657066/java-regular-expression-finding-comments-in-code
source = source.replaceAll( "//.*|(\"(?:\\\\[^\"]|\\\\\"|.)*?\")|(?s)/\\*.*?\\*/", "$1 " );
for (String line : source.split("\\r?\\n")) {
line = line.trim();
if (!line.isEmpty()) {
int idx = line.indexOf("package ");
if (idx != -1) {
return line.substring(line.indexOf(' ', idx), line.indexOf(';', idx)).trim();
}
return null; // Package definition must be on the first non-comment line
}
}
return null;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}