r1066 - in xwiki/trunk: . lib src/main/java/com/xpn/xwiki src/main/java/com/xpn/xwiki/cache/api src/main/java/com/xpn/xwiki/cache/impl src/main/java/com/xpn/xwiki/plugin/feed src/main/java/com/xpn/xwiki/plugin/image src/main/java/com/xpn/xwiki/render src/main/web/WEB-INF

Matthew Conway wr0ngway at users.forge.objectweb.org
Thu May 11 06:14:43 CEST 2006


Author: wr0ngway
Date: 2006-05-11 06:14:42 +0200 (Thu, 11 May 2006)
New Revision: 1066

Added:
   xwiki/trunk/lib/concurrent.jar
   xwiki/trunk/lib/jgroups-2.2.9.1.jar
   xwiki/trunk/lib/oscache-2.2.jar
   xwiki/trunk/src/main/java/com/xpn/xwiki/cache/impl/XWikiCacheListener.java
   xwiki/trunk/src/main/web/WEB-INF/oscache-local.properties
   xwiki/trunk/src/main/web/WEB-INF/oscache.properties
Removed:
   xwiki/trunk/lib/jgroups-2.2.5.jar
   xwiki/trunk/lib/oscache-2.0.2.jar
Modified:
   xwiki/trunk/
   xwiki/trunk/.classpath
   xwiki/trunk/build.xml
   xwiki/trunk/src/main/java/com/xpn/xwiki/XWiki.java
   xwiki/trunk/src/main/java/com/xpn/xwiki/cache/api/XWikiCacheService.java
   xwiki/trunk/src/main/java/com/xpn/xwiki/cache/impl/OSCacheCache.java
   xwiki/trunk/src/main/java/com/xpn/xwiki/cache/impl/OSCacheService.java
   xwiki/trunk/src/main/java/com/xpn/xwiki/plugin/feed/FeedPlugin.java
   xwiki/trunk/src/main/java/com/xpn/xwiki/plugin/image/ImagePlugin.java
   xwiki/trunk/src/main/java/com/xpn/xwiki/render/XWikiRenderingEngine.java
Log:
XWIKI-267 Added initial clustering support


Property changes on: xwiki/trunk
___________________________________________________________________
Name: svn:ignore
   - build
release
target

   + 
build
release
target
.settings


Modified: xwiki/trunk/.classpath
===================================================================
--- xwiki/trunk/.classpath	2006-05-10 20:08:38 UTC (rev 1065)
+++ xwiki/trunk/.classpath	2006-05-11 04:14:42 UTC (rev 1066)
@@ -8,23 +8,6 @@
 	<classpathentry kind="lib" path="lib/commons-net-1.1.0.jar"/>
 	<classpathentry kind="lib" path="lib/commons-pool-1.1.jar"/>
 	<classpathentry kind="lib" path="lib/ecs-1.4.2.jar"/>
-	<classpathentry kind="lib" path="lib/exo-base-services-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exo-chart-service-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exo-chart-service-impl-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exo-commons-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exo-organization-service-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exoplatform.container-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exoplatform.services.chart.api-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exoplatform.services.chart.impl-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exoplatform.services.common.api-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exoplatform.services.database.api-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exoplatform.services.database.impl-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exoplatform.services.organization.api-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exoplatform.services.organization.impl-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exoplatform.services.security.api-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exoplatform.services.security.impl-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exo-security-service-1.0.jar"/>
-	<classpathentry kind="lib" path="lib/exo-services-container-1.0.jar"/>
 	<classpathentry kind="lib" path="lib/InlineJavaServer.jar"/>
 	<classpathentry kind="lib" path="lib/InlineJavaUser.jar"/>
 	<classpathentry kind="lib" path="lib/jcommon-1.0.0-rc1.jar"/>
@@ -44,6 +27,18 @@
 	<classpathentry kind="lib" path="lib/swarmcache.jar"/>
 	<classpathentry kind="lib" path="lib/velocity-1.4.jar"/>
 	<classpathentry kind="lib" path="lib/velocity-tools-1.1.jar"/>
+	<classpathentry kind="lib" path="lib/ical4j-0.9.19M.jar"/>
+	<classpathentry kind="lib" path="lib/exo-platform.service.sercurity.impl-2.0.jar"/>
+	<classpathentry kind="lib" path="lib/exo-platform.service.sercurity.api-2.0.jar"/>
+	<classpathentry kind="lib" path="lib/exo-platform.service.organization.impl-2.0.jar"/>
+	<classpathentry kind="lib" path="lib/exo-platform.service.organization.api-2.0.jar"/>
+	<classpathentry kind="lib" path="lib/exo-platform.service.database.impl-2.0.jar"/>
+	<classpathentry kind="lib" path="lib/exo-platform.service.database.api-2.0.jar"/>
+	<classpathentry kind="lib" path="lib/exo-platform.service.common.api-2.0.jar"/>
+	<classpathentry kind="lib" path="lib/exo-platform.service.chart.impl-2.0.jar"/>
+	<classpathentry kind="lib" path="lib/exo-platform.service.chart.api-2.0.jar"/>
+	<classpathentry kind="lib" path="lib/exo-platform.container-2.0.jar"/>
+	<classpathentry kind="lib" path="lib/exo-platform.commons.jar"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="lib" path="lib/aspectjrt-1.2.1.jar"/>
 	<classpathentry kind="lib" path="lib/cactus-1.7.jar"/>
@@ -69,10 +64,10 @@
 	<classpathentry kind="lib" path="lib/ehcache-1.1.jar"/>
 	<classpathentry kind="lib" path="lib/fop-0.20.5.jar"/>
 	<classpathentry kind="lib" path="lib/hibernate-tools-2.1.3.jar"/>
-	<classpathentry kind="lib" path="lib/jgroups-2.2.5.jar"/>
+	<classpathentry kind="lib" path="lib/jgroups-2.2.9.1.jar"/>
 	<classpathentry kind="lib" path="lib/odmg-3.0.jar"/>
 	<classpathentry kind="lib" path="lib/oro-2.0.8.jar"/>
-	<classpathentry kind="lib" path="lib/oscache-2.0.2.jar"/>
+	<classpathentry kind="lib" path="lib/oscache-2.2.jar"/>
 	<classpathentry kind="lib" path="lib/securityfilter-2.0.jar"/>
 	<classpathentry kind="lib" path="lib/struts-1.2.4.jar"/>
 	<classpathentry kind="lib" path="lib/xalan-2.6.0.jar"/>
@@ -97,7 +92,6 @@
 	<classpathentry kind="lib" path="lib/googleadwords.jar"/>
 	<classpathentry kind="lib" path="lib/googleapi.jar"/>
 	<classpathentry kind="lib" path="lib/hsqldb-1.7.3.jar"/>
-	<classpathentry kind="lib" path="lib/ical4j-0.9.12.jar"/>
 	<classpathentry kind="lib" path="lib/ipresolver.jar"/>
 	<classpathentry kind="lib" path="lib/jaxrpc-1.1.jar"/>
 	<classpathentry kind="lib" path="lib/mail-1.3.2.jar"/>

Modified: xwiki/trunk/build.xml
===================================================================
--- xwiki/trunk/build.xml	2006-05-10 20:08:38 UTC (rev 1065)
+++ xwiki/trunk/build.xml	2006-05-11 04:14:42 UTC (rev 1066)
@@ -85,7 +85,7 @@
       includes="hibernate-3.0.3.jar" />
 
     <fileset id="libs.main.fileset" dir="${lib.dir}"
