| /******************************************************************************* |
| * Copyright (c) 2007 IBM Corporation and Others |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Kentarou FUKUDA - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.actf.visualization.util.html2view; |
| |
| import java.io.BufferedReader; |
| import java.io.BufferedWriter; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.io.UnsupportedEncodingException; |
| import java.util.Vector; |
| |
| import org.eclipse.actf.util.FileUtils; |
| import org.eclipse.actf.util.JapaneseEncodingDetector; |
| |
| /** |
| * Utility class to enable mapping between line number and ACTF_ID. This utility |
| * embeds ACTF_ID into HTML file. |
| */ |
| @SuppressWarnings("nls") |
| public class Html2ViewMapMaker { |
| Vector<Html2ViewMapData> html2viewV; |
| |
| int id; |
| |
| int line; |
| |
| int column; |
| |
| int startLine; |
| |
| int startColumn; |
| |
| boolean changeBase; |
| |
| boolean insertBaseNow; |
| |
| String baseUrl; |
| |
| boolean inXmlDef; // <?xml |
| |
| boolean inDoctype; // <!DOCTYPE |
| |
| boolean inSingle; // alt=' |
| |
| boolean inDouble; // alt=" |
| |
| boolean inTag; // <a |
| |
| boolean inEndTag; // </a |
| |
| boolean inComment; // <!-- |
| |
| boolean inScript; // <script |
| |
| boolean inScriptComment; |
| |
| boolean inNoscript; // <noscript //TODO more improvement |
| |
| boolean inTitle; // <title |
| |
| boolean inHeader; // <head |
| |
| StringBuffer resultSB; |
| |
| StringBuffer toFindHtmlSB; |
| |
| StringBuffer scriptSB; |
| |
| String currentTargetString; |
| |
| private Html2ViewMapMaker() { |
| } |
| |
| /** |
| * Create mapping information between line number and ACTF_ID. The resulting |
| * HTML file that includes ACTF_ID will be stored as a file. |
| * |
| * @param filename |
| * file path of target HTML |
| * @param resultFileName |
| * file name of resulting HTML file |
| * @param targetDir |
| * path for target directory to save result file |
| * @return mapping information as vector of {@link Html2ViewMapData} |
| */ |
| public static Vector<Html2ViewMapData> makeMap(String filename, |
| String resultFileName, String targetDir) { |
| Html2ViewMapMaker maker = new Html2ViewMapMaker(); |
| maker.changeBase = false; |
| return (maker.makeMapLocal(filename, resultFileName, targetDir, true)); |
| } |
| |
| private void init() { |
| inXmlDef = false; |
| inDoctype = false; |
| inSingle = false; |
| inDouble = false; |
| inTag = false; |
| inEndTag = false; |
| inComment = false; |
| inScript = false; |
| inScriptComment = false; |
| |
| insertBaseNow = false; |
| |
| id = 0; |
| line = 0; |
| column = 0; |
| startLine = 0; |
| startColumn = 0; |
| |
| html2viewV = new Vector<Html2ViewMapData>(); |
| resultSB = new StringBuffer(); |
| } |
| |
| // TODO throw syntactic error |
| private Vector<Html2ViewMapData> makeMapLocal(String filename, |
| String resultFileName, String tmpDir, boolean useTmpDir) { |
| |
| PrintWriter htmlWriter; |
| FileInputStream fis = null; |
| |
| String _tmpDir = ""; |
| |
| if (useTmpDir) { |
| // _tmpDir = ADesignerPlugin.getTmpDirectory(); |
| _tmpDir = tmpDir; |
| } |
| |
| init(); |
| |
| String tmpS; |
| |
| BufferedReader br = null; |
| |
| String encoding = "MS932"; |
| |
| // System.out.println(tmpDir + filename); |
| File target = new File(_tmpDir + filename); |
| JapaneseEncodingDetector JED; |
| if (target.isFile() && target.canRead()) { |
| try { |
| fis = new FileInputStream(target); |
| JED = new JapaneseEncodingDetector(fis); |
| encoding = JED.detect(); |
| } catch (Exception e2) { |
| e2.printStackTrace(); |
| return (html2viewV); |
| } finally { |
| if (fis != null) { |
| try { |
| fis.close(); |
| } catch (IOException e1) { |
| e1.printStackTrace(); |
| } |
| } |
| } |
| } else { |
| return (html2viewV); |
| } |
| |
| try { |
| FileOutputStream fos = new FileOutputStream(new File(_tmpDir |
| + resultFileName)); |
| BufferedWriter bos = new BufferedWriter(new OutputStreamWriter(fos, |
| encoding)); |
| htmlWriter = new PrintWriter(bos); |
| } catch (FileNotFoundException fnfe) { |
| fnfe.printStackTrace(); |
| return new Vector<Html2ViewMapData>(); |
| } catch (UnsupportedEncodingException uee) { |
| uee.printStackTrace(); |
| return new Vector<Html2ViewMapData>(); |
| } |
| |
| try { |
| // fis = new FileInputStream(tmpDir + filename); |
| // InputStreamReader isr = new InputStreamReader(fis, encoding); |
| InputStreamReader isr = new InputStreamReader(JED.getInputStream(), |
| encoding); |
| br = new BufferedReader(isr); |
| while ((tmpS = br.readLine()) != null) { |
| |
| // while (!(inScript || inComment) && tmpS.length() > 512) { |
| // int index = tmpS.indexOf("<"); |
| // int index2 = tmpS.indexOf(">"); |
| // |
| // String tmpS2; |
| // if (index2 > index) { |
| // tmpS2 = tmpS.substring(0, index2 + 1); |
| // doFilter(tmpS2); |
| // tmpS = tmpS.substring(index2 + 1); |
| // } else if (index > 0) { |
| // tmpS2 = tmpS.substring(0, index); |
| // doFilter(tmpS2); |
| // tmpS = tmpS.substring(index); |
| // } else { |
| // break; |
| // } |
| // |
| // } |
| // while(doFilter(tmpS)); |
| doSourceLine(tmpS); |
| // System.out.println(tmpS); |
| line++; |
| column = 0; |
| } |
| |
| } catch (Exception e) { |
| // e.printStackTrace(); |
| |
| try { |
| fis.close(); |
| init(); |
| fis = new FileInputStream(_tmpDir + filename); |
| InputStreamReader isr = new InputStreamReader(fis); |
| br = new BufferedReader(isr); |
| while ((tmpS = br.readLine()) != null) { |
| doSourceLine(tmpS); |
| line++; |
| column = 0; |
| } |
| } catch (Exception e2) { |
| e2.printStackTrace(); |
| return (new Vector<Html2ViewMapData>()); |
| } |
| } finally { |
| try { |
| fis.close(); |
| } catch (IOException e1) { |
| e1.printStackTrace(); |
| } |
| } |
| |
| htmlWriter.print(resultSB.toString()); |
| htmlWriter.flush(); |
| htmlWriter.close(); |
| return (html2viewV); |
| } |
| |
| private void doSourceLine(String target) { |
| currentTargetString = target; |
| boolean flag = true; |
| while (flag) { |
| flag = doFilter(currentTargetString); |
| // System.out.println(currentTargetString); |
| } |
| } |
| |
| private boolean doFilter(String targetS) { |
| if (targetS == null) { |
| return false; |
| } else if (targetS.equals("")) { |
| resultSB.append(FileUtils.LINE_SEP); |
| return false; |
| } else { |
| if (inSingle) { |
| doValueSingle(targetS); |
| } else if (inDouble) { |
| doValueDouble(targetS); |
| } else if (inTag) { |
| doTag(targetS); |
| } else if (inEndTag) { |
| doEndTag(targetS); |
| } else if (inComment) { |
| doComment(targetS); |
| } else if (inDoctype) { |
| doDoctype(targetS); |
| } else if (inScript) { |
| if (inScriptComment) { |
| doScriptComment(targetS); |
| } else { |
| doScript(targetS); |
| } |
| } else if (inXmlDef) { |
| doXmlDef(targetS); |
| } else { |
| doNormal(targetS); |
| } |
| } |
| return true; |
| } |
| |
| private void doValueSingle(String targetS) { |
| doValue(targetS, "\'"); |
| } |
| |
| private void doValueDouble(String targetS) { |
| doValue(targetS, "\""); |
| } |
| |
| private void doValue(String targetS, String quatation) { |
| int endIndex = targetS.indexOf(quatation); |
| // System.out.println("target: "+targetS); |
| |
| // not permitted |
| int startIndex = targetS.indexOf("<"); |
| if (startIndex > -1 && (endIndex < 0 || endIndex > startIndex)) { |
| |
| // " < or " < " |
| |
| int threshold = endIndex; |
| if (endIndex < 0) { |
| threshold = Integer.MAX_VALUE; |
| } |
| |
| // <+alphabet? -> might be tag |
| String tmpS = ""; |
| try { |
| tmpS = targetS.substring(startIndex + 1); |
| } catch (Exception e) { |
| } |
| int tmpLine = line + 1; |
| while (startIndex > -1 && startIndex < threshold |
| && !tmpS.matches("\\p{Alpha}.*")) { |
| startIndex = targetS.indexOf("<", startIndex + 1); |
| if (startIndex > -1) { |
| tmpS = ""; |
| try { |
| tmpS = targetS.substring(startIndex + 1); |
| } catch (Exception e) { |
| } |
| } |
| } |
| |
| if (startIndex > -1 && startIndex < threshold) { |
| System.out |
| .print("HTMLVMM: start tag in attribute value : line: " |
| + tmpLine + " : " + targetS + " : "); |
| |
| int tagEndIndex = targetS.indexOf(">"); |
| if (tagEndIndex > -1 && tagEndIndex < startIndex) { |
| targetS = targetS.substring(0, tagEndIndex) + quatation |
| + targetS.substring(tagEndIndex); |
| endIndex = targetS.indexOf(quatation); |
| System.out.println("with end tag"); |
| } else { |
| targetS = targetS.substring(0, startIndex) + quatation |
| + ">" + targetS.substring(startIndex); |
| endIndex = targetS.indexOf(quatation); |
| System.out.println("without end tag"); |
| } |
| |
| } |
| } |
| |
| if (endIndex > -1) { |
| inSingle = false; |
| inDouble = false; |
| |
| if (changeBase) { |
| toFindHtmlSB.append(targetS.substring(0, endIndex)); |
| } |
| |
| doNext(targetS, endIndex); |
| } else { |
| if (changeBase) { |
| toFindHtmlSB.append(targetS); |
| } |
| doNext(targetS, endIndex); |
| } |
| } |
| |
| private boolean checkIndex(int endIndex, int quatationIndex) { |
| if (quatationIndex > -1) { |
| if (endIndex > -1 && (endIndex < quatationIndex)) { |
| return (false); |
| } |
| return (true); |
| } |
| return (false); |
| } |
| |
| private boolean isUnexpectedStartTag(int singleIndex, int doubleIndex, |
| int endIndex, int startTagIndex) { |
| if (startTagIndex > -1) { |
| return ((endIndex < 0 || endIndex > startTagIndex) |
| && (singleIndex < 0 || singleIndex > startTagIndex) && (doubleIndex < 0 || doubleIndex > startTagIndex)); |
| } |
| return (false); |
| } |
| |
| private int getAttributeIndex(String targetS, boolean isDouble, int endIndex) { |
| String quatation = "\'"; |
| if (isDouble) { |
| quatation = "\""; |
| } |
| |
| int threshold = endIndex; |
| if (endIndex < 0) { |
| threshold = Integer.MAX_VALUE; |
| } |
| |
| int index = targetS.indexOf(quatation); |
| while (index > -1 && index < threshold) { |
| String tmpS = targetS.substring(0, index); |
| if (tmpS.matches(".*=\\p{Space}*")) { |
| return (index); |
| } |
| // System.out.println("not attribute: "+tmpS); |
| index = targetS.indexOf(quatation, index + 1); |
| } |
| return index; |
| } |
| |
| private void doTag(String targetS) { |
| int endIndex = targetS.indexOf(">"); |
| |
| // int singleIndex = targetS.indexOf("\'"); |
| // int doubleIndex = targetS.indexOf("\""); |
| |
| int singleIndex = getAttributeIndex(targetS, false, endIndex); |
| int doubleIndex = getAttributeIndex(targetS, true, endIndex); |
| |
| boolean singleC = checkIndex(endIndex, singleIndex); |
| boolean doubleC = checkIndex(endIndex, doubleIndex); |
| |
| if (singleC && doubleC) { |
| if (doubleIndex < singleIndex) { |
| singleC = false; |
| } else { |
| doubleC = false; |
| } |
| } |
| |
| // unexpected next tag start |
| int startIndex = targetS.indexOf("<"); |
| |
| if (isUnexpectedStartTag(singleIndex, doubleIndex, endIndex, startIndex)) { |
| int tmpLine = line + 1; |
| System.out.println("HTMLVMM: unexpected start tag: line:" + tmpLine |
| + " : " + targetS); |
| |
| targetS = targetS.substring(0, startIndex) + ">" |
| + targetS.substring(startIndex); |
| |
| // System.out.println(targetS); |
| singleC = false; |
| doubleC = false; |
| |
| endIndex = targetS.indexOf(">"); |
| |
| } |
| |
| if (singleC) { |
| // single |
| inSingle = true; |
| if (changeBase) { |
| toFindHtmlSB.append(targetS.substring(0, singleIndex)); |
| } |
| doNext(targetS, singleIndex); |
| } else if (doubleC) { |
| // double |
| inDouble = true; |
| if (changeBase) { |
| toFindHtmlSB.append(targetS.substring(0, doubleIndex)); |
| } |
| doNext(targetS, doubleIndex); |
| } else { |
| boolean endWithSlash = false; |
| |
| if (endIndex > -1) { |
| inTag = false; |
| |
| int tmpIndex = targetS.indexOf("/>"); |
| // System.out.println(tmpIndex+" "+endIndex); |
| if (tmpIndex > -1 && (tmpIndex == endIndex - 1)) { |
| endWithSlash = true; |
| } |
| |
| if (changeBase) { |
| String tmpS = toFindHtmlSB.toString() |
| + targetS.substring(0, endIndex); |
| tmpS = tmpS.toLowerCase(); |
| |
| if (tmpS.startsWith("html")) { |
| // System.out.println("find html"); |
| changeBase = false; |
| insertBaseNow = true; |
| } |
| |
| } |
| |
| Html2ViewMapData h2vmd = new Html2ViewMapData(new int[] { |
| startLine, startColumn }, new int[] { line, |
| column + endIndex + 1 }); |
| // System.out.println(h2vmd.toString()); |
| html2viewV.add(h2vmd); |
| doNext(targetS, endIndex, true, endWithSlash); |
| } else { |
| if (changeBase) { |
| toFindHtmlSB.append(targetS); |
| } |
| doNext(targetS, endIndex); |
| } |
| |
| } |
| |
| } |
| |
| private void doEndTag(String targetS) { |
| int endIndex = targetS.indexOf(">"); |
| if (endIndex > -1) { |
| inEndTag = false; |
| } |
| doNext(targetS, endIndex); |
| } |
| |
| private void doComment(String targetS) { |
| int endIndex = targetS.indexOf("-->"); |
| if (endIndex > -1) { |
| inComment = false; |
| } |
| doNext(targetS, endIndex); |
| } |
| |
| private void doScript(String targetS) { |
| int commentIndex = targetS.toLowerCase().indexOf("<!--"); |
| int endIndex = targetS.toLowerCase().indexOf("</script>"); |
| |
| inScriptComment = checkIndex(endIndex, commentIndex); |
| |
| if (inScriptComment) { |
| scriptSB.append(targetS.substring(0, commentIndex + 1)); |
| doNext(targetS, commentIndex); |
| return; |
| } else if (endIndex > -1) { |
| scriptSB.append(targetS.substring(0, endIndex + 8)); |
| String tmpScript = scriptSB.toString(); |
| String tmpScript2 = tmpScript.toLowerCase(); |
| |
| if (changeBase && tmpScript2.indexOf(".createstylesheet") > -1) { |
| resultSB.insert(resultSB.indexOf("<HEAD><BASE") + 6, tmpScript |
| + ">"); |
| resultSB.append("<!-- acc_memo script move to top--"); |
| } else { |
| resultSB.append(tmpScript); |
| } |
| targetS = targetS.substring(endIndex + 8); |
| endIndex = 0; |
| inScript = false; |
| } else { |
| scriptSB.append(targetS + FileUtils.LINE_SEP); |
| } |
| doNext(targetS, endIndex); |
| } |
| |
| private void doScriptComment(String targetS) { |
| int endIndex = targetS.indexOf("-->"); |
| if (endIndex > -1) { |
| scriptSB.append(targetS.substring(0, endIndex + 1)); |
| inScriptComment = false; |
| } else { |
| scriptSB.append(targetS + FileUtils.LINE_SEP); |
| } |
| doNext(targetS, endIndex); |
| } |
| |
| private void doDoctype(String targetS) { |
| int endIndex = targetS.indexOf(">"); |
| if (endIndex > -1) { |
| inDoctype = false; |
| } |
| // System.out.println(targetS); |
| doNext(targetS, endIndex); |
| } |
| |
| private void doXmlDef(String targetS) { |
| int endIndex = targetS.indexOf(">"); |
| if (endIndex > -1) { |
| inXmlDef = false; |
| } |
| // System.out.println(targetS); |
| doNext(targetS, endIndex); |
| } |
| |
| |
| private void doNormal(String targetS) { |
| int startIndex = targetS.indexOf("<"); |
| if (startIndex > -1) { |
| startLine = line; |
| startColumn = column + startIndex; |
| |
| // TODO Newline, NOSCRIPT |
| String tmpS = targetS.toLowerCase(); |
| int endTagIndex = tmpS.indexOf("</"); |
| int tmpIndex = tmpS.indexOf("<!--"); |
| int tmpIndex2 = tmpS.indexOf("<!doctype"); |
| int tmpIndex3 = tmpS.indexOf("<script"); |
| int tmpIndex4 = tmpS.indexOf("<?xml"); |
| // System.out.println(tmpS+" : "+endTagIndex+" "+tmpIndex+" |
| // "+tmpIndex2+" "+tmpIndex3); |
| if (startIndex == endTagIndex) { |
| // System.out.println("start endTag: "+line+" "+startColumn); |
| inEndTag = true; |
| } else if (startIndex == tmpIndex) { |
| // System.out.println("start comment: "+line+" "+startColumn); |
| inComment = true; |
| } else if (startIndex == tmpIndex2) { |
| // System.out.println("start doctype: "+line+" "+startColumn); |
| inDoctype = true; |
| } else if (startIndex == tmpIndex3) { |
| // System.out.println("start script: "+line+" "+startColumn); |
| inScript = true; |
| scriptSB = new StringBuffer("<"); |
| resultSB.append(targetS.substring(0, startIndex)); |
| } else if (startIndex == tmpIndex4) { |
| inXmlDef = true; |
| } else { |
| // System.out.println("start tag: "+line+" "+startColumn); |
| if (changeBase) { |
| toFindHtmlSB = new StringBuffer(); |
| } |
| inTag = true; |
| } |
| } |
| doNext(targetS, startIndex); |
| } |
| |
| private void doNext(String targetS, int _index) { |
| doNext(targetS, _index, false, false); |
| } |
| |
| // private void doNext(String targetS, int _index, boolean insertId) { |
| // doNext(targetS, _index, insertId, false); |
| // } |
| |
| private void doNext(String targetS, int _index, boolean insertId, |
| boolean endWithSlash) { |
| if (_index > -1) { |
| int index = _index + 1; |
| column = column + index; |
| |
| if (insertId) { |
| if (endWithSlash) { |
| resultSB.append(targetS.substring(0, _index - 1) + " " |
| + Html2ViewMapData.ACTF_ID + "=\'" + id + "\'/>"); |
| } else { |
| resultSB.append(targetS.substring(0, _index) + " " |
| + Html2ViewMapData.ACTF_ID + "=\'" + id + "\'>"); |
| } |
| id++; |
| } else { |
| if (!inScript) { |
| resultSB.append(targetS.substring(0, index)); |
| } |
| } |
| |
| if (insertBaseNow) { |
| resultSB.append("<HEAD><BASE href=\"" + baseUrl + "\"></HEAD>"); |
| insertBaseNow = false; |
| } |
| |
| // doFilter(targetS.substring(index)); |
| currentTargetString = targetS.substring(index); |
| } else { |
| if (!inScript) { |
| resultSB.append(targetS + FileUtils.LINE_SEP); |
| } |
| currentTargetString = null; |
| } |
| |
| } |
| |
| } |