Ergänzungen und Korrekturen für den XMLDeliveryCache

git-svn-id: https://svn.libreccm.org/ccm/trunk@2152 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2013-05-14 13:01:39 +00:00
parent f21e8f8fc1
commit 7d362ba2e6
11 changed files with 484 additions and 295 deletions

View File

@ -1320,6 +1320,11 @@ public class ContentItem extends VersionedACSObject implements CustomCopy {
Assert.isTrue(isLive(), "Attempt to republish non live item " + getOID()); Assert.isTrue(isLive(), "Attempt to republish non live item " + getOID());
//ToDo Remove item from cache
if (CMSConfig.getInstance().getEnableXmlCache()) {
XMLDeliveryCache.getInstance().removeFromCache(getOID());
}
Lifecycle cycle = getLifecycle(); Lifecycle cycle = getLifecycle();
Assert.exists(cycle, Lifecycle.class); Assert.exists(cycle, Lifecycle.class);
//resets lifecycle if opted //resets lifecycle if opted

View File

@ -46,11 +46,11 @@ import java.util.Iterator;
*/ */
class DomainCopier extends DomainService { class DomainCopier extends DomainService {
private static Logger s_log = Logger.getLogger(DomainCopier.class); private static final Logger s_log = Logger.getLogger(DomainCopier.class);
// A map of OID => DomainObject // A map of OID => DomainObject
private final HashMap m_copied; private final HashMap m_copied;
protected final TraversedSet m_traversed; protected final TraversedSet m_traversed;
final Tracer m_trace; protected final Tracer m_trace;
/** /**
* Constructs a new <code>DomainCopier</code> * Constructs a new <code>DomainCopier</code>
@ -127,7 +127,7 @@ class DomainCopier extends DomainService {
} }
} }
protected void copyData(final DomainObject source, DomainObject target) { protected void copyData(final DomainObject source, final DomainObject target) {
final ObjectType type = source.getObjectType(); final ObjectType type = source.getObjectType();
if (s_log.isDebugEnabled()) { if (s_log.isDebugEnabled()) {
@ -300,6 +300,7 @@ class DomainCopier extends DomainService {
Assert.exists(data, DataObject.class); Assert.exists(data, DataObject.class);
final DomainObject domain = domain(data); final DomainObject domain = domain(data);
checkXmlCache(domain);
m_traversed.add(domain, prop.getAssociatedProperty()); m_traversed.add(domain, prop.getAssociatedProperty());
@ -313,6 +314,7 @@ class DomainCopier extends DomainService {
set(target, name, null); set(target, name, null);
} else { } else {
final DomainObject domain = domain(data); final DomainObject domain = domain(data);
checkXmlCache(domain);
m_traversed.add(domain, prop.getAssociatedProperty()); m_traversed.add(domain, prop.getAssociatedProperty());
@ -362,6 +364,7 @@ class DomainCopier extends DomainService {
m_traversed.add(selem, reverse); m_traversed.add(selem, reverse);
final DomainObject telem = copy(source, target, selem, prop); final DomainObject telem = copy(source, target, selem, prop);
checkXmlCache(telem);
DataObject tgtLink = null; DataObject tgtLink = null;
@ -469,16 +472,31 @@ class DomainCopier extends DomainService {
return contains(object.getOID() + "." + prop.getName()); return contains(object.getOID() + "." + prop.getName());
} }
} }
protected final class WrapperDomainObject extends DomainObject { protected final class WrapperDomainObject extends DomainObject {
public WrapperDomainObject(DataObject dobj) { public WrapperDomainObject(final DataObject dobj) {
super(dobj); super(dobj);
} }
public WrapperDomainObject(OID oid) { public WrapperDomainObject(final OID oid) {
super(oid); super(oid);
} }
} }
/**
* Helper method for invalidating the cached XML of associated objects when an item is (re-)published.
*
* @param dobj
*/
private void checkXmlCache(final DomainObject dobj) {
if ((dobj instanceof ContentItem) && CMSConfig.getInstance().getEnableXmlCache()) {
final ContentItem item = (ContentItem) dobj;
XMLDeliveryCache.getInstance().removeFromCache(item.getOID());
}
}
} }

View File

@ -19,7 +19,6 @@
package com.arsdigita.cms.dispatcher; package com.arsdigita.cms.dispatcher;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.caching.CacheTable;
import com.arsdigita.cms.CMS; import com.arsdigita.cms.CMS;
import com.arsdigita.cms.CMSConfig; import com.arsdigita.cms.CMSConfig;
import com.arsdigita.cms.ContentItem; import com.arsdigita.cms.ContentItem;
@ -27,6 +26,7 @@ import com.arsdigita.cms.ContentItemXMLRenderer;
import com.arsdigita.cms.ExtraXMLGenerator; import com.arsdigita.cms.ExtraXMLGenerator;
import com.arsdigita.cms.SecurityManager; import com.arsdigita.cms.SecurityManager;
import com.arsdigita.cms.UserDefinedContentItem; import com.arsdigita.cms.UserDefinedContentItem;
import com.arsdigita.cms.XMLDeliveryCache;
import com.arsdigita.cms.util.GlobalizationUtil; import com.arsdigita.cms.util.GlobalizationUtil;
import com.arsdigita.domain.DataObjectNotFoundException; import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.domain.DomainObjectFactory;
@ -42,7 +42,6 @@ import com.arsdigita.persistence.OID;
import com.arsdigita.persistence.metadata.Property; import com.arsdigita.persistence.metadata.Property;
import com.arsdigita.util.UncheckedWrapperException; import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.xml.Element; import com.arsdigita.xml.Element;
import java.util.HashMap;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -84,17 +83,6 @@ public class SimpleXMLGenerator implements XMLGenerator {
*/ */
private String itemElemName = "cms:item"; private String itemElemName = "cms:item";
private String itemElemNs = CMS.CMS_XML_NS; private String itemElemNs = CMS.CMS_XML_NS;
//Cache for generated XML
private static final CacheTable CACHE = new CacheTable(
SimpleXMLGenerator.class.getName() + "Cache",
CMSConfig.getInstance().getXmlCacheSize(),
CMSConfig.getInstance().getXmlCacheAge(),
true);
//Stores the master ID of the cached items and the ID of cached version. Used to delete obsolete entries in the
//cash after republishing
private static final Map<String, String> CACHED_ITEMS = new HashMap<String, String>();
//private static final Map<OID, Element> cache = new HashMap<OID, Element>();
//private static final boolean USE_CACHE = false;
// Register general purpose adaptor for all content items // Register general purpose adaptor for all content items
static { static {
@ -201,29 +189,14 @@ public class SimpleXMLGenerator implements XMLGenerator {
// This is the preferred method // This is the preferred method
//final Element content = startElement(useContext, parent); //final Element content = startElement(useContext, parent);
final Element content; final Element content = startElement(useContext);
if (CMSConfig.getInstance().getEnableXmlCache() && (CACHE.get(item.getOID().toString()) != null)) {
s_log.debug("Item found in cache, using cached XML");
final Element cached = (Element) CACHE.get(item.getOID().toString());
//parent.importElement(content);
cached.syncDocs();
content = startElement(useContext);
final Iterator entries = cached.getAttributes().entrySet().iterator();
Map.Entry entry;
while (entries.hasNext()) {
entry = (Map.Entry) entries.next();
content.addAttribute((String) entry.getKey(), (String) entry.getValue());
}
final Iterator childs = cached.getChildren().iterator();
while (childs.hasNext()) {
copyElement(content, (Element) childs.next());
}
} else {
s_log.debug("Item is not in cache, generating item."); s_log.debug("Item is not in cache, generating item.");
content = startElement(useContext); final XMLDeliveryCache xmlCache = XMLDeliveryCache.getInstance();
if (CMSConfig.getInstance().getEnableXmlCache() && xmlCache.isCached(item.getOID(), useContext, listMode)) {
xmlCache.retrieveFromCache(content, item.getOID(), useContext, listMode);
} else {
final ContentItemXMLRenderer renderer = new ContentItemXMLRenderer(content); final ContentItemXMLRenderer renderer = new ContentItemXMLRenderer(content);
renderer.setWrapAttributes(true); renderer.setWrapAttributes(true);
@ -241,29 +214,6 @@ public class SimpleXMLGenerator implements XMLGenerator {
//parent.addContent(content); //parent.addContent(content);
if (CMSConfig.getInstance().getEnableXmlCache()) {
validateCache(item);
}
//Only published items
//Only the XML of the item itself, no extra XML
if (CMSConfig.getInstance().getEnableXmlCache() && item.isLiveVersion()) {
s_log.debug("Putting item item into the cache.");
final Element cachedElem = startCachedElement(useContext);
final Iterator entries = content.getAttributes().entrySet().iterator();
Map.Entry entry;
while (entries.hasNext()) {
entry = (Map.Entry) entries.next();
cachedElem.addAttribute((String) entry.getKey(), (String) entry.getValue());
}
final Iterator childs = content.getChildren().iterator();
while (childs.hasNext()) {
//cachedElem.newChildElement((Element) childs.next());
copyElement(cachedElem, (Element) childs.next());
}
CACHE.put(item.getOID().toString(), cachedElem);
}
}
//Only item XML Cache End //Only item XML Cache End
// s_log.debug("Content elem content: "); // s_log.debug("Content elem content: ");
@ -286,27 +236,13 @@ public class SimpleXMLGenerator implements XMLGenerator {
generator.generateXML(item, content, state); generator.generateXML(item, content, state);
} }
} }
// System.out.
// printf("Rendered ExtraXML in %d ms\n", (System.nanoTime() - extraXMLStart) / 1000000);
// System.out.printf(" -----\n");
//Complete cache begin //Only published items
// if (CMSConfig.getInstance().getEnableXmlCache() && item.isLiveVersion()) { //Only the XML of the item itself, no extra XML
// final Element cachedElem = startElement(useContext); if (CMSConfig.getInstance().getEnableXmlCache() && item.isLiveVersion()) {
// final Iterator entries = content.getAttributes().entrySet().iterator(); xmlCache.cache(item.getOID(), item, content, useContext, listMode);
// Map.Entry entry; }
// while (entries.hasNext()) { }
// entry = (Map.Entry) entries.next();
// cachedElem.addAttribute((String) entry.getKey(), (String) entry.getValue());
// }
// final Iterator childs = content.getChildren().iterator();
// while (childs.hasNext()) {
// cachedElem.newChildElement((Element) childs.next());
// }
// CACHE.put(item.getOID().toString(), cachedElem);
// }
// }
//complete cache end
if (PermissionService.checkPermission(edit)) { if (PermissionService.checkPermission(edit)) {
final ItemResolver resolver = item.getContentSection().getItemResolver(); final ItemResolver resolver = item.getContentSection().getItemResolver();
@ -506,20 +442,4 @@ public class SimpleXMLGenerator implements XMLGenerator {
return builder.toString(); return builder.toString();
} }
private void validateCache(final ContentItem item) {
if (item.isDraftVersion()) {
//Draft version are not cached
return;
}
final String itemId = item.getOID().toString();
final String masterId = item.getDraftVersion().getOID().toString();
final String cachedId = CACHED_ITEMS.get(masterId);
if ((cachedId != null)
&& !cachedId.equals(itemId)) {
CACHE.remove(cachedId);
}
}
} }

View File

@ -16,7 +16,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
*/ */
package com.arsdigita.ui.admin; package com.arsdigita.ui.admin;
import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Page;
@ -47,30 +46,31 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
* Web Developer Support Application Servlet class, central entry point to * Web Developer Support Application Servlet class, central entry point to create and process the applications UI.
* create and process the applications UI.
* *
* We should have subclassed BebopApplicationServlet but couldn't overwrite * We should have subclassed BebopApplicationServlet but couldn't overwrite doService() method to add permission
* doService() method to add permission checking. So we use our own page * checking. So we use our own page mapping. The general logic is the same as for BebopApplicationServlet.
* mapping. The general logic is the same as for BebopApplicationServlet. * {
* {@see com.arsdigita.bebop.page.BebopApplicationServlet} *
* @see com.arsdigita.bebop.page.BebopApplicationServlet}
* *
* @author pb * @author pb
*/ */
public class AdminServlet extends BaseApplicationServlet public class AdminServlet extends BaseApplicationServlet
implements AdminConstants{ implements AdminConstants {
/** Logger instance for debugging */ /**
* Logger instance for debugging
*/
private static final Logger s_log = Logger.getLogger( private static final Logger s_log = Logger.getLogger(
AdminServlet.class.getName()); AdminServlet.class.getName());
/**
/** URL (pathinfo) -> Page object mapping. Based on it (and the http * URL (pathinfo) -> Page object mapping. Based on it (and the http request url) the doService method to selects a
* request url) the doService method to selects a page to display */ * page to display
*/
private final Map m_pages = new HashMap(); private final Map m_pages = new HashMap();
/** /**
* User extension point, overwrite this method to setup a URL - page mapping * User extension point, overwrite this method to setup a URL - page mapping
* *
@ -84,10 +84,9 @@ public class AdminServlet extends BaseApplicationServlet
} }
/** /**
* Central service method, checks for required permission, determines the * Central service method, checks for required permission, determines the requested page and passes the page object
* requested page and passes the page object to PresentationManager. * to PresentationManager.
*/ */
public final void doService(HttpServletRequest sreq, public final void doService(HttpServletRequest sreq,
HttpServletResponse sresp, HttpServletResponse sresp,
@ -104,8 +103,7 @@ public class AdminServlet extends BaseApplicationServlet
throw new LoginSignal(sreq); throw new LoginSignal(sreq);
} }
/* Determine access privilege: Admin privileges must be granted */ /* Determine access privilege: Admin privileges must be granted */
PermissionDescriptor admin = new PermissionDescriptor PermissionDescriptor admin = new PermissionDescriptor(PrivilegeDescriptor.ADMIN, app, party);
(PrivilegeDescriptor.ADMIN, app, party);
if (!PermissionService.checkPermission(admin)) { if (!PermissionService.checkPermission(admin)) {
throw new AccessDeniedException("User is not an administrator"); throw new AccessDeniedException("User is not an administrator");
} }
@ -123,7 +121,7 @@ public class AdminServlet extends BaseApplicationServlet
* trailing '/' if a "virtual" page, i.e. not a real jsp, but * trailing '/' if a "virtual" page, i.e. not a real jsp, but
* result of a servlet mapping. But Application requires url * result of a servlet mapping. But Application requires url
* NOT to end with a trailing '/' for legacy free applications. */ * NOT to end with a trailing '/' for legacy free applications. */
pathInfo = pathInfo.substring(0, pathInfo.length()-1); pathInfo = pathInfo.substring(0, pathInfo.length() - 1);
} }
final Page page = (Page) m_pages.get(pathInfo); final Page page = (Page) m_pages.get(pathInfo);
@ -143,7 +141,6 @@ public class AdminServlet extends BaseApplicationServlet
} }
/** /**
* Adds one pair of Url - Page to the internal hash map, used as a cache. * Adds one pair of Url - Page to the internal hash map, used as a cache.
* *
@ -171,7 +168,7 @@ public class AdminServlet extends BaseApplicationServlet
p.addGlobalStateParam(USER_ID_PARAM); p.addGlobalStateParam(USER_ID_PARAM);
p.addGlobalStateParam(GROUP_ID_PARAM); p.addGlobalStateParam(GROUP_ID_PARAM);
// p.addGlobalStateParam(APPLICATIONS_ID_PARAM); p.addGlobalStateParam(APPLICATIONS_ID_PARAM);
/* Create User split panel. */ /* Create User split panel. */
AdminSplitPanel userSplitPanel = AdminSplitPanel userSplitPanel =
@ -198,8 +195,8 @@ public class AdminServlet extends BaseApplicationServlet
/* /*
* Create group administration panel * Create group administration panel
*/ */
// ApplicationsAdministrationTab appsAdministrationTab = ApplicationsAdministrationTab appsAdministrationTab =
// new ApplicationsAdministrationTab(); new ApplicationsAdministrationTab();
// Create the Admin's page tab bar, currently 2 elements: user & groups // Create the Admin's page tab bar, currently 2 elements: user & groups
TabbedPane tb = new TabbedPane(); TabbedPane tb = new TabbedPane();
@ -207,19 +204,15 @@ public class AdminServlet extends BaseApplicationServlet
tb.addTab(USER_TAB_TITLE, userSplitPanel); tb.addTab(USER_TAB_TITLE, userSplitPanel);
tb.addTab(GROUP_TAB_TITLE, groupAdministrationTab); tb.addTab(GROUP_TAB_TITLE, groupAdministrationTab);
// tb.addTab(APPLICATIONS_TAB_TITLE, appsAdministrationTab); tb.addTab(APPLICATIONS_TAB_TITLE, appsAdministrationTab);
browsePane.setTabbedPane(tb); browsePane.setTabbedPane(tb);
browsePane.setGroupAdministrationTab(groupAdministrationTab); browsePane.setGroupAdministrationTab(groupAdministrationTab);
// browsePane.setAppsAdministrationTab(appsAdministrationTab); //browsePane.setAppsAdministrationTab(appsAdministrationTab);
p.add(tb); p.add(tb);
p.lock(); p.lock();
return p; return p;
} }
} }