-      includes="c3p0-0.8.4.5.jar,cglib-2.1.jar,dom4j-1.6.jar,ehcache-1.1.jar,hibernate-tools-2.1.3.jar,mysql-connector-java-3.1.7-bin.jar,hsqldb-1.7.3.jar,odmg-3.0.jar,oscache-2.0.2.jar,jgroups-2.2.5.jar,swarmcache.jar,xalan-2.6.0.jar,xerces-2.4.0.jar,xml-apis-2.0.2.jar,jta.jar,antlr-2.7.5.jar,asm-1.5.3.jar,asm-util-1.5.3.jar,
+      includes="c3p0-0.8.4.5.jar,cglib-2.1.jar,dom4j-1.6.jar,ehcache-1.1.jar,hibernate-tools-2.1.3.jar,mysql-connector-java-3.1.7-bin.jar,hsqldb-1.7.3.jar,odmg-3.0.jar,oscache-2.2.jar,concurrent.jar,jgroups-2.2.9.1.jar,swarmcache.jar,xalan-2.6.0.jar,xerces-2.4.0.jar,xml-apis-2.0.2.jar,jta.jar,antlr-2.7.5.jar,asm-1.5.3.jar,asm-util-1.5.3.jar,
      	commons-beanutils-1.7.0.jar,commons-codec-1.3.jar,commons-collections-3.1.jar,commons-dbcp-1.2.1.jar,commons-digester-1.6.jar,commons-fileupload-1.0.jar,commons-lang-2.1.jar,commons-logging-1.0.4.jar,commons-pool-1.1.jar,commons-net-1.1.0.jar,commons-httpclient-2.0.2.jar,ecs-1.4.2.jar,oro-2.0.8.jar,log4j-1.2.8.jar,
      	org.apache.commons.jrcs.rcs.jar,
      	struts-1.2.4.jar,
@@ -210,7 +210,7 @@
             <fileset includes="**" excludes="JSTrim*.*,**/*_src.js"
                 dir="${web.main.src.dir}" />
         </copy>
-
+    	
         <copy todir="${build.dir}/web/WEB-INF">
             <fileset includes="license.txt"
                 dir="${basedir}" />
@@ -225,7 +225,7 @@
         </copy>
 
     </target>
-
+	
     <target name="xwiki" depends="clover-yes, clover-no, xwiki.nonjava">
         <javac srcdir="${java.main.src.dir}"
             destdir="${classes.dir}"

Added: xwiki/trunk/lib/concurrent.jar
===================================================================
(Binary files differ)


Property changes on: xwiki/trunk/lib/concurrent.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Deleted: xwiki/trunk/lib/jgroups-2.2.5.jar
===================================================================
(Binary files differ)

Added: xwiki/trunk/lib/jgroups-2.2.9.1.jar
===================================================================
(Binary files differ)


Property changes on: xwiki/trunk/lib/jgroups-2.2.9.1.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Deleted: xwiki/trunk/lib/oscache-2.0.2.jar
===================================================================
(Binary files differ)

Added: xwiki/trunk/lib/oscache-2.2.jar
===================================================================
(Binary files differ)


Property changes on: xwiki/trunk/lib/oscache-2.2.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: xwiki/trunk/src/main/java/com/xpn/xwiki/XWiki.java
===================================================================
--- xwiki/trunk/src/main/java/com/xpn/xwiki/XWiki.java	2006-05-10 20:08:38 UTC (rev 1065)
+++ xwiki/trunk/src/main/java/com/xpn/xwiki/XWiki.java	2006-05-11 04:14:42 UTC (rev 1066)
@@ -20,6 +20,7 @@
  * @author ludovic
  * @author namphunghai
  * @author wr0ngway
+ * @author markj
  * @author erwan
  * @author vmassol
  * @author jeremi
@@ -36,6 +37,7 @@
 import com.xpn.xwiki.cache.api.XWikiCacheService;
 import com.xpn.xwiki.cache.api.XWikiCacheNeedsRefreshException;
 import com.xpn.xwiki.cache.impl.OSCacheService;
+import com.xpn.xwiki.cache.impl.XWikiCacheListener;
 import com.xpn.xwiki.doc.XWikiAttachment;
 import com.xpn.xwiki.doc.XWikiDocument;
 import com.xpn.xwiki.notify.*;
@@ -485,6 +487,9 @@
         getNotificationManager().addNamedRule("XWiki.XWikiPreferences",
                 new PropertyChangedRule(this, "XWiki.XWikiPreferences", "plugin"));
 
+        // HACK: can anyone think of a better way to do this?
+        XWikiCacheListener.setXWiki(this);
+        
         // Make sure these classes exists
         if (noupdate) {
             getPrefsClass(context);
@@ -3179,6 +3184,7 @@
 
             try {
                 cacheService = (XWikiCacheService) Class.forName(cacheClass).newInstance();
+                cacheService.init(this);
             } catch (Exception e) {
                 e.printStackTrace();
                 cacheService = new OSCacheService();
@@ -3186,7 +3192,7 @@
         }
         return cacheService;
     }
