< prev index next >

application/org.openjdk.jmc.flightrecorder.ui/src/main/java/org/openjdk/jmc/flightrecorder/ui/overview/ResultReportUi.java

Print this page




  70 import org.openjdk.jmc.flightrecorder.rules.Result;
  71 import org.openjdk.jmc.flightrecorder.rules.Severity;
  72 import org.openjdk.jmc.flightrecorder.rules.report.html.internal.HtmlResultGroup;
  73 import org.openjdk.jmc.flightrecorder.rules.report.html.internal.HtmlResultProvider;
  74 import org.openjdk.jmc.flightrecorder.rules.report.html.internal.RulesHtmlToolkit;
  75 import org.openjdk.jmc.flightrecorder.rules.util.RulesToolkit;
  76 import org.openjdk.jmc.flightrecorder.ui.DataPageDescriptor;
  77 import org.openjdk.jmc.flightrecorder.ui.FlightRecorderUI;
  78 import org.openjdk.jmc.flightrecorder.ui.IPageContainer;
  79 import org.openjdk.jmc.ui.misc.DisplayToolkit;
  80 
  81 /**
  82  * This class handles creation of a HTML/JS based result report, it has two modes, Single Page and
  83  * Full Report. Single Page is used by the ResultPage PageBookView and the Full Report by the Result
  84  * Overview page.
  85  */
  86 public class ResultReportUi {
  87 
  88         private static final String OVERVIEW_MAKE_SCALABLE = "overview.makeScalable();"; //$NON-NLS-1$
  89         private static final String OVERVIEW_UPDATE_PAGE_HEADERS_VISIBILITY = "overview.updatePageHeadersVisibility();"; //$NON-NLS-1$
  90         private static final Pattern HTML_ANCHOR_PATTERN = Pattern.compile("<a href=\"(.*?)\">(.*?)</a>");
  91         private static final String OPEN_BROWSER_WINDOW = "openWindowByUrl";
  92 
  93         private static class Linker extends BrowserFunction {
  94 
  95                 private Iterable<HtmlResultGroup> resultGroups;
  96                 private IPageContainer editor;
  97 
  98                 public Linker(Browser browser, String name, Iterable<HtmlResultGroup> resultGroups, IPageContainer editor) {
  99                         super(browser, name);
 100                         this.resultGroups = resultGroups;
 101                         this.editor = editor;
 102                 }
 103 
 104                 @Override
 105                 public Object function(Object[] arguments) {
 106                         if (arguments.length != 1 && !(arguments[0] instanceof String)) {
 107                                 return null;
 108                         }
 109                         String id = arguments[0].toString();
 110                         for (HtmlResultGroup group : resultGroups) {
 111                                 if (group instanceof PageDescriptorResultGroup && id.equals(group.getId())) {


 274             });
 275         }
 276 
 277         /*
 278      * We replace the anchors in the HTML when running in the JMC UI to make
 279      * it possible to follow them. See JMC-5419 for more information.
 280      */
 281         private static String adjustAnchorFollowAction(String html) {
 282                 Map<String, String> map = new HashMap<>();
 283                 Matcher m = HTML_ANCHOR_PATTERN.matcher(html);
 284                 while (m.find()) {
 285                         map.put(m.group(1), m.group(2));
 286                 }
 287                 for(Map.Entry<String, String> e: map.entrySet()){
 288                         html = html.replace(e.getKey(), openWindowMethod(e.getKey(), e.getValue()));
 289                 }
 290                 return html;
 291         }
 292 
 293         private static String openWindowMethod(String url, String name){
 294         return new StringBuilder().append("#\" onclick=\"").append(OPEN_BROWSER_WINDOW).append("(").append("\u0027")
 295                 .append(url).append("\u0027").append(',').append("\u0027")
 296                 .append(name).append("\u0027").append(");return false;").toString();
 297     }
 298 
 299         public ResultReportUi(boolean isSinglePage) {
 300                 this.isSinglePage = isSinglePage;
 301         }
 302 
 303         public List<String> getHtml(IPageContainer editor) {
 304                 List<String> overviewHtml = new ArrayList<>(1);
 305                 String adjustedHtml = adjustAnchorFollowAction(RulesHtmlToolkit.generateStructuredHtml(new PageContainerResultProvider(editor), descriptors,
 306                                 resultExpandedStates, true));
 307                 overviewHtml.add(adjustedHtml);
 308                 return overviewHtml;
 309         }
 310 
 311         public void setShowOk(boolean showOk) {
 312                 this.showOk = showOk;
 313                 if (!isSinglePage) {
 314                         try {
 315                                 // FIXME: Avoid implicit dependency on HTML/javascript template. Generate script in RulesHtmlToolkit instead
 316                                 browser.evaluate(String.format("overview.showOk(%b);", showOk)); //$NON-NLS-1$


 334         private Collection<String> topics = RulesToolkit.getAllTopics();
 335         private Collection<Result> results;
 336 
 337         public void updateRule(IRule rule) {
 338                 // FIXME: Possible race condition where elements may be added to the queue without being consumed
 339                 if (resultEventQueue.isEmpty()) {
 340                         resultEventQueue.add(rule);
 341                         DisplayToolkit.safeAsyncExec(() -> {
 342                                 if (browser.isDisposed()) {
 343                                         return;
 344                                 }
 345                                 // FIXME: Avoid implicit dependency on HTML/javascript template. Generate script in RulesHtmlToolkit instead
 346                                 StringBuilder script = new StringBuilder();
 347                                 while (!resultEventQueue.isEmpty()) {
 348                                         IRule next = resultEventQueue.poll();
 349                                         Result result = editor.getRuleManager().getResult(next);
 350                                         if (result == null) {
 351                                                 continue;
 352                                         }
 353                                         long score = Math.round(result.getScore());
 354                                         String adjustedHtml = adjustAnchorFollowAction(RulesHtmlToolkit.getDescription(result));//$NON-NLS-1$ //$NON-NLS-2$
 355                                         String quoteEscape = adjustedHtml.replaceAll("\\\"", "\\\\\""); //$NON-NLS-1$ //$NON-NLS-2$
 356                                         String description = quoteEscape.replaceAll("\n", "</br>"); //$NON-NLS-1$ //$NON-NLS-2$
 357                                         script.append(String.format("overview.updateResult(\"%s\", %d, \"%s\");", //$NON-NLS-1$
 358                                                         result.getRule().getId(), score, description));
 359                                 }
 360                                 String[] topicsArray = topics.toArray(new String[topics.size()]);
 361                                 if (!isSinglePage) {
 362                                         boolean allOk = editor.getRuleManager().getScoreStream(topicsArray)
 363                                                         .allMatch(d -> d > RulesHtmlToolkit.IN_PROGRESS && d < Severity.INFO.getLimit()) && !showOk;
 364                                         script.append(String.format("overview.allOk(%b);", allOk)); //$NON-NLS-1$
 365                                 }
 366                                 boolean allIgnored = editor.getRuleManager().getScoreStream(topicsArray)
 367                                                 .allMatch(d -> d == Result.IGNORE);
 368                                 script.append(String.format("overview.allIgnored(%b);", allIgnored)); //$NON-NLS-1$
 369                                 try {
 370                                         if (isLoaded) {
 371                                                 browser.evaluate(script.toString());
 372                                                 browser.evaluate(OVERVIEW_UPDATE_PAGE_HEADERS_VISIBILITY);
 373                                         } else {
 374                                                 final String finalScript = script.toString();


 413                 try {
 414                         this.showOk = Boolean.valueOf(state.getChild("report").getChild("showOk").getAttribute("value")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 415                 } catch (NullPointerException npe) {
 416                 }
 417                 browser.addListener(SWT.MenuDetect, new Listener() {
 418                         @Override
 419                         public void handleEvent(Event event) {
 420                                 event.doit = false;
 421                         }
 422                 });
 423                 try {
 424                         String html = isSinglePage ? RulesHtmlToolkit.generateSinglePageHtml(results)
 425                                         : RulesHtmlToolkit.generateStructuredHtml(new PageContainerResultProvider(editor), descriptors,
 426                                                         resultExpandedStates, false);
 427                         String adjustedHtml = adjustAnchorFollowAction(html);
 428                         browser.setText(adjustedHtml, true);
 429                         browser.setJavascriptEnabled(true);
 430                         browser.addProgressListener(new ProgressAdapter() {
 431                                 @Override
 432                                 public void completed(ProgressEvent event) {
 433                                         new OpenWindowFunction(browser, OPEN_BROWSER_WINDOW); //$NON-NLS-1$
 434                                         new Linker(browser, "linker", descriptors, editor); //$NON-NLS-1$
 435                                         new Expander(browser, "expander"); //$NON-NLS-1$
 436                                         browser.execute(String.format("overview.showOk(%b);", showOk)); //$NON-NLS-1$
 437                                         if (isSinglePage) {
 438                                                 browser.execute(OVERVIEW_MAKE_SCALABLE);
 439                                         }
 440                                         browser.evaluate(OVERVIEW_UPDATE_PAGE_HEADERS_VISIBILITY);
 441                                         isLoaded = true;
 442                                 }
 443                         });
 444                 } catch (IOException | IllegalArgumentException e) {
 445                         FlightRecorderUI.getDefault().getLogger().log(Level.WARNING, "Could not create Report Overview", e); //$NON-NLS-1$
 446                         return false;
 447                 }
 448                 return true;
 449         }
 450 
 451         public void saveTo(IWritableState state) {
 452                 state.createChild("report").createChild("showOk").putString("value", showOk.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 453         }


  70 import org.openjdk.jmc.flightrecorder.rules.Result;
  71 import org.openjdk.jmc.flightrecorder.rules.Severity;
  72 import org.openjdk.jmc.flightrecorder.rules.report.html.internal.HtmlResultGroup;
  73 import org.openjdk.jmc.flightrecorder.rules.report.html.internal.HtmlResultProvider;
  74 import org.openjdk.jmc.flightrecorder.rules.report.html.internal.RulesHtmlToolkit;
  75 import org.openjdk.jmc.flightrecorder.rules.util.RulesToolkit;
  76 import org.openjdk.jmc.flightrecorder.ui.DataPageDescriptor;
  77 import org.openjdk.jmc.flightrecorder.ui.FlightRecorderUI;
  78 import org.openjdk.jmc.flightrecorder.ui.IPageContainer;
  79 import org.openjdk.jmc.ui.misc.DisplayToolkit;
  80 
  81 /**
  82  * This class handles creation of a HTML/JS based result report, it has two modes, Single Page and
  83  * Full Report. Single Page is used by the ResultPage PageBookView and the Full Report by the Result
  84  * Overview page.
  85  */
  86 public class ResultReportUi {
  87 
  88         private static final String OVERVIEW_MAKE_SCALABLE = "overview.makeScalable();"; //$NON-NLS-1$
  89         private static final String OVERVIEW_UPDATE_PAGE_HEADERS_VISIBILITY = "overview.updatePageHeadersVisibility();"; //$NON-NLS-1$
  90         private static final Pattern HTML_ANCHOR_PATTERN = Pattern.compile("<a href=\"(.*?)\">(.*?)</a>"); //$NON-NLS-1$
  91         private static final String OPEN_BROWSER_WINDOW = "openWindowByUrl"; //$NON-NLS-1$
  92 
  93         private static class Linker extends BrowserFunction {
  94 
  95                 private Iterable<HtmlResultGroup> resultGroups;
  96                 private IPageContainer editor;
  97 
  98                 public Linker(Browser browser, String name, Iterable<HtmlResultGroup> resultGroups, IPageContainer editor) {
  99                         super(browser, name);
 100                         this.resultGroups = resultGroups;
 101                         this.editor = editor;
 102                 }
 103 
 104                 @Override
 105                 public Object function(Object[] arguments) {
 106                         if (arguments.length != 1 && !(arguments[0] instanceof String)) {
 107                                 return null;
 108                         }
 109                         String id = arguments[0].toString();
 110                         for (HtmlResultGroup group : resultGroups) {
 111                                 if (group instanceof PageDescriptorResultGroup && id.equals(group.getId())) {


 274             });
 275         }
 276 
 277         /*
 278      * We replace the anchors in the HTML when running in the JMC UI to make
 279      * it possible to follow them. See JMC-5419 for more information.
 280      */
 281         private static String adjustAnchorFollowAction(String html) {
 282                 Map<String, String> map = new HashMap<>();
 283                 Matcher m = HTML_ANCHOR_PATTERN.matcher(html);
 284                 while (m.find()) {
 285                         map.put(m.group(1), m.group(2));
 286                 }
 287                 for(Map.Entry<String, String> e: map.entrySet()){
 288                         html = html.replace(e.getKey(), openWindowMethod(e.getKey(), e.getValue()));
 289                 }
 290                 return html;
 291         }
 292 
 293         private static String openWindowMethod(String url, String name){
 294         return new StringBuilder().append("#\" onclick=\"").append(OPEN_BROWSER_WINDOW).append("(").append("\u0027") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 295                 .append(url).append("\u0027").append(',').append("\u0027") //$NON-NLS-1$ //$NON-NLS-2$
 296                 .append(name).append("\u0027").append(");return false;").toString();  //$NON-NLS-1$//$NON-NLS-2$
 297     }
 298 
 299         public ResultReportUi(boolean isSinglePage) {
 300                 this.isSinglePage = isSinglePage;
 301         }
 302 
 303         public List<String> getHtml(IPageContainer editor) {
 304                 List<String> overviewHtml = new ArrayList<>(1);
 305                 String adjustedHtml = adjustAnchorFollowAction(RulesHtmlToolkit.generateStructuredHtml(new PageContainerResultProvider(editor), descriptors,
 306                                 resultExpandedStates, true));
 307                 overviewHtml.add(adjustedHtml);
 308                 return overviewHtml;
 309         }
 310 
 311         public void setShowOk(boolean showOk) {
 312                 this.showOk = showOk;
 313                 if (!isSinglePage) {
 314                         try {
 315                                 // FIXME: Avoid implicit dependency on HTML/javascript template. Generate script in RulesHtmlToolkit instead
 316                                 browser.evaluate(String.format("overview.showOk(%b);", showOk)); //$NON-NLS-1$


 334         private Collection<String> topics = RulesToolkit.getAllTopics();
 335         private Collection<Result> results;
 336 
 337         public void updateRule(IRule rule) {
 338                 // FIXME: Possible race condition where elements may be added to the queue without being consumed
 339                 if (resultEventQueue.isEmpty()) {
 340                         resultEventQueue.add(rule);
 341                         DisplayToolkit.safeAsyncExec(() -> {
 342                                 if (browser.isDisposed()) {
 343                                         return;
 344                                 }
 345                                 // FIXME: Avoid implicit dependency on HTML/javascript template. Generate script in RulesHtmlToolkit instead
 346                                 StringBuilder script = new StringBuilder();
 347                                 while (!resultEventQueue.isEmpty()) {
 348                                         IRule next = resultEventQueue.poll();
 349                                         Result result = editor.getRuleManager().getResult(next);
 350                                         if (result == null) {
 351                                                 continue;
 352                                         }
 353                                         long score = Math.round(result.getScore());
 354                                         String adjustedHtml = adjustAnchorFollowAction(RulesHtmlToolkit.getDescription(result));
 355                                         String quoteEscape = adjustedHtml.replaceAll("\\\"", "\\\\\""); //$NON-NLS-1$ //$NON-NLS-2$
 356                                         String description = quoteEscape.replaceAll("\n", "</br>"); //$NON-NLS-1$ //$NON-NLS-2$
 357                                         script.append(String.format("overview.updateResult(\"%s\", %d, \"%s\");", //$NON-NLS-1$
 358                                                         result.getRule().getId(), score, description));
 359                                 }
 360                                 String[] topicsArray = topics.toArray(new String[topics.size()]);
 361                                 if (!isSinglePage) {
 362                                         boolean allOk = editor.getRuleManager().getScoreStream(topicsArray)
 363                                                         .allMatch(d -> d > RulesHtmlToolkit.IN_PROGRESS && d < Severity.INFO.getLimit()) && !showOk;
 364                                         script.append(String.format("overview.allOk(%b);", allOk)); //$NON-NLS-1$
 365                                 }
 366                                 boolean allIgnored = editor.getRuleManager().getScoreStream(topicsArray)
 367                                                 .allMatch(d -> d == Result.IGNORE);
 368                                 script.append(String.format("overview.allIgnored(%b);", allIgnored)); //$NON-NLS-1$
 369                                 try {
 370                                         if (isLoaded) {
 371                                                 browser.evaluate(script.toString());
 372                                                 browser.evaluate(OVERVIEW_UPDATE_PAGE_HEADERS_VISIBILITY);
 373                                         } else {
 374                                                 final String finalScript = script.toString();


 413                 try {
 414                         this.showOk = Boolean.valueOf(state.getChild("report").getChild("showOk").getAttribute("value")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 415                 } catch (NullPointerException npe) {
 416                 }
 417                 browser.addListener(SWT.MenuDetect, new Listener() {
 418                         @Override
 419                         public void handleEvent(Event event) {
 420                                 event.doit = false;
 421                         }
 422                 });
 423                 try {
 424                         String html = isSinglePage ? RulesHtmlToolkit.generateSinglePageHtml(results)
 425                                         : RulesHtmlToolkit.generateStructuredHtml(new PageContainerResultProvider(editor), descriptors,
 426                                                         resultExpandedStates, false);
 427                         String adjustedHtml = adjustAnchorFollowAction(html);
 428                         browser.setText(adjustedHtml, true);
 429                         browser.setJavascriptEnabled(true);
 430                         browser.addProgressListener(new ProgressAdapter() {
 431                                 @Override
 432                                 public void completed(ProgressEvent event) {
 433                                         new OpenWindowFunction(browser, OPEN_BROWSER_WINDOW);
 434                                         new Linker(browser, "linker", descriptors, editor); //$NON-NLS-1$
 435                                         new Expander(browser, "expander"); //$NON-NLS-1$
 436                                         browser.execute(String.format("overview.showOk(%b);", showOk)); //$NON-NLS-1$
 437                                         if (isSinglePage) {
 438                                                 browser.execute(OVERVIEW_MAKE_SCALABLE);
 439                                         }
 440                                         browser.evaluate(OVERVIEW_UPDATE_PAGE_HEADERS_VISIBILITY);
 441                                         isLoaded = true;
 442                                 }
 443                         });
 444                 } catch (IOException | IllegalArgumentException e) {
 445                         FlightRecorderUI.getDefault().getLogger().log(Level.WARNING, "Could not create Report Overview", e); //$NON-NLS-1$
 446                         return false;
 447                 }
 448                 return true;
 449         }
 450 
 451         public void saveTo(IWritableState state) {
 452                 state.createChild("report").createChild("showOk").putString("value", showOk.toString()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 453         }
< prev index next >