View File

@ -5,22 +5,36 @@
package com.arsdigita.ui.admin; package com.arsdigita.ui.admin;
import com.arsdigita.bebop.BoxPanel; import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Link;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SplitPanel; import com.arsdigita.bebop.SplitPanel;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.event.ChangeEvent; import com.arsdigita.bebop.event.ChangeEvent;
import com.arsdigita.bebop.event.ChangeListener; import com.arsdigita.bebop.event.ChangeListener;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.event.TableActionListener;
import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.bebop.table.TableColumnModel;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.bebop.table.TableModelBuilder;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.util.LockableImpl;
import com.arsdigita.web.Application;
import com.arsdigita.web.ApplicationCollection;
/** /**
* *
* @author pb * @author pb
* @author Jens Pelzetter
*/ */
public class ApplicationsAdministrationTab extends BoxPanel public class ApplicationsAdministrationTab extends BoxPanel
implements AdminConstants, ChangeListener { implements AdminConstants, ChangeListener {
private GlobalizedMessage m_title; private GlobalizedMessage m_title;
/** /**
* Constructor * Constructor
*/ */
@ -33,20 +47,23 @@ public class ApplicationsAdministrationTab extends BoxPanel
// m_keys = new ArrayList(); // m_keys = new ArrayList();
BoxPanel box = new BoxPanel(); final BoxPanel box = new BoxPanel();
box.setClassAttr("main"); box.setClassAttr("main");
SplitPanel panel = new SplitPanel(); final SplitPanel panel = new SplitPanel();
panel.setClassAttr("sidebarNavPanel"); panel.setClassAttr("sidebarNavPanel");
panel.setRightComponent(box); panel.setRightComponent(box);
box.add(new ApplicationsTable());
add(panel);
} }
/** /**
* *
* @param e * @param e
*/ */
@Override
public void stateChanged(ChangeEvent e) { public void stateChanged(ChangeEvent e) {
PageState ps = e.getPageState(); PageState ps = e.getPageState();
@ -58,6 +75,182 @@ public class ApplicationsAdministrationTab extends BoxPanel
// setTab(selectedIndex, ps); // setTab(selectedIndex, ps);
} }
private class ApplicationsTable extends Table implements TableActionListener {
private static final String COL_APP_CLASS = "col_app_class";
private static final String COL_APP_TYPE = "col_app_type";
private static final String COL_APP_VIEW_URL = "col_app_view_url";
private static final String COL_APP_ADMIN_URL = "col_app_admin_url";
private static final String COL_APP_SINGLETON = "col_app_singleton";
public ApplicationsTable() {
super();
setEmptyView(new Label("No applications installed."));
final TableColumnModel colModel = getColumnModel();
colModel.add(new TableColumn(
0,
"App Class",
COL_APP_CLASS));
colModel.add(new TableColumn(
1,
"App Type",
COL_APP_TYPE));
colModel.add(new TableColumn(
2,
"App View URL",
COL_APP_VIEW_URL));
colModel.add(new TableColumn(
3,
"Is Singleton?",
COL_APP_SINGLETON));
setModelBuilder(new ApplicationsTableModelBuilder());
colModel.get(0).setCellRenderer(new TableCellRenderer() {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
return new Label(value.toString());
}
});
colModel.get(1).setCellRenderer(new TableCellRenderer() {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
return new Label(value.toString());
}
});
colModel.get(2).setCellRenderer(new TableCellRenderer() {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
return new Link(value.toString(), value.toString());
}
});
colModel.get(3).setCellRenderer(new TableCellRenderer() {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
return new Label(value.toString());
}
});
addTableActionListener(this);
}
private class ApplicationsTableModelBuilder extends LockableImpl implements TableModelBuilder {
@Override
public TableModel makeModel(final Table table, final PageState state) {
return new ApplicationsTableModel(table);
}
}
private class ApplicationsTableModel implements TableModel {
private final Table table;
private final ApplicationCollection apps;
private Application app;
public ApplicationsTableModel(final Table table) {
this.table = table;
apps = Application.retrieveAllApplications();
apps.addOrder("objectType");
}
@Override
public int getColumnCount() {
return table.getColumnModel().size();
}
@Override
public boolean nextRow() {
boolean ret;
if ((apps != null) && apps.next()) {
app = apps.getApplication();
ret = true;
} else {
ret = false;
}
return ret;
}
@Override
public Object getElementAt(final int columnIndex) {
switch (columnIndex) {
case 0:
return String.format("%s (%s)", app.getObjectType().getName(), app.getClass().getName());
case 1:
return app.getApplicationType().getTitle();
case 2:
return app.getPath();
case 3:
return Boolean.toString(app.getApplicationType().isSingleton());
default:
return null;
}
}
@Override
public Object getKeyAt(final int columnIndex) {
return app.getID();
}
private String constructAppPath(final Application app) {
if (app.getParentApplication() == null) {
return app.getPath();
} else {
return String.format("%s/%s", constructAppPath(app.getParentApplication()), app.getPath());
}
}
}
@Override
public void cellSelected(final TableActionEvent event) {
//Nothing for now
}
@Override
public void headSelected(final TableActionEvent event) {
//Nothing for now
}
}
} }

