Weiterer Teil Umstellung webdevSupport von sitenode type auf legacy free application.

git-svn-id: https://svn.libreccm.org/ccm/trunk@1514 8810af33-2d31-482b-a856-94f89814c4df
master
pb 2012-02-17 02:24:38 +00:00
parent 6232654cda
commit 9cc5a910f9
16 changed files with 1106 additions and 103 deletions

View File

@ -24,9 +24,10 @@ import com.arsdigita.util.Lockable;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
/** /**
* The common interface implemented by all Bebop * The common interface implemented by all Bebop components.
* components. During its lifetime, a component receives the following *
* calls from the containing page. * During its lifetime, a component receives the following calls
* from the containing page.
* *
* <ul> * <ul>
* <li> During initialization/creation of the containing page: * <li> During initialization/creation of the containing page:

View File

@ -20,10 +20,10 @@ package com.arsdigita.bebop;
/** /**
* The common interface that is implemented by all * The common interface that is implemented by all Bebop containers.
* Bebop containers. The Container interface extends the Component *
* interface. A container is simply a component that contains other * The Container interface extends the Component interface. A container is
* components. * simply a component that contains other components.
* *
* @author David Lutterkort * @author David Lutterkort
* @author Uday Mathur * @author Uday Mathur

View File

@ -54,8 +54,8 @@ import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
* <P>The top-level container for all Bebop components and * <p>The top-level container for all Bebop components and containers. </p>
* containers. </P> *
* <UL> * <UL>
* <LI>Holds references to the components of a page.</LI> * <LI>Holds references to the components of a page.</LI>
* <LI>Provides methods for servicing requests and for notifying * <LI>Provides methods for servicing requests and for notifying
@ -249,6 +249,7 @@ public class Page extends BlockStylable implements Container {
// request will be kept // request will be kept
m_currentTitle = new RequestLocal() { m_currentTitle = new RequestLocal() {
@Override
protected Object initialValue(PageState state) { protected Object initialValue(PageState state) {
return m_title.firePrintEvent(state); return m_title.firePrintEvent(state);
} }
@ -400,6 +401,7 @@ public class Page extends BlockStylable implements Container {
return m_panel.size(); return m_panel.size();
} }
@Override
public Iterator children() { public Iterator children() {
return Collections.singletonList(m_panel).iterator(); return Collections.singletonList(m_panel).iterator();
} }
@ -498,29 +500,6 @@ public class Page extends BlockStylable implements Container {
return m_errorDisplay; return m_errorDisplay;
} }
// /**
// * Sets a stylesheet that should be used in HTML output. To use
// * a CSS stylesheet, call something like
// * <code>setStyleSheet("style.css", "text/css")</code>.
// * <p>
// * These values will ultimately wind up in a <tt>&lt;link&gt;</tt> tag in
// * the head of the HTML page.
// * <p>
// * Note that the stylesheet set with this call has nothing to do with the
// * XSLT stylesheet (transformer) that is applied to the XML generated
// * from this page.
// *
// * @param styleSheetURI the location of the stylesheet
// * @param styleSheetType the MIME type of the stylesheet, usually
// * <tt>text/css</tt>
// * @pre ! isLocked()
// * @deprecated Use {@link #addClientStylesheet addClientStylesheet}
// * instead. Will be removed on 2001-05-31.
// */
// public void setStyleSheet(String styleSheetURI, String styleSheetType) {
// Assert.isUnlocked(this);
// addClientStylesheet(styleSheetURI, styleSheetType);
// }
/** /**
* Adds a client-side stylesheet that should be used in HTML * Adds a client-side stylesheet that should be used in HTML
* output. Arbitrarily many client-side stylesheets can be added with * output. Arbitrarily many client-side stylesheets can be added with
@ -532,7 +511,7 @@ public class Page extends BlockStylable implements Container {
* *
* <p> Note that the stylesheet set with this call has nothing to do with * <p> Note that the stylesheet set with this call has nothing to do with
* the XSLT stylesheet (transformer) that is applied to the XML generated * the XSLT stylesheet (transformer) that is applied to the XML generated
* from this page. * from this page!
* *
* @param styleSheetURI the location of the stylesheet * @param styleSheetURI the location of the stylesheet
* @param mimeType the MIME type of the stylesheet, usually * @param mimeType the MIME type of the stylesheet, usually

View File

@ -42,6 +42,20 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
* A common servlet to provide a generic URL-to-Bebop-Page map based dispatch
* pattern.
* It provides methods to setup a url - page map. The doService method uses
* the request's URL to determine the page to display and forwards to the
* presentation manager for the Page handling.
*
* This class is a servlet based version of BebopMapDispatcher and associated
* classes and is generally used in the same way by legacy free applications.
*
* Subclasses usually overwrite the doService method to create Page objects
* and use this.put method to construct the mapping.
*
* Subclasses may overwrite the doService method to add additional functionality,
* e.g. permission checking.
* *
* @author Justin Ross &lt;jross@redhat.com&gt; * @author Justin Ross &lt;jross@redhat.com&gt;
* @author chris gilbert - allow BebopApplicationServlet pages to disable * @author chris gilbert - allow BebopApplicationServlet pages to disable
@ -53,12 +67,18 @@ public class BebopApplicationServlet extends BaseApplicationServlet {
private static final Logger s_log = Logger.getLogger private static final Logger s_log = Logger.getLogger
(BebopApplicationServlet.class); (BebopApplicationServlet.class);
// String pathInfo => Page page /** URL (pathinfo) -> Page object mapping. Based on it (and the http
* request url) the doService method to selects a page to display */
private final Map m_pages = new HashMap(); private final Map m_pages = new HashMap();
// Set of pathinfo // Set of pathinfo
private final Set m_clientCacheDisabledPages = new HashSet(); private final Set m_clientCacheDisabledPages = new HashSet();
/** /**
* Initializer uses parent class's initializer to setup the servlet request /
* response and application context. Usually a user of this class will NOT
* overwrite this method but the user extension point doInit() to perform
* local initialization tasks, in case of this servlet typically to setup
* the page-url mapping using the provided mapping methods of this class.
* *
* @throws ServletException * @throws ServletException
*/ */
@ -68,15 +88,29 @@ public class BebopApplicationServlet extends BaseApplicationServlet {
} }
/** /**
* User extension point, overwrite this method to setup a URL - page mapping
* *
* @param pathInfo * @throws ServletException
* @param page */
@Override
public void doInit() throws ServletException {
// nothing here
}
/**
* Adds one Url-Page mapping to the internal mapping table.
*
* @param pathInfo url stub for a page to display
* @param page Page object to display
*/ */
protected final void put(final String pathInfo, protected final void put(final String pathInfo,
final Page page) { final Page page) {
Assert.exists(pathInfo, String.class); Assert.exists(pathInfo, String.class);
Assert.exists(page, Page.class); Assert.exists(page, Page.class);
Assert.isTrue(pathInfo.startsWith("/"), "path starts with '/'"); // Current Implementation requires pathInfo to start with a leading '/'
// SUN Servlet API specifies: "PathInfo *may be empty* or will start
// with a '/' character."
Assert.isTrue(pathInfo.startsWith("/"), "path starts not with '/'");
m_pages.put(pathInfo, page); m_pages.put(pathInfo, page);
} }
@ -94,6 +128,9 @@ public class BebopApplicationServlet extends BaseApplicationServlet {
} }
/** /**
* Main processing unit searches in the page map for the request's url
* and forwards the page to display to the appropriate presentation
* manager to serve the page.
* *
* @param sreq * @param sreq
* @param sresp * @param sresp

View File

@ -31,7 +31,13 @@ import org.apache.log4j.Logger;
import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.DefaultHandler;
/** /**
* Common base class for a generic URL-to-Bebop-Page dispatching pattern. * Common base class for a generic URL-to-Bebop-Page dispatching pattern. This
* class provides methods to setup a url - page map. URL is used as a key to a
* dispatcher type class whose dispatch() method will provide the Page handling.
*
* Dispatching is done by the parent class on a general url - dispatcher class
* mapping.
*
* This class may be used directly by applications, or it may be subclassed * This class may be used directly by applications, or it may be subclassed
* to be coded with a specific map or to override the map lookup for certain * to be coded with a specific map or to override the map lookup for certain
* sets of URLs. * sets of URLs.
@ -53,8 +59,8 @@ public class BebopMapDispatcher extends MapDispatcher {
public BebopMapDispatcher() { public BebopMapDispatcher() {
super(); super();
//mount the confirmation page
Map m = new HashMap(); Map m = new HashMap();
//mount the confirmation page
m.put(ConfirmPage.CONFIRM_URL, new ConfirmPage()); m.put(ConfirmPage.CONFIRM_URL, new ConfirmPage());
setMap(m); setMap(m);
} }

View File

@ -34,16 +34,14 @@ import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.DefaultHandler;
/** /**
* Base class for * Base class for a generic URL-to-Dispatcher mapping dispatch. This class may
* a generic URL-to-Dispatcher mapping dispatch. This class may * be used directly by applications, or it may be subclassed to be coded with
* be used directly by applications, or it may be subclassed to * a specific map or override the map lookup for certain sets of URLs.
* be coded with a specific
* map or override the map lookup for certain sets of URLs.
* <p> * <p>
* URLs are mapped to Dispatcher objects. When the dispatch method is called, * URLs are mapped to Dispatcher objects. When the dispatch method is called,
* this first looks up the remainingURL (from the request context) in the map and * this first looks up the remainingURL (from the request context) in the map
* dispatches to the target object. Then we call * and dispatches to the target object. Then we call the dispatch method on
* the dispatch method on the target. * the target.
* *
* <p>A configurable "not found" dispatcher is available to handle the case * <p>A configurable "not found" dispatcher is available to handle the case
* where no target is mapped for a URL. By default, this is set to * where no target is mapped for a URL. By default, this is set to
@ -55,9 +53,9 @@ import org.xml.sax.helpers.DefaultHandler;
* exact mapping. If a not-found handler is specified, it is up to this * exact mapping. If a not-found handler is specified, it is up to this
* specified dispatcher to set the status code appropriately. * specified dispatcher to set the status code appropriately.
* *
* <p>Note that any URLs that do not have a file extension will * <p>Note that any URLs that do not have a file extension will automatically
* automatically be required to have a trailing slash. Your relative * be required to have a trailing slash. Your relative links MUST COMPENSATE
* links must compensate for this. * for this.
* *
* <p>Example: Assume we set up a map dispatcher as follows: * <p>Example: Assume we set up a map dispatcher as follows:
* <pre> * <pre>
@ -100,8 +98,9 @@ public class MapDispatcher implements Dispatcher {
private static final Logger s_log = private static final Logger s_log =
Logger.getLogger(MapDispatcher.class.getName()); Logger.getLogger(MapDispatcher.class.getName());
/* Creates MapDispatcher with empty URL mapped to "/". /**
**/ * Constructor creates MapDispatcher with empty URL mapped to "/".
*/
public MapDispatcher() { public MapDispatcher() {
m_notFoundHandler = JSPApplicationDispatcher.getInstance(); m_notFoundHandler = JSPApplicationDispatcher.getInstance();
} }

