/** * OLAT - Online Learning and Training<br> * http://www.olat.org * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br> * University of Zurich, Switzerland. * <hr> * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * This file has been modified by the OpenOLAT community. Changes are licensed * under the Apache 2.0 license as the original file. * <p> * Initial code contributed and copyrighted by<br> * JGS goodsolutions GmbH, http://www.goodsolutions.ch * <p> */ package org.olat.core.gui.render.intercept.debug; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.olat.core.commons.editor.plaintexteditor.PlainTextEditorController; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.ComponentRenderer; import org.olat.core.gui.components.delegating.DelegatingComponent; import org.olat.core.gui.components.panel.StackedPanel; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.dev.Util; import org.olat.core.gui.dev.controller.SourceViewController; import org.olat.core.gui.render.RenderResult; import org.olat.core.gui.render.Renderer; import org.olat.core.gui.render.RenderingState; import org.olat.core.gui.render.StringOutput; import org.olat.core.gui.render.URLBuilder; import org.olat.core.gui.render.intercept.DebugHelper; import org.olat.core.gui.render.intercept.InterceptHandler; import org.olat.core.gui.render.intercept.InterceptHandlerInstance; import org.olat.core.gui.translator.Translator; /** * Description:<br> * <P> * Initial Date: 20.05.2006 <br> * * @author Felix Jost */ public class GuiDebugDispatcherController extends BasicController implements InterceptHandler, InterceptHandlerInstance { private URLBuilder debugURLBuilder; private DelegatingComponent dc; private Map<String, Component> idToComponent = new HashMap<String, Component>(); private PlainTextEditorController vcEditorController; private StackedPanel mainP; /** * @param ureq * @param wControl needed for subsequent debug-actions e.g. on a modal screen */ public GuiDebugDispatcherController(UserRequest ureq, WindowControl wControl) { super(ureq, wControl); dc = new DelegatingComponent("deleg", new ComponentRenderer() { @Override public void render(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator, RenderResult renderResult, String[] args) { // save urlbuilder for later use (valid only for one request scope thus // transient, normally you may not save the url builder for later usage) debugURLBuilder = ubu; } @Override public void renderHeaderIncludes(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator, RenderingState rstate) { // void } @Override public void renderBodyOnLoadJSFunctionCall(Renderer renderer, StringOutput sb, Component source, RenderingState rstate) { // void } }); dc.addListener(this); dc.setDomReplaceable(false); mainP = putInitialPanel(dc); mainP.setDomReplaceable(false); } /** * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest, * org.olat.core.gui.components.Component, * org.olat.core.gui.control.Event) */ @Override public void event(UserRequest ureq, Component source, Event event) { if (source == dc) { String com = ureq.getParameter("com"); // ------- open java IDE ------- if (com.equals("ojava")) { String cl = ureq.getParameter("class"); // cl e.g. org.olat.core.MyClass //ide does not work yet, just show sourcecode in new browser window try { ureq.getDispatchResult().setResultingMediaResource(SourceViewController.showjavaSource(cl)); } catch (IOException e) { getWindowControl().setError("Could not render java source code. Make sure you have set the source path (olat and olatcore) in the config (olat.properties) and have the source files there available"); } } } } @Override protected void event(UserRequest ureq, Controller source, Event event) { if (source == vcEditorController) { // saving was already done by editor, just pop getWindowControl().pop(); } } /** * @see org.olat.core.gui.control.DefaultController#doDispose(boolean) */ @Override protected void doDispose() { // } /* * (non-Javadoc) * * @see org.olat.core.gui.render.debug.DebugHandler#createDebugComponentRenderer(org.olat.core.gui.components.ComponentRenderer) */ @Override public ComponentRenderer createInterceptComponentRenderer(final ComponentRenderer originalRenderer) { return new ComponentRenderer() { @Override public void render(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator, RenderResult renderResult, String[] args) { if (debugURLBuilder != null && !DebugHelper.isProtected(source)) { // remember source for later debug info access String did = source.getDispatchID(); String didS = String.valueOf(did); idToComponent.put(didS, source); int lev = renderResult.getNestedLevel(); String cname = source.getClass().getName(); String cnameShort = cname.substring(cname.lastIndexOf('.') + 1); // header before component sb.append("<div class='o_dev_w'>"); sb.append("<div class='o_dev_h'><span id='o_guidebugst").append(did).append("' onmouseover=\"o_debu_show(this.parentNode.parentNode, jQuery('#o_guidebugtt").append(did).append("'))\">"); sb.append(source.getComponentName()).append(" (").append(cnameShort).append(")"); sb.append("</span></div>"); sb.append("<div class='o_dev_c'><div id='o_guidebugtt").append(did).append("' class='o_dev_i'>"); sb.append("Info: <b>").append(source.getComponentName()).append("</b> ("+cnameShort+") id:"); sb.append(String.valueOf(source.getDispatchID())).append("  level:").append(lev); Controller listC = Util.getListeningControllerFor(source); if (listC != null) { sb.append("<br /><b>controller:</b> <a target=\"_blank\" href=\""); String controllerClassName = listC.getClass().getName(); debugURLBuilder.buildURI(sb, new String[] { "cid", "com", "class" }, new String[] { String.valueOf(did), "ojava", controllerClassName}); sb.append("\">"); sb.append(controllerClassName); sb.append("</a>"); } sb.append("<br /><i>listeners</i>: "); if (!source.isEnabled()) { sb.append(" NOT ENABLED"); } String listeners = source.getListenerInfo(); sb.append(listeners); if (!source.isVisible()) { sb.append("<br />INVISIBLE"); } sb.append("<br />"); // we must let the original renderer do its work so that the collecting translator is callbacked. // we save the result in a new var since it is too early to append it to the 'stream' right now. StringOutput sbOrig = new StringOutput(); try { originalRenderer.render(renderer, sbOrig, source, ubu, translator, renderResult, args); } catch (Exception e) { String emsg = "exception while rendering component '" + source.getComponentName() + "' (" + source.getClass().getName() + ") " + source.getListenerInfo() + "<br />Message of exception: " + e.getMessage(); sbOrig.append("<span style=\"color:red\">Exception</span><br /><pre>"+emsg+"</pre>"); } sb.append("</div>"); // add original component sb.append(sbOrig); sb.append("</div></div>"); } else { // e.g. when the render process take place before the delegating // component of this controller here was rendered. // the delegating component should be placed near the <html> tag in // order to be rendered first. // the contentpane of the window and the first implementing container // will not be provided with debug info, which is on purpose, // since those are contents from the chiefcontroller which control the // window. // render original component originalRenderer.render(renderer, sb, source, ubu, translator, renderResult, args); } } @Override public void renderHeaderIncludes(Renderer renderer, StringOutput sb, Component source, URLBuilder ubu, Translator translator, RenderingState rstate) { originalRenderer.renderHeaderIncludes(renderer, sb, source, ubu, translator, rstate); } @Override public void renderBodyOnLoadJSFunctionCall(Renderer renderer, StringOutput sb, Component source, RenderingState rstate) { originalRenderer.renderBodyOnLoadJSFunctionCall(renderer, sb, source, rstate); } }; } /* * (non-Javadoc) * * @see org.olat.core.gui.render.debug.DebugHandler#createDebugHandlerRenderInstance() */ @Override public InterceptHandlerInstance createInterceptHandlerInstance() { // clear all previous data and return this. // otherwise this map would collect all components from all clicks, but we // need only one click debugURLBuilder = null; idToComponent.clear(); return this; } /** * @param showDebugInfo */ public void setShowDebugInfo(boolean showDebugInfo) { if (showDebugInfo) { mainP.setContent(dc); } else { mainP.setContent(null); } } }