View File

@ -68,17 +68,14 @@ public class Application extends Resource {
/** Logger instance for debugging. */ /** Logger instance for debugging. */
private static final Logger s_log = Logger.getLogger(Application.class); private static final Logger s_log = Logger.getLogger(Application.class);
/** PDL property, basic object type for all applications of this type */ /** PDL property, basic object type for all applications of this type */
public static final String BASE_DATA_OBJECT_TYPE = public static final String BASE_DATA_OBJECT_TYPE =
"com.arsdigita.web.Application"; "com.arsdigita.web.Application";
/** PDL property, the applications base URL. */ /** PDL property, the applications base URL. */
public static final String PRIMARY_URL = "primaryURL"; public static final String PRIMARY_URL = "primaryURL";
/** Internal String to denote a Path delimiter. */ /** Internal String to denote a Path delimiter. */
private static final String SLASH = "/"; private static final String SLASH = "/";
/** /**
* Provides the base object type. * Provides the base object type.
*/ */
@ -151,7 +148,7 @@ public class Application extends Resource {
final String title, final String title,
final Application parent) { final Application parent) {
s_log.debug("Create Application"); s_log.debug("Create Application");
return Application.createApplication(type,fragment,title,parent,false); return Application.createApplication(type, fragment, title, parent, false);
} }
// For convenience. // For convenience.
@ -168,7 +165,7 @@ public class Application extends Resource {
final String title, final String title,
final Application parent) { final Application parent) {
return Application.createApplication(typeName,fragment,title,parent,false); return Application.createApplication(typeName, fragment, title, parent, false);
} }
/** /**
@ -193,8 +190,8 @@ public class Application extends Resource {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"No ApplicationType found for type name " + typeName); "No ApplicationType found for type name " + typeName);
} }
return Application.createApplication(type,fragment, return Application.createApplication(type, fragment,
title,parent,createContainerGroup); title, parent, createContainerGroup);
} }
/** /**
@ -224,7 +221,7 @@ public class Application extends Resource {
Assert.isTrue(!fragment.equals(""), Assert.isTrue(!fragment.equals(""),
"The URL fragment must not be the empty string"); "The URL fragment must not be the empty string");
} }
return Application.make(type,fragment,title,parent, return Application.make(type, fragment, title, parent,
createContainerGroup); createContainerGroup);
} }
@ -252,8 +249,7 @@ public class Application extends Resource {
} }
if (Assert.isEnabled() && fragment != null) { if (Assert.isEnabled() && fragment != null) {
Assert.isTrue(fragment.indexOf('/') == -1, Assert.isTrue(fragment.indexOf('/') == -1,
"The URL fragment must not contain " + "The URL fragment must not contain " + "slashes; I got '" + fragment + "'");
"slashes; I got '" + fragment + "'");
} }
/* Problem with "slash or not slash" /* Problem with "slash or not slash"
@ -285,7 +281,6 @@ public class Application extends Resource {
return app; return app;
} }
/** /**
* *
* @param id * @param id
@ -338,8 +333,7 @@ public class Application extends Resource {
Assert.exists(obj, ACSObject.class); Assert.exists(obj, ACSObject.class);
ACSObject result = obj.gimmeContainer(); ACSObject result = obj.gimmeContainer();
while (result != null && while (result != null && !(result instanceof Application)) {
!(result instanceof Application)) {
result = result.gimmeContainer(); result = result.gimmeContainer();
} }
@ -372,7 +366,6 @@ public class Application extends Resource {
// /////////////////////// // ///////////////////////
// Association properties // Association properties
// /////////////////////// // ///////////////////////
/** /**
* *
* @return (Cannot return null.) * @return (Cannot return null.)
@ -445,14 +438,12 @@ public class Application extends Resource {
* @param applicationType * @param applicationType
* @return * @return
*/ */
public ApplicationCollection getChildApplicationsForType public ApplicationCollection getChildApplicationsForType(String applicationType) {
(String applicationType) {
ApplicationCollection children = getChildApplications(); ApplicationCollection children = getChildApplications();
children.addEqualsFilter("objectType", applicationType); children.addEqualsFilter("objectType", applicationType);
return children; return children;
} }
// Can return null. // Can return null.
/** /**
* @deprecated Use {@link * @deprecated Use {@link
@ -471,7 +462,6 @@ public class Application extends Resource {
// ////////////////// // //////////////////
// Member properties // Member properties
// ////////////////// // //////////////////
/** /**
* Returns the path to this application through the dispatcher. * Returns the path to this application through the dispatcher.
* This path ends in a slash. Returns <code>null</code> if the * This path ends in a slash. Returns <code>null</code> if the
@ -526,7 +516,7 @@ public class Application extends Resource {
public final void setPath(String path) { public final void setPath(String path) {
if (Assert.isEnabled()) { if (Assert.isEnabled()) {
Assert.exists(path, String.class); Assert.exists(path, String.class);
/* Modified by pboy April 2011 /* Modified by pboy April 2011
* This Assert statement prevents a trailing slash. setPath is currently called * This Assert statement prevents a trailing slash. setPath is currently called
* only by Applicatiom#make which creates a LEGACY FREE application. * only by Applicatiom#make which creates a LEGACY FREE application.
* Legacy compatible applications are currently created WITH a trailing slash * Legacy compatible applications are currently created WITH a trailing slash
@ -564,27 +554,24 @@ public class Application extends Resource {
// exclude all portlets (no application at all) and portal panes // exclude all portlets (no application at all) and portal panes
// (no application but sort of "sub-application"). // (no application but sort of "sub-application").
dataCollection.addEqualsFilter dataCollection.addEqualsFilter("resourceType.hasFullPageView", Boolean.TRUE);
("resourceType.hasFullPageView", Boolean.TRUE);
ApplicationCollection apps = new ApplicationCollection ApplicationCollection apps = new ApplicationCollection(dataCollection);
(dataCollection);
return apps; return apps;
} }
/** /**
* Retrieve all installed applications (portlets excluded). * Retrieve all installed applications (portlets excluded).
* @return a collection of installed * @return a collection of installed
*/ */
public static ApplicationCollection retrieveAllApplications(String public static ApplicationCollection retrieveAllApplications(String applicationType) {
applicationType) {
DataCollection dataCollection = SessionManager.getSession() DataCollection dataCollection = SessionManager.getSession()
.retrieve(BASE_DATA_OBJECT_TYPE); .retrieve(BASE_DATA_OBJECT_TYPE);
// exclude all portlets (no application at all) and portal panes // exclude all portlets (no application at all) and portal panes
// (no application but sort of "sub-application"). // (no application but sort of "sub-application").
dataCollection.addEqualsFilter dataCollection.addEqualsFilter("resourceType.hasFullPageView", Boolean.TRUE);
("resourceType.hasFullPageView", Boolean.TRUE);
dataCollection.addEqualsFilter("objectType", applicationType); dataCollection.addEqualsFilter("objectType", applicationType);
ApplicationCollection apps = new ApplicationCollection(dataCollection); ApplicationCollection apps = new ApplicationCollection(dataCollection);
@ -598,7 +585,7 @@ public class Application extends Resource {
* @param path * @param path
* @return * @return
*/ */
public static boolean isInstalled (String applicationObjectType, public static boolean isInstalled(String applicationObjectType,
String path) { String path) {
DataCollection dataCollection = DataCollection dataCollection =
SessionManager.getSession().retrieve(applicationObjectType); SessionManager.getSession().retrieve(applicationObjectType);
@ -629,7 +616,7 @@ public class Application extends Resource {
canonicalURL = url.startsWith(SLASH) ? url : (SLASH + url); canonicalURL = url.startsWith(SLASH) ? url : (SLASH + url);
canonicalURL = url.endsWith(SLASH) ? canonicalURL : (canonicalURL + SLASH); canonicalURL = url.endsWith(SLASH) ? canonicalURL : (canonicalURL + SLASH);
return canonicalURL ; return canonicalURL;
} }
/** /**
@ -756,7 +743,6 @@ public class Application extends Resource {
} }
/** /**
* . * .
* *
@ -765,7 +751,7 @@ public class Application extends Resource {
* @param title * @param title
*/ */
@Override @Override
public void setTitle (String title) { public void setTitle(String title) {
super.setTitle(title); super.setTitle(title);
Group containerGroup = getGroup(); Group containerGroup = getGroup();
if (containerGroup != null) { if (containerGroup != null) {

View File

@ -153,10 +153,13 @@ public class DataCollectionRenderer extends LockableImpl {
int pageNumber = pageNum; int pageNumber = pageNum;
final long objectCount = objects.size();
// Quasimodo: Begin // Quasimodo: Begin
// If objects is null or empty, do not insert objectList-element // If objects is null or empty, do not insert objectList-element
// but do insert noContent-element and return immediately // but do insert noContent-element and return immediately
if (objects == null || objects.isEmpty()) { //if (objects == null || objects.isEmpty()) {
if (objects == null || (objectCount == 0)) {
return Navigation.newElement("noContent"); return Navigation.newElement("noContent");
} }
// Quasimodo: End // Quasimodo: End
@ -171,7 +174,7 @@ public class DataCollectionRenderer extends LockableImpl {
return content; return content;
} }
final long objectCount = objects.size();
final int pageCount = (int) Math.ceil((double) objectCount / (double) m_pageSize); final int pageCount = (int) Math.ceil((double) objectCount / (double) m_pageSize);
if (pageNumber < 1) { if (pageNumber < 1) {

View File

@ -18,9 +18,11 @@
package com.arsdigita.navigation.cms; package com.arsdigita.navigation.cms;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.cms.CMSConfig;
import com.arsdigita.cms.ContentItem; import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentItemXMLRenderer; import com.arsdigita.cms.ContentItemXMLRenderer;
import com.arsdigita.cms.ExtraXMLGenerator; import com.arsdigita.cms.ExtraXMLGenerator;
import com.arsdigita.cms.XMLDeliveryCache;
import com.arsdigita.cms.dispatcher.ItemResolver; import com.arsdigita.cms.dispatcher.ItemResolver;
import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.kernel.ACSObject; import com.arsdigita.kernel.ACSObject;
@ -69,6 +71,16 @@ public class CMSDataCollectionRenderer extends DataCollectionRenderer {
ACSObject obj, ACSObject obj,
int index) { int index) {
if (obj != null) { if (obj != null) {
if (CMSConfig.getInstance().getEnableXmlCache()
&& (obj instanceof ContentItem)
&& XMLDeliveryCache.getInstance().isCached(obj.getOID())) {
XMLDeliveryCache.getInstance().retrieveFromCache(item, obj.getOID());
createEditLink(item, (ContentItem) obj);
} else {
ContentItemXMLRenderer renderer = new ContentItemXMLRenderer(item); ContentItemXMLRenderer renderer = new ContentItemXMLRenderer(item);
renderer.setRevisitFullObject(false); renderer.setRevisitFullObject(false);
renderer.setWrapAttributes(true); renderer.setWrapAttributes(true);
@ -91,10 +103,37 @@ public class CMSDataCollectionRenderer extends DataCollectionRenderer {
generator.generateXML(contentItem, item, null); generator.generateXML(contentItem, item, null);
} }
XMLDeliveryCache.getInstance().cache(contentItem.getOID(), contentItem, item, "", false);
createEditLink(item, contentItem);
// Party currentParty = Kernel.getContext().getParty();
// if (currentParty == null) {
// currentParty = Kernel.getPublicUser();
// }
//
// final PermissionDescriptor edit = new PermissionDescriptor(PrivilegeDescriptor.get(
// com.arsdigita.cms.SecurityManager.CMS_EDIT_ITEM), contentItem, currentParty);
// if (PermissionService.checkPermission(edit)) {
// final ItemResolver resolver = contentItem.getContentSection().getItemResolver();
// final Element editLinkElem = item.newChildElement("editLink");
// final ContentItem draftItem = contentItem.getDraftVersion();
// editLinkElem.setText(resolver.generateItemURL(PageState.getPageState(),
// draftItem,
// contentItem.getContentSection(),
// draftItem.getVersion()));
// }
}
}
}
}
private void createEditLink(final Element item, final ContentItem contentItem) {
Party currentParty = Kernel.getContext().getParty(); Party currentParty = Kernel.getContext().getParty();
if (currentParty == null) { if (currentParty == null) {
currentParty = Kernel.getPublicUser(); currentParty = Kernel.getPublicUser();
} }
final PermissionDescriptor edit = new PermissionDescriptor(PrivilegeDescriptor.get( final PermissionDescriptor edit = new PermissionDescriptor(PrivilegeDescriptor.get(
com.arsdigita.cms.SecurityManager.CMS_EDIT_ITEM), contentItem, currentParty); com.arsdigita.cms.SecurityManager.CMS_EDIT_ITEM), contentItem, currentParty);
if (PermissionService.checkPermission(edit)) { if (PermissionService.checkPermission(edit)) {
@ -107,7 +146,4 @@ public class CMSDataCollectionRenderer extends DataCollectionRenderer {
draftItem.getVersion())); draftItem.getVersion()));
} }
} }
}
}
} }

View File

@ -93,6 +93,7 @@ public abstract class AbstractObjectList
public Element generateObjectListXML(HttpServletRequest request, public Element generateObjectListXML(HttpServletRequest request,
HttpServletResponse response) { HttpServletResponse response) {
final long start = System.nanoTime();
Assert.isLocked(this); Assert.isLocked(this);
String pageNumberValue = request.getParameter("pageNumber"); String pageNumberValue = request.getParameter("pageNumber");
@ -108,7 +109,11 @@ public abstract class AbstractObjectList
"cannot parse page number " + pageNumber, ex); "cannot parse page number " + pageNumber, ex);
} }
final long loadObjectsStart = System.nanoTime();
DataCollection objects = getObjects(request, response); DataCollection objects = getObjects(request, response);
////System.out.printf("Got objects for list in %d ms\n", (System.nanoTime() - loadObjectsStart) / 1000000);
////System.out.printf("(100) Needed %d ms until here...\n", (System.nanoTime() - start) / 1000000);
// Quasimodo: Begin // Quasimodo: Begin
// Limit list to objects in the negotiated language and language invariant items // Limit list to objects in the negotiated language and language invariant items
@ -130,8 +135,15 @@ public abstract class AbstractObjectList
} }
} }
// Quasimodo: End // Quasimodo: End
////System.out.printf("(200) Needed %d ms until here...\n", (System.nanoTime() - start) / 1000000);
return m_renderer.generateXML(objects, pageNumber.intValue()); //final long renderStart = System.nanoTime();
final Element listXML = m_renderer.generateXML(objects, pageNumber.intValue());
//System.out.printf("Rendered items of list in %d ms\n", (System.nanoTime() - renderStart) / 1000000);
//System.out.printf("Generated object list in %d ms\n", (System.nanoTime() - start) / 1000000);
return listXML;
} }
} }

