/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.build;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import org.jnode.vm.BaseVmArchitecture;
import org.jnode.vm.VmImpl;
import org.jnode.vm.VmSystemClassLoader;
import org.jnode.vm.classmgr.VmField;
import org.jnode.vm.classmgr.VmInstanceField;
import org.jnode.vm.classmgr.VmNormalClass;
import org.jnode.vm.classmgr.VmType;
import org.jnode.vm.facade.Vm;
/**
* TODO describe the class.
*
* @author epr
*/
public abstract class AbstractAsmConstBuilder {
private File destFile;
private String classesURL;
private ArrayList<ClassName> classes = new ArrayList<ClassName>();
/**
* Execute this task.
*
* @throws BuildException
*/
public void execute() throws BuildException {
try {
doExecute();
} catch (Throwable ex) {
ex.printStackTrace();
throw new BuildException(ex);
}
}
/**
* Execute this task.
*
* @throws BuildException
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws IOException
* @throws InstantiationException
*/
private void doExecute()
throws BuildException, ClassNotFoundException, IllegalAccessException, IOException, InstantiationException {
final BaseVmArchitecture arch = getArchitecture();
String[] urls = classesURL.split(",");
URL[] urla = new URL[urls.length];
for (int i = 0; i < urls.length; i++)
urla[i] = new URL(urls[i].trim());
final VmSystemClassLoader cl = new VmSystemClassLoader(urla, arch);
final Vm vm = new VmImpl("?", arch, cl.getSharedStatics(), false, cl, null);
vm.toString(); // Just to avoid compiler warnings
VmType.initializeForBootImage(cl);
long lastModified = 0;
FileWriter fw = new FileWriter(destFile);
PrintWriter out = new PrintWriter(fw);
out.println("; " + destFile.getPath());
out.println("; THIS file has been generated automatically on " + new Date());
out.println();
for (ClassName cn : classes) {
lastModified = Math.max(lastModified, cl.findResource(cn.getClassFileName()).
openConnection().getLastModified());
out.println("; Constants for " + cn.getClassName());
if (cn.isStatic()) {
Class<?> cls = Class.forName(cn.getClassName());
Field fields[] = cls.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field f = fields[i];
if (Modifier.isStatic(f.getModifiers()) && Modifier.isPublic(f.getModifiers())) {
Object value = f.get(null);
if (value instanceof Number) {
String cname = cls.getName();
int idx = cname.lastIndexOf('.');
if (idx > 0) {
cname = cname.substring(idx + 1);
}
String name = cname + "_" + f.getName();
out.println(name + " equ " + value);
}
}
}
out.println();
} else {
out.println("; VmClass: " + cn.getClassName());
VmType<?> vmClass = cl.loadClass(cn.getClassName(), true);
vmClass.link();
String cname = vmClass.getName().replace('/', '.');
int idx = cname.lastIndexOf('.');
if (idx > 0) {
cname = cname.substring(idx + 1);
}
int cnt = vmClass.getNoDeclaredFields();
for (int i = 0; i < cnt; i++) {
final VmField f = vmClass.getDeclaredField(i);
if (!f.isStatic()) {
final VmInstanceField instF = (VmInstanceField) f;
String name = cname + "_" + f.getName().toUpperCase();
if (f.getTypeSize() < 4) {
name = name + "_S" + f.getTypeSize();
}
name = name + "_OFS";
out.println(name + " equ " + instF.getOffset());
}
}
// The size
if (vmClass instanceof VmNormalClass) {
final VmNormalClass<?> cls = (VmNormalClass<?>) vmClass;
out.println(cname + "_SIZE equ " + cls.getObjectSize());
}
//
out.println();
}
}
out.flush();
fw.flush();
out.close();
fw.close();
destFile.setLastModified(lastModified);
}
public void addClass(ClassName cn) {
classes.add(cn);
}
/**
* Returns the destFile.
*
* @return File
*/
public File getDestFile() {
return destFile;
}
/**
* Sets the destFile.
*
* @param destFile The destFile to set
*/
public void setDestFile(File destFile) {
this.destFile = destFile;
}
public static class ClassName {
private String className;
private boolean _static = false;
public ClassName() {
}
/**
* Returns the className.
*
* @return String
*/
public String getClassName() {
return className;
}
/**
* Sets the className.
*
* @param className The className to set
*/
public void setClassName(String className) {
this.className = className;
}
/**
* Returns the _static.
*
* @return boolean
*/
public boolean isStatic() {
return _static;
}
/**
* Sets the _static.
*
* @param _static The _static to set
*/
public void setStatic(boolean _static) {
this._static = _static;
}
public URL getURL(URL root) throws MalformedURLException {
return new URL(root.toExternalForm() + "/" + className.replace('.', '/') + ".class");
}
public String getClassFileName() {
return "/" + className.replace('.', '/') + ".class";
}
}
/**
* Returns the classesURL.
*
* @return URL
*/
public String getClassesURL() {
return classesURL;
}
/**
* Sets the classesURL.
*
* @param classesURL The classesURL to set
*/
public void setClassesURL(String classesURL) {
this.classesURL = classesURL;
}
protected abstract BaseVmArchitecture getArchitecture();
}