package org.anodyneos.xpImpl.translater;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLConnection;
import java.util.List;
import org.anodyneos.commons.net.ClassLoaderURIHandler;
import org.anodyneos.commons.xml.UnifiedResolver;
import org.anodyneos.commons.xml.sax.BaseParser;
import org.anodyneos.xp.XpFileNotFoundException;
import org.anodyneos.xp.XpTranslationException;
import org.anodyneos.xp.tagext.TagLibraryRegistry;
import org.anodyneos.xpImpl.registry.RegistryParser;
import org.anodyneos.xpImpl.util.CodeWriter;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public class Translater extends BaseParser {
private static final int CL_XP_ROOT = 0;
private static final int CL_XP_PAGE = 1;
private static final int CL_JAVA_FILE = 2;
private static final int CL_REGISTRY_FILE = 3;
public Translater() {
// super();
}
public static void main(String[] args) throws Exception {
try {
OutputStream os;
Translater obj = new Translater();
long start = System.currentTimeMillis();
UnifiedResolver resolver = new UnifiedResolver();
resolver.addProtocolHandler("classpath",
new ClassLoaderURIHandler(Thread.currentThread().getContextClassLoader()));
translate(args[CL_XP_ROOT],args[CL_XP_PAGE],args[CL_JAVA_FILE],args[CL_REGISTRY_FILE],resolver);
System.out.println("Completed in " + (System.currentTimeMillis() - start) + " milliseconds.");
} catch (SAXParseException e) {
System.err.print(e.getSystemId());
System.err.print(":" + e.getLineNumber() + ":" + e.getColumnNumber() + ": ");
System.err.print(e.getLocalizedMessage());
if (null != e.getException()) {
System.err.println();
System.err.println("Cause: ");
e.printStackTrace(System.err);
}
}
}
public static TranslaterResult translate(String xpRoot, String xpPage,
String javaFile, String registryFile, EntityResolver er) throws Exception{
OutputStream os;
Translater obj = new Translater();
// registry
UnifiedResolver resolver = new UnifiedResolver();
resolver.addProtocolHandler("classpath",
new ClassLoaderURIHandler(Thread.currentThread().getContextClassLoader()));
InputSource is = new InputSource(new java.io.File(registryFile).toURI().toURL().toString());
TagLibraryRegistry registry = new RegistryParser().process(is, resolver);
// add a / if it doesn't exist
char lastChar = xpRoot.charAt(xpRoot.length()-1);
if ( lastChar != '/' && lastChar != '\\'){
xpRoot += File.separatorChar;
}
// translate codegen
String className = xpPage;
className = className.substring(xpRoot.length(),className.length());
if (className.startsWith("/")){
className = className.substring(1,className.length());
}
className = className.replace('/','.');
className = className.replace('\\','.');
className = className.substring(0, className.lastIndexOf('.'));
if (createDir(javaFile)){
os = new FileOutputStream(javaFile);
}else{
throw new Exception("Unable to create file: " + javaFile +
" because the directory structure could not be created.");
}
TranslaterResult result = obj.process(new InputSource(xpPage), os, registry, className, er);
os.close();
return result;
}
/**
* @param xpRoot - The physical directory where the xp are located
* @param tempRoot - The physical directory where the java file is to be based
* @param xpURI - The URI of the desired xp
* @param registryFile - RegistryFile of TLDs
* @param resolver - UnifiedResolver
* @return TranslaterResult
* @throws Exception
*/
public static TranslaterResult translate(String tempRoot, URI xpURI, String registryFile, UnifiedResolver resolver)
throws XpFileNotFoundException,XpTranslationException{
Translater obj = new Translater();
try{
InputSource is = resolver.resolveEntity(null,registryFile);
TagLibraryRegistry registry = new RegistryParser().process(is, resolver);
return obj.translate(tempRoot,xpURI,registry,resolver);
}catch(XpFileNotFoundException fnf){
throw fnf;
}catch(XpTranslationException te){
throw te;
}catch (Exception e){
throw new XpTranslationException(e);
}
}
public TranslaterResult translate(String tempRoot, URI xpURI, TagLibraryRegistry registry, UnifiedResolver resolver)
throws XpFileNotFoundException, XpTranslationException{
try{
InputSource xpSource = resolver.resolveEntity(null,xpURI.toString());
if (xpSource == null){
throw new XpTranslationException("File Not Found: " + xpURI.toString());
}
String javaFile = getJavaFile(tempRoot, xpURI);
String className = getClassName(xpURI); // i.e. xp.WEB_INF.common.header
OutputStream os;
if (createDir(javaFile)){
os = new FileOutputStream(javaFile);
}else{
throw new XpTranslationException("Unable to create file: " + javaFile +
" because the directory structure could not be created.");
}
TranslaterResult result = process(xpSource, os, registry, className, resolver);
os.close();
// now translate the dependents (There is no check to see if they are out of date)
// this is necessary in order to obtain the dependent list
List dependents = result.getDependents();
for (int i=0; i<dependents.size();i++){
String dependent = (String)dependents.get(i);
URI uriDep = new URI(dependent);
translate(tempRoot,uriDep,registry,resolver);
}
return result;
} catch (URISyntaxException ex) {
throw new XpTranslationException(ex);
} catch (IOException ioe) {
throw new XpTranslationException(ioe);
} catch (SAXException se) {
if (se.getException() != null) {
throw new XpTranslationException(se.getException());
} else if (se.getCause() != null) {
throw new XpTranslationException(se.getCause());
} else {
throw new XpTranslationException(se);
}
}
}
public TranslaterResult process(InputSource is, OutputStream os, TagLibraryRegistry taglibRegistry,
String fullClassName, EntityResolver er) throws SAXException, IOException {
CodeWriter out = new CodeWriter(os);
TranslaterContext ctx = new TranslaterContext(is, out, taglibRegistry);
ctx.setFullClassName(fullClassName);
TranslaterProcessor p = new ProcessorPage(ctx);
process(is, p, er);
out.flush();
return (TranslaterResult) ctx;
}
/*//REMOVED
* Check to see if xp is newer than java
* @param xpURI
* @param tempRoot
* @param resolver
* @return
*
public static boolean xpNeedsTranslating(URI xpURI, String tempRoot, UnifiedResolver resolver)
throws XpException{
File javaFile = new File(getJavaFile(tempRoot,xpURI));
if (javaFile.exists()){
return xpIsOutOfDate(xpURI,tempRoot,resolver,javaFile.lastModified());
}else{
// the java file does not exist, so the xp needs translating
return true;
}
}
*/
/*//REMOVED
* Check to see if xp is newer than class
*
* @param xpURI
* @param tempRoot
* @param resolver
* @return
*
public static boolean xpNeedsCompiling(URI xpURI, String tempRoot, UnifiedResolver resolver)
throws XpException{
File javaFile = new File(getClassFile(tempRoot,xpURI));
if (javaFile.exists()){
return xpIsOutOfDate(xpURI,tempRoot,resolver,javaFile.lastModified());
}else{
// the java file does not exist, so the xp needs translating
return true;
}
}
*/
public static boolean xpIsOutOfDate(URI xpURI, String tempRoot, UnifiedResolver resolver, long loadTime)
throws XpFileNotFoundException{
try{
URLConnection conn = resolver.openConnection(xpURI);
if (conn == null){
throw new IOException(xpURI.toString() + " does not exist.");
}
// conn.getLastModified() returns 0 if not known, so
// classpath: and webapp: type resources are ok
long xpLastModified = conn.getLastModified();
if (loadTime >= xpLastModified){
return false;
}else{
return true;
}
}catch (IOException ioe){
throw new XpFileNotFoundException(xpURI.toString());
}
}
public static boolean xpExists(URI xpURI, UnifiedResolver resolver){
try{
URLConnection conn = resolver.openConnection(xpURI);
if (conn == null){
return false;
}else{
return true;
}
}catch (IOException ioe){
return false;
}
}
private static String stripXpExtensionFromPath(String xpPath){
if (xpPath.trim().toUpperCase().endsWith(".XP")){
String trimmedPath = xpPath.trim();
return trimmedPath.substring(0,trimmedPath.length()-3);
}else{
return xpPath;
}
}
public static String getJavaFile(String tempRoot, URI xpURI){
String fullPath = concatPaths(TranslaterContext.DEFAULT_PACKAGE + "/",xpURI.getPath());
fullPath = stripXpExtensionFromPath(fullPath);
fullPath = fullPath.replace('-','_'); // TODO replace with more robust replacement
fullPath = fullPath.replace('.','_'); // TODO replace with more robust replacement
fullPath += ".java";
fullPath = concatPaths(tempRoot,fullPath);
return fullPath;
}
/* REMOVED
public static String getClassFile(String tempRoot, URI xpURI){
String fullPath = concatPaths(TranslaterContext.DEFAULT_PACKAGE + "/",xpURI.getPath());
fullPath = stripXpExtensionFromPath(fullPath);
fullPath = fullPath.replace('-','_'); // TODO replace with more robust replacement
fullPath = fullPath.replace('.','_'); // TODO replace with more robust replacement
fullPath += ".class";
fullPath = concatPaths(tempRoot,fullPath);
return fullPath;
}
*/
/**
*
* Convert webapp:///WEB-INF/xp/account/account_list.query.xp into xp.WEB_INF.xp.account.account_list_query
*
* @param xpURI
* @return String
*/
public static String getClassName(URI xpURI){
String fullPath = xpURI.getPath();
fullPath = stripXpExtensionFromPath(fullPath);
fullPath = fullPath.replace('-','_'); // TODO replace with more robust replacement
fullPath = fullPath.replace('.','_'); // TODO replace with more robust replacement
fullPath = concatPaths(TranslaterContext.DEFAULT_PACKAGE + "/",fullPath);
fullPath = fullPath.replace('/','.');
return fullPath;
}
/**
* concats pathPrefix and pathSuffix, with a / between the two
*
* @param pathPrefix
* @param pathSuffix
* @return pathPrefix + pathSuffix
* @throws Exception
*/
public static String concatPaths(String pathPrefix, String pathSuffix){
String c = null;
if (pathPrefix == null){
c = pathSuffix;
}else if (pathSuffix == null){
c = pathPrefix;
}else{
// start with the prefix
c = pathPrefix;
if (pathPrefix.endsWith("/")){
if (pathSuffix.startsWith("/")){
// if the prefix ends in / and the suffix begins with / then strip the / from the suffix
pathSuffix = pathSuffix.substring(1,pathSuffix.length());
}
}else{
if (!pathSuffix.startsWith("/")){
// if the prefix does NOT end in / and the suffix does NOT begin with / then append a / to c
c = c.concat("/");
}
}
// and add then concatenate the two together
c = c.concat(pathSuffix);
}
return c;
}
private static boolean createDir(String javaFile){
boolean created = false;
String filePath = javaFile.replaceFirst("[/\\\\]\\w*\\.java","");
File dir = new File(filePath);
if (!dir.exists()){
created = dir.mkdirs();
}else{
created = true;
}
return created;
}
}