View File

@ -454,27 +454,29 @@ public class CoreLoader extends PackageLoader {
private void loadWebDev() { private void loadWebDev() {
// Add the package type to the database // Add the package type to the database
/*
PackageType packType = PackageType.create
("webdev-support", "WebDeveloper Support", "WebDeveloper Supports",
"http://arsdigita.com/webdev-support");
// Add the node and the package instance on that node. /* LEGACY COMPATIBLE application type */
SiteNode node = SiteNode.createSiteNode("ds");
// Specify the URL stub for this package instance.
node.mountPackage(packType.createInstance("webdev-support"));
// Map the package type to a dispatcher class
packType.setDispatcherClass("com.arsdigita.webdevsupport.Dispatcher");
*/
ApplicationType webDevType = ApplicationType ApplicationType webDevType = ApplicationType
.createApplicationType("webdev-support", .createApplicationType("webdev-support",
"WebDeveloper Support", "WebDeveloper Support",
WebDevSupport.BASE_DATA_OBJECT_TYPE); WebDevSupport.BASE_DATA_OBJECT_TYPE);
webDevType.setDispatcherClass("com.arsdigita.webdevsupport.Dispatcher"); webDevType.setDispatcherClass("com.arsdigita.webdevsupport.Dispatcher");
/* LEGACY FREE application type */
// ApplicationType webDevType =
// new ApplicationType("WebDev Support",
// WebDevSupport.BASE_DATA_OBJECT_TYPE );
/* Legacy free / compatible INDEPENDENT application properties */
webDevType.setDescription("WebDeveloper Support application"); webDevType.setDescription("WebDeveloper Support application");
webDevType.save(); webDevType.save();
// create application instance as a legacy free or legacy comp. app.
// Whether a legacy compatible or a legacy free application is
// created depends on the type of ApplicationType above. No need to
// modify anything here
Application webDev = Application.createApplication(webDevType, Application webDev = Application.createApplication(webDevType,
"ds", "ds",
"WebDeveloper Support", "WebDeveloper Support",
@ -482,9 +484,6 @@ public class CoreLoader extends PackageLoader {
webDev.setDescription("The default WEB developer service instance."); webDev.setDescription("The default WEB developer service instance.");
webDev.save(); webDev.save();
} }
private Application loadAdminApp() { private Application loadAdminApp() {

View File

@ -63,13 +63,17 @@ public abstract class BaseServlet extends HttpServlet {
private static Logger s_log = Logger.getLogger(BaseServlet.class); private static Logger s_log = Logger.getLogger(BaseServlet.class);
/** /** The name of the request attribute used to store the originally
* The name of the request attribute used to store the originally * requested URL. */
* requested URL.
*/
public static final String REQUEST_URL_ATTRIBUTE = public static final String REQUEST_URL_ATTRIBUTE =
BaseServlet.class.getName() + ".request_url"; BaseServlet.class.getName() + ".request_url";
/**
* Initializer uses parent class's initializer to setup the servlet request /
* response and application context. Usually a user of this class will not
* overwrite this method but the user extension point doInit to perform
* local initialization tasks.
*/
@Override @Override
public void init(final ServletConfig sconfig) throws ServletException { public void init(final ServletConfig sconfig) throws ServletException {
if (s_log.isInfoEnabled()) { if (s_log.isInfoEnabled()) {

View File

@ -64,15 +64,18 @@ import com.arsdigita.web.URL;
import com.arsdigita.webdevsupport.log4j.CategoryPanel; import com.arsdigita.webdevsupport.log4j.CategoryPanel;
import com.arsdigita.webdevsupport.config.ConfigList; import com.arsdigita.webdevsupport.config.ConfigList;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
@ -83,22 +86,23 @@ import org.apache.log4j.Logger;
* *
* @author Joseph A. Bank (jbank@alum.mit.edu) * @author Joseph A. Bank (jbank@alum.mit.edu)
* @version 1.0 * @version 1.0
**/ * @version $Id: Dispatcher.java 1460 2007-03-02 14:36:38Z sskracic $
*/
public class Dispatcher extends BebopMapDispatcher { public class Dispatcher extends BebopMapDispatcher {
private static final Logger s_log = private static final Logger s_log =
Logger.getLogger(Dispatcher.class.getName()); Logger.getLogger(Dispatcher.class.getName());
public static final String APP_NAME = "ds"; public static final String APP_NAME = "ds";
public static final String versionId =
"$Id: Dispatcher.java 1460 2007-03-02 14:36:38Z sskracic $" +
" by $Author: sskracic $, " +
"$DateTime: 2004/08/16 18:10:38 $";
private static boolean s_showDSPages = false; private static boolean s_showDSPages = false;
private final static String CACHE_TABLE_URL = "cache-table"; private final static String CACHE_TABLE_URL = "cache-table";
/**
* Constructor builds the various Developer Support Pages and creates the
* corresponding URL - Page mapping.
*/
public Dispatcher() { public Dispatcher() {
super(); super();
Map m = new HashMap(); Map m = new HashMap();
@ -115,20 +119,35 @@ public class Dispatcher extends BebopMapDispatcher {
m.put("config", buildConfigPage()); m.put("config", buildConfigPage());
m.put(CACHE_TABLE_URL, buildCacheTablePage()); m.put(CACHE_TABLE_URL, buildCacheTablePage());
/** The rest of the URLs go here with more /* The rest of the URLs go here with more
* m_put statements. * m_put statements.
*/ */
/* Make the created map operational */
setMap(m); setMap(m);
} }
/**
* Overwrites parent's dispatch method to add permission checking. If
* required permissions are granted dispatching is delegatged to parent.
* @param req
* @param resp
* @param ctx
* @throws IOException
* @throws ServletException
*/
@Override
public void dispatch(HttpServletRequest req, public void dispatch(HttpServletRequest req,
HttpServletResponse resp, HttpServletResponse resp,
RequestContext ctx) RequestContext ctx)
throws IOException, ServletException { throws IOException, ServletException {
/* Determine access priviledge, only logged in users may access DS */
Party party = Kernel.getContext().getParty(); Party party = Kernel.getContext().getParty();
if (party == null) { if (party == null) {
throw new LoginSignal(req); throw new LoginSignal(req);
} }
SiteNode node = ((SiteNodeRequestContext)ctx).getSiteNode(); SiteNode node = ((SiteNodeRequestContext)ctx).getSiteNode();
PermissionDescriptor admin = new PermissionDescriptor PermissionDescriptor admin = new PermissionDescriptor
(PrivilegeDescriptor.ADMIN, node, party); (PrivilegeDescriptor.ADMIN, node, party);
@ -144,6 +163,10 @@ public class Dispatcher extends BebopMapDispatcher {
} }
/**
*
* @return index Page object
*/
private Page buildIndexPage() { private Page buildIndexPage() {
Page p = PageFactory.buildPage(APP_NAME, "Web Developer Support"); Page p = PageFactory.buildPage(APP_NAME, "Web Developer Support");
@ -154,8 +177,10 @@ public class Dispatcher extends BebopMapDispatcher {
links.add(new Link("Cache Table Browser", CACHE_TABLE_URL)); links.add(new Link("Cache Table Browser", CACHE_TABLE_URL));
ActionLink enable = new ActionLink("Enable request logging") { ActionLink enable = new ActionLink("Enable request logging") {
@Override
public boolean isVisible(PageState state) { public boolean isVisible(PageState state) {
return !DeveloperSupport.containsListener(WebDevSupportListener.getInstance()) return !DeveloperSupport.containsListener(
WebDevSupportListener.getInstance())
&& super.isVisible(state); && super.isVisible(state);
} }
}; };
@ -171,11 +196,14 @@ public class Dispatcher extends BebopMapDispatcher {
ActionLink disable = new ActionLink("Disable request logging") { ActionLink disable = new ActionLink("Disable request logging") {
@Override
public boolean isVisible(PageState state) { public boolean isVisible(PageState state) {
return DeveloperSupport.containsListener(WebDevSupportListener.getInstance()) return DeveloperSupport.containsListener(
WebDevSupportListener.getInstance())
&& super.isVisible(state); && super.isVisible(state);
} }
}; };
disable.addActionListener(new ActionListener() { disable.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
DeveloperSupport.removeListener(WebDevSupportListener.getInstance()); DeveloperSupport.removeListener(WebDevSupportListener.getInstance());
@ -225,6 +253,10 @@ public class Dispatcher extends BebopMapDispatcher {
return p; return p;
} }
/**
*
* @return log4j Page object
*/
private Page buildLog4jPage() { private Page buildLog4jPage() {
Page p = PageFactory.buildPage(APP_NAME, "Log4j Logger Adjuster"); Page p = PageFactory.buildPage(APP_NAME, "Log4j Logger Adjuster");
p.add(new CategoryPanel()); p.add(new CategoryPanel());
@ -232,6 +264,10 @@ public class Dispatcher extends BebopMapDispatcher {
return p; return p;
} }
/**
*
* @return config Page object
*/
private Page buildConfigPage() { private Page buildConfigPage() {
Page p = PageFactory.buildPage(APP_NAME, "Registry Config"); Page p = PageFactory.buildPage(APP_NAME, "Registry Config");
p.add(new ConfigList()); p.add(new ConfigList());
@ -247,6 +283,11 @@ public class Dispatcher extends BebopMapDispatcher {
} }
private ParameterModel m_request_id = new IntegerParameter("request_id"); private ParameterModel m_request_id = new IntegerParameter("request_id");
/**
*
* @return info Page object
*/
private Page buildInfoPage() { private Page buildInfoPage() {
Page p = PageFactory.buildPage(APP_NAME, "Request Information"); Page p = PageFactory.buildPage(APP_NAME, "Request Information");
p.addGlobalStateParam(m_request_id); p.addGlobalStateParam(m_request_id);
@ -258,6 +299,12 @@ public class Dispatcher extends BebopMapDispatcher {
private ParameterModel m_query_id = new IntegerParameter("query_id"); private ParameterModel m_query_id = new IntegerParameter("query_id");
private ParameterModel m_query_request_id = new IntegerParameter("request_id"); private ParameterModel m_query_request_id = new IntegerParameter("request_id");
/**
*
*
* @return queryInfo Page object
*/
private Page buildQueryInfoPage() { private Page buildQueryInfoPage() {
Page p = PageFactory.buildPage(APP_NAME, "Query Information"); Page p = PageFactory.buildPage(APP_NAME, "Query Information");
p.addGlobalStateParam(m_query_request_id); p.addGlobalStateParam(m_query_request_id);
@ -268,6 +315,7 @@ public class Dispatcher extends BebopMapDispatcher {
} }
private RequestLocal m_scoreboard = new RequestLocal() { private RequestLocal m_scoreboard = new RequestLocal() {
@Override
protected Object initialValue(PageState state) { protected Object initialValue(PageState state) {
// queryInfo.getID() => {textRepeats, queryRepeats} // queryInfo.getID() => {textRepeats, queryRepeats}
return new HashMap(); return new HashMap();
@ -561,10 +609,24 @@ public class Dispatcher extends BebopMapDispatcher {
return sb.toString(); return sb.toString();
} }
/**
*
*/
class RequestInfoComponent extends com.arsdigita.bebop.SimpleComponent { class RequestInfoComponent extends com.arsdigita.bebop.SimpleComponent {
/**
* Constructor
*/
public RequestInfoComponent() { public RequestInfoComponent() {
super(); super();
} }
/**
*
* @param state
* @param parent
*/
@Override
public void generateXML(PageState state, Element parent) { public void generateXML(PageState state, Element parent) {
Integer request_id = (Integer)state.getValue(m_request_id); Integer request_id = (Integer)state.getValue(m_request_id);
RequestInfo ri = RequestInfo ri =
@ -671,10 +733,24 @@ public class Dispatcher extends BebopMapDispatcher {
} }
} }
/**
* Class
*/
class QueryInfoComponent extends com.arsdigita.bebop.SimpleComponent { class QueryInfoComponent extends com.arsdigita.bebop.SimpleComponent {
/**
*
*/
public QueryInfoComponent() { public QueryInfoComponent() {
super(); super();
} }
/**
*
* @param state
* @param parent
*/
@Override
public void generateXML(PageState state, Element parent) { public void generateXML(PageState state, Element parent) {
Integer request_id = (Integer)state.getValue(m_query_request_id); Integer request_id = (Integer)state.getValue(m_query_request_id);
Integer query_id = (Integer)state.getValue(m_query_id); Integer query_id = (Integer)state.getValue(m_query_id);

View File

@ -53,7 +53,7 @@ import com.arsdigita.bebop.parameters.IntegerParameter;
* *
* @author Daniel Berrange (berrange@redhat.com) * @author Daniel Berrange (berrange@redhat.com)
* @version 1.0 * @version 1.0
**/ */
public class QueryLog implements com.arsdigita.dispatcher.Dispatcher { public class QueryLog implements com.arsdigita.dispatcher.Dispatcher {
private static final Logger s_log = private static final Logger s_log =
Logger.getLogger(QueryLog.class.getName()); Logger.getLogger(QueryLog.class.getName());

View File

@ -46,7 +46,7 @@ public class WebDevSupport extends Application {
public static final String BASE_DATA_OBJECT_TYPE = public static final String BASE_DATA_OBJECT_TYPE =
"com.arsdigita.webdevsupport.WebDevSupport"; "com.arsdigita.webdevsupport.WebDevSupport";
public WebDevSupport(DataObject obj) { public WebDevSupport(final DataObject obj) {
super(obj); super(obj);
} }
@ -66,5 +66,10 @@ public class WebDevSupport extends Application {
return BASE_DATA_OBJECT_TYPE; return BASE_DATA_OBJECT_TYPE;
} }
@Override
public String getServletPath() {
return "/webdevsupport";
}
} }

View File

@ -0,0 +1,876 @@
/*
* Copyright (C) 2012 Peter Boy <pb@zes.uni-bremen.de> All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.webdevsupport;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.ColumnPanel;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Container;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Link;
import com.arsdigita.bebop.ListPanel;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageFactory;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.RequestLocal;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.TableActionAdapter;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.parameters.IntegerParameter;
import com.arsdigita.bebop.parameters.ParameterModel;
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.bebop.table.TableModelBuilder;
import com.arsdigita.developersupport.DeveloperSupport;
import com.arsdigita.dispatcher.AccessDeniedException;
import com.arsdigita.dispatcher.DispatcherHelper;
import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.Party;
import com.arsdigita.kernel.permissions.PermissionDescriptor;
import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.templating.PresentationManager;
import com.arsdigita.templating.Templating;
import com.arsdigita.util.Assert;
import com.arsdigita.util.StringUtils;
import com.arsdigita.web.Application;
import com.arsdigita.web.BaseApplicationServlet;
import com.arsdigita.web.LoginSignal;
import com.arsdigita.web.ParameterMap;
import com.arsdigita.web.RedirectSignal;
import com.arsdigita.web.URL;
import com.arsdigita.webdevsupport.config.ConfigList;
import com.arsdigita.webdevsupport.log4j.CategoryPanel;
import com.arsdigita.xml.Document;
import com.arsdigita.xml.Element;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
/**
* Web Developer Support Application Servlet class, central entry point to
* create and process the applications UI.
*
* We should have subclassed BebopApplicationServlet but couldn't overwrite
* doService() method to add permission checking. So we use our own page
* mapping. The general logic is the same as for BebopApplicationServlet.
* {@see com.arsdigita.bebop.page.BebopApplicationServlet}
*
* @author pb
*/
public class WebDevSupportServlet extends BaseApplicationServlet {
private static final Logger s_log =
Logger.getLogger(Dispatcher.class.getName());
public static final String APP_NAME = "ds";
private static boolean s_showDSPages = false;
/** URL (pathinfo) -> Page object mapping. Based on it (and the http
* request url) the doService method to selects a page to display */
private final Map m_pages = new HashMap();
/**
* User extension point, overwrite this method to setup a URL - page mapping
*
* @throws ServletException
*/
@Override
public void doInit() throws ServletException {
addPage("/", buildIndexPage()); // index page at address ~/ds
// addPage("/index.jsp", buildIndexPage()); // index page at address ~/ds
addPage("/log4j", buildLog4jPage()); // Logger Adjuster at addr. ~/ds/log4j
addPage("/config", buildConfigPage()); // config browser @ ~/ds/config
// cache table browser @ ~/ds/cache-table
addPage("/cache-table", buildCacheTablePage());
// XXXX!!
// QueryLog is a class of its own in webdevsupport, based upon dispatcher.Disp
// and prints out all queries in a request
// put("query-log", new QueryLog());
addPage("/request-info", buildInfoPage());
addPage("/query-info", buildQueryInfoPage());
addPage("/query-plan", buildQueryPlanPage());
}
/**
* Central service method, checks for required permission, determines the
* requested page and passes the page object to PresentationManager.
*/
public final void doService(HttpServletRequest sreq,
HttpServletResponse sresp,
Application app)
throws ServletException, IOException {
// /////// Some preparational steps ///////////////
/* Determine access privilege: only logged in users may access DS */
Party party = Kernel.getContext().getParty();
if (party == null) {
throw new LoginSignal(sreq);
}
/* Determine access privilege: Admin privileges must be granted */
PermissionDescriptor admin = new PermissionDescriptor
(PrivilegeDescriptor.ADMIN, app, party);
if (!PermissionService.checkPermission(admin)) {
throw new AccessDeniedException("User is not an administrator");
}
/* Want ds to always show the latest stuff... */
DispatcherHelper.cacheDisable(sresp);
// /////// Everything OK here - DO IT ///////////////
String pathInfo = sreq.getPathInfo();
Assert.exists(pathInfo, "String pathInfo");
if (pathInfo.length() > 1 && pathInfo.endsWith("/")) {
/* NOTE: ServletAPI specifies, pathInfo may be empty or will
* start with a '/' character. It currently carries a
* trailing '/' if a "virtual" page, i.e. not a real jsp, but
* result of a servlet mapping. But Application requires url
* NOT to end with a trailing '/' for legacy free applications. */
pathInfo = pathInfo.substring(0, pathInfo.length()-1);
}
final Page page = (Page) m_pages.get(pathInfo);
if (page != null) {
final Document doc = page.buildDocument(sreq, sresp);
PresentationManager pm = Templating.getPresentationManager();
pm.servePage(doc, sreq, sresp);
} else {
sresp.sendError(404, "No such page for path " + pathInfo);
// throw new IllegalStateException("No such page for path " + pathInfo);
}
}
/**
* Adds one Url-Page mapping to the internal mapping table.
*
* @param pathInfo url stub for a page to display
* @param page Page object to display
*/
private void addPage(final String pathInfo, final Page page) {
Assert.exists(pathInfo, String.class);
Assert.exists(page, Page.class);
// Current Implementation requires pathInfo to start with a leading '/'
// SUN Servlet API specifies: "PathInfo *may be empty* or will start
// with a '/' character."
Assert.isTrue(pathInfo.startsWith("/"), "path starts not with '/'");
m_pages.put(pathInfo, page);
}
/**
*
* @return index Page object
*/
private Page buildIndexPage() {
Page p = PageFactory.buildPage(APP_NAME, "Web Developer Support");
BoxPanel links = new BoxPanel(BoxPanel.VERTICAL);
links.add(new Link("Log4j Logger Adjuster", "/ds/log4j"));
links.add(new Link("Config Browser", "/ds/config"));
links.add(new Link("Cache Table Browser", "/ds/cache-table"));
ActionLink enable = new ActionLink("Enable request logging") {
@Override
public boolean isVisible(PageState state) {
return !DeveloperSupport.containsListener(
WebDevSupportListener.getInstance())
&& super.isVisible(state);
}
};
enable.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DeveloperSupport.addListener(WebDevSupportListener.getInstance());
throw new RedirectSignal(URL.request(e.getPageState().getRequest(),
null), true);
}
});
links.add(enable);
ActionLink disable = new ActionLink("Disable request logging") {
@Override
public boolean isVisible(PageState state) {
return DeveloperSupport.containsListener(
WebDevSupportListener.getInstance())
&& super.isVisible(state);
}
};
disable.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DeveloperSupport.removeListener(WebDevSupportListener.getInstance());
WebDevSupportListener.getInstance().clearRequestHistory();
throw new RedirectSignal(URL.request(e.getPageState().getRequest(),
null), true);
}
});
links.add(disable);
BoxPanel logs = new BoxPanel(BoxPanel.VERTICAL) {
@Override
public boolean isVisible(PageState state) {
return DeveloperSupport
.containsListener(WebDevSupportListener.getInstance())
&& super.isVisible(state);
}
};
logs.add(new Label("") {
@Override
public String getLabel(PageState ps) {
return "Currently storing the last " +
WebDevSupportListener.getInstance().getMaxRequests() +
" requests";
}
});
Label toggle = new Label("") {
@Override
public String getLabel(PageState ps) {
return s_showDSPages ? "Hide hits to developer support" :
"Show hits to developer support";
}
};
ControlLink cl = new ControlLink(toggle) {
@Override
public void respond(PageState s) {
s_showDSPages = !s_showDSPages;
}
@Override
public void setControlEvent(PageState s) {
s.setControlEvent(this);
}
};
logs.add(cl);
logs.add(new Label("<h3>Available Request Information</h3>", false));
logs.add(makeRequestTable());
p.add(links);
p.add(logs);
p.lock();
return p;
}
/**
*
* @return log4j Page object
*/
private Page buildLog4jPage() {
Page p = PageFactory.buildPage(APP_NAME, "Log4j Logger Adjuster");
p.add(new CategoryPanel());
p.lock();
return p;
}
/**
*
* @return config Page object
*/
private Page buildConfigPage() {
Page p = PageFactory.buildPage(APP_NAME, "Registry Config");
p.add(new ConfigList());
p.lock();
return p;
}
private Page buildCacheTablePage() {
Page p = PageFactory.buildPage(APP_NAME, "Cache Table Browser");
p.add(new CacheTableBrowser());
p.lock();
return p;
}
private ParameterModel m_request_id = new IntegerParameter("request_id");
/**
*
* @return info Page object
*/
private Page buildInfoPage() {
Page p = PageFactory.buildPage(APP_NAME, "Request Information");
p.addGlobalStateParam(m_request_id);
// p.add(new RequestInfoComponent());
p.add(makeDatabaseRequestComponent());
p.lock();
return p;
}
private ParameterModel m_query_id = new IntegerParameter("query_id");
private ParameterModel m_query_request_id = new IntegerParameter("request_id");
/**
*
*
* @return queryInfo Page object
*/
private Page buildQueryInfoPage() {
Page p = PageFactory.buildPage(APP_NAME, "Query Information");
p.addGlobalStateParam(m_query_request_id);
p.addGlobalStateParam(m_query_id);
p.add(new QueryInfoComponent());
p.lock();
return p;
}
private RequestLocal m_scoreboard = new RequestLocal() {
@Override
protected Object initialValue(PageState state) {
// queryInfo.getID() => {textRepeats, queryRepeats}
return new HashMap();
}
};
// Used below in makeDatabaseRequestComponent to generate a query
// scoreboard.
private void incrementScore(final PageState state, final QueryInfo key,
final int index) {
Map map = (Map) m_scoreboard.get(state);
Integer[] row = (Integer[]) map.get(new Integer(key.getID()));
if (row == null) {
row = new Integer[] { new Integer(0), new Integer(0) };
map.put(new Integer(key.getID()), row);
}
row[index] = new Integer(row[index].intValue() + 1);
}
private Component makeDatabaseRequestComponent() {
final String[] headers =
{ "ID", "Duration (execution)", "Conn", "Command", "Exception" };
TableModelBuilder b = new AbstractTableModelBuilder() {
public TableModel makeModel(Table t, final PageState s) {
Integer request_id = (Integer)s.getValue(m_request_id);
RequestInfo ri =
WebDevSupportListener.getInstance().getRequest(request_id.intValue());
final Iterator iter = (ri == null) ? new ArrayList().iterator() :
ri.getQueries();
return new TableModel() {
private HashMap seenQueryAndValues = new HashMap();
private HashMap seenQuery = new HashMap();
private boolean duplicateQueryAndValues = false;
private boolean duplicateQuery = false;
private QueryInfo current = null;
public int getColumnCount() {
return 5;
}
public boolean nextRow() {
if (iter.hasNext()) {
current = (QueryInfo) iter.next();
duplicateQueryAndValues =
seenQueryAndValues.containsKey(current);
duplicateQuery =
seenQuery.containsKey(current.getQuery());
if (!duplicateQueryAndValues) {
seenQueryAndValues.put(current, current);
}
if (!duplicateQuery) {
seenQuery.put(current.getQuery(), current);
}
incrementScore
(s, (QueryInfo) seenQueryAndValues.get(current),
0);
incrementScore
(s, (QueryInfo) seenQuery.get(current.getQuery()),
1);
return true;
} else {
return false;
}
}
public Object getElementAt(int columnIndex) {
switch (columnIndex) {
case 0: {
StringBuffer result = new StringBuffer();
result.append(current.getID());
if (duplicateQueryAndValues) {
result.append(
" duplicates #" +
((QueryInfo)seenQueryAndValues.get(
current)).getID()
);
}
if (duplicateQuery) {
result.append(
" duplicates text of #" +
((QueryInfo)seenQuery.get(
current.getQuery())).getID()
);
}
return result.toString();
}
case 1: return (current.isClosed() ?
current.getTotalTime() + " ms" :
"unknown")
+ "<br/> (" + current.getTime() + " ms)";
case 2: return current.getConnectionID();
case 3: return "<blockquote><pre>" +
current.getQuery() +
"</pre><br>BINDS: " +
current.getBindvars() +
"</blockquote>";
case 4: return current.getSQLE();
default: return null;
}
}
public Object getKeyAt(int columnIndex) {
return new Integer(current.getID());
}
};
}
};
Table table = new Table(b, headers);
table.setBorder("1");
table.getColumn(1).setCellRenderer(new NonEscapedTableCellRenderer(false));
table.getColumn(3).setCellRenderer(new NonEscapedTableCellRenderer());
table.getColumn(0).setCellRenderer(new
DefaultTableCellRenderer(true));
table.addTableActionListener(new TableActionAdapter() {
@Override
public void cellSelected(TableActionEvent e) {
PageState s = e.getPageState();
Integer request_id = (Integer) s.getValue(m_query_request_id);
final ParameterMap params = new ParameterMap();
params.setParameter("request_id", request_id);
params.setParameter("query_id", e.getRowKey());
if (e.getColumn().intValue() == 0) {
throw new RedirectSignal(URL.getDispatcherPath() +
"/ds/query-info" + params, true);
} else {
throw new RedirectSignal(URL.getDispatcherPath() +
"/ds/query-log" + params, true);
}
}
});
Label l = new Label("None");
l.setFontWeight(Label.ITALIC);
l.setStyleAttr("padding-left: 3em");
table.setEmptyView(l);
table.setWidth("100%");
BoxPanel panel = new BoxPanel(BoxPanel.VERTICAL);
panel.add(table);
TableModelBuilder scoreBuilder = new AbstractTableModelBuilder() {
public TableModel makeModel(Table t, final PageState state) {
return new TableModel() {
Map map = (Map) m_scoreboard.get(state);
Iterator iter = map.keySet().iterator();
Integer key;
Integer[] row;
public int getColumnCount() {
return 3;
}
public boolean nextRow() {
if (iter.hasNext()) {
key = (Integer) iter.next();
row = (Integer[]) map.get(key);
return true;
} else {
return false;
}
}
public Object getElementAt(int column) {
switch (column) {
case 0:
return key;
case 1:
return row[0];
case 2:
return row[1];
default:
return null;
}
}
public Object getKeyAt(int column) {
return key;
}
};
}
};
final String[] scoreHeaders = {"ID", "Duplicates", "Text-Duplicates"};
Table scoreTable = new Table(scoreBuilder, scoreHeaders);
panel.add(scoreTable);
return panel;
}
private Table makeRequestTable() {
final String[] headers = { "Time", "Duration", "Queries", "IP",
"Request", "Extra" };
TableModelBuilder b = new AbstractTableModelBuilder() {
public TableModel makeModel(Table t, PageState s) {
return new TableModel() {
ListIterator iter =
WebDevSupportListener.getInstance().getRequestsReverse();
private RequestInfo current = null;
public int getColumnCount() {
return 6;
}
public boolean nextRow() {
while (iter.hasPrevious()) {
current = (RequestInfo) iter.previous();
boolean isdevsupp = current.isDevSupportRequest();
if (s_showDSPages || !isdevsupp) {
return true;
}
}
return false;
}
static final int MAXSTR = 35;
public Object getElementAt(int columnIndex) {
switch (columnIndex) {
case 0: return current.getTime();
case 1: return current.getDuration();
case 2: return current.getNumQueries()+"";
case 3: return current.getIP();
case 4: {
String req = current.getRequest();
if (req.length() > MAXSTR) {
return req.substring(0, MAXSTR)+"...";
} else {
return req;
}
}
case 5:
return "[query log]";
default: return null;
}
}
public Object getKeyAt(int columnIndex) {
return new Integer(current.getID());
}
};
}
};
Table result = new Table(b, headers);
result.getColumn(4).setCellRenderer(new
DefaultTableCellRenderer(true));
result.getColumn(5).setCellRenderer(new
DefaultTableCellRenderer(true));
result.addTableActionListener(new TableActionAdapter() {
@Override
public void cellSelected(TableActionEvent e) {
final ParameterMap params = new ParameterMap();
params.setParameter("request_id", e.getRowKey());
if (e.getColumn().intValue() == 4) {
throw new RedirectSignal(URL.getDispatcherPath() +
"/ds/request-info" + params, true);
} else if (e.getColumn().intValue() == 5) {
throw new RedirectSignal(URL.getDispatcherPath() +
"/ds/query-log" + params, true);
}
}
});
Label l = new Label("None");
l.setFontWeight(Label.ITALIC);
l.setStyleAttr("padding-left: 3em");
result.setEmptyView(l);
result.setWidth("100%");
return result;
}
String dashes(int depth) {
StringBuilder sb = new StringBuilder();
while (depth-- > 0) sb.append("--");
return sb.toString();
}
private ParameterModel m_query_p_id = new IntegerParameter("query_id");
private ParameterModel m_query_p_request_id =
new IntegerParameter("request_id");
private Page buildQueryPlanPage() {
Page p = PageFactory.buildPage(APP_NAME, "Query Execution Plan");
p.addGlobalStateParam(m_query_p_request_id);
p.addGlobalStateParam(m_query_p_id);
p.add(new QueryPlanComponent());
p.lock();
return p;
}
/**
*
*/
class RequestInfoComponent extends com.arsdigita.bebop.SimpleComponent {
/**
* Constructor
*/
public RequestInfoComponent() {
super();
}
/**
*
* @param state
* @param parent
*/
@Override
public void generateXML(PageState state, Element parent) {
Integer request_id = (Integer)state.getValue(m_request_id);
RequestInfo ri =
WebDevSupportListener.getInstance().getRequest(request_id.intValue());
if (ri != null) {
Container param_list;
Container form_list;
Container comment_list;
Container headers_list;
Container stages_list;
BoxPanel bp = new BoxPanel();
bp.add(new Label("<h3>Parameters</h3>", false));
bp.add(param_list = new ColumnPanel(2));
param_list.add(new Label("Request Start Time:"));
param_list.add(new Label(ri.getTime()));
param_list.add(new Label("Request Completion Time: "));
param_list.add(new Label(ri.getEndTime()));
param_list.add(new Label("Request Duration: "));
param_list.add(new Label(ri.getDuration()));
param_list.add(new Label("IP: "));
param_list.add(new Label(ri.getIP()));
param_list.add(new Label("Method: "));
param_list.add(new Label(ri.getMethod()));
param_list.add(new Label("URL: "));
param_list.add(new Label(ri.getURL()));
param_list.add(new Label("Query: "));
param_list.add(new Label(StringUtils.quoteHtml( ri.getQuery())));
param_list.add(new Label("Request Parameters: "));
param_list.add(form_list = new ColumnPanel(2));
Iterator iter = ri.getParameterNames();
while (iter.hasNext()) {
String param = (String)iter.next();
form_list.add(new Label(param + ":"));
form_list.add(new Label(ri.getParameter(param)));
}
bp.add(new Label("<h3>Headers</h3>", false));
bp.add(headers_list = new ColumnPanel(2));
iter = ri.headerKeys();
while (iter.hasNext()) {
String header = (String)iter.next();
headers_list.add(new Label(header +": "));
headers_list.add(new Label(ri.getHeader(header)));
}
//Doesn't appear to be possible to get the output headers
//bp.add(new Label("Output Headers"));
if (ri.numComments() > 0) {
bp.add(new Label("<h3>Comments</h3>", false));
bp.add(comment_list = new ListPanel(false));
iter = ri.getComments();
while (iter.hasNext()) {
comment_list.add(new Label((String)iter.next()));
}
}
if (ri.numStages() > 0) {
bp.add(new Label("<h3>Stages</h3>", false));
bp.add(stages_list = new ColumnPanel(4));
iter = ri.getStages();
stages_list.add(new Label("Stage"));
stages_list.add(new Label("Time"));
stages_list.add(new Label("Queries"));
stages_list.add(new Label("Processing"));
while (iter.hasNext()) {
StageInfo si = (StageInfo)iter.next();
String leaf = si.leaf() ? "*" : "";
int numqueries = si.numQueries();
long time = si.time();
stages_list.add(new Label(dashes(si.depth()) + si.getName()));
stages_list.add(new Label(time + " ms" + leaf));
if (numqueries != 0) {
long queryTime = si.queryTime(ri.getQueries());
long non_queryTime = time-queryTime;
stages_list.add(new Label(queryTime + " ms" + leaf +
" ("+numqueries+" queries)"));
stages_list.add(new Label(non_queryTime + " ms" + leaf));
} else {
stages_list.add(new Label(""));
stages_list.add(new Label(time + " ms"+ leaf));
}
}
}
bp.add(new Label("<h3>Database Requests</h3>", false));
int query_count = 0;
long total_time = 0;
long total_execute = 0;
int unclosed_count = 0;
iter = ri.getQueries();
while (iter.hasNext()) {
QueryInfo qi = (QueryInfo)iter.next();
query_count++;
total_execute += qi.getTime();
total_time += qi.getTotalTime();
if (!qi.isClosed()) {
unclosed_count++;
}
}
bp.add(new Label("Total Queries: " + query_count +
(unclosed_count > 0 ? " (" + unclosed_count +
" unclosed)" : "")));
bp.add(new Label("Total Time: " + total_time +
" ms (execution: " + total_execute + " ms)"));
bp.generateXML(state, parent);
}
}
}
/**
* Class
*/
class QueryInfoComponent extends com.arsdigita.bebop.SimpleComponent {
/**
*
*/
public QueryInfoComponent() {
super();
}
/**
*
* @param state
* @param parent
*/
@Override
public void generateXML(PageState state, Element parent) {
Integer request_id = (Integer)state.getValue(m_query_request_id);
Integer query_id = (Integer)state.getValue(m_query_id);
RequestInfo ri =
WebDevSupportListener.getInstance().getRequest(request_id.intValue());
if (ri != null) {
QueryInfo qi = ri.getQuery(query_id.intValue());
if (qi != null) {
ListPanel info_list;
BoxPanel bp = new BoxPanel();
bp.add(info_list = new ListPanel(false));
info_list.add(new Label("Total query duration: " +
qi.getTotalTime() + " ms"));
info_list.add(new Label("Query execution time: " +
qi.getTime() + " ms"));
info_list.add(new Label("Statement closed: " +
qi.isClosed()));
info_list.add(new Label("Connection ID: " +
qi.getConnectionID()));
info_list.add(new Label("Type: " +
qi.getType()));
info_list.add(new Label("Query: <br/><pre>" +
StringUtils.quoteHtml(
qi.getQuery() ) + "</pre>", false));
info_list.add(new Label("Bindvars: " +
qi.getBindvars()));
Link l = new Link ("Query Execution Plan",
"../query-plan/");
l.setVar("request_id", request_id.toString());
l.setVar("query_id", query_id.toString());
info_list.add(l);
info_list.add(new Label("Exception: " +
qi.getSQLE()));
info_list.add(new Label("StackTrace: <br/><pre>" +
StringUtils.quoteHtml(qi.getStackTrace()) +
"</pre>", false));
bp.generateXML(state, parent);
}
}
}
}
// We need NonEscapedTableCellRenderer
// Currently part of (thisPackage) Dispatcher.java
// When the class will we deleted we must copy first!
}

View File

@ -83,6 +83,11 @@
<servlet-class>com.arsdigita.versioning.VersioningServlet</servlet-class> <servlet-class>com.arsdigita.versioning.VersioningServlet</servlet-class>
</servlet> </servlet>
<servlet>
<servlet-name>webdevsupport</servlet-name>
<servlet-class>com.arsdigita.webdevsupport.WebDevSupportServlet</servlet-class>
</servlet>
<servlet> <servlet>
<servlet-name>oid-redirect</servlet-name> <servlet-name>oid-redirect</servlet-name>
<servlet-class>com.arsdigita.web.OIDRedirectServlet</servlet-class> <servlet-class>com.arsdigita.web.OIDRedirectServlet</servlet-class>
@ -176,6 +181,11 @@
<url-pattern>/versioning/*</url-pattern> <url-pattern>/versioning/*</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping>
<servlet-name>webdevsupport</servlet-name>
<url-pattern>/webdevsupport/*</url-pattern>
</servlet-mapping>
<servlet-mapping> <servlet-mapping>
<servlet-name>oid-redirect</servlet-name> <servlet-name>oid-redirect</servlet-name>
<url-pattern>/redirect/*</url-pattern> <url-pattern>/redirect/*</url-pattern>

View File

@ -53,9 +53,10 @@ public class ForumServlet extends BebopApplicationServlet
@Override @Override
public void init() throws ServletException { public void init() throws ServletException {
super.init(); super.init();
s_log.debug("creating forum page");
s_log.debug("creating forum page");
final Page forum = ForumPageFactory.getPage(ForumPageFactory.FORUM_PAGE); final Page forum = ForumPageFactory.getPage(ForumPageFactory.FORUM_PAGE);
s_log.debug("creating thread page"); s_log.debug("creating thread page");
final Page thread = ForumPageFactory.getPage(ForumPageFactory.THREAD_PAGE); final Page thread = ForumPageFactory.getPage(ForumPageFactory.THREAD_PAGE);

View File

@ -122,6 +122,11 @@
<servlet-class>com.arsdigita.versioning.VersioningServlet</servlet-class> <servlet-class>com.arsdigita.versioning.VersioningServlet</servlet-class>
</servlet> </servlet>
<servlet>
<servlet-name>webdevsupport</servlet-name>
<servlet-class>com.arsdigita.webdevsupport.WebDevSupportServlet</servlet-class>
</servlet>
<servlet> <servlet>
<servlet-name>oid-redirect</servlet-name> <servlet-name>oid-redirect</servlet-name>
<servlet-class>com.arsdigita.web.OIDRedirectServlet</servlet-class> <servlet-class>com.arsdigita.web.OIDRedirectServlet</servlet-class>
@ -439,6 +444,11 @@
<url-pattern>/versioning/*</url-pattern> <url-pattern>/versioning/*</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping>
<servlet-name>webdevsupport</servlet-name>
<url-pattern>/webdevsupport/*</url-pattern>
</servlet-mapping>
<servlet-mapping> <servlet-mapping>
<servlet-name>oid-redirect</servlet-name> <servlet-name>oid-redirect</servlet-name>
<url-pattern>/redirect/*</url-pattern> <url-pattern>/redirect/*</url-pattern>