-
+    
     public String getURLContent(String surl) throws IOException {
         HttpClient client = new HttpClient();
 

Modified: xwiki/trunk/src/main/java/com/xpn/xwiki/cache/api/XWikiCacheService.java
===================================================================
--- xwiki/trunk/src/main/java/com/xpn/xwiki/cache/api/XWikiCacheService.java	2006-05-10 20:08:38 UTC (rev 1065)
+++ xwiki/trunk/src/main/java/com/xpn/xwiki/cache/api/XWikiCacheService.java	2006-05-11 04:14:42 UTC (rev 1066)
@@ -18,10 +18,35 @@
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  *
  */
-
-package com.xpn.xwiki.cache.api;
-
-public interface XWikiCacheService {
-   public XWikiCache newCache();
-   public XWikiCache newCache(int capacity);
-}
+
+package com.xpn.xwiki.cache.api;
+
+import com.xpn.xwiki.XWiki;
+
+public interface XWikiCacheService
+{
+    /**
+     * Initializes the service
+     */
+    public void init(XWiki context);
+    
+    /*
+     * Returns a local only (never clustered) cache
+     */
+    public XWikiCache newLocalCache();
+
+    /*
+     * Returns a local only (never clustered) cache with given capacity
+     */
+    public XWikiCache newLocalCache(int capacity);
+
+    /*
+     * Returns a cache that could be configured to be clustered
+     */
+    public XWikiCache newCache();
+
+    /*
+     * Returns a cache that could be configured to be clustered with the given capacity
+     */
+    public XWikiCache newCache(int capacity);
+}

Modified: xwiki/trunk/src/main/java/com/xpn/xwiki/cache/impl/OSCacheCache.java
===================================================================
--- xwiki/trunk/src/main/java/com/xpn/xwiki/cache/impl/OSCacheCache.java	2006-05-10 20:08:38 UTC (rev 1065)
+++ xwiki/trunk/src/main/java/com/xpn/xwiki/cache/impl/OSCacheCache.java	2006-05-11 04:14:42 UTC (rev 1066)
@@ -1,100 +1,174 @@
-/*
- * Copyright 2006, XpertNet SARL, and individual contributors as indicated
- * by the contributors.txt.
- *
- * This 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 software 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 software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
+package com.xpn.xwiki.cache.impl;
+
+import java.util.Date;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.opensymphony.oscache.base.Cache;
+import com.opensymphony.oscache.base.EntryRefreshPolicy;
+import com.opensymphony.oscache.base.NeedsRefreshException;
+import com.opensymphony.oscache.general.GeneralCacheAdministrator;
+import com.xpn.xwiki.cache.api.XWikiCache;
+import com.xpn.xwiki.cache.api.XWikiCacheNeedsRefreshException;
+
+/**
+ * Copyright 2006, XpertNet SARL, and individual contributors as indicated by
+ * the contributors.txt.
+ * 
+ * This 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 software 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 software; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
+ * site: http://www.fsf.org.
+ * 
+ * Implements XWikiCache using oscache
+ * 
  * @author ludovic
  * @author sdumitriu
+ * @author markj
+ * @author wr0ngway
+ * 
  */
-
-package com.xpn.xwiki.cache.impl;
-
-import java.util.Date;
-import java.util.Properties;
-
-import com.opensymphony.oscache.base.Cache;
-import com.opensymphony.oscache.base.EntryRefreshPolicy;
-import com.opensymphony.oscache.base.NeedsRefreshException;
-import com.opensymphony.oscache.base.Config;
-import com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener;
-import com.xpn.xwiki.cache.api.XWikiCache;
-import com.xpn.xwiki.cache.api.XWikiCacheNeedsRefreshException;
-
-public class OSCacheCache implements XWikiCache {
-    private Cache cache;
-
-    public OSCacheCache() {
-       cache = new Cache(true, false);
-    }
-
-    public OSCacheCache(int capacity) {
-       cache = new Cache(true, false, false, null, capacity);
-    }
-
-    public OSCacheCache(int capacity, boolean diskCache, String path) {
-       if (diskCache==false)
-        cache = new Cache(true, false, false, null, capacity);
-       else {
-           cache = new Cache(true, true, false, null, capacity);
-           DiskPersistenceListener dpl = new DiskPersistenceListener();
-           Properties p = new Properties();
-           p.put("cache.path", path);
-           dpl.configure(new Config(p));
-           cache.setPersistenceListener(dpl);
-       }
-    }
-
-    public void setCapacity(int capacity) {
-     cache.setCapacity(capacity);
-    }
-
-    public void flushEntry(String key) {
-     cache.flushEntry(key);
-    }
-
-    public void putInCache(String key, Object obj) {
-     cache.putInCache(key, obj);
-    }
-
-    public void putInCache(String key, Object obj, EntryRefreshPolicy expiry) {
-     cache.putInCache(key, obj, expiry);
-    }
-
-    public Object getFromCache(String key) throws XWikiCacheNeedsRefreshException {
-        try {
-         return cache.getFromCache(key);
-        } catch (NeedsRefreshException e) {
-            throw new XWikiCacheNeedsRefreshException(e);
-        }
-    }
-
-    public Object getFromCache(String key, int refeshPeriod) throws XWikiCacheNeedsRefreshException {
-        try {
-         return cache.getFromCache(key, refeshPeriod);
-        } catch (NeedsRefreshException e) {
-            throw new XWikiCacheNeedsRefreshException(e);
-        }
-    }
-
-    public void cancelUpdate(String key) {
-        cache.cancelUpdate(key);
-    }
-
-    public void flushAll() {
-        cache.flushAll(new Date());
-    }
-}
+public class OSCacheCache implements XWikiCache
+{
+    private static final Log          log = LogFactory.getLog(OSCacheCache.class);
+
+    private GeneralCacheAdministrator cache;
+    private String                    name;
+    private int                       capacity;
+
+    public OSCacheCache(Properties props)
+    {
+        cache = new GeneralCacheAdministrator(props);
+    }
+
+    public OSCacheCache(Properties props, int capacity)
+    {
+        this(props);
+        cache.setCacheCapacity(capacity);
+        this.capacity = capacity;
+    }
+
+    /**
+     * Provide package-private access to the underlying m_cache
+     */
+    Cache getCache()
+    {
+        return cache.getCache();
+    }
+
+    public void setCapacity(int capacity)
+    {
+        cache.setCacheCapacity(capacity);
+        this.capacity = capacity;
+    }
+
+    public void flushEntry(String key)
+    {
+        cache.flushEntry(key);
+    }
+
+    public void putInCache(String key, Object obj)
+    {
+        cache.putInCache(key, obj);
+        logCacheAdd(key, obj);
+    }
+
+    public void putInCache(String key, Object obj, EntryRefreshPolicy expiry)
+    {
+        cache.putInCache(key, obj, expiry);
+        logCacheAdd(key, obj);
+    }
+
+    public Object getFromCache(String key) throws XWikiCacheNeedsRefreshException
+    {
+        try
+        {
+            return cache.getFromCache(key);
+        }
+        catch (NeedsRefreshException e)
+        {
+            throw new XWikiCacheNeedsRefreshException(e);
+        }
+    }
+
+    public Object getFromCache(String key, int refeshPeriod) throws XWikiCacheNeedsRefreshException
+    {
+        try
+        {
+            return cache.getFromCache(key, refeshPeriod);
+        }
+        catch (NeedsRefreshException e)
+        {
+            throw new XWikiCacheNeedsRefreshException(e);
+        }
+    }
+
+    public void cancelUpdate(String key)
+    {
+        cache.cancelUpdate(key);
+    }
+
+    public void flushAll()
+    {
+        cache.flushAll(new Date());
+    }
+
+    /**
+     * Method called here is labeled "for test only" in OSCache JavaDoc, so
+     * don't call this a lot!
+     */
+    public int getNumberEntries()
+    {
+        return cache.getCache().getNbEntries();
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public int getCapacity()
+    {
+        return capacity;
+    }
+
+    private void logCacheAdd(String sKey, Object obj)
+    {
+        if (log.isDebugEnabled())
+        {
+            StringBuffer sbEntry = new StringBuffer();
+            sbEntry.append(getName());
+            sbEntry.append(" adding object key=");
+            sbEntry.append(sKey);
+            sbEntry.append("; class=");
+            if (obj == null)
+            {
+                sbEntry.append("null");
+            }
+            else
+            {
+                sbEntry.append(obj.getClass().toString());
+                sbEntry.append("; toString=");
+                sbEntry.append(obj.toString());
+                log.debug(sbEntry.toString());
+            }
+        }
+    }
+}

Modified: xwiki/trunk/src/main/java/com/xpn/xwiki/cache/impl/OSCacheService.java
===================================================================
--- xwiki/trunk/src/main/java/com/xpn/xwiki/cache/impl/OSCacheService.java	2006-05-10 20:08:38 UTC (rev 1065)
+++ xwiki/trunk/src/main/java/com/xpn/xwiki/cache/impl/OSCacheService.java	2006-05-11 04:14:42 UTC (rev 1066)
@@ -1,3 +1,23 @@
+package com.xpn.xwiki.cache.impl;
+
+import java.io.InputStream;
+import java.lang.ref.WeakReference;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.opensymphony.oscache.base.AbstractCacheAdministrator;
+import com.xpn.xwiki.XWiki;
+import com.xpn.xwiki.cache.api.XWikiCache;
+import com.xpn.xwiki.cache.api.XWikiCacheService;
+
 /*
  * Copyright 2006, XpertNet SARL, and individual contributors as indicated
  * by the contributors.txt.
@@ -17,19 +37,159 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  *
+ * Allows initilization of OSCache in the proper way to use JGroups for
+ * clustering. Basically this involves reading the oscache.properties file
+ * located in WEB-INF/classes. This contains a listener setting for JGroups (and
+ * other settings we could use if desired).
+ * 
+
  * @author sdumitriu
+ * @author markj
+ * @author wr0ngway
+ * 
  */
-
-package com.xpn.xwiki.cache.impl;
-
-import com.xpn.xwiki.cache.api.XWikiCache;
-import com.xpn.xwiki.cache.api.XWikiCacheService;
-
-public class OSCacheService implements XWikiCacheService {
-    public XWikiCache newCache() {
-        return new OSCacheCache();
-    }
-    public XWikiCache newCache(int capacity) {
-        return new OSCacheCache(capacity);
-    }
-}
+public class OSCacheService implements XWikiCacheService, Runnable
+{
+    private static final Log    log                  = LogFactory.getLog(OSCacheService.class);
+    private static final String PROPS_FILENAME       = "/WEB-INF/oscache.properties";
+    private static final String LOCAL_PROPS_FILENAME = "/WEB-INF/oscache-local.properties";
+
+    private XWiki               xwiki;
+    private Properties          cacheProperties;
+    private Properties          localCacheProperties;
+    private static int          cacheCount           = 0;
+    // used by watcher thread to keep an eye on caches
+    private List                cacheList            = new LinkedList();
+    
+    public OSCacheService()
+    {
+        super();
+    }
+
+    public void init(XWiki xwiki)
+    {
+        log.info("Initializing OSCacheService");
+        this.xwiki = xwiki;
+        cacheProperties = loadProps(PROPS_FILENAME);
+        localCacheProperties = loadProps(LOCAL_PROPS_FILENAME);
+        Thread watcherThread = new Thread(this, "OSCacheService Cache Monitor");
+        watcherThread.start();
+        log.info("Initialized OSCacheService");
+    }
+    
+    public XWikiCache newLocalCache()
+    {
+        return new OSCacheCache(localCacheProperties);
+    }
+
+    public XWikiCache newLocalCache(int capacity)
+    {
+        return new OSCacheCache(localCacheProperties, capacity);
+    }
+
+    public XWikiCache newCache(Properties props)
+    {
+        OSCacheCache cc = new OSCacheCache(props);
+        initCache(cc);
+        return cc;
+    }
+
+    public XWikiCache newCache()
+    {
+        OSCacheCache cc = new OSCacheCache(cacheProperties);
+        initCache(cc);
+        return cc;
+    }
+
+    public XWikiCache newCache(int capacity)
+    {
+        OSCacheCache cc = new OSCacheCache(cacheProperties, capacity);
+        initCache(cc);
+        return cc;
+    }
+
+    private void initCache(OSCacheCache cc)
+    {
+        cacheCount++;
+        cc.setName("Cache # " + cacheCount);
+
+        if (log.isInfoEnabled())
+        {
+            DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
+            log.info("Created " + cc.getName() + " of size " + cc.getCapacity() + " at " + df.format(new Date())
+                    + ", current count is " + cacheCount);
+        }
+
+        synchronized (cacheList)
+        {
+            cacheList.add(new WeakReference(cc));
+        }
+    }
+
+    private Properties loadProps(String propertiesFilename)
+    {
+        log.info("Loading cache properties: " + propertiesFilename);
+        Properties props = new Properties();
+        InputStream is = null;
+
+        try
+        {
+            is = xwiki.getResourceAsStream(propertiesFilename);
+            props.load(is);
+            log.info("Properties loaded: " + propertiesFilename);
+        }
+        catch (Exception e)
+        {
+            log.error("Could not load cache properties " + propertiesFilename, e);
+        }
+        finally
+        {
+            try
+            {
+                is.close();
+            }
+            catch (Exception e)
+            {
+            }
+        }
+        return props;
+    }
+
+    /**
+     * The cache watcher thread
+     */
+    public void run()
+    {
+        while (true)
+        {
+            if (log.isInfoEnabled())
+            {
+                synchronized (cacheList)
+                {
+                    Iterator i = cacheList.iterator();
+                    while (i.hasNext())
+                    {
+                        WeakReference wr = (WeakReference) i.next();
+                        if (wr != null)
+                        {
+                            OSCacheCache cc = (OSCacheCache) wr.get();
+                            if (cc != null)
+                            {
+                                log.info("OSCacheCache item count for " + cc.getName() + " = "
+                                        + cc.getNumberEntries() + " capacity is " + cc.getCapacity());
+                            }
+                        }
+                    }
+                }
+            }
+            try
+            {
+                Thread.sleep(1000 * 60 * 5); // 5 min
+            }
+            catch (InterruptedException e)
+            {
+            }
+
+        }
+    }
+}
\ No newline at end of file

Added: xwiki/trunk/src/main/java/com/xpn/xwiki/cache/impl/XWikiCacheListener.java
===================================================================
--- xwiki/trunk/src/main/java/com/xpn/xwiki/cache/impl/XWikiCacheListener.java	2006-05-10 20:08:38 UTC (rev 1065)
+++ xwiki/trunk/src/main/java/com/xpn/xwiki/cache/impl/XWikiCacheListener.java	2006-05-11 04:14:42 UTC (rev 1066)
@@ -0,0 +1,146 @@
+package com.xpn.xwiki.cache.impl;
+
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.opensymphony.oscache.base.events.CacheEntryEvent;
+import com.opensymphony.oscache.base.events.CacheEntryEventListener;
+import com.opensymphony.oscache.base.events.CacheGroupEvent;
+import com.opensymphony.oscache.base.events.CachePatternEvent;
+import com.opensymphony.oscache.base.events.CachewideEvent;
+import com.xpn.xwiki.XWiki;
+import com.xpn.xwiki.XWikiContext;
+import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.web.XWikiServletRequest;
+
+/*
+ * Copyright 2006, XpertNet SARL, and individual contributors as indicated
+ * by the contributors.txt.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * Allows initilization of OSCache in the proper way to use JGroups for
+ * clustering. Basically this involves reading the oscache.properties file
+ * located in WEB-INF/classes. This contains a listener setting for JGroups (and
+ * other settings we could use if desired).
+
+ * Catch when a doc is flushed from the cache so we can send our own
+ * event.
+ *
+ * This event is mostly called due to jgroups flushing items from the cache.
+ *
+ * @author fitzgerald
+ * @author wr0ngway
+ * 
+ */
+public class XWikiCacheListener implements CacheEntryEventListener
+{
+    private static final Log log = LogFactory.getLog(XWikiCacheListener.class);
+    
+    private static XWiki xwiki;
+
+    public static void setXWiki(XWiki xwiki)
+    {
+        XWikiCacheListener.xwiki = xwiki;
+    }
+
+    public void cacheEntryAdded(CacheEntryEvent event)
+    {
+
+    }
+
+    public void cacheEntryFlushed(CacheEntryEvent event)
+    {
+        String sKey = event.getKey();
+
+        // HACK: Figure out a better way to get a handle on the Context and XWiki here.
+        
+        XWikiContext context = new XWikiContext();
+        context.setDatabase(xwiki.getDatabase());
+        context.setWiki(xwiki);
+        XWikiDocument doc = null;
+        try
+        {
+            doc = new XWikiDocument();
+            String[] parts = sKey.split(":\\.");
+            switch (parts.length)
+            {
+                case 4:
+                    doc.setLanguage(parts[3]);
+                case 3:
+                    doc.setDatabase(parts[0]);
+                    doc.setWeb(parts[1]);
+                    doc.setName(parts[2]);
+                    doc = xwiki.getStore().loadXWikiDoc(doc, context);
+                    break;
+                case 2:
+                    doc.setWeb(parts[0]);
+                    doc.setName(parts[1]);
+                    doc = xwiki.getStore().loadXWikiDoc(doc, context);
+                    break;
+                default:
+                    log.error("Failed to parse document id from cache key: " + sKey);
+                    break;
+            }
+        }
+        catch (Exception e)
+        {
+            log.error("cacheEntryFlushedError for key " + sKey + ": ", e);
+        }
+
+        if (doc != null)
+        {
+            // TODO: need to create an xwiki event code for when a cluster
+            // member receives a cache flush for an object so that plugins that
+            // need to know a document has changed can update their state (e.g.
+            // email notification, lucene plugin)
+            //
+            // This doesn't really work since the context may not have stuff like the request object
+            xwiki.getNotificationManager().verify(doc, "flush", context);
+        }
+        else
+        {
+            log.error("cannot send flush notification doc is null for key " + sKey);
+        }
+
+        log.info("entry flushed: " + sKey);
+    }
+
+    public void cacheEntryRemoved(CacheEntryEvent event)
+    {
+
+    }
+
+    public void cacheEntryUpdated(CacheEntryEvent event)
+    {
+
+    }
+
+    public void cacheGroupFlushed(CacheGroupEvent event)
+    {
+    }
+
+    public void cachePatternFlushed(CachePatternEvent event)
+    {
+    }
+
+    public void cacheFlushed(CachewideEvent event)
+    {
+    }
+}
+                   
\ No newline at end of file

Modified: xwiki/trunk/src/main/java/com/xpn/xwiki/plugin/feed/FeedPlugin.java
===================================================================
--- xwiki/trunk/src/main/java/com/xpn/xwiki/plugin/feed/FeedPlugin.java	2006-05-10 20:08:38 UTC (rev 1065)
+++ xwiki/trunk/src/main/java/com/xpn/xwiki/plugin/feed/FeedPlugin.java	2006-05-11 04:14:42 UTC (rev 1066)
@@ -107,7 +107,7 @@
 
     public void init(XWikiContext context) {
         super.init(context);
-        feedCache = new OSCacheCache();
+        feedCache = context.getWiki().getCacheService().newLocalCache();
         refreshPeriod = (int) context.getWiki().ParamAsLong("xwiki.plugins.feed.cacherefresh", 3600);
     }
 

Modified: xwiki/trunk/src/main/java/com/xpn/xwiki/plugin/image/ImagePlugin.java
===================================================================
--- xwiki/trunk/src/main/java/com/xpn/xwiki/plugin/image/ImagePlugin.java	2006-05-10 20:08:38 UTC (rev 1065)
+++ xwiki/trunk/src/main/java/com/xpn/xwiki/plugin/image/ImagePlugin.java	2006-05-11 04:14:42 UTC (rev 1066)
@@ -32,9 +32,13 @@
 import java.awt.image.BufferedImage;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.util.Properties;
 
 import javax.imageio.ImageIO;
 
+import com.opensymphony.oscache.base.Cache;
+import com.opensymphony.oscache.base.Config;
+import com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener;
 import com.xpn.xwiki.XWikiContext;
 import com.xpn.xwiki.XWikiException;
 import com.xpn.xwiki.cache.api.XWikiCache;
@@ -86,7 +90,17 @@
             if (log.isErrorEnabled())
              log.error("Error in ImagePlugin reading capacity: " + capacityParam, e);
         } 
-        imageCache = new OSCacheCache(capacity, true, "temp/imageCache");
+        
+        Properties props = new Properties();
+        props.put("cache.memory", "true");
+        props.put("cache.unlimited.disk", "true");
+        props.put("cache.persistence.overflow.only", "false");
+        props.put("cache.blocking", "false");
+
+        props.put("cache.persistence.class", "com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener");
+        props.put("cache.path", "temp/imageCache");
+        
+        imageCache = new OSCacheCache(props, capacity);
     }
 
     public void flushCache() {

Modified: xwiki/trunk/src/main/java/com/xpn/xwiki/render/XWikiRenderingEngine.java
===================================================================
--- xwiki/trunk/src/main/java/com/xpn/xwiki/render/XWikiRenderingEngine.java	2006-05-10 20:08:38 UTC (rev 1065)
+++ xwiki/trunk/src/main/java/com/xpn/xwiki/render/XWikiRenderingEngine.java	2006-05-11 04:14:42 UTC (rev 1066)
@@ -1,247 +1,251 @@
-/*
- * Copyright 2006, XpertNet SARL, and individual contributors as indicated
- * by the contributors.txt.
- *
- * This 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 software 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 software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * @author ludovic
- * @author sdumitriu
- */
-
-package com.xpn.xwiki.render;
-
-import java.util.*;
-
-import com.xpn.xwiki.XWiki;
-import com.xpn.xwiki.XWikiContext;
-import com.xpn.xwiki.XWikiException;
-import com.xpn.xwiki.web.XWikiRequest;
-import com.xpn.xwiki.cache.api.XWikiCache;
-import com.xpn.xwiki.cache.api.XWikiCacheNeedsRefreshException;
-import com.xpn.xwiki.cache.impl.OSCacheCache;
-import com.xpn.xwiki.doc.XWikiDocument;
-import com.xpn.xwiki.monitor.api.MonitorPlugin;
-import com.xpn.xwiki.render.groovy.XWikiGroovyRenderer;
-import com.xpn.xwiki.util.Util;
-
-public class XWikiRenderingEngine {
-
-    private List renderers = new ArrayList();
-    private HashMap renderermap = new LinkedHashMap();
-    private XWikiCache cache = new OSCacheCache(100);
-
-    public XWikiRenderingEngine(XWiki xwiki, XWikiContext context) throws XWikiException {
-        if (xwiki.Param("xwiki.render.macromapping", "0").equals("1"))
-            addRenderer("mapping", new XWikiMacrosMappingRenderer(xwiki, context));
-        // addRenderer(new XWikiJSPRenderer());
-        if (xwiki.Param("xwiki.render.velocity", "1").equals("1"))
-            addRenderer("velocity", new XWikiVelocityRenderer());
-        if (xwiki.Param("xwiki.render.groovy", "1").equals("1"))
-            addRenderer("groovy", new XWikiGroovyRenderer());
-        if (xwiki.Param("xwiki.render.plugin", "1").equals("1"))
-            addRenderer("plugin", new XWikiPluginRenderer());
-
-        // The first should not removePre
-        // The last one should removePre
-        if (xwiki.Param("xwiki.render.wiki", "1").equals("1"))
-            addRenderer("wiki", new XWikiRadeoxRenderer(false));
-
-        // if (xwiki.Param("xwiki.render.wiki2", "1").equals("1"))
-        // addRenderer("wiki2", new XWikiWikiParser2Renderer(false));
-
-        if (xwiki.Param("xwiki.render.wikiwiki", "0").equals("1")) {
-            addRenderer("xwiki", new XWikiWikiBaseRenderer(true, true));
-        } else {
-            addRenderer("xwiki", new XWikiWikiBaseRenderer(false, true));
-        }
-
-        try {
-        String capacity = xwiki.Param("xwiki.render.cache.capacity");
-        if (capacity != null)
-            cache.setCapacity(Integer.parseInt(capacity));
-        } catch (Exception e) {}
-    }
-
-    public void addRenderer(String name, XWikiRenderer renderer) {
-        renderers.add(renderer);
-        renderermap.put(name, renderer);
-    }
-    
-    public XWikiRenderer getRenderer(String name) {
-		return (XWikiRenderer) renderermap.get(name);
-	}
-
-	public List getRendererList() {
-		return (List) ((ArrayList) renderers).clone();
-	}
-
-	public List getRendererNames() {
-		return new LinkedList(renderermap.keySet());
-	}
-	
-	protected XWikiRenderer removeRenderer(String name) {
-		XWikiRenderer result = (XWikiRenderer) renderermap.remove(name);
-		if (result != null) {
-			renderers.remove(result);
-		}
-		return result;
-	}
-	
-    public String renderDocument(XWikiDocument doc, XWikiContext context) throws XWikiException {
-           return renderText(doc.getTranslatedContent(context), doc, context);
-    }
-
-    public String renderDocument(XWikiDocument doc, XWikiDocument includingdoc, XWikiContext context) throws XWikiException {
-        return renderText(doc.getTranslatedContent(context), includingdoc, context);
-    }
-
-    public String renderText(String text, XWikiDocument includingdoc, XWikiContext context) {
-        return renderText(text, includingdoc, includingdoc, context);
-    }
-
-    public void addToCached(String key, XWikiContext context) {
-        List cached = (ArrayList) context.get("render_cached");
-        if (cached==null) {
-            cached = new ArrayList();
-            context.put("render_cached", cached);
-        }
-        cached.add(key);
-    }
-
-    public void addToRefreshed(String key, XWikiContext context) {
-        List cached = (ArrayList) context.get("render_refreshed");
-        if (cached==null) {
-            cached = new ArrayList();
-            context.put("render_refreshed", cached);
-        }
-        cached.add(key);
-    }
-
-    public String renderText(String text, XWikiDocument contentdoc, XWikiDocument includingdoc, XWikiContext context) {
-        String key = getKey(text, contentdoc, includingdoc, context);
-        synchronized (key) {
-            try {
-                XWikiRenderingCache cacheObject = null;
-                try {
-                    cacheObject = (XWikiRenderingCache) cache.getFromCache(key);
-                } catch (XWikiCacheNeedsRefreshException e2) {
-                    cache.cancelUpdate(key);
-                }
-                if (cacheObject!=null) {
-                    XWikiRequest request = context.getRequest();
-                    boolean refresh = (request!=null) && ("1".equals(request.get("refresh")));
-                    if ((cacheObject.isValid()&&(!refresh))) {
-                        addToCached(key, context);
-                        return cacheObject.getContent();
-                    } else {
-                        addToRefreshed(key, context);
-                    }
-                }
-            } catch (Exception e) {
-            }
-
-            MonitorPlugin monitor  = Util.getMonitorPlugin(context);
-            try {
-                // Start monitoring timer
-                if (monitor!=null)
-                    monitor.startTimer("rendering");
-
-                XWikiDocument doc = context.getDoc();
-                XWikiDocument cdoc = context.getDoc();
-
-                // Let's call the beginRendering loop
-                context.getWiki().getPluginManager().beginRendering(context);
-
-                String content = text;
-
-                // Which is the current idoc and sdoc
-                XWikiDocument idoc = (XWikiDocument) context.get("idoc");
-                XWikiDocument sdoc = (XWikiDocument) context.get("sdoc");
-                // We put the including and security doc in the context
-                // It will be needed to verify programming rights
-                context.put("idoc", includingdoc);
-                context.put("sdoc", contentdoc);
-
-                try {
-
-                    for (int i=0;i<renderers.size();i++)
-                        content = ((XWikiRenderer)renderers.get(i)).render(content, contentdoc, includingdoc, context);
-                } finally {
-                    // Remove including doc or set the previous one
-                    if (idoc==null)
-                        context.remove("idoc");
-                    else
-                        context.put("idoc", idoc);
-
-                    // Remove security doc or set the previous one
-                    if (sdoc==null)
-                        context.remove("sdoc");
-                    else
-                        context.put("sdoc", sdoc);
-
-                    // Let's call the endRendering loop
-                    context.getWiki().getPluginManager().endRendering(context);
-                }
-
-                try {
-                    int cacheDuration = context.getCacheDuration();
-                    if (cacheDuration>0) {
-                        XWikiRenderingCache cacheObject = new XWikiRenderingCache(key, content, cacheDuration, new Date());
-                        cache.putInCache(key, (Object)cacheObject);
-                    }
-                } catch (Exception e) {}
-                return content;
-            }
-            finally {
-                if (monitor!=null)
-                    monitor.endTimer("rendering");
-            }
-        }
-    }
-
-    private String getKey(String text, XWikiDocument contentdoc, XWikiDocument includingdoc, XWikiContext context) {
-        return ((context==null) ? "xwiki" : context.getDatabase()) + "-"
-                + ((contentdoc==null) ? "" : contentdoc.getDatabase() + ":" + contentdoc.getFullName()) + "-"
-                + ((includingdoc==null) ? "" : includingdoc.getDatabase() + ":" + includingdoc.getFullName()) + "-"
-                + ((context.getRequest()==null) ? "" : context.getRequest().getQueryString())
-                + "-" + text.hashCode();
-    }
-
-    public void flushCache() {
-        for (int i=0;i<renderers.size();i++)
-           ((XWikiRenderer)renderers.get(i)).flushCache();
-        cache.flushAll();
-    }
-
-    public String convertMultiLine(String macroname, String params, String data, String allcontent, XWikiVirtualMacro macro, XWikiContext context) {
-        String language = macro.getLanguage();
-        XWikiRenderer renderer = (XWikiRenderer) renderermap.get(language);
-        if (renderer==null)
-            return allcontent;
-        else
-            return renderer.convertMultiLine(macroname, params, data, allcontent, macro, context);
-    }
-
-    public String convertSingleLine(String macroname, String params, String allcontent, XWikiVirtualMacro macro, XWikiContext context) {
-        String language = macro.getLanguage();
-        XWikiRenderer renderer = (XWikiRenderer) renderermap.get(language);
-        if (renderer==null)
-            return allcontent;
-        else
-            return renderer.convertSingleLine(macroname, params, allcontent, macro, context);
-    }
-
-}
+/*
+ * Copyright 2006, XpertNet SARL, and individual contributors as indicated
+ * by the contributors.txt.
+ *
+ * This 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 software 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 software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * @author ludovic
+ * @author sdumitriu
+ */
+
+package com.xpn.xwiki.render;
+
+import java.util.*;
+
+import com.xpn.xwiki.XWiki;
+import com.xpn.xwiki.XWikiContext;
+import com.xpn.xwiki.XWikiException;
+import com.xpn.xwiki.web.XWikiRequest;
+import com.xpn.xwiki.cache.api.XWikiCache;
+import com.xpn.xwiki.cache.api.XWikiCacheNeedsRefreshException;
+import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.monitor.api.MonitorPlugin;
+import com.xpn.xwiki.render.groovy.XWikiGroovyRenderer;
+import com.xpn.xwiki.util.Util;
+
+public class XWikiRenderingEngine {
+
+    private List renderers = new ArrayList();
+    private HashMap renderermap = new LinkedHashMap();
+    private XWikiCache cache = null;
+
+    public XWikiRenderingEngine(XWiki xwiki, XWikiContext context) throws XWikiException {
+        if (xwiki.Param("xwiki.render.macromapping", "0").equals("1"))
+            addRenderer("mapping", new XWikiMacrosMappingRenderer(xwiki, context));
+        // addRenderer(new XWikiJSPRenderer());
+        if (xwiki.Param("xwiki.render.velocity", "1").equals("1"))
+            addRenderer("velocity", new XWikiVelocityRenderer());
+        if (xwiki.Param("xwiki.render.groovy", "1").equals("1"))
+            addRenderer("groovy", new XWikiGroovyRenderer());
+        if (xwiki.Param("xwiki.render.plugin", "1").equals("1"))
+            addRenderer("plugin", new XWikiPluginRenderer());
+
+        // The first should not removePre
+        // The last one should removePre
+        if (xwiki.Param("xwiki.render.wiki", "1").equals("1"))
+            addRenderer("wiki", new XWikiRadeoxRenderer(false));
+
+        // if (xwiki.Param("xwiki.render.wiki2", "1").equals("1"))
+        // addRenderer("wiki2", new XWikiWikiParser2Renderer(false));
+
+        if (xwiki.Param("xwiki.render.wikiwiki", "0").equals("1")) {
+            addRenderer("xwiki", new XWikiWikiBaseRenderer(true, true));
+        } else {
+            addRenderer("xwiki", new XWikiWikiBaseRenderer(false, true));
+        }
+
+        try {
+        	String capacity = xwiki.Param("xwiki.render.cache.capacity");
+			if (capacity != null) {
+				cache = xwiki.getCacheService().newCache(Integer.parseInt(capacity));
+			} else {
+				cache = xwiki.getCacheService().newCache();
+			}
+        } catch (Exception e) {
+			e.printStackTrace();        
+        }
+    }
+
+    public void addRenderer(String name, XWikiRenderer renderer) {
+        renderers.add(renderer);
+        renderermap.put(name, renderer);
+    }
+    
+    public XWikiRenderer getRenderer(String name) {
+		return (XWikiRenderer) renderermap.get(name);
+	}
+
+	public List getRendererList() {
+		return (List) ((ArrayList) renderers).clone();
+	}
+
+	public List getRendererNames() {
+		return new LinkedList(renderermap.keySet());
+	}
+	
+	protected XWikiRenderer removeRenderer(String name) {
+		XWikiRenderer result = (XWikiRenderer) renderermap.remove(name);
+		if (result != null) {
+			renderers.remove(result);
+		}
+		return result;
+	}
+	
+    public String renderDocument(XWikiDocument doc, XWikiContext context) throws XWikiException {
+           return renderText(doc.getTranslatedContent(context), doc, context);
+    }
+
+    public String renderDocument(XWikiDocument doc, XWikiDocument includingdoc, XWikiContext context) throws XWikiException {
+        return renderText(doc.getTranslatedContent(context), includingdoc, context);
+    }
+
+    public String renderText(String text, XWikiDocument includingdoc, XWikiContext context) {
+        return renderText(text, includingdoc, includingdoc, context);
+    }
+
+    public void addToCached(String key, XWikiContext context) {
+        List cached = (ArrayList) context.get("render_cached");
+        if (cached==null) {
+            cached = new ArrayList();
+            context.put("render_cached", cached);
+        }
+        cached.add(key);
+    }
+
+    public void addToRefreshed(String key, XWikiContext context) {
+        List cached = (ArrayList) context.get("render_refreshed");
+        if (cached==null) {
+            cached = new ArrayList();
+            context.put("render_refreshed", cached);
+        }
+        cached.add(key);
+    }
+
+    public String renderText(String text, XWikiDocument contentdoc, XWikiDocument includingdoc, XWikiContext context) {
+        String key = getKey(text, contentdoc, includingdoc, context);
+        synchronized (key) {
+            try {
+                XWikiRenderingCache cacheObject = null;
+                try {
+                    cacheObject = (XWikiRenderingCache) cache.getFromCache(key);
+                } catch (XWikiCacheNeedsRefreshException e2) {
+                    cache.cancelUpdate(key);
+                }
+                if (cacheObject!=null) {
+                    XWikiRequest request = context.getRequest();
+                    boolean refresh = (request!=null) && ("1".equals(request.get("refresh")));
+                    if ((cacheObject.isValid()&&(!refresh))) {
+                        addToCached(key, context);
+                        return cacheObject.getContent();
+                    } else {
+                        addToRefreshed(key, context);
+                    }
+                }
+            } catch (Exception e) {
+            }
+
+            MonitorPlugin monitor  = Util.getMonitorPlugin(context);
+            try {
+                // Start monitoring timer
+                if (monitor!=null)
+                    monitor.startTimer("rendering");
+
+                XWikiDocument doc = context.getDoc();
+                XWikiDocument cdoc = context.getDoc();
+
+                // Let's call the beginRendering loop
+                context.getWiki().getPluginManager().beginRendering(context);
+
+                String content = text;
+
+                // Which is the current idoc and sdoc
+                XWikiDocument idoc = (XWikiDocument) context.get("idoc");
+                XWikiDocument sdoc = (XWikiDocument) context.get("sdoc");
+                // We put the including and security doc in the context
+                // It will be needed to verify programming rights
+                context.put("idoc", includingdoc);
+                context.put("sdoc", contentdoc);
+
+                try {
+
+                    for (int i=0;i<renderers.size();i++)
+                        content = ((XWikiRenderer)renderers.get(i)).render(content, contentdoc, includingdoc, context);
+                } finally {
+                    // Remove including doc or set the previous one
+                    if (idoc==null)
+                        context.remove("idoc");
+                    else
+                        context.put("idoc", idoc);
+
+                    // Remove security doc or set the previous one
+                    if (sdoc==null)
+                        context.remove("sdoc");
+                    else
+                        context.put("sdoc", sdoc);
+
+                    // Let's call the endRendering loop
+                    context.getWiki().getPluginManager().endRendering(context);
+                }
+
+                try {
+                    int cacheDuration = context.getCacheDuration();
+                    if (cacheDuration>0) {
+                        XWikiRenderingCache cacheObject = new XWikiRenderingCache(key, content, cacheDuration, new Date());
+                        cache.putInCache(key, (Object)cacheObject);
+                    }
+                } catch (Exception e) {}
+                return content;
+            }
+            finally {
+                if (monitor!=null)
+                    monitor.endTimer("rendering");
+            }
+        }
+    }
+
+    private String getKey(String text, XWikiDocument contentdoc, XWikiDocument includingdoc, XWikiContext context) {
+        return ((context==null) ? "xwiki" : context.getDatabase()) + "-"
+                + ((contentdoc==null) ? "" : contentdoc.getDatabase() + ":" + contentdoc.getFullName()) + "-"
+                + ((includingdoc==null) ? "" : includingdoc.getDatabase() + ":" + includingdoc.getFullName()) + "-"
+                + ((context.getRequest()==null) ? "" : context.getRequest().getQueryString())
+                + "-" + text.hashCode();
+    }
+
+    public void flushCache() {
+        for (int i=0;i<renderers.size();i++)
+           ((XWikiRenderer)renderers.get(i)).flushCache();
+        cache.flushAll();
+    }
+
+    public String convertMultiLine(String macroname, String params, String data, String allcontent, XWikiVirtualMacro macro, XWikiContext context) {
+        String language = macro.getLanguage();
+        XWikiRenderer renderer = (XWikiRenderer) renderermap.get(language);
+        if (renderer==null)
+            return allcontent;
+        else
+            return renderer.convertMultiLine(macroname, params, data, allcontent, macro, context);
+    }
+
+    public String convertSingleLine(String macroname, String params, String allcontent, XWikiVirtualMacro macro, XWikiContext context) {
+        String language = macro.getLanguage();
+        XWikiRenderer renderer = (XWikiRenderer) renderermap.get(language);
+        if (renderer==null)
+            return allcontent;
+        else
+            return renderer.convertSingleLine(macroname, params, allcontent, macro, context);
+    }
+
+}

Added: xwiki/trunk/src/main/web/WEB-INF/oscache-local.properties
===================================================================
--- xwiki/trunk/src/main/web/WEB-INF/oscache-local.properties	2006-05-10 20:08:38 UTC (rev 1065)
+++ xwiki/trunk/src/main/web/WEB-INF/oscache-local.properties	2006-05-11 04:14:42 UTC (rev 1066)
@@ -0,0 +1,116 @@
+# This property file configures local-only caches
+# Clustered cache settings should be done in oscache.properties
+
+
+# CACHE IN MEMORY
+# If you want to disable memory caching, just uncomment this line.
+# cache.memory=false
+
+
+# CACHE KEY
+#
+# This is the key that will be used to store the cache in the application
+# and session scope.
+#
+# If you want to set the cache key to anything other than the default
+# uncomment this line and change the cache.key
+#
+cache.key=XWiki-Local
+
+
+# USE HOST DOMAIN NAME IN KEY
+#
+# Servers for multiple host domains may wish to add host name info to
+# the generation of the key.  If this is true, then uncomment the
+# following line.
+#
+# cache.use.host.domain.in.key=true
+
+
+# CACHE LISTENERS
+#
+# These hook OSCache events and perform various actions such as logging
+# cache hits and misses, or broadcasting to other cache instances across a cluster.
+# See the documentation for further information.
+#
+# cache.event.listeners=com.opensymphony.oscache.plugins.clustersupport.JMSBroadcastingListener,  \
+#                       com.opensymphony.oscache.extra.CacheEntryEventListenerImpl,               \
+#                       com.opensymphony.oscache.extra.CacheMapAccessEventListenerImpl,           \
+#                       com.opensymphony.oscache.extra.ScopeEventListenerImpl
+
+
+# CACHE PERSISTENCE CLASS
+#
+# Specify the class to use for persistence. If you use the supplied DiskPersistenceListener,
+# don't forget to supply the cache.path property to specify the location of the cache
+# directory.
+# 
+# If a persistence class is not specified, OSCache will use memory caching only.
+#
+# cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener
+
+# CACHE OVERFLOW PERSISTENCE
+# Use persistent cache in overflow or not. The default value is false, which means
+# the persistent cache will be used at all times for every entry.  true is the recommended setting.
+#
+# cache.persistence.overflow.only=true
+
+# CACHE DIRECTORY
+#
+# This is the directory on disk where caches will be stored by the DiskPersistenceListener.
+# it will be created if it doesn't already exist. Remember that OSCache must have
+# write permission to this directory.
+#
+# Note: for Windows machines, this needs \ to be escaped
+# ie Windows:
+# cache.path=c:\\myapp\\cache
+# or *ix:
+# cache.path=/opt/myapp/cache
+#
+# cache.path=c:\\app\\cache
+
+
+# CACHE ALGORITHM
+#
+# Default cache algorithm to use. Note that in order to use an algorithm
+# the cache size must also be specified. If the cache size is not specified,
+# the cache algorithm will be Unlimited cache.
+#
+# cache.algorithm=com.opensymphony.oscache.base.algorithm.LRUCache
+# cache.algorithm=com.opensymphony.oscache.base.algorithm.FIFOCache
+# cache.algorithm=com.opensymphony.oscache.base.algorithm.UnlimitedCache
+
+# THREAD BLOCKING BEHAVIOR
+#
+# When a request is made for a stale cache entry, it is possible that another thread is already
+# in the process of rebuilding that entry. This setting specifies how OSCache handles the
+# subsequent 'non-building' threads. The default behaviour (cache.blocking=false) is to serve
+# the old content to subsequent threads until the cache entry has been updated. This provides
+# the best performance (at the cost of serving slightly stale data). When blocking is enabled,
+# threads will instead block until the new cache entry is ready to be served. Once the new entry
+# is put in the cache the blocked threads will be restarted and given the new entry.
+# Note that even if blocking is disabled, when there is no stale data available to be served
+# threads will block until the data is added to the cache by the thread that is responsible
+# for building the data.
+#
+# cache.blocking=false
+
+# CACHE SIZE
+#
+# Default cache size in number of items. If a size is specified but not
+# an algorithm, the cache algorithm used will be LRUCache.
+#
+cache.capacity=100000
+
+
+# CACHE UNLIMITED DISK
+# Use unlimited disk cache or not. The default value is false, which means
+# the disk cache will be limited in size to the value specified by cache.capacity.
+#
+# cache.unlimited.disk=false
+
+
+# JMS CLUSTER PROPERTIES
+# This cache is for non clustered caches only, cluster settings should be done in oscache-clustered.properties
+
+

Added: xwiki/trunk/src/main/web/WEB-INF/oscache.properties
===================================================================
--- xwiki/trunk/src/main/web/WEB-INF/oscache.properties	2006-05-10 20:08:38 UTC (rev 1065)
+++ xwiki/trunk/src/main/web/WEB-INF/oscache.properties	2006-05-11 04:14:42 UTC (rev 1066)
@@ -0,0 +1,144 @@
+# This property file configures caches that could be cluster enabled
+# Local-only cache settings should be done in oscache-local.properties
+# Uncomment cache.event.listeners to enable clustering
+
+# CACHE IN MEMORY
+# If you want to disable memory caching, just uncomment this line.
+# cache.memory=false
+
+
+# CACHE KEY
+#
+# This is the key that will be used to store the cache in the application
+# and session scope.
+#
+# If you want to set the cache key to anything other than the default
+# uncomment this line and change the cache.key
+#
+# 
+cache.key=XWiki
+
+
+# USE HOST DOMAIN NAME IN KEY
+#
+# Servers for multiple host domains may wish to add host name info to
+# the generation of the key.  If this is true, then uncomment the
+# following line.
+#
+# cache.use.host.domain.in.key=true
+
+
+# CACHE LISTENERS
+#
+# These hook OSCache events and perform various actions such as logging
+# cache hits and misses, or broadcasting to other cache instances across a cluster.
+# See the documentation for further information.
+#
+# cache.event.listeners=com.opensymphony.oscache.plugins.clustersupport.JMSBroadcastingListener,  \
+#                       com.opensymphony.oscache.extra.CacheEntryEventListenerImpl,               \
+#                       com.opensymphony.oscache.extra.CacheMapAccessEventListenerImpl,           \
+#                       com.opensymphony.oscache.extra.ScopeEventListenerImpl
+
+# uncomment this to enable clustering
+#
+cache.event.listeners=com.opensymphony.oscache.plugins.clustersupport.JavaGroupsBroadcastingListener,com.xpn.xwiki.cache.impl.XWikiCacheListener
+
+# CACHE PERSISTENCE CLASS
+#
+# Specify the class to use for persistence. If you use the supplied DiskPersistenceListener,
+# don't forget to supply the cache.path property to specify the location of the cache
+# directory.
+# 
+# If a persistence class is not specified, OSCache will use memory caching only.
+#
+# cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener
+
+# CACHE OVERFLOW PERSISTENCE
+# Use persistent cache in overflow or not. The default value is false, which means
+# the persistent cache will be used at all times for every entry.  true is the recommended setting.
+#
+# cache.persistence.overflow.only=true
+
+# CACHE DIRECTORY
+#
+# This is the directory on disk where caches will be stored by the DiskPersistenceListener.
+# it will be created if it doesn't already exist. Remember that OSCache must have
+# write permission to this directory.
+#
+# Note: for Windows machines, this needs \ to be escaped
+# ie Windows:
+# cache.path=c:\\myapp\\cache
+# or *ix:
+# cache.path=/opt/myapp/cache
+#
+# cache.path=c:\\app\\cache
+
+
+# CACHE ALGORITHM
+#
+# Default cache algorithm to use. Note that in order to use an algorithm
+# the cache size must also be specified. If the cache size is not specified,
+# the cache algorithm will be Unlimited cache.
+#
+# cache.algorithm=com.opensymphony.oscache.base.algorithm.LRUCache
+# cache.algorithm=com.opensymphony.oscache.base.algorithm.FIFOCache
+# cache.algorithm=com.opensymphony.oscache.base.algorithm.UnlimitedCache
+
+# THREAD BLOCKING BEHAVIOR
+#
+# When a request is made for a stale cache entry, it is possible that another thread is already
+# in the process of rebuilding that entry. This setting specifies how OSCache handles the
+# subsequent 'non-building' threads. The default behaviour (cache.blocking=false) is to serve
+# the old content to subsequent threads until the cache entry has been updated. This provides
+# the best performance (at the cost of serving slightly stale data). When blocking is enabled,
+# threads will instead block until the new cache entry is ready to be served. Once the new entry
+# is put in the cache the blocked threads will be restarted and given the new entry.
+# Note that even if blocking is disabled, when there is no stale data available to be served
+# threads will block until the data is added to the cache by the thread that is responsible
+# for building the data.
+#
+# cache.blocking=false
+
+# CACHE SIZE
+#
+# Default cache size in number of items. If a size is specified but not
+# an algorithm, the cache algorithm used will be LRUCache.
+#
+cache.capacity=10000
+
+
+# CACHE UNLIMITED DISK
+# Use unlimited disk cache or not. The default value is false, which means
+# the disk cache will be limited in size to the value specified by cache.capacity.
+#
+# cache.unlimited.disk=false
+
+
+# JMS CLUSTER PROPERTIES
+#
+# Configuration properties for JMS clustering. See the clustering documentation
+# for more information on these settings.
+#
+#cache.cluster.jms.topic.factory=java:comp/env/jms/TopicConnectionFactory
+#cache.cluster.jms.topic.name=java:comp/env/jms/OSCacheTopic
+#cache.cluster.jms.node.name=node1
+
+
+# JAVAGROUPS CLUSTER PROPERTIES
+#
+# Configuration properites for the JavaGroups clustering. Only one of these
+# should be specified. Default values (as shown below) will be used if niether
+# property is set. See the clustering documentation and the JavaGroups project
+# (www.javagroups.com) for more information on these settings.
+#
+#cache.cluster.properties=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;\
+#mcast_send_buf_size=150000;mcast_recv_buf_size=80000):\
+#PING(timeout=2000;num_initial_members=3):\
+#MERGE2(min_interval=5000;max_interval=10000):\
+#FD_SOCK:VERIFY_SUSPECT(timeout=1500):\
+#pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800;max_xmit_size=8192):\
+#UNICAST(timeout=300,600,1200,2400):\
+#pbcast.STABLE(desired_avg_gossip=20000):\
+#FRAG(frag_size=8096;down_thread=false;up_thread=false):\
+#pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=true)
+#cache.cluster.multicast.ip=231.12.21.132





More information about the Xwiki-notifications mailing list