blob: 6a601fc8aab59c931e741a9d1d44d67e2ad09b28 [file] [log] [blame]
package org.apache.flex.compiler.internal.graph;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.apache.flex.compiler.internal.projects.DependencyGraph;
import org.apache.flex.compiler.units.ICompilationUnit;
public class GoogDepsWriter {
public GoogDepsWriter(ICompilationUnit mainCU, File outputFolder)
{
this.mainCU = mainCU;
this.outputFolderPath = outputFolder.getAbsolutePath();
this.sourceFolderPath = mainCU.getAbsoluteFilename();
File sourceFile = new File(sourceFolderPath);
sourceFile = sourceFile.getParentFile();
this.sourceFolderPath = sourceFile.getAbsolutePath();
String flexJSHome = System.getenv("FLEXJS_HOME");
if (flexJSHome == null || flexJSHome.length() == 0)
System.out.println("FLEXJS_HOME not defined. Should point to root of FlexJS source.");
frameworkRoot = flexJSHome;
}
private ICompilationUnit mainCU;
private String outputFolderPath;
private String sourceFolderPath;
private HashMap<String,GoogDep> depMap = new HashMap<String,GoogDep>();
public ArrayList<String> getListOfFiles() throws InterruptedException
{
buildDB();
String mainName = mainCU.getShortNames().get(0);
ArrayList<GoogDep> dps = sort(mainName);
ArrayList<String> files = new ArrayList<String>();
for (GoogDep gd : dps)
{
files.add(gd.filePath);
}
return files;
}
public void writeToStream(OutputStream outputStream) throws InterruptedException, FileNotFoundException
{
buildDB();
String mainName = mainCU.getShortNames().get(0);
ArrayList<GoogDep> dps = sort(mainName);
String outString = "// generated by FalconJS" + "\n";
int n = dps.size();
for (int i = n - 1; i >= 0; i--)
{
GoogDep gd = dps.get(i);
String s = "goog.addDependency('";
s += relativePath(gd.filePath);
s += "', ['";
s += gd.className;
s += "'], [";
s += getDependencies(gd.deps);
s += "]);\n";
outString += s;
}
System.out.println("Assumptions:");
System.out.println(" 1) Output folder has copy of goog folder from GoogleClosure/library/closure/goog");
System.out.println(" 2) Output folder has copy of FlexJS source in FlexJS folder");
System.out.println(" 3) Output Folder structure is:");
System.out.println(" OutputFolder/");
System.out.println(" goog/");
System.out.println(" base.js");
System.out.println(" ...");
System.out.println(" flash/ (from FlexJS/src)");
System.out.println(" events/ (from FlexJS/src)");
System.out.println(" org/ (from FlexJS/src)");
System.out.println(" apache/ (from FlexJS/src)");
System.out.println(" 4) Output folder has html file of the form:");
System.out.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
System.out.println("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
System.out.println("<head>");
System.out.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />");
System.out.println("<script type=\"text/javascript\" src=\"goog/base.js\" ></script>");
System.out.println("<script type=\"text/javascript\" src=\"" + mainName + "Deps.js" + "\" ></script>");
System.out.println("<script type=\"text/javascript\">");
System.out.println(" goog.require('" + mainName + "')");
System.out.println("</script>");
System.out.println("<script type=\"text/javascript\">");
System.out.println(" var app = new " + mainName + "();");
System.out.println("</script>");
System.out.println("<title>" + mainName + "</title>");
System.out.println("</head>");
System.out.println("<body onload=\"app.start()\">");
System.out.println("</body>");
System.out.println("</html>");
File htmlFile = new File(outputFolderPath + File.separator + mainName + ".example.html");
BufferedOutputStream outputbuffer = new BufferedOutputStream(new FileOutputStream(htmlFile));
String html = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
html += "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n";
html += "<head>\n";
html += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n";
html += "<script type=\"text/javascript\" src=\"goog/base.js\" ></script>\n";
html += "<script type=\"text/javascript\" src=\"" + mainName + "Deps.js" + "\" ></script>\n";
html += "<script type=\"text/javascript\">\n";
html += " goog.require('" + mainName + "')\n";
html += "</script>\n";
html += "<script type=\"text/javascript\">\n";
html += " var app = new " + mainName + "();\n";
html += "</script>\n";
html += "<title>" + mainName + "</title>\n";
html += "</head>\n";
html += "<body onload=\"app.start()\">\n";
html += "</body>\n";
html += "</html>\n";
try
{
outputbuffer.write(html.getBytes());
outputbuffer.flush();
outputbuffer.close();
outputStream.write(outString.getBytes());
}
catch (IOException e)
{
}
}
private void buildDB()
{
try {
addDeps(mainCU.getShortNames().get(0));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private HashMap<String, GoogDep> visited = new HashMap<String, GoogDep>();
private ArrayList<GoogDep> sort(String rootClassName)
{
ArrayList<GoogDep> arr = new ArrayList<GoogDep>();
GoogDep current = depMap.get(rootClassName);
sortFunction(current, arr);
return arr;
}
private void sortFunction(GoogDep current, ArrayList<GoogDep> arr)
{
visited.put(current.className, current);
ArrayList<String> deps = current.deps;
for (String className : deps)
{
if (!visited.containsKey(className))
{
GoogDep gd = depMap.get(className);
sortFunction(gd, arr);
}
}
arr.add(current);
}
private void addDeps(String className)
{
if (depMap.containsKey(className))
return;
// build goog dependency list
GoogDep gd = new GoogDep();
gd.className = className;
gd.filePath = getFilePath(className);
depMap.put(gd.className, gd);
ArrayList<String> deps = getDirectDependencies(gd.filePath);
gd.deps = new ArrayList<String>();
for (String dep : deps)
{
gd.deps.add(dep);
addDeps(dep);
}
}
String frameworkRoot;
String getFilePath(String className)
{
System.out.println("Finding file for class: " + className);
String classPath = className.replace(".", File.separator);
String fn = frameworkRoot + File.separator + classPath + ".js";
File f = new File(fn);
if (f.exists())
return fn;
fn = sourceFolderPath + File.separator + classPath + ".js";
f = new File(fn);
if (f.exists())
{
fn = outputFolderPath + File.separator + classPath + ".js";
File destFile = new File(fn);
// copy source to output
try {
FileUtils.copyFile(f, destFile);
System.out.println("Copying file for class: " + className);
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Error copying file for class: " + className);
}
return fn;
}
fn = outputFolderPath + File.separator + classPath + ".js";
f = new File(fn);
if (f.exists())
return fn;
if (className.indexOf('.') > -1)
{
classPath = className.substring(className.lastIndexOf('.') + 1);
fn = outputFolderPath + File.separator + classPath + ".js";
f = new File(fn);
if (f.exists())
return fn;
}
System.out.println("Could not find file for class: " + className);
return "";
}
private ArrayList<String> getDirectDependencies(String fn)
{
ArrayList<String> deps = new ArrayList<String>();
FileInputStream fis;
try {
fis = new FileInputStream(fn);
Scanner scanner = new Scanner(fis, "UTF-8");
while (scanner.hasNextLine())
{
String s = scanner.nextLine();
if (s.indexOf("goog.inherits") > -1)
break;
int c = s.indexOf("goog.require");
if (c > -1)
{
int c2 = s.indexOf(")");
s = s.substring(c + 14, c2 - 1);
deps.add(s);
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return deps;
}
private String getDependencies(ArrayList<String> deps)
{
String s = "";
for (String dep : deps)
{
if (s.length() > 0)
{
s += ", ";
}
s += "'" + dep + "'";
}
return s;
}
String relativePath(String path)
{
if (path.indexOf(frameworkRoot) == 0)
{
path = path.replace(frameworkRoot, "");
}
else if (path.indexOf(outputFolderPath) == 0)
{
path = path.replace(outputFolderPath, "");
}
// paths are actually URIs and always have forward slashes
path = path.replace('\\', '/');
return ".." + path;
}
private class GoogDep
{
public String filePath;
public String className;
public ArrayList<String> deps;
}
}