/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2011.
*/
package x10c.visit;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import polyglot.ast.Node;
import polyglot.ast.NodeFactory;
import polyglot.frontend.Job;
import polyglot.main.Options;
import polyglot.types.SemanticException;
import polyglot.types.TypeSystem;
import polyglot.util.ErrorInfo;
import polyglot.visit.NodeVisitor;
import x10.ast.X10ClassDecl;
import x10.emitter.Emitter;
import x10.types.X10ClassDef;
import x10.util.FileUtils;
public class NativeClassVisitor extends x10.visit.NativeClassVisitor {
public NativeClassVisitor(Job job, TypeSystem ts, NodeFactory nf, String theLanguage) {
super(job, ts, nf, theLanguage);
}
private static boolean findAndCopySourceFile(Options options, String cpackage, String cname, File sourceDirOrJarFile) throws IOException {
String sourceDirOrJarFilePath = sourceDirOrJarFile.getAbsolutePath();
if (sourceDirOrJarFile.isDirectory()) {
if (cpackage != null) {
sourceDirOrJarFilePath += File.separator + cpackage.replace('.', File.separatorChar);
}
File sourceDir = new File(sourceDirOrJarFilePath);
File sourceFile = new File(sourceDir, cname + ".java");
if (sourceFile.isFile()) { // found java source
// copy
String targetDirpath = options.output_directory.getAbsolutePath();
if (cpackage != null) {
targetDirpath += File.separator + cpackage.replace('.', File.separatorChar);
}
File targetDir = new File(targetDirpath);
targetDir.mkdirs();
File targetFile = new File(targetDir, cname + ".java");
FileUtils.copyFile(sourceFile, targetFile);
return true;
}
} else if (sourceDirOrJarFile.isFile() && (sourceDirOrJarFilePath.endsWith(".jar") || sourceDirOrJarFilePath.endsWith(".zip"))) {
String sourceFilePathInJarFile = cpackage != null ? (cpackage.replace('.', '/') + '/') : "";
sourceFilePathInJarFile += cname + ".java";
JarFile jarFile = new JarFile(sourceDirOrJarFile);
Enumeration<JarEntry> e = jarFile.entries();
while (e.hasMoreElements()) {
JarEntry jarEntry = e.nextElement();
String entryName = jarEntry.getName();
if (entryName.equals(sourceFilePathInJarFile)) { // found java source
// copy
String targetDirpath = options.output_directory.getAbsolutePath();
if (cpackage != null) {
targetDirpath += File.separator + cpackage.replace('.', File.separatorChar);
}
File targetDir = new File(targetDirpath);
targetDir.mkdirs();
File targetFile = new File(targetDir, cname + ".java");
InputStream sourceInputStream = jarFile.getInputStream(jarEntry);
long sourceSize = jarEntry.getSize();
FileUtils.copyFile(sourceInputStream, sourceSize, targetFile);
return true;
}
}
}
return false;
}
/*
* copy source files of Java classes that are referenced by @NativeClass or @NativeRep annotation from sourcepath (or classpath) to output_directory
*/
protected Node leaveCall(Node parent, Node old, Node n, NodeVisitor v) throws SemanticException {
if (n instanceof X10ClassDecl) {
X10ClassDecl cdecl = (X10ClassDecl) n;
X10ClassDef cdef = (X10ClassDef) cdecl.classDef();
String cname = null;
String cpackage = null;
if (getNativeClassName(cdef) != null) {
cname = getNativeClassName(cdef);
cpackage = getNativeClassPackage(cdef);
} else if (Emitter.getJavaRep(cdef) != null) {
cname = Emitter.getJavaRep(cdef);
int index = cname.lastIndexOf('.');
if (index >= 0) {
cpackage = cname.substring(0, index);
cname = cname.substring(index + 1);
}
}
if (cname != null) {
Options options = ts.extensionInfo().getOptions();
try {
if (options.source_path != null && !options.source_path.isEmpty()) {
for (File sourceDirOrJarFile : options.source_path) {
boolean copied = findAndCopySourceFile(options, cpackage, cname, sourceDirOrJarFile);
if (copied) break;
}
} else {
for (String sourceDirOrJarFilePath : options.constructPostCompilerClasspath().split(File.pathSeparator)) {
File sourceDirOrJarFile = new File(sourceDirOrJarFilePath);
boolean copied = findAndCopySourceFile(options, cpackage, cname, sourceDirOrJarFile);
if (copied) break;
}
}
} catch (IOException e) {
job.compiler().errorQueue().enqueue(ErrorInfo.IO_ERROR, "I/O error copying Java source file: " + e.getMessage());
}
}
}
return super.leaveCall(parent, old, n, v);
}
}