View File

@ -211,6 +211,7 @@ public class PersonalPublications implements ContentGenerator {
List<PublicationBundle> publicationList = publications; List<PublicationBundle> publicationList = publications;
Collections.sort(publicationList, new Comparator<PublicationBundle>() { Collections.sort(publicationList, new Comparator<PublicationBundle>() {
@Override
public int compare(final PublicationBundle bundle1, final PublicationBundle bundle2) { public int compare(final PublicationBundle bundle1, final PublicationBundle bundle2) {
final Publication publication1 = bundle1.getPublication(GlobalizationHelper.getNegotiatedLocale(). final Publication publication1 = bundle1.getPublication(GlobalizationHelper.getNegotiatedLocale().
getLanguage()); getLanguage());

View File

@ -31,6 +31,7 @@ public class PublicationExtraXmlGenerator implements ExtraXMLGenerator {
public void generateXML(final ContentItem item, public void generateXML(final ContentItem item,
final Element element, final Element element,
final PageState state) { final PageState state) {
final long start = System.nanoTime();
if (!(item instanceof Publication)) { if (!(item instanceof Publication)) {
throw new IllegalArgumentException(String.format( throw new IllegalArgumentException(String.format(
"ExtraXMLGenerator '%s' only supports items of type '%s'.", "ExtraXMLGenerator '%s' only supports items of type '%s'.",
@ -40,7 +41,13 @@ public class PublicationExtraXmlGenerator implements ExtraXMLGenerator {
final Publication publication = (Publication) item; final Publication publication = (Publication) item;
createAuthorsXml(publication, element, state); createAuthorsXml(publication, element, state);
System.out.printf("[%s] Created authors XML in %d ms\n",
PublicationExtraXmlGenerator.class.getName(),
(System.nanoTime() - start) / 1000000);
createSeriesXml(publication, element, state); createSeriesXml(publication, element, state);
System.out.printf("[%s] Created series XML in %d ms\n",
PublicationExtraXmlGenerator.class.getName(),
(System.nanoTime() - start) / 1000000);
if (!listMode) { if (!listMode) {
createOrgaUnitsXml(publication, element, state); createOrgaUnitsXml(publication, element, state);
@ -50,15 +57,22 @@ public class PublicationExtraXmlGenerator implements ExtraXMLGenerator {
createExportLink(format, element, (Publication) item, state); createExportLink(format, element, (Publication) item, state);
} }
} }
System.out.printf("[%s] Created extra XML in %d ms\n",
PublicationExtraXmlGenerator.class.getName(),
(System.nanoTime() - start) / 1000000);
} }
private void createAuthorsXml(final Publication publication, private void createAuthorsXml(final Publication publication,
final Element parent, final Element parent,
final PageState state) { final PageState state) {
final long start = System.nanoTime();
final AuthorshipCollection authors = publication.getAuthors(); final AuthorshipCollection authors = publication.getAuthors();
if ((authors == null) || authors.isEmpty()) { if ((authors == null) || authors.isEmpty()) {
return; return;
} }
System.out.printf("[%s#createAuthorsXML] Got authors in %d ms\n",
PublicationExtraXmlGenerator.class.getName(),
(System.nanoTime() - start) / 1000000);
final Element authorsElem = parent.newChildElement("authors"); final Element authorsElem = parent.newChildElement("authors");
while (authors.next()) { while (authors.next()) {
@ -68,6 +82,9 @@ public class PublicationExtraXmlGenerator implements ExtraXMLGenerator {
authorsElem, authorsElem,
state); state);
} }
System.out.printf("[%s#createAuthorsXML] Created XML for authors in %d ms\n",
PublicationExtraXmlGenerator.class.getName(),
(System.nanoTime() - start) / 1000000);
} }
private void createAuthorXml(final GenericPerson author, private void createAuthorXml(final GenericPerson author,
@ -75,12 +92,17 @@ public class PublicationExtraXmlGenerator implements ExtraXMLGenerator {
final Integer order, final Integer order,
final Element authorsElem, final Element authorsElem,
final PageState state) { final PageState state) {
final long start = System.nanoTime();
final XmlGenerator generator = new XmlGenerator(author); final XmlGenerator generator = new XmlGenerator(author);
generator.setItemElemName("author", ""); generator.setItemElemName("author", "");
generator.addItemAttribute("isEditor", isAuthor.toString()); generator.addItemAttribute("isEditor", isAuthor.toString());
generator.addItemAttribute("order", order.toString()); generator.addItemAttribute("order", order.toString());
generator.setListMode(listMode); generator.setListMode(listMode);
generator.generateXML(state, authorsElem, ""); generator.generateXML(state, authorsElem, "");
System.out.printf("[%s] Created XML for author %s in %d ms\n",
PublicationExtraXmlGenerator.class.getName(),
author.getTitle(),
(System.nanoTime() - start) / 1000000);
} }
private void createOrgaUnitsXml(final Publication publication, private void createOrgaUnitsXml(final Publication publication,