applied patch 'r725578: Distributed Database Page Manager EhCache Cache Backport'
@@ -80,6 +80,11 @@ | ||
80 | 80 | <id>org.apache.portals.jetspeed-2:jetspeed-rdbms</id> |
81 | 81 | <version>${jetspeed.version}</version> |
82 | 82 | </dependency> |
83 | + <dependency> | |
84 | + <groupId>commons-jexl</groupId> | |
85 | + <artifactId>commons-jexl</artifactId> | |
86 | + <version>1.1</version> | |
87 | + </dependency> | |
83 | 88 | </dependencies> |
84 | 89 | |
85 | 90 | <build> |
@@ -1,82 +0,0 @@ | ||
1 | -<?xml version="1.0" encoding="UTF-8"?> | |
2 | -<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> | |
3 | -<!-- | |
4 | -Licensed to the Apache Software Foundation (ASF) under one or more | |
5 | -contributor license agreements. See the NOTICE file distributed with | |
6 | -this work for additional information regarding copyright ownership. | |
7 | -The ASF licenses this file to You under the Apache License, Version 2.0 | |
8 | -(the "License"); you may not use this file except in compliance with | |
9 | -the License. You may obtain a copy of the License at | |
10 | - | |
11 | - http://www.apache.org/licenses/LICENSE-2.0 | |
12 | - | |
13 | -Unless required by applicable law or agreed to in writing, software | |
14 | -distributed under the License is distributed on an "AS IS" BASIS, | |
15 | -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
16 | -See the License for the specific language governing permissions and | |
17 | -limitations under the License. | |
18 | ---> | |
19 | -<beans> | |
20 | - | |
21 | - <!-- Page Manager --> | |
22 | - <bean id="org.apache.jetspeed.page.PageManagerImpl" | |
23 | - name="securePageManagerImpl" | |
24 | - init-method="init" | |
25 | - class="org.apache.jetspeed.page.impl.DatabasePageManager"> | |
26 | - <!-- OJB configuration file resource path --> | |
27 | - <constructor-arg index="0"><value>JETSPEED-INF/ojb/page-manager-repository.xml</value></constructor-arg> | |
28 | - <!-- folder/page/link cache size, default=128, min=128 --> | |
29 | - <constructor-arg index="1"><value>128</value></constructor-arg> | |
30 | - <!-- folder/page/link cache expires seconds, default=150, infinite=0, min=30 --> | |
31 | - <constructor-arg index="2"><value>0</value></constructor-arg> | |
32 | - <!-- permissions security enabled flag, default=false --> | |
33 | - <constructor-arg index="3"><value>false</value></constructor-arg> | |
34 | - <!-- constraints security enabled flag, default=true --> | |
35 | - <constructor-arg index="4"><value>false</value></constructor-arg> | |
36 | - </bean> | |
37 | - | |
38 | - <!-- Transaction Proxying --> | |
39 | - <bean id="org.apache.jetspeed.page.PageManager" name="pageManager" parent="PageManagerTransactionProxy"> | |
40 | - <property name="proxyInterfaces"> | |
41 | - <value>org.apache.jetspeed.page.PageManager</value> | |
42 | - </property> | |
43 | - <property name="target"> | |
44 | - <ref bean="securePageManagerImpl" /> | |
45 | - </property> | |
46 | - <property name="transactionAttributes"> | |
47 | - <props> | |
48 | - <prop key="getPage*">PROPAGATION_SUPPORTS</prop> | |
49 | - <prop key="getLink*">PROPAGATION_SUPPORTS</prop> | |
50 | - <prop key="getFolder*">PROPAGATION_SUPPORTS</prop> | |
51 | - <prop key="getContentPage">PROPAGATION_SUPPORTS</prop> | |
52 | - <prop key="getAll">PROPAGATION_SUPPORTS</prop> | |
53 | - <prop key="getUserFolder">PROPAGATION_SUPPORTS</prop> | |
54 | - <prop key="update*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
55 | - <prop key="removePage">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
56 | - <prop key="removeFolder">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
57 | - <prop key="removeLink">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
58 | - <prop key="removePageSecurity">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
59 | - <prop key="createUserHomePagesFromRoles">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
60 | - <prop key="deepCopy*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
61 | - <prop key="addPages">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
62 | - <prop key="folderExists">PROPAGATION_SUPPORTS</prop> | |
63 | - <prop key="pageExists">PROPAGATION_SUPPORTS</prop> | |
64 | - <prop key="linkExists">PROPAGATION_SUPPORTS</prop> | |
65 | - <prop key="userFolderExists">PROPAGATION_SUPPORTS</prop> | |
66 | - <prop key="userPageExists">PROPAGATION_SUPPORTS</prop> | |
67 | - </props> | |
68 | - </property> | |
69 | - </bean> | |
70 | - | |
71 | - <!-- Inject Page Manager Proxy into Page Manager --> | |
72 | - <bean id="injectPageManagerProxy" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> | |
73 | - <property name="targetObject"><ref bean="securePageManagerImpl"/></property> | |
74 | - <property name="targetMethod"><value>setPageManagerProxy</value></property> | |
75 | - <property name="arguments"> | |
76 | - <list> | |
77 | - <ref bean="pageManager"/> | |
78 | - </list> | |
79 | - </property> | |
80 | - </bean> | |
81 | - | |
82 | -</beans> |
@@ -0,0 +1,69 @@ | ||
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!-- | |
3 | + Licensed to the Apache Software Foundation (ASF) under one or more | |
4 | + contributor license agreements. See the NOTICE file distributed with | |
5 | + this work for additional information regarding copyright ownership. | |
6 | + The ASF licenses this file to You under the Apache License, Version 2.0 | |
7 | + (the "License"); you may not use this file except in compliance with | |
8 | + the License. You may obtain a copy of the License at | |
9 | + | |
10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
11 | + | |
12 | + Unless required by applicable law or agreed to in writing, software | |
13 | + distributed under the License is distributed on an "AS IS" BASIS, | |
14 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | + See the License for the specific language governing permissions and | |
16 | + limitations under the License. | |
17 | +--> | |
18 | +<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"> | |
19 | + | |
20 | + <diskStore path="java.io.tmpdir"/> | |
21 | + | |
22 | + <cacheManagerEventListenerFactory class="" | |
23 | + properties=""/> | |
24 | + | |
25 | + | |
26 | + <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" | |
27 | + properties="peerDiscovery=automatic, | |
28 | + multicastGroupAddress=${org.apache.jetspeed.ehcache.group.address}, | |
29 | + multicastGroupPort=${org.apache.jetspeed.ehcache.group.port}, | |
30 | + timeToLive=${org.apache.jetspeed.ehcache.group.ttl}"/> | |
31 | + | |
32 | + <cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" | |
33 | + properties="hostName=${org.apache.jetspeed.ehcache.hostname}, | |
34 | + port=${org.apache.jetspeed.ehcache.port}"/> | |
35 | + | |
36 | + <defaultCache maxElementsInMemory="10000" | |
37 | + eternal="false" | |
38 | + timeToIdleSeconds="120" | |
39 | + timeToLiveSeconds="120" | |
40 | + overflowToDisk="true" | |
41 | + maxElementsOnDisk="10000000" | |
42 | + diskPersistent="false" | |
43 | + diskExpiryThreadIntervalSeconds="120" | |
44 | + memoryStoreEvictionPolicy="LRU"/> | |
45 | + | |
46 | + <cache name="pageManagerOidCache" | |
47 | + maxElementsInMemory="${org.apache.jetspeed.ehcache.pagemanager.maxelements}" | |
48 | + eternal="false" | |
49 | + overflowToDisk="false" | |
50 | + timeToIdleSeconds="${org.apache.jetspeed.ehcache.pagemanager.element.ttl}" | |
51 | + timeToLiveSeconds="${org.apache.jetspeed.ehcache.pagemanager.element.ttl}" | |
52 | + memoryStoreEvictionPolicy="LFU"/> | |
53 | + | |
54 | + <cache name="pageManagerPathCache" | |
55 | + maxElementsInMemory="${org.apache.jetspeed.ehcache.pagemanager.maxelements}" | |
56 | + eternal="false" | |
57 | + overflowToDisk="false" | |
58 | + timeToIdleSeconds="${org.apache.jetspeed.ehcache.pagemanager.element.ttl}" | |
59 | + timeToLiveSeconds="${org.apache.jetspeed.ehcache.pagemanager.element.ttl}" | |
60 | + memoryStoreEvictionPolicy="LFU"> | |
61 | + <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" | |
62 | + properties="replicateAsynchronously=true, | |
63 | + replicatePuts=false, | |
64 | + replicateUpdates=false, | |
65 | + replicateUpdatesViaCopy=false, | |
66 | + replicateRemovals=true"/> | |
67 | + </cache> | |
68 | + | |
69 | +</ehcache> |
@@ -0,0 +1,51 @@ | ||
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!-- | |
3 | + Licensed to the Apache Software Foundation (ASF) under one or more | |
4 | + contributor license agreements. See the NOTICE file distributed with | |
5 | + this work for additional information regarding copyright ownership. | |
6 | + The ASF licenses this file to You under the Apache License, Version 2.0 | |
7 | + (the "License"); you may not use this file except in compliance with | |
8 | + the License. You may obtain a copy of the License at | |
9 | + | |
10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
11 | + | |
12 | + Unless required by applicable law or agreed to in writing, software | |
13 | + distributed under the License is distributed on an "AS IS" BASIS, | |
14 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | + See the License for the specific language governing permissions and | |
16 | + limitations under the License. | |
17 | +--> | |
18 | +<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"> | |
19 | + | |
20 | + <diskStore path="java.io.tmpdir"/> | |
21 | + | |
22 | + <cacheManagerEventListenerFactory class="" | |
23 | + properties=""/> | |
24 | + | |
25 | + <defaultCache maxElementsInMemory="10000" | |
26 | + eternal="false" | |
27 | + timeToIdleSeconds="120" | |
28 | + timeToLiveSeconds="120" | |
29 | + overflowToDisk="true" | |
30 | + maxElementsOnDisk="10000000" | |
31 | + diskPersistent="false" | |
32 | + diskExpiryThreadIntervalSeconds="120" | |
33 | + memoryStoreEvictionPolicy="LRU"/> | |
34 | + | |
35 | + <cache name="pageManagerOidCache" | |
36 | + maxElementsInMemory="128" | |
37 | + eternal="false" | |
38 | + overflowToDisk="false" | |
39 | + timeToIdleSeconds="150" | |
40 | + timeToLiveSeconds="150" | |
41 | + memoryStoreEvictionPolicy="LFU"/> | |
42 | + | |
43 | + <cache name="pageManagerPathCache" | |
44 | + maxElementsInMemory="128" | |
45 | + eternal="false" | |
46 | + overflowToDisk="false" | |
47 | + timeToIdleSeconds="150" | |
48 | + timeToLiveSeconds="150" | |
49 | + memoryStoreEvictionPolicy="LFU"/> | |
50 | + | |
51 | +</ehcache> |
@@ -16,35 +16,14 @@ | ||
16 | 16 | limitations under the License. |
17 | 17 | --> |
18 | 18 | <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> |
19 | -<!-- | |
20 | - Database PSML Manager Interception for handling Cache Rollback | |
21 | - We also have examples here of replay interception for failover to | |
19 | + | |
20 | +<beans> | |
21 | + <!-- | |
22 | + Examples of replay interception for failover to | |
22 | 23 | a second database on update failures |
23 | - --> | |
24 | -<beans> | |
24 | + --> | |
25 | 25 | |
26 | - <bean id="pageManagerInterceptor" class="org.apache.jetspeed.util.interceptors.PageManagerInterceptor"> | |
27 | - </bean> | |
28 | - | |
29 | - | |
30 | - <bean id="PageManagerTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" | |
31 | - abstract="true"> | |
32 | - <property name="transactionManager"><ref bean="transactionManager"/></property> | |
33 | - <property name="transactionAttributes"> | |
34 | - <props> | |
35 | - <prop key="*">PROPAGATION_REQUIRED</prop> | |
36 | - </props> | |
37 | - </property> | |
38 | - <property name="preInterceptors"> | |
39 | - <list> | |
40 | - <ref local="pageManagerInterceptor" /> | |
41 | - </list> | |
42 | - </property> | |
43 | - </bean> | |
44 | - | |
45 | - <!-- | |
46 | - Replay support: | |
47 | - | |
26 | + <!-- | |
48 | 27 | <bean id="replayTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" |
49 | 28 | abstract="true"> |
50 | 29 | <property name="transactionManager"><ref bean="transactionManager"/></property> |
@@ -53,17 +32,17 @@ | ||
53 | 32 | <prop key="*">PROPAGATION_REQUIRED</prop> |
54 | 33 | </props> |
55 | 34 | </property> |
56 | - <property name="preInterceptors"> | |
35 | + <property name="preInterceptors"> | |
57 | 36 | <list> |
58 | 37 | <ref local="methodReplayInterceptor" /> |
59 | 38 | </list> |
60 | 39 | </property> |
61 | 40 | </bean> |
62 | - | |
63 | - <bean id="replayDecisionMakerBean" | |
41 | + | |
42 | + <bean id="replayDecisionMakerBean" | |
64 | 43 | class="org.apache.jetspeed.util.interceptors.TransactionalMethodReplayDecisionMaker"> |
65 | 44 | <property name="sqlErrorCodes"> |
66 | - <value>9999, 400, -80</value> | |
45 | + <value>9999, 400, -80</value> | |
67 | 46 | <value>9999</value> |
68 | 47 | </property> |
69 | 48 | </bean> |
@@ -73,11 +52,11 @@ | ||
73 | 52 | <value>3</value> |
74 | 53 | </property> |
75 | 54 | <property name="retryInterval"> |
76 | - <value>500</value></property> retry every 500 milliseconds | |
55 | + <value>500</value></property> retry every 500 milliseconds | |
77 | 56 | <property name="replayDecisionMaker"> |
78 | 57 | <ref bean="replayDecisionMakerBean"/> |
79 | 58 | </property> |
80 | 59 | </bean> |
81 | - --> | |
82 | - | |
60 | + --> | |
61 | + | |
83 | 62 | </beans> |
@@ -18,65 +18,20 @@ | ||
18 | 18 | --> |
19 | 19 | <beans> |
20 | 20 | |
21 | + <import resource="database-page-manager-base.xml"/> | |
22 | + | |
21 | 23 | <!-- Page Manager --> |
22 | - <bean id="org.apache.jetspeed.page.PageManagerImpl" | |
23 | - name="securePermissionsPageManagerImpl" | |
24 | - init-method="init" | |
25 | - class="org.apache.jetspeed.page.impl.DatabasePageManager"> | |
24 | + <bean name="pageManagerImpl" init-method="init" class="org.apache.jetspeed.page.impl.DatabasePageManager"> | |
26 | 25 | <!-- OJB configuration file resource path --> |
27 | 26 | <constructor-arg index="0"><value>JETSPEED-INF/ojb/page-manager-repository.xml</value></constructor-arg> |
28 | - <!-- folder/page/link cache size, default=128, min=128 --> | |
29 | - <constructor-arg index="1"><value>128</value></constructor-arg> | |
30 | - <!-- folder/page/link cache expires seconds, default=150, infinite=0, min=30 --> | |
31 | - <constructor-arg index="2"><value>0</value></constructor-arg> | |
32 | 27 | <!-- permissions security enabled flag, default=false --> |
33 | - <constructor-arg index="3"><value>true</value></constructor-arg> | |
28 | + <constructor-arg index="1"><value>true</value></constructor-arg> | |
34 | 29 | <!-- constraints security enabled flag, default=true --> |
35 | - <constructor-arg index="4"><value>false</value></constructor-arg> | |
30 | + <constructor-arg index="2"><value>false</value></constructor-arg> | |
31 | + <!-- folder/page/link cache --> | |
32 | + <constructor-arg index="3"><ref bean="pageManagerOidCache"/></constructor-arg> | |
33 | + <!-- folder/page/link path cache --> | |
34 | + <constructor-arg index="4"><ref bean="pageManagerPathCache"/></constructor-arg> | |
36 | 35 | </bean> |
37 | 36 | |
38 | - <!-- Transaction Proxying --> | |
39 | - <bean id="org.apache.jetspeed.page.PageManager" name="pageManager" parent="baseTransactionProxy"> | |
40 | - <property name="proxyInterfaces"> | |
41 | - <value>org.apache.jetspeed.page.PageManager</value> | |
42 | - </property> | |
43 | - <property name="target"> | |
44 | - <ref bean="securePermissionsPageManagerImpl" /> | |
45 | - </property> | |
46 | - <property name="transactionAttributes"> | |
47 | - <props> | |
48 | - <prop key="getPage*">PROPAGATION_SUPPORTS</prop> | |
49 | - <prop key="getLink*">PROPAGATION_SUPPORTS</prop> | |
50 | - <prop key="getFolder*">PROPAGATION_SUPPORTS</prop> | |
51 | - <prop key="getContentPage">PROPAGATION_SUPPORTS</prop> | |
52 | - <prop key="getAll">PROPAGATION_SUPPORTS</prop> | |
53 | - <prop key="getUserFolder">PROPAGATION_SUPPORTS</prop> | |
54 | - <prop key="update*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
55 | - <prop key="removePage">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
56 | - <prop key="removeFolder">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
57 | - <prop key="removeLink">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
58 | - <prop key="removePageSecurity">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
59 | - <prop key="createUserHomePagesFromRoles">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
60 | - <prop key="deepCopy*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
61 | - <prop key="addPages">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
62 | - <prop key="folderExists">PROPAGATION_SUPPORTS</prop> | |
63 | - <prop key="pageExists">PROPAGATION_SUPPORTS</prop> | |
64 | - <prop key="linkExists">PROPAGATION_SUPPORTS</prop> | |
65 | - <prop key="userFolderExists">PROPAGATION_SUPPORTS</prop> | |
66 | - <prop key="userPageExists">PROPAGATION_SUPPORTS</prop> | |
67 | - </props> | |
68 | - </property> | |
69 | - </bean> | |
70 | - | |
71 | - <!-- Inject Page Manager Proxy into Page Manager --> | |
72 | - <bean id="injectPageManagerProxy" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> | |
73 | - <property name="targetObject"><ref bean="securePermissionsPageManagerImpl"/></property> | |
74 | - <property name="targetMethod"><value>setPageManagerProxy</value></property> | |
75 | - <property name="arguments"> | |
76 | - <list> | |
77 | - <ref bean="pageManager"/> | |
78 | - </list> | |
79 | - </property> | |
80 | - </bean> | |
81 | - | |
82 | 37 | </beans> |
@@ -18,65 +18,20 @@ | ||
18 | 18 | --> |
19 | 19 | <beans> |
20 | 20 | |
21 | + <import resource="database-page-manager-base.xml"/> | |
22 | + | |
21 | 23 | <!-- Page Manager --> |
22 | - <bean id="org.apache.jetspeed.page.PageManagerImpl" | |
23 | - name="pageManagerImpl" | |
24 | - init-method="init" | |
25 | - class="org.apache.jetspeed.page.impl.DatabasePageManager"> | |
24 | + <bean id="pageManagerImpl" init-method="init" class="org.apache.jetspeed.page.impl.DatabasePageManager"> | |
26 | 25 | <!-- OJB configuration file resource path --> |
27 | - <constructor-arg index="0"><value>JETSPEED-INF/ojb/page-manager-repository.xml</value></constructor-arg> | |
28 | - <!-- folder/page/link cache size, default=128, min=128 --> | |
29 | - <constructor-arg index="1"><value>128</value></constructor-arg> | |
30 | - <!-- folder/page/link cache expires seconds, default=150, infinite=0, min=30 --> | |
31 | - <constructor-arg index="2"><value>0</value></constructor-arg> | |
26 | + <constructor-arg index="0"><value>JETSPEED-INF/ojb/page-manager-repository.xml</value></constructor-arg> | |
32 | 27 | <!-- permissions security enabled flag, default=false --> |
33 | - <constructor-arg index="3"><value>false</value></constructor-arg> | |
28 | + <constructor-arg index="1"><value>false</value></constructor-arg> | |
34 | 29 | <!-- constraints security enabled flag, default=true --> |
35 | - <constructor-arg index="4"><value>false</value></constructor-arg> | |
30 | + <constructor-arg index="2"><value>false</value></constructor-arg> | |
31 | + <!-- folder/page/link cache --> | |
32 | + <constructor-arg index="3"><ref bean="pageManagerOidCache"/></constructor-arg> | |
33 | + <!-- folder/page/link path cache --> | |
34 | + <constructor-arg index="4"><ref bean="pageManagerPathCache"/></constructor-arg> | |
36 | 35 | </bean> |
37 | 36 | |
38 | - <!-- Transaction Proxying --> | |
39 | - <bean id="org.apache.jetspeed.page.PageManager" name="pageManager" parent="baseTransactionProxy"> | |
40 | - <property name="proxyInterfaces"> | |
41 | - <value>org.apache.jetspeed.page.PageManager</value> | |
42 | - </property> | |
43 | - <property name="target"> | |
44 | - <ref bean="pageManagerImpl" /> | |
45 | - </property> | |
46 | - <property name="transactionAttributes"> | |
47 | - <props> | |
48 | - <prop key="getPage*">PROPAGATION_SUPPORTS</prop> | |
49 | - <prop key="getLink*">PROPAGATION_SUPPORTS</prop> | |
50 | - <prop key="getFolder*">PROPAGATION_SUPPORTS</prop> | |
51 | - <prop key="getContentPage">PROPAGATION_SUPPORTS</prop> | |
52 | - <prop key="getAll">PROPAGATION_SUPPORTS</prop> | |
53 | - <prop key="getUserFolder">PROPAGATION_SUPPORTS</prop> | |
54 | - <prop key="update*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
55 | - <prop key="removePage">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
56 | - <prop key="removeFolder">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
57 | - <prop key="removeLink">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
58 | - <prop key="removePageSecurity">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
59 | - <prop key="createUserHomePagesFromRoles">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
60 | - <prop key="deepCopy*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
61 | - <prop key="addPages">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
62 | - <prop key="folderExists">PROPAGATION_SUPPORTS</prop> | |
63 | - <prop key="pageExists">PROPAGATION_SUPPORTS</prop> | |
64 | - <prop key="linkExists">PROPAGATION_SUPPORTS</prop> | |
65 | - <prop key="userFolderExists">PROPAGATION_SUPPORTS</prop> | |
66 | - <prop key="userPageExists">PROPAGATION_SUPPORTS</prop> | |
67 | - </props> | |
68 | - </property> | |
69 | - </bean> | |
70 | - | |
71 | - <!-- Inject Page Manager Proxy into Page Manager --> | |
72 | - <bean id="injectPageManagerProxy" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> | |
73 | - <property name="targetObject"><ref bean="pageManagerImpl"/></property> | |
74 | - <property name="targetMethod"><value>setPageManagerProxy</value></property> | |
75 | - <property name="arguments"> | |
76 | - <list> | |
77 | - <ref bean="pageManager"/> | |
78 | - </list> | |
79 | - </property> | |
80 | - </bean> | |
81 | - | |
82 | 37 | </beans> |
@@ -0,0 +1,692 @@ | ||
1 | +/* | |
2 | + * Licensed to the Apache Software Foundation (ASF) under one or more | |
3 | + * contributor license agreements. See the NOTICE file distributed with | |
4 | + * this work for additional information regarding copyright ownership. | |
5 | + * The ASF licenses this file to You under the Apache License, Version 2.0 | |
6 | + * (the "License"); you may not use this file except in compliance with | |
7 | + * the License. You may obtain a copy of the License at | |
8 | + * | |
9 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + * | |
11 | + * Unless required by applicable law or agreed to in writing, software | |
12 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + * See the License for the specific language governing permissions and | |
15 | + * limitations under the License. | |
16 | + */ | |
17 | +package org.apache.jetspeed.page.cache; | |
18 | + | |
19 | +import java.io.BufferedReader; | |
20 | +import java.io.BufferedWriter; | |
21 | +import java.io.File; | |
22 | +import java.io.IOException; | |
23 | +import java.io.InputStreamReader; | |
24 | +import java.io.OutputStreamWriter; | |
25 | +import java.net.URI; | |
26 | +import java.net.URL; | |
27 | +import java.net.URLClassLoader; | |
28 | +import java.util.ArrayList; | |
29 | +import java.util.HashMap; | |
30 | +import java.util.Iterator; | |
31 | +import java.util.List; | |
32 | +import java.util.Map; | |
33 | + | |
34 | +import junit.framework.Test; | |
35 | +import junit.framework.TestCase; | |
36 | +import junit.framework.TestSuite; | |
37 | + | |
38 | +import org.apache.commons.logging.Log; | |
39 | +import org.apache.commons.logging.LogFactory; | |
40 | +import org.apache.jetspeed.cache.impl.EhCacheConfigResource; | |
41 | + | |
42 | +/** | |
43 | + * TestDatabasePageManagerCache | |
44 | + * | |
45 | + * @author <a href="mailto:rwatler@apache.org">Randy Watler</a> | |
46 | + * @version $Id: $ | |
47 | + */ | |
48 | +public class TestDatabasePageManagerCache extends TestCase | |
49 | +{ | |
50 | + | |
51 | + protected static Log log = LogFactory | |
52 | + .getLog(TestDatabasePageManagerCache.class); | |
53 | + | |
54 | + // Members | |
55 | + | |
56 | + private String osExecutableExtension; | |
57 | + | |
58 | + private String fileSeparator; | |
59 | + | |
60 | + private File javaExecutablePath; | |
61 | + | |
62 | + private String classPathSeparator; | |
63 | + | |
64 | + private File projectDirectoryPath; | |
65 | + | |
66 | + private Map systemProperties; | |
67 | + | |
68 | + private String classPath; | |
69 | + | |
70 | + // Test methods | |
71 | + | |
72 | + /** | |
73 | + * Tests distributed cache operation for DatabasePageManager | |
74 | + */ | |
75 | + public void testDatabasePageManagerCache() | |
76 | + { | |
77 | + String result; | |
78 | + | |
79 | + // create and start servers | |
80 | + final TestProgram server0 = new TestProgram("server-0", | |
81 | + DatabasePageManagerServer.class, 0); | |
82 | + final TestProgram server1 = new TestProgram("server-1", | |
83 | + DatabasePageManagerServer.class, 1); | |
84 | + try | |
85 | + { | |
86 | + // start servers | |
87 | + server0.start(); | |
88 | + server1.start(); | |
89 | + | |
90 | + // wait until servers have started | |
91 | + server0.execute(""); | |
92 | + server1.execute(""); | |
93 | + | |
94 | + // check to ensure servers have distributed page manager caches | |
95 | + boolean server0Distributed = false; | |
96 | + boolean server1Distributed = false; | |
97 | + final long distributedCheckStarted = System.currentTimeMillis(); | |
98 | + do | |
99 | + { | |
100 | + // check servers | |
101 | + if (!server0Distributed) | |
102 | + { | |
103 | + result = server0.execute("pageManager.isDistributed();"); | |
104 | + assertTrue(result.indexOf("Exception") == -1); | |
105 | + server0Distributed = result.endsWith("true"); | |
106 | + } | |
107 | + if (!server1Distributed) | |
108 | + { | |
109 | + result = server1.execute("pageManager.isDistributed();"); | |
110 | + assertTrue(result.indexOf("Exception") == -1); | |
111 | + server1Distributed = result.endsWith("true"); | |
112 | + } | |
113 | + | |
114 | + // wait if servers not distributed | |
115 | + if (!server0Distributed || !server1Distributed) | |
116 | + { | |
117 | + Thread.sleep(250); | |
118 | + } | |
119 | + } while ((!server0Distributed || !server1Distributed) | |
120 | + && (System.currentTimeMillis() - distributedCheckStarted < 5000)); | |
121 | + if (!server0Distributed && !server1Distributed) | |
122 | + { | |
123 | + System.out | |
124 | + .println("Server page managers not distributed: possible system limitation... test skipped"); | |
125 | + log | |
126 | + .warn("Server page managers not distributed: possible system limitation... test skipped"); | |
127 | + return; | |
128 | + } | |
129 | + assertTrue(server0Distributed); | |
130 | + assertTrue(server1Distributed); | |
131 | + | |
132 | + // clean and setup database page managers | |
133 | + result = server0 | |
134 | + .execute("removeRootFolder = pageManager.getFolder(\"/\");"); | |
135 | + if (result.indexOf("FolderNotFoundException") == -1) | |
136 | + { | |
137 | + result = server0 | |
138 | + .execute("pageManager.removeFolder(removeRootFolder);"); | |
139 | + assertTrue(result.indexOf("Exception") == -1); | |
140 | + } | |
141 | + result = server0.execute("pageManager.reset();"); | |
142 | + assertTrue(result.indexOf("Exception") == -1); | |
143 | + result = server1.execute("pageManager.reset();"); | |
144 | + assertTrue(result.indexOf("Exception") == -1); | |
145 | + | |
146 | + // create folder and documents in first page manager | |
147 | + result = server0.execute("folder = pageManager.newFolder(\"/\");"); | |
148 | + assertTrue(result.indexOf("Exception") == -1); | |
149 | + result = server0.execute("folder.setTitle(\"Root Folder\");"); | |
150 | + assertTrue(result.indexOf("Exception") == -1); | |
151 | + result = server0.execute("pageManager.updateFolder(folder);"); | |
152 | + assertTrue(result.indexOf("Exception") == -1); | |
153 | + result = server0 | |
154 | + .execute("page = pageManager.newPage(\"/default-page.psml\");"); | |
155 | + assertTrue(result.indexOf("Exception") == -1); | |
156 | + result = server0.execute("page.setTitle(\"Default Page\");"); | |
157 | + assertTrue(result.indexOf("Exception") == -1); | |
158 | + result = server0.execute("pageManager.updatePage(page);"); | |
159 | + assertTrue(result.indexOf("Exception") == -1); | |
160 | + result = server0 | |
161 | + .execute("page = pageManager.newPage(\"/another-page.psml\");"); | |
162 | + assertTrue(result.indexOf("Exception") == -1); | |
163 | + result = server0.execute("page.setTitle(\"Another Page\");"); | |
164 | + assertTrue(result.indexOf("Exception") == -1); | |
165 | + result = server0.execute("pageManager.updatePage(page);"); | |
166 | + assertTrue(result.indexOf("Exception") == -1); | |
167 | + result = server0 | |
168 | + .execute("page = pageManager.newPage(\"/some-other-page.psml\");"); | |
169 | + assertTrue(result.indexOf("Exception") == -1); | |
170 | + result = server0.execute("page.setTitle(\"Some Other Page\");"); | |
171 | + assertTrue(result.indexOf("Exception") == -1); | |
172 | + result = server0.execute("pageManager.updatePage(page);"); | |
173 | + assertTrue(result.indexOf("Exception") == -1); | |
174 | + result = server0 | |
175 | + .execute("link = pageManager.newLink(\"/default.link\");"); | |
176 | + assertTrue(result.indexOf("Exception") == -1); | |
177 | + result = server0.execute("link.setTitle(\"Default Link\");"); | |
178 | + assertTrue(result.indexOf("Exception") == -1); | |
179 | + result = server0 | |
180 | + .execute("link.setUrl(\"http://www.default.org/\");"); | |
181 | + assertTrue(result.indexOf("Exception") == -1); | |
182 | + result = server0.execute("pageManager.updateLink(link);"); | |
183 | + assertTrue(result.indexOf("Exception") == -1); | |
184 | + result = server0 | |
185 | + .execute("folder = pageManager.newFolder(\"/deep-0\");"); | |
186 | + assertTrue(result.indexOf("Exception") == -1); | |
187 | + result = server0.execute("folder.setTitle(\"Deep 0 Folder\");"); | |
188 | + assertTrue(result.indexOf("Exception") == -1); | |
189 | + result = server0.execute("pageManager.updateFolder(folder);"); | |
190 | + assertTrue(result.indexOf("Exception") == -1); | |
191 | + result = server0 | |
192 | + .execute("page = pageManager.newPage(\"/deep-0/deep-page-0.psml\");"); | |
193 | + assertTrue(result.indexOf("Exception") == -1); | |
194 | + result = server0.execute("page.setTitle(\"Deep Page 0\");"); | |
195 | + assertTrue(result.indexOf("Exception") == -1); | |
196 | + result = server0.execute("pageManager.updatePage(page);"); | |
197 | + assertTrue(result.indexOf("Exception") == -1); | |
198 | + result = server0 | |
199 | + .execute("folder = pageManager.newFolder(\"/deep-1\");"); | |
200 | + assertTrue(result.indexOf("Exception") == -1); | |
201 | + result = server0.execute("folder.setTitle(\"Deep 1 Folder\");"); | |
202 | + assertTrue(result.indexOf("Exception") == -1); | |
203 | + result = server0.execute("pageManager.updateFolder(folder);"); | |
204 | + assertTrue(result.indexOf("Exception") == -1); | |
205 | + result = server0 | |
206 | + .execute("page = pageManager.newPage(\"/deep-1/deep-page-1.psml\");"); | |
207 | + assertTrue(result.indexOf("Exception") == -1); | |
208 | + result = server0.execute("page.setTitle(\"Deep Page 1\");"); | |
209 | + assertTrue(result.indexOf("Exception") == -1); | |
210 | + result = server0.execute("pageManager.updatePage(page);"); | |
211 | + assertTrue(result.indexOf("Exception") == -1); | |
212 | + result = server0 | |
213 | + .execute("pageSecurity = pageManager.newPageSecurity();"); | |
214 | + assertTrue(result.indexOf("Exception") == -1); | |
215 | + result = server0 | |
216 | + .execute("pageManager.updatePageSecurity(pageSecurity);"); | |
217 | + assertTrue(result.indexOf("Exception") == -1); | |
218 | + | |
219 | + // populate folders and documents in second page manager | |
220 | + result = server1 | |
221 | + .execute("pageManager.getFolder(\"/\").getTitle();"); | |
222 | + assertTrue(result.endsWith("Root Folder")); | |
223 | + result = server1 | |
224 | + .execute("pageManager.getPage(\"/default-page.psml\").getTitle();"); | |
225 | + assertTrue(result.endsWith("Default Page")); | |
226 | + result = server1 | |
227 | + .execute("pageManager.getPage(\"/another-page.psml\").getTitle();"); | |
228 | + assertTrue(result.endsWith("Another Page")); | |
229 | + result = server1 | |
230 | + .execute("pageManager.getPage(\"/some-other-page.psml\").getTitle();"); | |
231 | + assertTrue(result.endsWith("Some Other Page")); | |
232 | + result = server1 | |
233 | + .execute("pageManager.getLink(\"/default.link\").getTitle();"); | |
234 | + assertTrue(result.endsWith("Default Link")); | |
235 | + result = server1 | |
236 | + .execute("pageManager.getFolder(\"/deep-0\").getTitle();"); | |
237 | + assertTrue(result.endsWith("Deep 0 Folder")); | |
238 | + result = server1 | |
239 | + .execute("pageManager.getPage(\"/deep-0/deep-page-0.psml\").getTitle();"); | |
240 | + assertTrue(result.endsWith("Deep Page 0")); | |
241 | + result = server1 | |
242 | + .execute("pageManager.getFolder(\"/deep-1\").getTitle();"); | |
243 | + assertTrue(result.endsWith("Deep 1 Folder")); | |
244 | + result = server1 | |
245 | + .execute("pageManager.getPage(\"/deep-1/deep-page-1.psml\").getTitle();"); | |
246 | + assertTrue(result.endsWith("Deep Page 1")); | |
247 | + result = server1 | |
248 | + .execute("pageManager.getPageSecurity().getPath();"); | |
249 | + assertTrue(result.endsWith("/page.security")); | |
250 | + | |
251 | + // update/remove objects in second page manager | |
252 | + result = server1 | |
253 | + .execute("page = pageManager.getPage(\"/default-page.psml\");"); | |
254 | + assertTrue(result.indexOf("Exception") == -1); | |
255 | + result = server1.execute("page.setTitle(\"Edited Default Page\");"); | |
256 | + assertTrue(result.indexOf("Exception") == -1); | |
257 | + result = server1.execute("pageManager.updatePage(page);"); | |
258 | + assertTrue(result.indexOf("Exception") == -1); | |
259 | + result = server1 | |
260 | + .execute("page = pageManager.getPage(\"/some-other-page.psml\");"); | |
261 | + assertTrue(result.indexOf("Exception") == -1); | |
262 | + result = server1.execute("pageManager.removePage(page);"); | |
263 | + assertTrue(result.indexOf("Exception") == -1); | |
264 | + result = server1 | |
265 | + .execute("link = pageManager.getLink(\"/default.link\");"); | |
266 | + assertTrue(result.indexOf("Exception") == -1); | |
267 | + result = server1.execute("link.setTitle(\"Edited Default Link\");"); | |
268 | + assertTrue(result.indexOf("Exception") == -1); | |
269 | + result = server1.execute("pageManager.updateLink(link);"); | |
270 | + assertTrue(result.indexOf("Exception") == -1); | |
271 | + result = server1 | |
272 | + .execute("folder = pageManager.getFolder(\"/deep-0\");"); | |
273 | + assertTrue(result.indexOf("Exception") == -1); | |
274 | + result = server1 | |
275 | + .execute("folder.setTitle(\"Edited Deep 0 Folder\");"); | |
276 | + assertTrue(result.indexOf("Exception") == -1); | |
277 | + result = server1.execute("pageManager.updateFolder(folder);"); | |
278 | + assertTrue(result.indexOf("Exception") == -1); | |
279 | + result = server1 | |
280 | + .execute("folder = pageManager.getFolder(\"/deep-1\");"); | |
281 | + assertTrue(result.indexOf("Exception") == -1); | |
282 | + result = server1.execute("pageManager.removeFolder(folder);"); | |
283 | + assertTrue(result.indexOf("Exception") == -1); | |
284 | + | |
285 | + // test objects in both page managers for cache coherency | |
286 | + result = server1 | |
287 | + .execute("pageManager.getPage(\"/default-page.psml\").getTitle();"); | |
288 | + assertTrue(result.endsWith("Edited Default Page")); | |
289 | + result = server1 | |
290 | + .execute("pageManager.getPage(\"/some-other-page.psml\");"); | |
291 | + assertTrue(result.indexOf("PageNotFoundException") != -1); | |
292 | + result = server1 | |
293 | + .execute("pageManager.getFolder(\"/\").getPages().size();"); | |
294 | + assertTrue(result.endsWith("2")); | |
295 | + result = server1 | |
296 | + .execute("pageManager.getLink(\"/default.link\").getTitle();"); | |
297 | + assertTrue(result.endsWith("Edited Default Link")); | |
298 | + result = server1 | |
299 | + .execute("pageManager.getFolder(\"/deep-0\").getTitle();"); | |
300 | + assertTrue(result.endsWith("Edited Deep 0 Folder")); | |
301 | + result = server1 | |
302 | + .execute("pageManager.getPage(\"/deep-1/deep-page-1.psml\");"); | |
303 | + assertTrue(result.indexOf("PageNotFoundException") != -1); | |
304 | + result = server1.execute("pageManager.getFolder(\"/deep-1\");"); | |
305 | + assertTrue(result.indexOf("FolderNotFoundException") != -1); | |
306 | + result = server1 | |
307 | + .execute("pageManager.getFolder(\"/\").getFolders().size();"); | |
308 | + assertTrue(result.endsWith("1")); | |
309 | + boolean defaultPageUpdated = false; | |
310 | + boolean someOtherPageRemoved = false; | |
311 | + boolean rootFolderPagesCountTwo = false; | |
312 | + boolean defaultLinkUpdated = false; | |
313 | + boolean deep0FolderUpdated = false; | |
314 | + boolean deepPage1Removed = false; | |
315 | + boolean deep1FolderRemoved = false; | |
316 | + boolean rootFolderFoldersCountOne = false; | |
317 | + final long coherencyCheckStarted = System.currentTimeMillis(); | |
318 | + do | |
319 | + { | |
320 | + // check cache coherency | |
321 | + if (!defaultPageUpdated) | |
322 | + { | |
323 | + result = server0 | |
324 | + .execute("pageManager.getPage(\"/default-page.psml\").getTitle();"); | |
325 | + defaultPageUpdated = result.endsWith("Edited Default Page"); | |
326 | + } | |
327 | + if (!someOtherPageRemoved) | |
328 | + { | |
329 | + result = server0 | |
330 | + .execute("pageManager.getPage(\"/some-other-page.psml\");"); | |
331 | + someOtherPageRemoved = (result | |
332 | + .indexOf("PageNotFoundException") != -1); | |
333 | + } | |
334 | + if (!rootFolderPagesCountTwo) | |
335 | + { | |
336 | + result = server0 | |
337 | + .execute("pageManager.getFolder(\"/\").getPages().size();"); | |
338 | + rootFolderPagesCountTwo = result.endsWith("2"); | |
339 | + } | |
340 | + if (!defaultLinkUpdated) | |
341 | + { | |
342 | + result = server0 | |
343 | + .execute("pageManager.getLink(\"/default.link\").getTitle();"); | |
344 | + defaultLinkUpdated = result.endsWith("Edited Default Link"); | |
345 | + } | |
346 | + if (!deep0FolderUpdated) | |
347 | + { | |
348 | + result = server0 | |
349 | + .execute("pageManager.getFolder(\"/deep-0\").getTitle();"); | |
350 | + deep0FolderUpdated = result | |
351 | + .endsWith("Edited Deep 0 Folder"); | |
352 | + } | |
353 | + if (!deepPage1Removed) | |
354 | + { | |
355 | + result = server0 | |
356 | + .execute("pageManager.getPage(\"/deep-1/deep-page-1.psml\");"); | |
357 | + deepPage1Removed = (result.indexOf("PageNotFoundException") != -1); | |
358 | + } | |
359 | + if (!deep1FolderRemoved) | |
360 | + { | |
361 | + result = server0 | |
362 | + .execute("pageManager.getFolder(\"/deep-1\");"); | |
363 | + deep1FolderRemoved = (result | |
364 | + .indexOf("FolderNotFoundException") != -1); | |
365 | + } | |
366 | + if (!rootFolderFoldersCountOne) | |
367 | + { | |
368 | + result = server0 | |
369 | + .execute("pageManager.getFolder(\"/\").getFolders().size();"); | |
370 | + rootFolderFoldersCountOne = result.endsWith("1"); | |
371 | + } | |
372 | + | |
373 | + // wait for cache coherency | |
374 | + if (!defaultPageUpdated || !someOtherPageRemoved | |
375 | + || !rootFolderPagesCountTwo || !defaultLinkUpdated | |
376 | + || !deep0FolderUpdated || !deepPage1Removed | |
377 | + || !deep1FolderRemoved || !rootFolderFoldersCountOne) | |
378 | + { | |
379 | + Thread.sleep(250); | |
380 | + } | |
381 | + } while ((!defaultPageUpdated || !someOtherPageRemoved | |
382 | + || !rootFolderPagesCountTwo || !defaultLinkUpdated | |
383 | + || !deep0FolderUpdated || !deepPage1Removed | |
384 | + || !deep1FolderRemoved || !rootFolderFoldersCountOne) | |
385 | + && (System.currentTimeMillis() - coherencyCheckStarted < 5000)); | |
386 | + assertTrue(defaultPageUpdated); | |
387 | + assertTrue(someOtherPageRemoved); | |
388 | + assertTrue(rootFolderPagesCountTwo); | |
389 | + assertTrue(defaultLinkUpdated); | |
390 | + assertTrue(deep0FolderUpdated); | |
391 | + assertTrue(deepPage1Removed); | |
392 | + assertTrue(deep1FolderRemoved); | |
393 | + assertTrue(rootFolderFoldersCountOne); | |
394 | + | |
395 | + // reset database page managers | |
396 | + result = server0.execute("pageManager.reset();"); | |
397 | + assertTrue(result.indexOf("Exception") == -1); | |
398 | + result = server1.execute("pageManager.reset();"); | |
399 | + assertTrue(result.indexOf("Exception") == -1); | |
400 | + } | |
401 | + catch (final Exception e) | |
402 | + { | |
403 | + log.error("Server test exception: " + e, e); | |
404 | + fail("Server test exception: " + e); | |
405 | + } | |
406 | + finally | |
407 | + { | |
408 | + // silently shutdown servers | |
409 | + try | |
410 | + { | |
411 | + server0.shutdown(); | |
412 | + } | |
413 | + catch (final Exception e) | |
414 | + { | |
415 | + log.error("Server shutdown exception: " + e, e); | |
416 | + } | |
417 | + try | |
418 | + { | |
419 | + server1.shutdown(); | |
420 | + } | |
421 | + catch (final Exception e) | |
422 | + { | |
423 | + log.error("Server shutdown exception: " + e, e); | |
424 | + } | |
425 | + } | |
426 | + } | |
427 | + | |
428 | + // Implementation classes | |
429 | + | |
430 | + protected class TestProgram | |
431 | + { | |
432 | + | |
433 | + private String name; | |
434 | + | |
435 | + private Class mainClass; | |
436 | + | |
437 | + private int index; | |
438 | + | |
439 | + private Process process; | |
440 | + | |
441 | + private BufferedWriter processInput; | |
442 | + | |
443 | + private BufferedReader processOutput; | |
444 | + | |
445 | + public TestProgram(final String name, final Class mainClass, | |
446 | + final int index) | |
447 | + { | |
448 | + this.name = name; | |
449 | + this.mainClass = mainClass; | |
450 | + this.index = index; | |
451 | + } | |
452 | + | |
453 | + public synchronized void start() throws IOException | |
454 | + { | |
455 | + assertNull(process); | |
456 | + | |
457 | + // configure launcher with paths, properties, and indexed properties | |
458 | + final List commandAndArgs = new ArrayList(); | |
459 | + commandAndArgs.add(javaExecutablePath.getCanonicalPath()); | |
460 | + for (Iterator iter = systemProperties.entrySet().iterator(); iter | |
461 | + .hasNext();) | |
462 | + { | |
463 | + final Map.Entry systemProperty = (Map.Entry) iter.next(); | |
464 | + final String propertyName = (String) systemProperty.getKey(); | |
465 | + String propertyValue = (String) systemProperty.getValue(); | |
466 | + if (propertyName | |
467 | + .equals(EhCacheConfigResource.EHCACHE_PORT_PROP_NAME)) | |
468 | + { | |
469 | + propertyValue = Integer.toString(Integer | |
470 | + .parseInt(propertyValue) | |
471 | + + index); | |
472 | + } | |
473 | + commandAndArgs.add("-D" + propertyName + "=" + propertyValue); | |
474 | + } | |
475 | + commandAndArgs.add("-Dlog4j.configuration=log4j-stdout.properties"); | |
476 | + commandAndArgs.add("-classpath"); | |
477 | + commandAndArgs.add(classPath); | |
478 | + commandAndArgs.add(mainClass.getName()); | |
479 | + | |
480 | + // launch test programs | |
481 | + process = Runtime.getRuntime().exec( | |
482 | + (String[]) commandAndArgs.toArray(new String[commandAndArgs | |
483 | + .size()]), null, projectDirectoryPath); | |
484 | + | |
485 | + // setup I/O for process | |
486 | + processInput = new BufferedWriter(new OutputStreamWriter(process | |
487 | + .getOutputStream())); | |
488 | + processOutput = new BufferedReader(new InputStreamReader(process | |
489 | + .getInputStream())); | |
490 | + | |
491 | + // read messages from process | |
492 | + for (String line; (processOutput.ready() && ((line = processOutput | |
493 | + .readLine()) != null));) | |
494 | + { | |
495 | + logProcessLine(line); | |
496 | + } | |
497 | + } | |
498 | + | |
499 | + public synchronized String execute(final String scriptLine) | |
500 | + throws IOException | |
501 | + { | |
502 | + assertNotNull(process); | |
503 | + | |
504 | + // read messages from process | |
505 | + for (String line; (processOutput.ready() && ((line = processOutput | |
506 | + .readLine()) != null));) | |
507 | + { | |
508 | + logProcessLine(line); | |
509 | + } | |
510 | + | |
511 | + // write script line to process | |
512 | + processInput.write(scriptLine); | |
513 | + processInput.newLine(); | |
514 | + processInput.flush(); | |
515 | + | |
516 | + // read result or messages from process | |
517 | + String resultLine = null; | |
518 | + for (String line; ((line = processOutput.readLine()) != null);) | |
519 | + { | |
520 | + if (!line | |
521 | + .startsWith(DatabasePageManagerServer.SCRIPT_RESULT_LINE_PREFIX)) | |
522 | + { | |
523 | + logProcessLine(line); | |
524 | + } | |
525 | + else | |
526 | + { | |
527 | + resultLine = line; | |
528 | + break; | |
529 | + } | |
530 | + } | |
531 | + if (resultLine == null) { throw new IOException( | |
532 | + "Unexpected EOF from process output"); } | |
533 | + return resultLine; | |
534 | + } | |
535 | + | |
536 | + public synchronized void shutdown() throws IOException, | |
537 | + InterruptedException | |
538 | + { | |
539 | + assertNotNull(process); | |
540 | + | |
541 | + // start thread to destroy process on timeout | |
542 | + final Thread destroyThread = new Thread(new Runnable() | |
543 | + { | |
544 | + | |
545 | + public void run() | |
546 | + { | |
547 | + try | |
548 | + { | |
549 | + Thread.sleep(10000); | |
550 | + if (process != null) | |
551 | + { | |
552 | + log.warn("Forcibly stopping " + name); | |
553 | + process.destroy(); | |
554 | + } | |
555 | + } | |
556 | + catch (final Exception e) | |
557 | + { | |
558 | + } | |
559 | + } | |
560 | + }, "DestroyThread"); | |
561 | + destroyThread.setDaemon(true); | |
562 | + destroyThread.start(); | |
563 | + | |
564 | + // close process input to shutdown server and read messages | |
565 | + processInput.close(); | |
566 | + for (String line; ((line = processOutput.readLine()) != null);) | |
567 | + { | |
568 | + logProcessLine(line); | |
569 | + } | |
570 | + | |
571 | + // join on process completion | |
572 | + process.waitFor(); | |
573 | + processOutput.close(); | |
574 | + process = null; | |
575 | + | |
576 | + // join on destroy thread | |
577 | + destroyThread.interrupt(); | |
578 | + destroyThread.join(); | |
579 | + } | |
580 | + | |
581 | + private void logProcessLine(final String line) | |
582 | + { | |
583 | + if ((line.indexOf("ERROR") == -1) | |
584 | + && ((line.indexOf("ERROR") != -1) | |
585 | + || (line.indexOf("Exception") != -1) || line | |
586 | + .startsWith(" at "))) | |
587 | + { | |
588 | + log.error("{" + name + "} " + line); | |
589 | + } | |
590 | + else | |
591 | + { | |
592 | + log.info("{" + name + "} " + line); | |
593 | + } | |
594 | + } | |
595 | + } | |
596 | + | |
597 | + // TestCase implementation | |
598 | + | |
599 | + /* (non-Javadoc) | |
600 | + * @see junit.framework.TestCase#setUp() | |
601 | + */ | |
602 | + protected void setUp() throws Exception | |
603 | + { | |
604 | + // setup cache properties | |
605 | + EhCacheConfigResource | |
606 | + .getInstance( | |
607 | + EhCacheConfigResource.EHCACHE_CONFIG_RESOURCE_DISTRIBUTED_CACHE, | |
608 | + true); | |
609 | + | |
610 | + // environment setup | |
611 | + osExecutableExtension = (System.getProperty("os.name").startsWith( | |
612 | + "Windows") ? ".exe" : ""); | |
613 | + fileSeparator = System.getProperty("file.separator"); | |
614 | + javaExecutablePath = new File(System.getProperty("java.home") | |
615 | + + fileSeparator + "bin" + fileSeparator + "java" | |
616 | + + osExecutableExtension); | |
617 | + classPathSeparator = System.getProperty("path.separator"); | |
618 | + projectDirectoryPath = new File(System.getProperty("basedir")); | |
619 | + systemProperties = new HashMap(); | |
620 | + for (Iterator iter = System.getProperties().entrySet().iterator(); iter | |
621 | + .hasNext();) | |
622 | + { | |
623 | + final Map.Entry systemProperty = (Map.Entry) iter.next(); | |
624 | + final String propertyName = systemProperty.getKey().toString(); | |
625 | + final String propertyValue = systemProperty.getValue().toString(); | |
626 | + if (propertyName.startsWith("org.apache.jetspeed.") | |
627 | + || propertyName.startsWith("java.net.") | |
628 | + || propertyName.equals("basedir")) | |
629 | + { | |
630 | + systemProperties.put(propertyName, propertyValue); | |
631 | + } | |
632 | + } | |
633 | + | |
634 | + // construct launcher classpath from current class loader | |
635 | + final StringBuffer classPathBuilder = new StringBuffer(); | |
636 | + final ClassLoader loader = this.getClass().getClassLoader(); | |
637 | + assertTrue(loader instanceof URLClassLoader); | |
638 | + final URLClassLoader urlLoader = (URLClassLoader) loader; | |
639 | + assertNotNull(urlLoader.getURLs()); | |
640 | + for (int i = 0; (i < urlLoader.getURLs().length); i++) | |
641 | + { | |
642 | + final URL pathURL = urlLoader.getURLs()[i]; | |
643 | + | |
644 | + // convert path URL to file path | |
645 | + final String path = new File(new URI(pathURL.toString())) | |
646 | + .getCanonicalPath(); | |
647 | + | |
648 | + // build class path | |
649 | + if (classPathBuilder.length() > 0) | |
650 | + { | |
651 | + classPathBuilder.append(classPathSeparator); | |
652 | + } | |
653 | + classPathBuilder.append(path); | |
654 | + } | |
655 | + classPath = classPathBuilder.toString(); | |
656 | + assertTrue(classPath.length() > 0); | |
657 | + | |
658 | + // continue setup | |
659 | + super.setUp(); | |
660 | + } | |
661 | + | |
662 | + /* (non-Javadoc) | |
663 | + * @see junit.framework.TestCase#tearDown() | |
664 | + */ | |
665 | + protected void tearDown() throws Exception | |
666 | + { | |
667 | + super.tearDown(); | |
668 | + } | |
669 | + | |
670 | + // Application entry point | |
671 | + | |
672 | + /** | |
673 | + * Start the tests. | |
674 | + * | |
675 | + * @param args not used | |
676 | + */ | |
677 | + public static void main(final String[] args) | |
678 | + { | |
679 | + junit.awtui.TestRunner.main(new String[] | |
680 | + {TestDatabasePageManagerCache.class.getName()}); | |
681 | + } | |
682 | + | |
683 | + /** | |
684 | + * Creates the test suite. | |
685 | + * | |
686 | + * @return a test suite that includes all methods starting with "test" | |
687 | + */ | |
688 | + public static Test suite() | |
689 | + { | |
690 | + return new TestSuite(TestDatabasePageManagerCache.class); | |
691 | + } | |
692 | +} |
@@ -0,0 +1,223 @@ | ||
1 | +/* | |
2 | + * Licensed to the Apache Software Foundation (ASF) under one or more | |
3 | + * contributor license agreements. See the NOTICE file distributed with | |
4 | + * this work for additional information regarding copyright ownership. | |
5 | + * The ASF licenses this file to You under the Apache License, Version 2.0 | |
6 | + * (the "License"); you may not use this file except in compliance with | |
7 | + * the License. You may obtain a copy of the License at | |
8 | + * | |
9 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + * | |
11 | + * Unless required by applicable law or agreed to in writing, software | |
12 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + * See the License for the specific language governing permissions and | |
15 | + * limitations under the License. | |
16 | + */ | |
17 | +package org.apache.jetspeed.page.cache; | |
18 | + | |
19 | +import java.io.BufferedReader; | |
20 | +import java.io.InputStreamReader; | |
21 | +import java.io.PrintWriter; | |
22 | +import java.util.Properties; | |
23 | + | |
24 | +import org.apache.commons.jexl.JexlContext; | |
25 | +import org.apache.commons.jexl.JexlHelper; | |
26 | +import org.apache.commons.jexl.Script; | |
27 | +import org.apache.commons.jexl.ScriptFactory; | |
28 | +import org.apache.commons.logging.Log; | |
29 | +import org.apache.commons.logging.LogFactory; | |
30 | +import org.apache.jetspeed.components.jndi.JetspeedTestJNDIComponent; | |
31 | +import org.apache.jetspeed.engine.JetspeedEngineConstants; | |
32 | +import org.apache.jetspeed.page.PageManager; | |
33 | +import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; | |
34 | +import org.springframework.context.ApplicationContext; | |
35 | +import org.springframework.context.support.ClassPathXmlApplicationContext; | |
36 | + | |
37 | +/** | |
38 | + * DatabasePageManagerServer | |
39 | + * | |
40 | + * @author <a href="mailto:rwatler@apache.org">Randy Watler</a> | |
41 | + * @version $Id: $ | |
42 | + */ | |
43 | +public class DatabasePageManagerServer | |
44 | +{ | |
45 | + | |
46 | + protected static Log log = LogFactory | |
47 | + .getLog(DatabasePageManagerServer.class); | |
48 | + | |
49 | + // Constants | |
50 | + | |
51 | + public static final String SCRIPT_RESULT_LINE_PREFIX = "> "; | |
52 | + | |
53 | + // Members | |
54 | + | |
55 | + private JetspeedTestJNDIComponent jndiDS; | |
56 | + | |
57 | + protected ClassPathXmlApplicationContext ctx; | |
58 | + | |
59 | + private String baseDir; | |
60 | + | |
61 | + private PageManager pageManager; | |
62 | + | |
63 | + private JexlContext jexlContext; | |
64 | + | |
65 | + private boolean exit; | |
66 | + | |
67 | + // Life cycle | |
68 | + | |
69 | + /** | |
70 | + * Initialize page manager server instance and script context. | |
71 | + * | |
72 | + * @throws Exception | |
73 | + */ | |
74 | + public void initialize() throws Exception | |
75 | + { | |
76 | + // setup jetspeed test datasource and component manager | |
77 | + jndiDS = new JetspeedTestJNDIComponent(); | |
78 | + jndiDS.setup(); | |
79 | + final String[] bootConfigurations = new String[] | |
80 | + {"boot/datasource.xml"}; | |
81 | + final String[] configurations = new String[] | |
82 | + {"database-page-manager.xml", "transaction.xml"}; | |
83 | + baseDir = System.getProperty("basedir"); | |
84 | + if ((baseDir == null) || (baseDir.length() == 0)) | |
85 | + { | |
86 | + baseDir = System.getProperty("user.dir"); | |
87 | + } | |
88 | + final String appRoot = baseDir + "/target/test-classes/webapp"; | |
89 | + final ApplicationContext bootContext = new ClassPathXmlApplicationContext( | |
90 | + bootConfigurations, true); | |
91 | + ctx = new ClassPathXmlApplicationContext(configurations, false, | |
92 | + bootContext); | |
93 | + PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); | |
94 | + Properties p = new Properties(); | |
95 | + p.setProperty(JetspeedEngineConstants.APPLICATION_ROOT_KEY, appRoot); | |
96 | + ppc.setProperties(p); | |
97 | + ctx.addBeanFactoryPostProcessor(ppc); | |
98 | + ctx.refresh(); | |
99 | + | |
100 | + // access page manager | |
101 | + pageManager = (PageManager) ctx.getBean("pageManager"); | |
102 | + | |
103 | + // craete jexl context | |
104 | + jexlContext = JexlHelper.createContext(); | |
105 | + jexlContext.getVars().put("pageManager", pageManager); | |
106 | + jexlContext.getVars().put("pageManagerServer", this); | |
107 | + | |
108 | + log.info("DatabasePageManager server initialized"); | |
109 | + } | |
110 | + | |
111 | + /** | |
112 | + * Terminate page manager server instance. | |
113 | + * | |
114 | + * @throws Exception | |
115 | + */ | |
116 | + public void terminate() throws Exception | |
117 | + { | |
118 | + // tear down jetspeed component manager and test datasource | |
119 | + ctx.close(); | |
120 | + jndiDS.tearDown(); | |
121 | + | |
122 | + log.info("DatabasePageManager server terminated"); | |
123 | + } | |
124 | + | |
125 | + // Implementation | |
126 | + | |
127 | + /** | |
128 | + * Execute a single line script against page manager server context. | |
129 | + * | |
130 | + * @param scriptLine jexl script | |
131 | + * @return script result line | |
132 | + */ | |
133 | + public String execute(final String scriptLine) | |
134 | + { | |
135 | + // execute script line and return result line | |
136 | + String resultLine = scriptLine; | |
137 | + try | |
138 | + { | |
139 | + final Script jexlScript = ScriptFactory.createScript(scriptLine); | |
140 | + final Object result = jexlScript.execute(jexlContext); | |
141 | + if (result != null) | |
142 | + { | |
143 | + resultLine += " -> " + result; | |
144 | + } | |
145 | + } | |
146 | + catch (final Exception e) | |
147 | + { | |
148 | + resultLine += " -> " + e; | |
149 | + } | |
150 | + return resultLine; | |
151 | + } | |
152 | + | |
153 | + /** | |
154 | + * Sets server exit flag. | |
155 | + */ | |
156 | + public void exit() | |
157 | + { | |
158 | + exit = true; | |
159 | + } | |
160 | + | |
161 | + // Data access | |
162 | + | |
163 | + /** | |
164 | + * @return server exit flag | |
165 | + */ | |
166 | + public boolean isExit() | |
167 | + { | |
168 | + return exit; | |
169 | + } | |
170 | + | |
171 | + // Application entry point | |
172 | + | |
173 | + /** | |
174 | + * Server main entry point. | |
175 | + * | |
176 | + * @param args not used | |
177 | + */ | |
178 | + public static void main(final String[] args) | |
179 | + { | |
180 | + try | |
181 | + { | |
182 | + // create and initialize server | |
183 | + final DatabasePageManagerServer server = new DatabasePageManagerServer(); | |
184 | + server.initialize(); | |
185 | + | |
186 | + // simple server reads script lines from standard | |
187 | + // input and writes results on standard output | |
188 | + final BufferedReader in = new BufferedReader(new InputStreamReader( | |
189 | + System.in)); | |
190 | + final PrintWriter out = new PrintWriter(System.out, true); | |
191 | + do | |
192 | + { | |
193 | + // read single line scripts to execute | |
194 | + String scriptLine = in.readLine(); | |
195 | + if (scriptLine != null) | |
196 | + { | |
197 | + scriptLine = scriptLine.trim(); | |
198 | + String resultLine = ""; | |
199 | + if (scriptLine.length() > 0) | |
200 | + { | |
201 | + // execute script | |
202 | + resultLine = server.execute(scriptLine); | |
203 | + } | |
204 | + | |
205 | + // write prefixed single line results | |
206 | + out.println(SCRIPT_RESULT_LINE_PREFIX + resultLine); | |
207 | + } | |
208 | + else | |
209 | + { | |
210 | + // exit server on input EOF | |
211 | + server.exit(); | |
212 | + } | |
213 | + } while (!server.isExit()); | |
214 | + | |
215 | + // terminate server | |
216 | + server.terminate(); | |
217 | + } | |
218 | + catch (final Throwable t) | |
219 | + { | |
220 | + log.error("Unexpected exception: " + t, t); | |
221 | + } | |
222 | + } | |
223 | +} |
@@ -71,12 +71,6 @@ | ||
71 | 71 | {"tx-page-manager.xml", "transaction.xml", "interceptors.xml"}; |
72 | 72 | } |
73 | 73 | |
74 | - protected String[] getBootConfigurations() | |
75 | - { | |
76 | - return new String[] | |
77 | - {"boot/datasource.xml"}; | |
78 | - } | |
79 | - | |
80 | 74 | public void testTx() throws Exception |
81 | 75 | { |
82 | 76 | if (pageManager.folderExists("/")) |
@@ -18,65 +18,20 @@ | ||
18 | 18 | --> |
19 | 19 | <beans> |
20 | 20 | |
21 | + <import resource="database-page-manager-base.xml"/> | |
22 | + | |
21 | 23 | <!-- Page Manager --> |
22 | - <bean id="org.apache.jetspeed.page.PageManagerImpl" | |
23 | - name="securePageManagerImpl" | |
24 | - init-method="init" | |
25 | - class="org.apache.jetspeed.page.impl.DatabasePageManager"> | |
24 | + <bean id="pageManagerImpl" init-method="init" class="org.apache.jetspeed.page.impl.DatabasePageManager"> | |
26 | 25 | <!-- OJB configuration file resource path --> |
27 | 26 | <constructor-arg index="0"><value>JETSPEED-INF/ojb/page-manager-repository.xml</value></constructor-arg> |
28 | - <!-- folder/page/link cache size, default=128, min=128 --> | |
29 | - <constructor-arg index="1"><value>128</value></constructor-arg> | |
30 | - <!-- folder/page/link cache expires seconds, default=150, infinite=0, min=30 --> | |
31 | - <constructor-arg index="2"><value>0</value></constructor-arg> | |
32 | 27 | <!-- permissions security enabled flag, default=false --> |
33 | - <constructor-arg index="3"><value>false</value></constructor-arg> | |
28 | + <constructor-arg index="1"><value>false</value></constructor-arg> | |
34 | 29 | <!-- constraints security enabled flag, default=true --> |
35 | - <constructor-arg index="4"><value>true</value></constructor-arg> | |
30 | + <constructor-arg index="2"><value>true</value></constructor-arg> | |
31 | + <!-- folder/page/link cache --> | |
32 | + <constructor-arg index="3"><ref bean="pageManagerOidCache"/></constructor-arg> | |
33 | + <!-- folder/page/link path cache --> | |
34 | + <constructor-arg index="4"><ref bean="pageManagerPathCache"/></constructor-arg> | |
36 | 35 | </bean> |
37 | 36 | |
38 | - <!-- Transaction Proxying --> | |
39 | - <bean id="org.apache.jetspeed.page.PageManager" name="pageManager" parent="baseTransactionProxy"> | |
40 | - <property name="proxyInterfaces"> | |
41 | - <value>org.apache.jetspeed.page.PageManager</value> | |
42 | - </property> | |
43 | - <property name="target"> | |
44 | - <ref bean="securePageManagerImpl" /> | |
45 | - </property> | |
46 | - <property name="transactionAttributes"> | |
47 | - <props> | |
48 | - <prop key="getPage*">PROPAGATION_SUPPORTS</prop> | |
49 | - <prop key="getLink*">PROPAGATION_SUPPORTS</prop> | |
50 | - <prop key="getFolder*">PROPAGATION_SUPPORTS</prop> | |
51 | - <prop key="getContentPage">PROPAGATION_SUPPORTS</prop> | |
52 | - <prop key="getAll">PROPAGATION_SUPPORTS</prop> | |
53 | - <prop key="getUserFolder">PROPAGATION_SUPPORTS</prop> | |
54 | - <prop key="update*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
55 | - <prop key="removePage">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
56 | - <prop key="removeFolder">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
57 | - <prop key="removeLink">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
58 | - <prop key="removePageSecurity">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
59 | - <prop key="createUserHomePagesFromRoles">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
60 | - <prop key="deepCopy*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
61 | - <prop key="addPages">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
62 | - <prop key="folderExists">PROPAGATION_SUPPORTS</prop> | |
63 | - <prop key="pageExists">PROPAGATION_SUPPORTS</prop> | |
64 | - <prop key="linkExists">PROPAGATION_SUPPORTS</prop> | |
65 | - <prop key="userFolderExists">PROPAGATION_SUPPORTS</prop> | |
66 | - <prop key="userPageExists">PROPAGATION_SUPPORTS</prop> | |
67 | - </props> | |
68 | - </property> | |
69 | - </bean> | |
70 | - | |
71 | - <!-- Inject Page Manager Proxy into Page Manager --> | |
72 | - <bean id="injectPageManagerProxy" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> | |
73 | - <property name="targetObject"><ref bean="securePageManagerImpl"/></property> | |
74 | - <property name="targetMethod"><value>setPageManagerProxy</value></property> | |
75 | - <property name="arguments"> | |
76 | - <list> | |
77 | - <ref bean="pageManager"/> | |
78 | - </list> | |
79 | - </property> | |
80 | - </bean> | |
81 | - | |
82 | 37 | </beans> |
@@ -0,0 +1,102 @@ | ||
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!-- | |
3 | +Licensed to the Apache Software Foundation (ASF) under one or more | |
4 | +contributor license agreements. See the NOTICE file distributed with | |
5 | +this work for additional information regarding copyright ownership. | |
6 | +The ASF licenses this file to You under the Apache License, Version 2.0 | |
7 | +(the "License"); you may not use this file except in compliance with | |
8 | +the License. You may obtain a copy of the License at | |
9 | + | |
10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
11 | + | |
12 | +Unless required by applicable law or agreed to in writing, software | |
13 | +distributed under the License is distributed on an "AS IS" BASIS, | |
14 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | +See the License for the specific language governing permissions and | |
16 | +limitations under the License. | |
17 | +--> | |
18 | +<beans xmlns="http://www.springframework.org/schema/beans" | |
19 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
20 | + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> | |
21 | + | |
22 | + <!-- Page Manager Caches --> | |
23 | + <bean id="cacheManagerConfig" class="org.apache.jetspeed.cache.impl.EhCacheConfigResource"> | |
24 | + <property name="defaultConfigResource" value="ehcache.xml"/> | |
25 | + <property name="test" value="true"/> | |
26 | + </bean> | |
27 | + | |
28 | + <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> | |
29 | + <property name="configLocation" ref="cacheManagerConfig"/> | |
30 | + </bean> | |
31 | + | |
32 | + <bean id="ehPageManagerOidCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> | |
33 | + <property name="cacheManager" ref="cacheManager"/> | |
34 | + <property name="cacheName" value="pageManagerOidCache"/> | |
35 | + </bean> | |
36 | + | |
37 | + <bean id="ehPageManagerPathCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> | |
38 | + <property name="cacheManager" ref="cacheManager"/> | |
39 | + <property name="cacheName" value="pageManagerPathCache"/> | |
40 | + </bean> | |
41 | + | |
42 | + <bean id="pageManagerOidCache" class="org.apache.jetspeed.cache.impl.EhCacheImpl"> | |
43 | + <constructor-arg><ref bean="ehPageManagerOidCache"/></constructor-arg> | |
44 | + </bean> | |
45 | + | |
46 | + <bean id="pageManagerPathCache" class="org.apache.jetspeed.cache.impl.EhCacheDistributedImpl"> | |
47 | + <constructor-arg><ref bean="ehPageManagerPathCache"/></constructor-arg> | |
48 | + </bean> | |
49 | + | |
50 | + <!-- Transaction Proxying --> | |
51 | + <bean id="pageManagerInterceptor" class="org.apache.jetspeed.util.interceptors.PageManagerInterceptor"> | |
52 | + </bean> | |
53 | + | |
54 | + <bean id="pageManager" parent="baseTransactionProxy"> | |
55 | + <property name="proxyInterfaces"> | |
56 | + <value>org.apache.jetspeed.page.PageManager</value> | |
57 | + </property> | |
58 | + <property name="target"> | |
59 | + <ref bean="pageManagerImpl" /> | |
60 | + </property> | |
61 | + <property name="transactionAttributes"> | |
62 | + <props> | |
63 | + <prop key="getPage*">PROPAGATION_SUPPORTS</prop> | |
64 | + <prop key="getLink*">PROPAGATION_SUPPORTS</prop> | |
65 | + <prop key="getFolder*">PROPAGATION_SUPPORTS</prop> | |
66 | + <prop key="getContentPage">PROPAGATION_SUPPORTS</prop> | |
67 | + <prop key="getAll">PROPAGATION_SUPPORTS</prop> | |
68 | + <prop key="getUserFolder">PROPAGATION_SUPPORTS</prop> | |
69 | + <prop key="update*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
70 | + <prop key="removePage">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
71 | + <prop key="removeFolder">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
72 | + <prop key="removeLink">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
73 | + <prop key="removePageSecurity">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
74 | + <prop key="createUserHomePagesFromRoles">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
75 | + <prop key="deepCopy*">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
76 | + <prop key="addPages">PROPAGATION_REQUIRED,-org.apache.jetspeed.page.document.NodeException</prop> | |
77 | + <prop key="folderExists">PROPAGATION_SUPPORTS</prop> | |
78 | + <prop key="pageExists">PROPAGATION_SUPPORTS</prop> | |
79 | + <prop key="linkExists">PROPAGATION_SUPPORTS</prop> | |
80 | + <prop key="userFolderExists">PROPAGATION_SUPPORTS</prop> | |
81 | + <prop key="userPageExists">PROPAGATION_SUPPORTS</prop> | |
82 | + </props> | |
83 | + </property> | |
84 | + <property name="preInterceptors"> | |
85 | + <list> | |
86 | + <ref bean="pageManagerInterceptor" /> | |
87 | + </list> | |
88 | + </property> | |
89 | + </bean> | |
90 | + | |
91 | + <!-- Inject Page Manager Proxy into Page Manager --> | |
92 | + <bean id="injectPageManagerProxy" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> | |
93 | + <property name="targetObject"><ref bean="pageManagerImpl"/></property> | |
94 | + <property name="targetMethod"><value>setPageManagerProxy</value></property> | |
95 | + <property name="arguments"> | |
96 | + <list> | |
97 | + <ref bean="pageManager"/> | |
98 | + </list> | |
99 | + </property> | |
100 | + </bean> | |
101 | + | |
102 | +</beans> |
@@ -16,12 +16,15 @@ | ||
16 | 16 | */ |
17 | 17 | package org.apache.jetspeed.page.impl; |
18 | 18 | |
19 | -import java.util.HashMap; | |
20 | 19 | import java.util.Iterator; |
21 | 20 | import java.util.LinkedList; |
22 | 21 | import java.util.List; |
23 | 22 | import java.util.Properties; |
24 | 23 | |
24 | +import org.apache.jetspeed.cache.CacheElement; | |
25 | +import org.apache.jetspeed.cache.JetspeedCache; | |
26 | +import org.apache.jetspeed.cache.JetspeedCacheEventListener; | |
27 | +import org.apache.jetspeed.om.folder.Folder; | |
25 | 28 | import org.apache.jetspeed.om.folder.impl.FolderImpl; |
26 | 29 | import org.apache.jetspeed.page.PageManager; |
27 | 30 | import org.apache.jetspeed.page.document.impl.NodeImpl; |
@@ -38,16 +41,12 @@ | ||
38 | 41 | public class DatabasePageManagerCache implements ObjectCache |
39 | 42 | { |
40 | 43 | |
41 | - private static HashMap cacheByOID; | |
44 | + // Members | |
42 | 45 | |
43 | - private static LinkedList cacheLRUList; | |
46 | + private static JetspeedCache oidCache; | |
44 | 47 | |
45 | - private static HashMap cacheByPath; | |
48 | + private static JetspeedCache pathCache; | |
46 | 49 | |
47 | - private static int cacheSize; | |
48 | - | |
49 | - private static int cacheExpiresSeconds; | |
50 | - | |
51 | 50 | private static boolean constraintsEnabled; |
52 | 51 | |
53 | 52 | private static boolean permissionsEnabled; |
@@ -54,6 +53,10 @@ | ||
54 | 53 | |
55 | 54 | private static PageManager pageManager; |
56 | 55 | |
56 | + private static ThreadLocal transactionedOperations = new ThreadLocal(); | |
57 | + | |
58 | + // Implementation | |
59 | + | |
57 | 60 | /** |
58 | 61 | * cacheInit |
59 | 62 | * |
@@ -62,24 +65,189 @@ | ||
62 | 65 | * @param pageManager |
63 | 66 | * configured page manager |
64 | 67 | */ |
65 | - public synchronized static void cacheInit(DatabasePageManager dbPageManager) | |
68 | + public synchronized static void cacheInit(final JetspeedCache oidCache, | |
69 | + final JetspeedCache pathCache, final DatabasePageManager pageManager) | |
66 | 70 | { |
67 | - if (pageManager != null) | |
71 | + | |
72 | + // initialize | |
73 | + DatabasePageManagerCache.oidCache = oidCache; | |
74 | + DatabasePageManagerCache.pathCache = pathCache; | |
75 | + constraintsEnabled = pageManager.getConstraintsEnabled(); | |
76 | + permissionsEnabled = pageManager.getPermissionsEnabled(); | |
77 | + | |
78 | + // setup local oid cache listener | |
79 | + oidCache.addEventListener(new JetspeedCacheEventListener() | |
68 | 80 | { |
69 | - cacheClear(); | |
70 | - } | |
71 | - cacheByOID = new HashMap(); | |
72 | - cacheLRUList = new LinkedList(); | |
73 | - cacheByPath = new HashMap(); | |
74 | - cacheSize = dbPageManager.getCacheSize(); | |
75 | - cacheExpiresSeconds = dbPageManager.getCacheExpiresSeconds(); | |
76 | - constraintsEnabled = dbPageManager.getConstraintsEnabled(); | |
77 | - permissionsEnabled = dbPageManager.getPermissionsEnabled(); | |
78 | - pageManager = dbPageManager; | |
81 | + | |
82 | + /* (non-Javadoc) | |
83 | + * @see org.apache.jetspeed.cache.JetspeedCacheEventListener#notifyElementAdded(org.apache.jetspeed.cache.JetspeedCache, boolean, java.lang.Object, java.lang.Object) | |
84 | + */ | |
85 | + public void notifyElementAdded(final JetspeedCache cache, | |
86 | + final boolean local, final Object key, final Object element) | |
87 | + { | |
88 | + final NodeImpl node = (NodeImpl) element; | |
89 | + // infuse node with page manager configuration | |
90 | + // or the page manager itself and add to the | |
91 | + // paths cache | |
92 | + node.setConstraintsEnabled(constraintsEnabled); | |
93 | + node.setPermissionsEnabled(permissionsEnabled); | |
94 | + if (node instanceof FolderImpl) | |
95 | + { | |
96 | + ((FolderImpl) node).setPageManager(pageManager); | |
97 | + } | |
98 | + } | |
99 | + | |
100 | + /* (non-Javadoc) | |
101 | + * @see org.apache.jetspeed.cache.JetspeedCacheEventListener#notifyElementChanged(org.apache.jetspeed.cache.JetspeedCache, boolean, java.lang.Object, java.lang.Object) | |
102 | + */ | |
103 | + public void notifyElementChanged(final JetspeedCache cache, | |
104 | + final boolean local, final Object key, final Object element) | |
105 | + { | |
106 | + final NodeImpl node = (NodeImpl) element; | |
107 | + // infuse node with page manager configuration | |
108 | + // or the page manager itself and add to the | |
109 | + // paths cache | |
110 | + node.setConstraintsEnabled(constraintsEnabled); | |
111 | + node.setPermissionsEnabled(permissionsEnabled); | |
112 | + if (node instanceof FolderImpl) | |
113 | + { | |
114 | + ((FolderImpl) node).setPageManager(pageManager); | |
115 | + } | |
116 | + } | |
117 | + | |
118 | + /* (non-Javadoc) | |
119 | + * @see org.apache.jetspeed.cache.JetspeedCacheEventListener#notifyElementEvicted(org.apache.jetspeed.cache.JetspeedCache, boolean, java.lang.Object, java.lang.Object) | |
120 | + */ | |
121 | + public void notifyElementEvicted(final JetspeedCache cache, | |
122 | + final boolean local, final Object key, final Object element) | |
123 | + { | |
124 | + final NodeImpl node = (NodeImpl) element; | |
125 | + // reset internal FolderImpl caches | |
126 | + if (node instanceof FolderImpl) | |
127 | + { | |
128 | + ((FolderImpl) node).resetAll(false); | |
129 | + } | |
130 | + } | |
131 | + | |
132 | + /* (non-Javadoc) | |
133 | + * @see org.apache.jetspeed.cache.JetspeedCacheEventListener#notifyElementExpired(org.apache.jetspeed.cache.JetspeedCache, boolean, java.lang.Object, java.lang.Object) | |
134 | + */ | |
135 | + public void notifyElementExpired(final JetspeedCache cache, | |
136 | + final boolean local, final Object key, final Object element) | |
137 | + { | |
138 | + final NodeImpl node = (NodeImpl) element; | |
139 | + // reset internal FolderImpl caches | |
140 | + if (node instanceof FolderImpl) | |
141 | + { | |
142 | + ((FolderImpl) node).resetAll(false); | |
143 | + } | |
144 | + } | |
145 | + | |
146 | + /* (non-Javadoc) | |
147 | + * @see org.apache.jetspeed.cache.JetspeedCacheEventListener#notifyElementRemoved(org.apache.jetspeed.cache.JetspeedCache, boolean, java.lang.Object, java.lang.Object) | |
148 | + */ | |
149 | + public void notifyElementRemoved(final JetspeedCache cache, | |
150 | + final boolean local, final Object key, final Object element) | |
151 | + { | |
152 | + final NodeImpl node = (NodeImpl) element; | |
153 | + // reset internal FolderImpl caches | |
154 | + if (node instanceof FolderImpl) | |
155 | + { | |
156 | + ((FolderImpl) node).resetAll(false); | |
157 | + } | |
158 | + } | |
159 | + }, true); | |
160 | + | |
161 | + // setup remote path cache listener | |
162 | + pathCache.addEventListener(new JetspeedCacheEventListener() | |
163 | + { | |
164 | + | |
165 | + /* (non-Javadoc) | |
166 | + * @see org.apache.jetspeed.cache.JetspeedCacheEventListener#notifyElementAdded(org.apache.jetspeed.cache.JetspeedCache, boolean, java.lang.Object, java.lang.Object) | |
167 | + */ | |
168 | + public void notifyElementAdded(final JetspeedCache cache, | |
169 | + final boolean local, final Object key, final Object element) | |
170 | + { | |
171 | + } | |
172 | + | |
173 | + /* (non-Javadoc) | |
174 | + * @see org.apache.jetspeed.cache.JetspeedCacheEventListener#notifyElementChanged(org.apache.jetspeed.cache.JetspeedCache, boolean, java.lang.Object, java.lang.Object) | |
175 | + */ | |
176 | + public void notifyElementChanged(final JetspeedCache cache, | |
177 | + final boolean local, final Object key, final Object element) | |
178 | + { | |
179 | + } | |
180 | + | |
181 | + /* (non-Javadoc) | |
182 | + * @see org.apache.jetspeed.cache.JetspeedCacheEventListener#notifyElementEvicted(org.apache.jetspeed.cache.JetspeedCache, boolean, java.lang.Object, java.lang.Object) | |
183 | + */ | |
184 | + public void notifyElementEvicted(final JetspeedCache cache, | |
185 | + final boolean local, final Object key, final Object element) | |
186 | + { | |
187 | + } | |
188 | + | |
189 | + /* (non-Javadoc) | |
190 | + * @see org.apache.jetspeed.cache.JetspeedCacheEventListener#notifyElementExpired(org.apache.jetspeed.cache.JetspeedCache, boolean, java.lang.Object, java.lang.Object) | |
191 | + */ | |
192 | + public void notifyElementExpired(final JetspeedCache cache, | |
193 | + final boolean local, final Object key, final Object element) | |
194 | + { | |
195 | + } | |
196 | + | |
197 | + /* (non-Javadoc) | |
198 | + * @see org.apache.jetspeed.cache.JetspeedCacheEventListener#notifyElementRemoved(org.apache.jetspeed.cache.JetspeedCache, boolean, java.lang.Object, java.lang.Object) | |
199 | + */ | |
200 | + public void notifyElementRemoved(final JetspeedCache cache, | |
201 | + final boolean local, final Object key, final Object element) | |
202 | + { | |
203 | + final DatabasePageManagerCacheObject cacheObject = (DatabasePageManagerCacheObject) element; | |
204 | + // remove cache object from local oid cache | |
205 | + if (cacheObject != null) | |
206 | + { | |
207 | + final Identity oid = cacheObject.getId(); | |
208 | + final String path = cacheObject.getPath(); | |
209 | + if ((oid != null) || (path != null)) | |
210 | + { | |
211 | + synchronized (DatabasePageManagerCache.class) | |
212 | + { | |
213 | + if (oid != null) | |
214 | + { | |
215 | + // get object cached by oid | |
216 | + final NodeImpl node = (NodeImpl) cacheLookup(oid); | |
217 | + // reset internal FolderImpl caches | |
218 | + if (node instanceof FolderImpl) | |
219 | + { | |
220 | + ((FolderImpl) node).resetAll(false); | |
221 | + } | |
222 | + // remove from cache | |
223 | + oidCache.removeQuiet(oid); | |
224 | + } | |
225 | + if (path != null) | |
226 | + { | |
227 | + // lookup parent object cached by path and oid | |
228 | + final int pathLastSeparatorIndex = path | |
229 | + .lastIndexOf(Folder.PATH_SEPARATOR); | |
230 | + final String parentPath = ((pathLastSeparatorIndex > 0) ? path | |
231 | + .substring(0, pathLastSeparatorIndex) | |
232 | + : Folder.PATH_SEPARATOR); | |
233 | + final NodeImpl parentNode = cacheLookup(parentPath); | |
234 | + // reset internal FolderImpl caches in case element removed | |
235 | + if (parentNode instanceof FolderImpl) | |
236 | + { | |
237 | + ((FolderImpl) parentNode).resetAll(false); | |
238 | + } | |
239 | + // remove from cache | |
240 | + pathCache.removeQuiet(path); | |
241 | + } | |
242 | + } | |
243 | + } | |
244 | + } | |
245 | + } | |
246 | + }, false); | |
79 | 247 | } |
80 | 248 | |
81 | 249 | /** |
82 | - * setPageManagerProxy | |
250 | + * Override page manager specified during create with proxy. | |
83 | 251 | * |
84 | 252 | * @param proxy |
85 | 253 | * proxied page manager interface used to inject into Folder |
@@ -99,94 +267,86 @@ | ||
99 | 267 | /** |
100 | 268 | * cacheLookup |
101 | 269 | * |
102 | - * Lookup node instances by unique path. | |
270 | + * Lookup object instances by unique path. | |
103 | 271 | * |
104 | 272 | * @param path |
105 | 273 | * node unique path |
106 | 274 | * @return cached node |
107 | 275 | */ |
108 | - public synchronized static NodeImpl cacheLookup(String path) | |
276 | + public synchronized static NodeImpl cacheLookup(final String path) | |
109 | 277 | { |
110 | 278 | if (path != null) |
111 | 279 | { |
112 | - // return valid object cached by path | |
113 | - return (NodeImpl) cacheValidateEntry((Entry) cacheByPath.get(path)); | |
280 | + // return valid object cached by path and oid | |
281 | + final CacheElement pathElement = pathCache.get(path); | |
282 | + if (pathElement != null) | |
283 | + { | |
284 | + final DatabasePageManagerCacheObject cacheObject = (DatabasePageManagerCacheObject) pathElement | |
285 | + .getContent(); | |
286 | + final NodeImpl node = (NodeImpl) cacheLookup(cacheObject | |
287 | + .getId()); | |
288 | + return node; | |
289 | + } | |
290 | + | |
114 | 291 | } |
115 | 292 | return null; |
116 | 293 | } |
117 | 294 | |
118 | 295 | /** |
119 | - * cacheAdd | |
120 | - * | |
121 | - * Add object to cache and cache node instances by unique path; infuse nodes | |
296 | + * Add object to cache and cache instances by unique path; | |
122 | 297 | * loaded by OJB with page manager configuration. |
123 | 298 | * |
124 | 299 | * @param oid |
125 | - * object/node indentity | |
300 | + * object/node identity | |
126 | 301 | * @param obj |
127 | 302 | * object/node to cache |
128 | 303 | */ |
129 | - public synchronized static void cacheAdd(Identity oid, Object obj) | |
304 | + public synchronized static void cacheAdd(final Identity oid, | |
305 | + final Object obj) | |
130 | 306 | { |
131 | - Entry entry = (Entry) cacheByOID.get(oid); | |
132 | - if (entry != null) | |
307 | + if (obj instanceof NodeImpl) | |
133 | 308 | { |
134 | - // update cache LRU order | |
135 | - cacheLRUList.remove(entry); | |
136 | - cacheLRUList.addFirst(entry); | |
137 | - // refresh cache entry | |
138 | - entry.touch(); | |
309 | + final NodeImpl node = (NodeImpl) obj; | |
310 | + final String nodePath = node.getPath(); | |
311 | + | |
312 | + // add node to caches | |
313 | + oidCache.remove(oid); | |
314 | + final CacheElement element = oidCache.createElement(oid, node); | |
315 | + oidCache.put(element); | |
316 | + pathCache.remove(nodePath); | |
317 | + final CacheElement pathElement = pathCache.createElement(nodePath, | |
318 | + new DatabasePageManagerCacheObject(oid, nodePath)); | |
319 | + pathCache.put(pathElement); | |
139 | 320 | } |
140 | - else | |
141 | - { | |
142 | - // create new cache entry and map | |
143 | - entry = new Entry(obj, oid); | |
144 | - cacheByOID.put(oid, entry); | |
145 | - cacheLRUList.addFirst(entry); | |
146 | - // infuse node with page manager configuration | |
147 | - // or the page manager itself and add to the | |
148 | - // paths cache | |
149 | - if (obj instanceof NodeImpl) | |
150 | - { | |
151 | - NodeImpl node = (NodeImpl) obj; | |
152 | - node.setConstraintsEnabled(constraintsEnabled); | |
153 | - node.setPermissionsEnabled(permissionsEnabled); | |
154 | - cacheByPath.put(node.getPath(), entry); | |
155 | - if (obj instanceof FolderImpl) | |
156 | - { | |
157 | - ((FolderImpl) obj).setPageManager(pageManager); | |
158 | - } | |
159 | - } | |
160 | - // trim cache as required to maintain cache size | |
161 | - while (cacheLRUList.size() > cacheSize) | |
162 | - { | |
163 | - cacheRemoveEntry((Entry) cacheLRUList.getLast(), true); | |
164 | - } | |
165 | - } | |
166 | 321 | } |
167 | 322 | |
168 | 323 | /** |
169 | 324 | * cacheClear |
170 | 325 | * |
171 | - * Clear object and node caches. | |
326 | + * Clear object and path caches. | |
172 | 327 | */ |
173 | 328 | public synchronized static void cacheClear() |
174 | 329 | { |
175 | - // remove all cache entries | |
176 | - Iterator removeIter = cacheLRUList.iterator(); | |
177 | - while (removeIter.hasNext()) | |
330 | + // remove all items from oid cache individually | |
331 | + // to ensure notifications are run to detach | |
332 | + // elements; do not invoke oidCache.clear() | |
333 | + final Iterator removeOidIter = oidCache.getKeys().iterator(); | |
334 | + while (removeOidIter.hasNext()) | |
178 | 335 | { |
179 | - cacheRemoveEntry((Entry) removeIter.next(), false); | |
336 | + oidCache.remove((Identity) removeOidIter.next()); | |
180 | 337 | } |
181 | - // clear cache | |
182 | - cacheByOID.clear(); | |
183 | - cacheLRUList.clear(); | |
184 | - cacheByPath.clear(); | |
338 | + // remove all items from path cache individually | |
339 | + // to avoid potential distributed clear invocation | |
340 | + // that would be performed against all peers; do | |
341 | + // not invoke pathCache.clear() | |
342 | + final Iterator removePathIter = pathCache.getKeys().iterator(); | |
343 | + while (removePathIter.hasNext()) | |
344 | + { | |
345 | + pathCache.removeQuiet(removePathIter.next()); | |
346 | + } | |
185 | 347 | } |
186 | 348 | |
187 | 349 | /** |
188 | - * cacheLookup | |
189 | - * | |
190 | 350 | * Lookup objects by identity. |
191 | 351 | * |
192 | 352 | * @param oid |
@@ -193,199 +353,139 @@ | ||
193 | 353 | * object identity |
194 | 354 | * @return cached object |
195 | 355 | */ |
196 | - public synchronized static Object cacheLookup(Identity oid) | |
356 | + public synchronized static Object cacheLookup(final Identity oid) | |
197 | 357 | { |
198 | 358 | if (oid != null) |
199 | 359 | { |
200 | 360 | // return valid object cached by oid |
201 | - return cacheValidateEntry((Entry) cacheByOID.get(oid)); | |
361 | + final CacheElement element = oidCache.get(oid); | |
362 | + if (element != null) { return element.getContent(); } | |
363 | + | |
202 | 364 | } |
203 | 365 | return null; |
204 | 366 | } |
205 | 367 | |
206 | 368 | /** |
207 | - * cacheRemove | |
369 | + * Remove identified object from object and path caches. | |
208 | 370 | * |
209 | - * Remove identified object from object and node caches. | |
210 | - * | |
211 | 371 | * @param oid |
212 | 372 | * object identity |
213 | 373 | */ |
214 | - public synchronized static void cacheRemove(Identity oid) | |
374 | + public synchronized static void cacheRemove(final Identity oid) | |
215 | 375 | { |
216 | 376 | // remove from cache by oid |
217 | - cacheRemoveEntry((Entry) cacheByOID.get(oid), true); | |
377 | + if (oid != null) | |
378 | + { | |
379 | + final NodeImpl node = (NodeImpl) cacheLookup(oid); | |
380 | + if (node != null) | |
381 | + { | |
382 | + // remove from caches | |
383 | + oidCache.remove(oid); | |
384 | + pathCache.remove(node.getPath()); | |
385 | + } | |
386 | + } | |
218 | 387 | } |
219 | 388 | |
220 | 389 | /** |
221 | - * cacheRemove | |
390 | + * Remove identified object from object and path caches. | |
222 | 391 | * |
223 | - * Remove identified object from object and node caches. | |
224 | - * | |
225 | 392 | * @param path |
226 | 393 | * object path |
227 | 394 | */ |
228 | - public synchronized static void cacheRemove(String path) | |
395 | + public synchronized static void cacheRemove(final String path) | |
229 | 396 | { |
230 | 397 | // remove from cache by path |
231 | - cacheRemoveEntry((Entry) cacheByPath.get(path), true); | |
398 | + if (path != null) | |
399 | + { | |
400 | + final CacheElement pathElement = pathCache.get(path); | |
401 | + if (pathElement != null) | |
402 | + { | |
403 | + final DatabasePageManagerCacheObject cacheObject = (DatabasePageManagerCacheObject) pathElement | |
404 | + .getContent(); | |
405 | + // remove from caches | |
406 | + oidCache.remove(cacheObject.getId()); | |
407 | + pathCache.remove(path); | |
408 | + } | |
409 | + } | |
232 | 410 | } |
233 | 411 | |
234 | 412 | /** |
235 | - * cacheValidateEntry | |
236 | - * | |
237 | - * Validate specified entry from cache, returning cached object if valid. | |
238 | - * | |
239 | - * @param entry | |
240 | - * cache entry to validate | |
241 | - * @return validated object from cache | |
413 | + * Reset cached security constraints in all cached objects. | |
242 | 414 | */ |
243 | - private synchronized static Object cacheValidateEntry(Entry entry) | |
415 | + public synchronized static void resetCachedSecurityConstraints() | |
244 | 416 | { |
245 | - if (entry != null) | |
417 | + // reset cached objects | |
418 | + final Iterator resetIter = oidCache.getKeys().iterator(); | |
419 | + while (resetIter.hasNext()) | |
246 | 420 | { |
247 | - if (!entry.isExpired()) | |
248 | - { | |
249 | - // update cache LRU order | |
250 | - cacheLRUList.remove(entry); | |
251 | - cacheLRUList.addFirst(entry); | |
252 | - // refresh cache entry and return object | |
253 | - entry.touch(); | |
254 | - return entry.getObject(); | |
255 | - } | |
256 | - else | |
257 | - { | |
258 | - // remove expired entry | |
259 | - cacheRemoveEntry(entry, true); | |
260 | - } | |
421 | + final NodeImpl node = (NodeImpl) cacheLookup((Identity) resetIter | |
422 | + .next()); | |
423 | + node.resetCachedSecurityConstraints(); | |
261 | 424 | } |
262 | - return null; | |
263 | 425 | } |
264 | 426 | |
265 | 427 | /** |
266 | - * cacheRemoveEntry | |
428 | + * Get transactions registered on current thread | |
267 | 429 | * |
268 | - * Remove specified entry from cache. | |
269 | - * | |
270 | - * @param entry | |
271 | - * cache entry to remove | |
272 | - * @param remove | |
273 | - * enable removal from cache | |
430 | + * @return transactions list | |
274 | 431 | */ |
275 | - private synchronized static void cacheRemoveEntry(Entry entry, | |
276 | - boolean remove) | |
432 | + public static List getTransactions() | |
277 | 433 | { |
278 | - if (entry != null) | |
434 | + List operations = (List) transactionedOperations.get(); | |
435 | + if (operations == null) | |
279 | 436 | { |
280 | - Object removeObj = entry.getObject(); | |
281 | - if (remove) | |
282 | - { | |
283 | - // remove entry, optimize for removal from end | |
284 | - // of list as cache size is met or entries expire | |
285 | - if (cacheLRUList.getLast() == entry) | |
286 | - { | |
287 | - cacheLRUList.removeLast(); | |
288 | - } | |
289 | - else | |
290 | - { | |
291 | - int removeIndex = cacheLRUList.lastIndexOf(entry); | |
292 | - if (removeIndex > 0) | |
293 | - { | |
294 | - cacheLRUList.remove(removeIndex); | |
295 | - } | |
296 | - } | |
297 | - // unmap entry | |
298 | - cacheByOID.remove(entry.getOID()); | |
299 | - if (removeObj instanceof NodeImpl) | |
300 | - { | |
301 | - cacheByPath.remove(((NodeImpl) removeObj).getPath()); | |
302 | - } | |
303 | - } | |
304 | - // reset internal FolderImpl caches | |
305 | - if (removeObj instanceof FolderImpl) | |
306 | - { | |
307 | - ((FolderImpl) removeObj).resetAll(false); | |
308 | - } | |
437 | + operations = new LinkedList(); | |
438 | + transactionedOperations.set(operations); | |
309 | 439 | } |
440 | + return operations; | |
310 | 441 | } |
311 | 442 | |
312 | 443 | /** |
313 | - * resetCachedSecurityConstraints | |
444 | + * Register transactions with current thread | |
314 | 445 | * |
315 | - * Reset cached security constraints in all cached node objects. | |
446 | + * @param operation transaction operation | |
316 | 447 | */ |
317 | - public synchronized static void resetCachedSecurityConstraints() | |
448 | + public static void addTransaction(TransactionedOperation operation) | |
318 | 449 | { |
319 | - // reset cached objects | |
320 | - Iterator resetIter = cacheLRUList.iterator(); | |
321 | - while (resetIter.hasNext()) | |
322 | - { | |
323 | - Object obj = ((Entry) resetIter.next()).getObject(); | |
324 | - if (obj instanceof NodeImpl) | |
325 | - { | |
326 | - ((NodeImpl) obj).resetCachedSecurityConstraints(); | |
327 | - } | |
328 | - } | |
450 | + final List transactions = getTransactions(); | |
451 | + transactions.add(operation); | |
329 | 452 | } |
330 | 453 | |
331 | 454 | /** |
332 | - * Entry | |
333 | - * | |
334 | - * Cache entry class adding entry timestamp to track expiration | |
455 | + * Rollback transactions registered with current thread. | |
335 | 456 | */ |
336 | - private static class Entry | |
457 | + public synchronized static void rollbackTransactions() | |
337 | 458 | { |
338 | - | |
339 | - public long timestamp; | |
340 | - | |
341 | - public Object object; | |
342 | - | |
343 | - public Identity oid; | |
344 | - | |
345 | - public Entry(Object object, Identity oid) | |
459 | + final Iterator transactions = getTransactions().iterator(); | |
460 | + while (transactions.hasNext()) | |
346 | 461 | { |
347 | - touch(); | |
348 | - this.object = object; | |
349 | - this.oid = oid; | |
462 | + final TransactionedOperation operation = (TransactionedOperation) transactions | |
463 | + .next(); | |
464 | + cacheRemove(operation.getPath()); | |
350 | 465 | } |
466 | + } | |
351 | 467 | |
352 | - public boolean isExpired() | |
353 | - { | |
354 | - if (DatabasePageManagerCache.cacheExpiresSeconds > 0) | |
355 | - { | |
356 | - long now = System.currentTimeMillis(); | |
357 | - if (((now - timestamp) / 1000) < DatabasePageManagerCache.cacheExpiresSeconds) | |
358 | - { | |
359 | - timestamp = now; | |
360 | - return false; | |
361 | - } | |
362 | - return true; | |
363 | - } | |
364 | - return false; | |
365 | - } | |
468 | + /** | |
469 | + * Clear transactions registered with current thread. | |
470 | + */ | |
471 | + public synchronized static void clearTransactions() | |
472 | + { | |
473 | + transactionedOperations.set(null); | |
474 | + } | |
366 | 475 | |
367 | - public void touch() | |
368 | - { | |
369 | - if (DatabasePageManagerCache.cacheExpiresSeconds > 0) | |
370 | - { | |
371 | - timestamp = System.currentTimeMillis(); | |
372 | - } | |
373 | - } | |
476 | + /** | |
477 | + * Returns whether this cache is currently part of a distributed cache cluster. | |
478 | + * | |
479 | + * @return distributed flag | |
480 | + */ | |
481 | + public static boolean isDistributed() | |
482 | + { | |
483 | + return pathCache.isDistributed(); | |
484 | + } | |
374 | 485 | |
375 | - public Object getObject() | |
376 | - { | |
377 | - return object; | |
378 | - } | |
486 | + // OJB Constructor | |
379 | 487 | |
380 | - public Identity getOID() | |
381 | - { | |
382 | - return oid; | |
383 | - } | |
384 | - } | |
385 | - | |
386 | 488 | /** |
387 | - * DatabasePageManagerCache | |
388 | - * | |
389 | 489 | * Construct a cache instance using OJB compliant signatures. |
390 | 490 | * |
391 | 491 | * @param broker |
@@ -397,6 +497,8 @@ | ||
397 | 497 | { |
398 | 498 | } |
399 | 499 | |
500 | + // OJB ObjectCache Implementation | |
501 | + | |
400 | 502 | /* |
401 | 503 | * (non-Javadoc) |
402 | 504 | * |
@@ -443,61 +545,24 @@ | ||
443 | 545 | cacheRemove(oid); |
444 | 546 | } |
445 | 547 | |
548 | + // Utilities | |
549 | + | |
550 | + /** | |
551 | + * Dump cache paths and oids to standard out. | |
552 | + */ | |
553 | + | |
446 | 554 | public synchronized static void dump() |
447 | 555 | { |
448 | - System.out.println("--------------------------1"); | |
449 | - Iterator dumpIter = cacheLRUList.iterator(); | |
556 | + System.out.println("--------------------------"); | |
557 | + final Iterator dumpIter = oidCache.getKeys().iterator(); | |
450 | 558 | while (dumpIter.hasNext()) |
451 | 559 | { |
452 | - Entry entry = (Entry) dumpIter.next(); | |
453 | - Object entryObject = entry.getObject(); | |
454 | - if (entryObject instanceof NodeImpl) | |
455 | - { | |
456 | - System.out.println("entry = " | |
457 | - + ((NodeImpl) entryObject).getPath() + ", " | |
458 | - + entry.getOID()); | |
459 | - } | |
460 | - else | |
461 | - { | |
462 | - System.out.println("entry = <none>, " + entry.getOID()); | |
463 | - } | |
560 | + final Identity oid = (Identity) dumpIter.next(); | |
561 | + final NodeImpl node = (NodeImpl) cacheLookup(oid); | |
562 | + System.out.println("node=" + node.getPath() + ", oid=" + oid); | |
464 | 563 | } |
465 | - System.out.println("--------------------------2"); | |
466 | - } | |
467 | 564 | |
468 | - // TODO Findbugs | |
469 | - protected static ThreadLocal transactionedOperations = new ThreadLocal(); | |
470 | - | |
471 | - public static List getTransactions() | |
472 | - { | |
473 | - List operations = (List) transactionedOperations.get(); | |
474 | - if (operations == null) | |
475 | - { | |
476 | - operations = new LinkedList(); | |
477 | - transactionedOperations.set(operations); | |
478 | - } | |
479 | - | |
480 | - return operations; | |
565 | + System.out.println("--------------------------"); | |
481 | 566 | } |
482 | 567 | |
483 | - /** | |
484 | - * @param principal | |
485 | - * The principal to set. | |
486 | - */ | |
487 | - public static void addTransaction(TransactionedOperation operation) | |
488 | - { | |
489 | - List transactions = getTransactions(); | |
490 | - transactions.add(operation); | |
491 | - } | |
492 | - | |
493 | - public static void rollbackTransactions() | |
494 | - { | |
495 | - Iterator transactions = getTransactions().iterator(); | |
496 | - while (transactions.hasNext()) | |
497 | - { | |
498 | - TransactionedOperation operation = (TransactionedOperation) transactions | |
499 | - .next(); | |
500 | - cacheRemove(operation.getPath()); | |
501 | - } | |
502 | - } | |
503 | 568 | } |
@@ -0,0 +1,120 @@ | ||
1 | +/* | |
2 | + * Licensed to the Apache Software Foundation (ASF) under one or more | |
3 | + * contributor license agreements. See the NOTICE file distributed with | |
4 | + * this work for additional information regarding copyright ownership. | |
5 | + * The ASF licenses this file to You under the Apache License, Version 2.0 | |
6 | + * (the "License"); you may not use this file except in compliance with | |
7 | + * the License. You may obtain a copy of the License at | |
8 | + * | |
9 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + * | |
11 | + * Unless required by applicable law or agreed to in writing, software | |
12 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + * See the License for the specific language governing permissions and | |
15 | + * limitations under the License. | |
16 | + */ | |
17 | +package org.apache.jetspeed.page.impl; | |
18 | + | |
19 | +import org.apache.jetspeed.cache.CacheElement; | |
20 | +import org.apache.jetspeed.cache.DistributedCacheObject; | |
21 | +import org.apache.ojb.broker.Identity; | |
22 | + | |
23 | +/** | |
24 | + * DatabasePageManagerCacheObject | |
25 | + * | |
26 | + * @author <a href="mailto:rwatler@apache.org">Randy Watler</a> | |
27 | + * @version $Id: $ | |
28 | +*/ | |
29 | +public class DatabasePageManagerCacheObject implements DistributedCacheObject | |
30 | +{ | |
31 | + | |
32 | + private static final long serialVersionUID = 3575475610695136850L; | |
33 | + | |
34 | + // Members | |
35 | + | |
36 | + private Identity id = null; | |
37 | + | |
38 | + private String path = null; | |
39 | + | |
40 | + // Constructor | |
41 | + | |
42 | + /** | |
43 | + * Construct new cache object with id and path | |
44 | + * | |
45 | + * @param id | |
46 | + * @param path | |
47 | + */ | |
48 | + public DatabasePageManagerCacheObject(final Identity id, final String path) | |
49 | + { | |
50 | + this.path = path; | |
51 | + this.id = id; | |
52 | + } | |
53 | + | |
54 | + /** | |
55 | + * Serialization constructor | |
56 | + */ | |
57 | + public DatabasePageManagerCacheObject() | |
58 | + { | |
59 | + } | |
60 | + | |
61 | + // Implementation | |
62 | + | |
63 | + /* (non-Javadoc) | |
64 | + * @see org.apache.jetspeed.cache.DistributedCacheObject#notifyChange(int) | |
65 | + */ | |
66 | + public void notifyChange(int action) | |
67 | + { | |
68 | + switch (action) | |
69 | + { | |
70 | + case CacheElement.ActionAdded: | |
71 | + case CacheElement.ActionChanged: | |
72 | + case CacheElement.ActionRemoved: | |
73 | + case CacheElement.ActionEvicted: | |
74 | + case CacheElement.ActionExpired: | |
75 | + break; | |
76 | + default: | |
77 | + return; | |
78 | + } | |
79 | + return; | |
80 | + } | |
81 | + | |
82 | + /* (non-Javadoc) | |
83 | + * @see java.lang.Object#equals(java.lang.Object) | |
84 | + */ | |
85 | + public boolean equals(Object obj) | |
86 | + { | |
87 | + if ((obj != null) && (obj instanceof DatabasePageManagerCacheObject)) | |
88 | + { | |
89 | + final DatabasePageManagerCacheObject other = (DatabasePageManagerCacheObject) obj; | |
90 | + return getPath().equals(other.getPath()); | |
91 | + } | |
92 | + return false; | |
93 | + } | |
94 | + | |
95 | + /* (non-Javadoc) | |
96 | + * @see java.lang.Object#hashCode() | |
97 | + */ | |
98 | + public int hashCode() | |
99 | + { | |
100 | + return getPath().hashCode(); | |
101 | + } | |
102 | + | |
103 | + // Data access | |
104 | + | |
105 | + /** | |
106 | + * @return wrapper id | |
107 | + */ | |
108 | + public Identity getId() | |
109 | + { | |
110 | + return id; | |
111 | + } | |
112 | + | |
113 | + /** | |
114 | + * @return wrapper path | |
115 | + */ | |
116 | + public String getPath() | |
117 | + { | |
118 | + return path; | |
119 | + } | |
120 | +} |
@@ -28,6 +28,7 @@ | ||
28 | 28 | import jp.sf.pal.portal.logging.LogFactory; |
29 | 29 | |
30 | 30 | import org.apache.jetspeed.JetspeedActions; |
31 | +import org.apache.jetspeed.cache.JetspeedCache; | |
31 | 32 | import org.apache.jetspeed.components.dao.InitablePersistenceBrokerDaoSupport; |
32 | 33 | import org.apache.jetspeed.om.common.SecurityConstraint; |
33 | 34 | import org.apache.jetspeed.om.common.SecurityConstraints; |
@@ -105,12 +106,6 @@ | ||
105 | 106 | implements PageManager |
106 | 107 | { |
107 | 108 | |
108 | - private static final int DEFAULT_CACHE_SIZE = 128; | |
109 | - | |
110 | - private static final int MIN_CACHE_EXPIRES_SECONDS = 30; | |
111 | - | |
112 | - private static final int DEFAULT_CACHE_EXPIRES_SECONDS = 150; | |
113 | - | |
114 | 109 | private static Map modelClasses = new HashMap(); |
115 | 110 | static |
116 | 111 | { |
@@ -159,60 +154,22 @@ | ||
159 | 154 | |
160 | 155 | private DelegatingPageManager delegator; |
161 | 156 | |
162 | - private int cacheSize; | |
163 | - | |
164 | - private int cacheExpiresSeconds; | |
165 | - | |
166 | 157 | private PageManager pageManagerProxy; |
167 | 158 | |
168 | 159 | protected static final Log log = LogFactory |
169 | 160 | .getLog(DatabasePageManager.class); |
170 | 161 | |
171 | - public DatabasePageManager(String repositoryPath, int cacheSize, | |
172 | - int cacheExpiresSeconds, boolean isPermissionsSecurity, | |
173 | - boolean isConstraintsSecurity) | |
162 | + public DatabasePageManager(String repositoryPath, | |
163 | + boolean isPermissionsSecurity, boolean isConstraintsSecurity, | |
164 | + JetspeedCache oidCache, JetspeedCache pathCache) | |
174 | 165 | { |
175 | 166 | super(repositoryPath); |
176 | 167 | delegator = new DelegatingPageManager(isPermissionsSecurity, |
177 | 168 | isConstraintsSecurity, modelClasses); |
178 | - this.cacheSize = Math.max(cacheSize, DEFAULT_CACHE_SIZE); | |
179 | - if (cacheExpiresSeconds < 0) | |
180 | - { | |
181 | - this.cacheExpiresSeconds = DEFAULT_CACHE_EXPIRES_SECONDS; | |
182 | - } | |
183 | - else if (cacheExpiresSeconds == 0) | |
184 | - { | |
185 | - this.cacheExpiresSeconds = 0; | |
186 | - } | |
187 | - else | |
188 | - { | |
189 | - this.cacheExpiresSeconds = Math.max(cacheExpiresSeconds, | |
190 | - MIN_CACHE_EXPIRES_SECONDS); | |
191 | - } | |
192 | - DatabasePageManagerCache.cacheInit(this); | |
169 | + DatabasePageManagerCache.cacheInit(oidCache, pathCache, this); | |
193 | 170 | } |
194 | 171 | |
195 | 172 | /** |
196 | - * getCacheSize | |
197 | - * | |
198 | - * @return configured cache size | |
199 | - */ | |
200 | - public int getCacheSize() | |
201 | - { | |
202 | - return cacheSize; | |
203 | - } | |
204 | - | |
205 | - /** | |
206 | - * getCacheExpiresSeconds | |
207 | - * | |
208 | - * @return configured cache expiration in seconds | |
209 | - */ | |
210 | - public int getCacheExpiresSeconds() | |
211 | - { | |
212 | - return cacheExpiresSeconds; | |
213 | - } | |
214 | - | |
215 | - /** | |
216 | 173 | * getPageManagerProxy |
217 | 174 | * |
218 | 175 | * @return proxied page manager interface used to inject into Folder |
@@ -2246,4 +2203,11 @@ | ||
2246 | 2203 | return pages.length; |
2247 | 2204 | } |
2248 | 2205 | |
2206 | + /* (non-Javadoc) | |
2207 | + * @see org.apache.jetspeed.page.PageManager#isDistributed() | |
2208 | + */ | |
2209 | + public boolean isDistributed() | |
2210 | + { | |
2211 | + return DatabasePageManagerCache.isDistributed(); | |
2212 | + } | |
2249 | 2213 | } |
@@ -881,6 +881,14 @@ | ||
881 | 881 | // nothing to shutdown by default |
882 | 882 | } |
883 | 883 | |
884 | + /* (non-Javadoc) | |
885 | + * @see org.apache.jetspeed.page.PageManager#isDistributed() | |
886 | + */ | |
887 | + public boolean isDistributed() | |
888 | + { | |
889 | + return false; | |
890 | + } | |
891 | + | |
884 | 892 | /** |
885 | 893 | * notifyNewNode - notify page manager event listeners of new node event |
886 | 894 | * |
@@ -46,6 +46,11 @@ | ||
46 | 46 | DatabasePageManagerCache.rollbackTransactions(); |
47 | 47 | throw exp; |
48 | 48 | } |
49 | + finally | |
50 | + { | |
51 | + DatabasePageManagerCache.clearTransactions(); | |
52 | + } | |
53 | + | |
49 | 54 | } |
50 | 55 | |
51 | 56 | } |
@@ -25,6 +25,7 @@ | ||
25 | 25 | import net.sf.ehcache.Cache; |
26 | 26 | import net.sf.ehcache.CacheManager; |
27 | 27 | |
28 | +import org.apache.jetspeed.cache.impl.EhCacheConfigResource; | |
28 | 29 | import org.apache.jetspeed.cache.impl.EhDecorationContentCacheImpl; |
29 | 30 | import org.apache.jetspeed.cache.impl.JetspeedCacheKeyGenerator; |
30 | 31 | import org.apache.jetspeed.mockobjects.request.MockRequestContext; |
@@ -51,6 +52,8 @@ | ||
51 | 52 | public void testContentCacheByUser() throws Exception |
52 | 53 | { |
53 | 54 | // initialize ehCache |
55 | + EhCacheConfigResource.getInstance( | |
56 | + EhCacheConfigResource.EHCACHE_CONFIG_RESOURCE_DEFAULT, true); | |
54 | 57 | CacheManager cacheManager = new CacheManager(); |
55 | 58 | Cache ehContentCache = new Cache("ehDecorationContentCache", 10000, |
56 | 59 | false, false, 28800, 28800); |
@@ -146,6 +149,8 @@ | ||
146 | 149 | public void testContentCacheBySession() throws Exception |
147 | 150 | { |
148 | 151 | // initialize ehCache |
152 | + EhCacheConfigResource.getInstance( | |
153 | + EhCacheConfigResource.EHCACHE_CONFIG_RESOURCE_DEFAULT, true); | |
149 | 154 | CacheManager cacheManager = new CacheManager(); |
150 | 155 | Cache ehContentCache = new Cache("ehDecorationContentCache", 10000, |
151 | 156 | false, false, 28800, 28800); |
@@ -26,6 +26,7 @@ | ||
26 | 26 | import net.sf.ehcache.CacheManager; |
27 | 27 | |
28 | 28 | import org.apache.jetspeed.aggregator.PortletContent; |
29 | +import org.apache.jetspeed.cache.impl.EhCacheConfigResource; | |
29 | 30 | import org.apache.jetspeed.cache.impl.EhPortletContentCacheImpl; |
30 | 31 | import org.apache.jetspeed.cache.impl.JetspeedCacheKeyGenerator; |
31 | 32 | import org.apache.jetspeed.mockobjects.request.MockRequestContext; |
@@ -52,6 +53,8 @@ | ||
52 | 53 | public void testContentCacheByUser() throws Exception |
53 | 54 | { |
54 | 55 | // initialize ehCache |
56 | + EhCacheConfigResource.getInstance( | |
57 | + EhCacheConfigResource.EHCACHE_CONFIG_RESOURCE_DEFAULT, true); | |
55 | 58 | CacheManager cacheManager = new CacheManager(); |
56 | 59 | Cache ehContentCache = new Cache("ehPortletContentCache", 10000, false, |
57 | 60 | false, 28800, 28800); |
@@ -151,6 +154,8 @@ | ||
151 | 154 | public void testContentCacheBySession() throws Exception |
152 | 155 | { |
153 | 156 | // initialize ehCache |
157 | + EhCacheConfigResource.getInstance( | |
158 | + EhCacheConfigResource.EHCACHE_CONFIG_RESOURCE_DEFAULT, true); | |
154 | 159 | CacheManager cacheManager = new CacheManager(); |
155 | 160 | Cache ehContentCache = new Cache("ehPortletContentCache", 10000, false, |
156 | 161 | false, 28800, 28800); |
@@ -23,8 +23,10 @@ | ||
23 | 23 | |
24 | 24 | import jp.sf.pal.portal.logging.Log; |
25 | 25 | import jp.sf.pal.portal.logging.LogFactory; |
26 | +import net.sf.ehcache.CacheException; | |
26 | 27 | import net.sf.ehcache.Ehcache; |
27 | 28 | import net.sf.ehcache.Element; |
29 | +import net.sf.ehcache.distribution.CacheManagerPeerProvider; | |
28 | 30 | import net.sf.ehcache.event.CacheEventListener; |
29 | 31 | |
30 | 32 | import org.apache.jetspeed.cache.CacheElement; |
@@ -78,12 +80,17 @@ | ||
78 | 80 | |
79 | 81 | public CacheElement createElement(Object key, Object content) |
80 | 82 | { |
81 | - if (!((key instanceof Serializable) || !(content instanceof Serializable))) | |
82 | - throw new IllegalArgumentException( | |
83 | - "The cache key and the object to cache must be serializable."); // return | |
84 | - // null; | |
85 | - return new EhCacheElementImpl((Serializable) key, | |
86 | - (Serializable) content); | |
83 | + if (!(key instanceof Serializable)) { throw new IllegalArgumentException( | |
84 | + "The cache key must be serializable."); } | |
85 | + if (content instanceof Serializable) | |
86 | + { | |
87 | + return new EhCacheElementImpl((Serializable) key, | |
88 | + (Serializable) content); | |
89 | + } | |
90 | + else | |
91 | + { | |
92 | + return new EhCacheElementImpl((Serializable) key, content); | |
93 | + } | |
87 | 94 | } |
88 | 95 | |
89 | 96 | public boolean remove(Object key) |
@@ -194,6 +201,22 @@ | ||
194 | 201 | return ehcache.getKeys(); |
195 | 202 | } |
196 | 203 | |
204 | + public boolean isDistributed() | |
205 | + { | |
206 | + // check if cache part of a distributed cluster | |
207 | + try | |
208 | + { | |
209 | + CacheManagerPeerProvider peerProvider = ehcache.getCacheManager() | |
210 | + .getCachePeerProvider(); | |
211 | + return ((peerProvider != null) && (peerProvider | |
212 | + .listRemoteCachePeers(ehcache).size() > 0)); | |
213 | + } | |
214 | + catch (CacheException ce) | |
215 | + { | |
216 | + } | |
217 | + return false; | |
218 | + } | |
219 | + | |
197 | 220 | // ------------------------------------------------------ |
198 | 221 | |
199 | 222 | public Object clone() throws CloneNotSupportedException |
@@ -51,6 +51,8 @@ | ||
51 | 51 | |
52 | 52 | private Map refList = Collections.synchronizedMap(new HashMap()); |
53 | 53 | |
54 | + private boolean removeAllLocal = false; | |
55 | + | |
54 | 56 | public EhCacheDistributedImpl(Ehcache ehcache) |
55 | 57 | { |
56 | 58 | super(ehcache); |
@@ -94,6 +96,11 @@ | ||
94 | 96 | |
95 | 97 | public CacheElement createElement(Object key, Object content) |
96 | 98 | { |
99 | + if (!(key instanceof Serializable)) { throw new IllegalArgumentException( | |
100 | + "The cache key must be serializable."); } | |
101 | + if (!(content instanceof DistributedCacheObject)) { throw new IllegalArgumentException( | |
102 | + "The cache content must be a distributed cache object."); } | |
103 | + | |
97 | 104 | return new EhCacheDistributedElementImpl((Serializable) key, |
98 | 105 | (DistributedCacheObject) content); |
99 | 106 | } |
@@ -131,7 +138,13 @@ | ||
131 | 138 | |
132 | 139 | public void clear() |
133 | 140 | { |
134 | - super.clear(); | |
141 | + // invoke removeAll with local flag set | |
142 | + synchronized (refList) | |
143 | + { | |
144 | + removeAllLocal = true; | |
145 | + super.clear(); | |
146 | + removeAllLocal = false; | |
147 | + } | |
135 | 148 | notifyListeners(true, CacheElement.ActionRemoved, null, null); |
136 | 149 | } |
137 | 150 |
@@ -306,16 +319,23 @@ | ||
306 | 319 | } |
307 | 320 | try |
308 | 321 | { |
309 | - Iterator it = refList.entrySet().iterator(); | |
310 | - while (it.hasNext()) | |
322 | + // synchronize on refList to ensure exclusive | |
323 | + // operation on refList and removeAllLocal flag | |
324 | + synchronized (refList) | |
311 | 325 | { |
312 | - EhCacheDistributedElementImpl e = (EhCacheDistributedElementImpl) it | |
313 | - .next(); | |
314 | - notifyListeners(false, CacheElement.ActionRemoved, e.getKey(), | |
315 | - e); | |
316 | - e.notifyChange(CacheElement.ActionRemoved); | |
326 | + // notify all listeners of element removal | |
327 | + // and each element of its removal | |
328 | + Iterator it = refList.values().iterator(); | |
329 | + while (it.hasNext()) | |
330 | + { | |
331 | + EhCacheDistributedElementImpl e = (EhCacheDistributedElementImpl) it | |
332 | + .next(); | |
333 | + notifyListeners(removeAllLocal, CacheElement.ActionRemoved, | |
334 | + e.getKey(), e.getContent()); | |
335 | + e.notifyChange(CacheElement.ActionRemoved); | |
336 | + } | |
337 | + refList.clear(); | |
317 | 338 | } |
318 | - refList.clear(); | |
319 | 339 | } |
320 | 340 | catch (Exception e) |
321 | 341 | { |
@@ -0,0 +1,400 @@ | ||
1 | +/* | |
2 | + * Licensed to the Apache Software Foundation (ASF) under one or more | |
3 | + * contributor license agreements. See the NOTICE file distributed with | |
4 | + * this work for additional information regarding copyright ownership. | |
5 | + * The ASF licenses this file to You under the Apache License, Version 2.0 | |
6 | + * (the "License"); you may not use this file except in compliance with | |
7 | + * the License. You may obtain a copy of the License at | |
8 | + * | |
9 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + * | |
11 | + * Unless required by applicable law or agreed to in writing, software | |
12 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + * See the License for the specific language governing permissions and | |
15 | + * limitations under the License. | |
16 | + */ | |
17 | +package org.apache.jetspeed.cache.impl; | |
18 | + | |
19 | +import java.io.File; | |
20 | +import java.io.IOException; | |
21 | +import java.io.InputStream; | |
22 | +import java.net.URL; | |
23 | + | |
24 | +import org.apache.commons.configuration.PropertiesConfiguration; | |
25 | +import org.apache.commons.logging.Log; | |
26 | +import org.apache.commons.logging.LogFactory; | |
27 | +import org.springframework.beans.factory.InitializingBean; | |
28 | +import org.springframework.core.io.AbstractResource; | |
29 | +import org.springframework.core.io.ClassPathResource; | |
30 | +import org.springframework.core.io.Resource; | |
31 | + | |
32 | +/** | |
33 | + * EhCacheConfigResource | |
34 | + * | |
35 | + * @author <a href="mailto:rwatler@apache.org">Randy Watler</a> | |
36 | + * @version $Id: $ | |
37 | + */ | |
38 | +public class EhCacheConfigResource extends AbstractResource implements | |
39 | + InitializingBean | |
40 | +{ | |
41 | + | |
42 | + protected static Log log = LogFactory.getLog(EhCacheConfigResource.class); | |
43 | + | |
44 | + // Constants | |
45 | + | |
46 | + public static final String EHCACHE_CONFIG_RESOURCE_PROP_NAME = "org.apache.jetspeed.ehcache.config.resource"; | |
47 | + | |
48 | + public static final String EHCACHE_CONFIG_RESOURCE_DEFAULT = "ehcache.xml"; | |
49 | + | |
50 | + public static final String EHCACHE_CONFIG_RESOURCE_DISTRIBUTED_CACHE = "distributed-ehcache.xml"; | |
51 | + | |
52 | + public static final String EHCACHE_GROUP_ADDRESS_PROP_NAME = "org.apache.jetspeed.ehcache.group.address"; | |
53 | + | |
54 | + public static final String EHCACHE_GROUP_ADDRESS_DEFAULT = "230.0.0.1"; | |
55 | + | |
56 | + public static final String EHCACHE_GROUP_PORT_PROP_NAME = "org.apache.jetspeed.ehcache.group.port"; | |
57 | + | |
58 | + public static final String EHCACHE_GROUP_PORT_DEFAULT = "4446"; | |
59 | + | |
60 | + public static final String EHCACHE_GROUP_TTL_PROP_NAME = "org.apache.jetspeed.ehcache.group.ttl"; | |
61 | + | |
62 | + public static final String EHCACHE_GROUP_TTL_DEFAULT = "1"; | |
63 | + | |
64 | + public static final String EHCACHE_GROUP_TTL_TEST_DEFAULT = "0"; | |
65 | + | |
66 | + public static final String EHCACHE_HOSTNAME_PROP_NAME = "org.apache.jetspeed.ehcache.hostname"; | |
67 | + | |
68 | + public static final String EHCACHE_HOSTNAME_DEFAULT = ""; | |
69 | + | |
70 | + public static final String EHCACHE_HOSTNAME_TEST_DEFAULT = "localhost"; | |
71 | + | |
72 | + public static final String EHCACHE_PORT_PROP_NAME = "org.apache.jetspeed.ehcache.port"; | |
73 | + | |
74 | + public static final String EHCACHE_PORT_DEFAULT = "40001"; | |
75 | + | |
76 | + public static final String EHCACHE_PAGE_MANAGER_MAX_ELEMENTS_LEGACY_PROP_NAME = "db.page.manager.cache.size"; | |
77 | + | |
78 | + public static final String EHCACHE_PAGE_MANAGER_MAX_ELEMENTS_PROP_NAME = "org.apache.jetspeed.ehcache.pagemanager.maxelements"; | |
79 | + | |
80 | + public static final String EHCACHE_PAGE_MANAGER_MAX_ELEMENTS_DEFAULT = "128"; | |
81 | + | |
82 | + public static final String EHCACHE_PAGE_MANAGER_ELEMENT_TTL_LEGACY_PROP_NAME = "db.page.manager.cache.expire"; | |
83 | + | |
84 | + public static final String EHCACHE_PAGE_MANAGER_ELEMENT_TTL_PROP_NAME = "org.apache.jetspeed.ehcache.pagemanager.element.ttl"; | |
85 | + | |
86 | + public static final String EHCACHE_PAGE_MANAGER_ELEMENT_TTL_DEFAULT = "150"; | |
87 | + | |
88 | + // Singleton implementation | |
89 | + | |
90 | + private static EhCacheConfigResource instance; | |
91 | + | |
92 | + public static EhCacheConfigResource getInstance( | |
93 | + final String defaultConfigResource, final boolean test) | |
94 | + { | |
95 | + // construct and return a default instance | |
96 | + if (instance == null) | |
97 | + { | |
98 | + instance = new EhCacheConfigResource(); | |
99 | + instance.setDefaultConfigResource(defaultConfigResource); | |
100 | + instance.setTest(test); | |
101 | + instance.afterPropertiesSet(); | |
102 | + } | |
103 | + return instance; | |
104 | + } | |
105 | + | |
106 | + // Members | |
107 | + | |
108 | + private PropertiesConfiguration configuration; | |
109 | + | |
110 | + private String defaultConfigResource; | |
111 | + | |
112 | + private boolean test; | |
113 | + | |
114 | + private String defaultGroupAddress; | |
115 | + | |
116 | + private String defaultGroupPort; | |
117 | + | |
118 | + private String defaultGroupTTL; | |
119 | + | |
120 | + private String defaultHostname; | |
121 | + | |
122 | + private String defaultPort; | |
123 | + | |
124 | + private String defaultPageManagerMaxElements; | |
125 | + | |
126 | + private String defaultPageManagerElementTTL; | |
127 | + | |
128 | + private ClassPathResource classPathResource; | |
129 | + | |
130 | + // InitializingBean implementation | |
131 | + | |
132 | + /* (non-Javadoc) | |
133 | + * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() | |
134 | + */ | |
135 | + public void afterPropertiesSet() | |
136 | + { | |
137 | + // copy specified configuration settings | |
138 | + if (configuration != null) | |
139 | + { | |
140 | + if (configuration.getString(EHCACHE_CONFIG_RESOURCE_PROP_NAME) != null) | |
141 | + { | |
142 | + defaultConfigResource = configuration | |
143 | + .getString(EHCACHE_CONFIG_RESOURCE_PROP_NAME); | |
144 | + } | |
145 | + if (configuration.getString(EHCACHE_GROUP_ADDRESS_PROP_NAME) != null) | |
146 | + { | |
147 | + defaultGroupAddress = configuration | |
148 | + .getString(EHCACHE_GROUP_ADDRESS_PROP_NAME); | |
149 | + } | |
150 | + if (configuration.getString(EHCACHE_GROUP_PORT_PROP_NAME) != null) | |
151 | + { | |
152 | + defaultGroupPort = configuration | |
153 | + .getString(EHCACHE_GROUP_PORT_PROP_NAME); | |
154 | + } | |
155 | + if (configuration.getString(EHCACHE_GROUP_TTL_PROP_NAME) != null) | |
156 | + { | |
157 | + defaultGroupTTL = configuration | |
158 | + .getString(EHCACHE_GROUP_TTL_PROP_NAME); | |
159 | + } | |
160 | + if (configuration.getString(EHCACHE_HOSTNAME_PROP_NAME) != null) | |
161 | + { | |
162 | + defaultHostname = configuration | |
163 | + .getString(EHCACHE_HOSTNAME_PROP_NAME); | |
164 | + } | |
165 | + if (configuration.getString(EHCACHE_PORT_PROP_NAME) != null) | |
166 | + { | |
167 | + defaultPort = configuration.getString(EHCACHE_PORT_PROP_NAME); | |
168 | + } | |
169 | + if (configuration | |
170 | + .getString(EHCACHE_PAGE_MANAGER_MAX_ELEMENTS_PROP_NAME) != null) | |
171 | + { | |
172 | + defaultPageManagerMaxElements = configuration | |
173 | + .getString(EHCACHE_PAGE_MANAGER_MAX_ELEMENTS_PROP_NAME); | |
174 | + } | |
175 | + if (configuration | |
176 | + .getString(EHCACHE_PAGE_MANAGER_ELEMENT_TTL_PROP_NAME) != null) | |
177 | + { | |
178 | + defaultPageManagerElementTTL = configuration | |
179 | + .getString(EHCACHE_PAGE_MANAGER_ELEMENT_TTL_PROP_NAME); | |
180 | + } | |
181 | + } | |
182 | + | |
183 | + // set system properties used in global cache configuration | |
184 | + if (System.getProperty(EHCACHE_CONFIG_RESOURCE_PROP_NAME) == null) | |
185 | + { | |
186 | + System.setProperty(EHCACHE_CONFIG_RESOURCE_PROP_NAME, | |
187 | + ((defaultConfigResource != null) ? defaultConfigResource | |
188 | + : EHCACHE_CONFIG_RESOURCE_DEFAULT)); | |
189 | + } | |
190 | + if (System.getProperty(EHCACHE_GROUP_ADDRESS_PROP_NAME) == null) | |
191 | + { | |
192 | + System.setProperty(EHCACHE_GROUP_ADDRESS_PROP_NAME, | |
193 | + ((defaultGroupAddress != null) ? defaultGroupAddress | |
194 | + : EHCACHE_GROUP_ADDRESS_DEFAULT)); | |
195 | + } | |
196 | + if (System.getProperty(EHCACHE_GROUP_PORT_PROP_NAME) == null) | |
197 | + { | |
198 | + System.setProperty(EHCACHE_GROUP_PORT_PROP_NAME, | |
199 | + ((defaultGroupPort != null) ? defaultGroupPort | |
200 | + : EHCACHE_GROUP_PORT_DEFAULT)); | |
201 | + } | |
202 | + if (System.getProperty(EHCACHE_GROUP_TTL_PROP_NAME) == null) | |
203 | + { | |
204 | + System.setProperty(EHCACHE_GROUP_TTL_PROP_NAME, | |
205 | + ((defaultGroupTTL != null) ? defaultGroupTTL | |
206 | + : (test ? EHCACHE_GROUP_TTL_TEST_DEFAULT | |
207 | + : EHCACHE_GROUP_TTL_DEFAULT))); | |
208 | + } | |
209 | + if (System.getProperty(EHCACHE_HOSTNAME_PROP_NAME) == null) | |
210 | + { | |
211 | + System.setProperty(EHCACHE_HOSTNAME_PROP_NAME, | |
212 | + ((defaultHostname != null) ? defaultHostname | |
213 | + : (test ? EHCACHE_HOSTNAME_TEST_DEFAULT | |
214 | + : EHCACHE_HOSTNAME_DEFAULT))); | |
215 | + } | |
216 | + if (System.getProperty(EHCACHE_PORT_PROP_NAME) == null) | |
217 | + { | |
218 | + System | |
219 | + .setProperty(EHCACHE_PORT_PROP_NAME, | |
220 | + ((defaultPort != null) ? defaultPort | |
221 | + : EHCACHE_PORT_DEFAULT)); | |
222 | + } | |
223 | + | |
224 | + // set system properties used in page manager cache configuration | |
225 | + if (System.getProperty(EHCACHE_PAGE_MANAGER_MAX_ELEMENTS_PROP_NAME) == null) | |
226 | + { | |
227 | + String pageManagerMaxElements = ((defaultPageManagerMaxElements != null) ? defaultPageManagerMaxElements | |
228 | + : System.getProperty( | |
229 | + EHCACHE_PAGE_MANAGER_MAX_ELEMENTS_LEGACY_PROP_NAME, | |
230 | + EHCACHE_PAGE_MANAGER_MAX_ELEMENTS_DEFAULT)); | |
231 | + if ((pageManagerMaxElements != null) | |
232 | + && (Integer.parseInt(pageManagerMaxElements) < 0)) | |
233 | + { | |
234 | + pageManagerMaxElements = EHCACHE_PAGE_MANAGER_MAX_ELEMENTS_DEFAULT; | |
235 | + } | |
236 | + System.setProperty(EHCACHE_PAGE_MANAGER_MAX_ELEMENTS_PROP_NAME, | |
237 | + pageManagerMaxElements); | |
238 | + } | |
239 | + if (System.getProperty(EHCACHE_PAGE_MANAGER_ELEMENT_TTL_PROP_NAME) == null) | |
240 | + { | |
241 | + String pageManagerElementTTL = ((defaultPageManagerElementTTL != null) ? defaultPageManagerElementTTL | |
242 | + : System.getProperty( | |
243 | + EHCACHE_PAGE_MANAGER_ELEMENT_TTL_LEGACY_PROP_NAME, | |
244 | + EHCACHE_PAGE_MANAGER_ELEMENT_TTL_DEFAULT)); | |
245 | + if ((pageManagerElementTTL != null) | |
246 | + && (Integer.parseInt(pageManagerElementTTL) < 0)) | |
247 | + { | |
248 | + pageManagerElementTTL = EHCACHE_PAGE_MANAGER_ELEMENT_TTL_DEFAULT; | |
249 | + } | |
250 | + System.setProperty(EHCACHE_PAGE_MANAGER_ELEMENT_TTL_PROP_NAME, | |
251 | + pageManagerElementTTL); | |
252 | + } | |
253 | + | |
254 | + // setup delegate ClassPathResource | |
255 | + final String configResource = System | |
256 | + .getProperty(EHCACHE_CONFIG_RESOURCE_PROP_NAME); | |
257 | + log.info("Configured with resource: " + configResource); | |
258 | + classPathResource = new ClassPathResource(configResource); | |
259 | + } | |
260 | + | |
261 | + // AbstractResource implementation | |
262 | + | |
263 | + /* (non-Javadoc) | |
264 | + * @see org.springframework.core.io.AbstractResource#createRelative(java.lang.String) | |
265 | + */ | |
266 | + public Resource createRelative(String relativePath) throws IOException | |
267 | + { | |
268 | + // delegate to ClassPathResource | |
269 | + return classPathResource.createRelative(relativePath); | |
270 | + } | |
271 | + | |
272 | + /* (non-Javadoc) | |
273 | + * @see org.springframework.core.io.AbstractResource#getFile() | |
274 | + */ | |
275 | + public File getFile() throws IOException | |
276 | + { | |
277 | + // delegate to ClassPathResource | |
278 | + return classPathResource.getFile(); | |
279 | + } | |
280 | + | |
281 | + /* (non-Javadoc) | |
282 | + * @see org.springframework.core.io.AbstractResource#getFilename() | |
283 | + */ | |
284 | + public String getFilename() throws IllegalStateException | |
285 | + { | |
286 | + // delegate to ClassPathResource | |
287 | + return classPathResource.getFilename(); | |
288 | + } | |
289 | + | |
290 | + /* (non-Javadoc) | |
291 | + * @see org.springframework.core.io.AbstractResource#getURL() | |
292 | + */ | |
293 | + public URL getURL() throws IOException | |
294 | + { | |
295 | + // delegate to ClassPathResource | |
296 | + return classPathResource.getURL(); | |
297 | + } | |
298 | + | |
299 | + /* (non-Javadoc) | |
300 | + * @see org.springframework.core.io.Resource#getDescription() | |
301 | + */ | |
302 | + public String getDescription() | |
303 | + { | |
304 | + // delegate to ClassPathResource | |
305 | + return classPathResource.getDescription(); | |
306 | + } | |
307 | + | |
308 | + /* (non-Javadoc) | |
309 | + * @see org.springframework.core.io.InputStreamSource#getInputStream() | |
310 | + */ | |
311 | + public InputStream getInputStream() throws IOException | |
312 | + { | |
313 | + // delegate to ClassPathResource | |
314 | + return classPathResource.getInputStream(); | |
315 | + } | |
316 | + | |
317 | + // Data access | |
318 | + | |
319 | + /** | |
320 | + * @param configuration the configuration to set | |
321 | + */ | |
322 | + public void setConfiguration(PropertiesConfiguration configuration) | |
323 | + { | |
324 | + this.configuration = configuration; | |
325 | + } | |
326 | + | |
327 | + /** | |
328 | + * @param defaultConfigResource the defaultConfigResource to set | |
329 | + */ | |
330 | + public void setDefaultConfigResource(String defaultConfigResource) | |
331 | + { | |
332 | + this.defaultConfigResource = defaultConfigResource; | |
333 | + } | |
334 | + | |
335 | + /** | |
336 | + * @param test the test to set | |
337 | + */ | |
338 | + public void setTest(boolean test) | |
339 | + { | |
340 | + this.test = test; | |
341 | + } | |
342 | + | |
343 | + /** | |
344 | + * @param defaultGroupAddress the defaultGroupAddress to set | |
345 | + */ | |
346 | + public void setDefaultGroupAddress(String defaultGroupAddress) | |
347 | + { | |
348 | + this.defaultGroupAddress = defaultGroupAddress; | |
349 | + } | |
350 | + | |
351 | + /** | |
352 | + * @param defaultGroupPort the defaultGroupPort to set | |
353 | + */ | |
354 | + public void setDefaultGroupPort(String defaultGroupPort) | |
355 | + { | |
356 | + this.defaultGroupPort = defaultGroupPort; | |
357 | + } | |
358 | + | |
359 | + /** | |
360 | + * @param defaultGroupTTL the defaultGroupTTL to set | |
361 | + */ | |
362 | + public void setDefaultGroupTTL(String defaultGroupTTL) | |
363 | + { | |
364 | + this.defaultGroupTTL = defaultGroupTTL; | |
365 | + } | |
366 | + | |
367 | + /** | |
368 | + * @param defaultHostname the defaultHostname to set | |
369 | + */ | |
370 | + public void setDefaultHostname(String defaultHostname) | |
371 | + { | |
372 | + this.defaultHostname = defaultHostname; | |
373 | + } | |
374 | + | |
375 | + /** | |
376 | + * @param defaultPort the defaultPort to set | |
377 | + */ | |
378 | + public void setDefaultPort(String defaultPort) | |
379 | + { | |
380 | + this.defaultPort = defaultPort; | |
381 | + } | |
382 | + | |
383 | + /** | |
384 | + * @param defaultPageManagerMaxElements the defaultPageManagerMaxElements to set | |
385 | + */ | |
386 | + public void setDefaultPageManagerMaxElements( | |
387 | + String defaultPageManagerMaxElements) | |
388 | + { | |
389 | + this.defaultPageManagerMaxElements = defaultPageManagerMaxElements; | |
390 | + } | |
391 | + | |
392 | + /** | |
393 | + * @param defaultPageManagerElementTTL the defaultPageManagerElementTTL to set | |
394 | + */ | |
395 | + public void setDefaultPageManagerElementTTL( | |
396 | + String defaultPageManagerElementTTL) | |
397 | + { | |
398 | + this.defaultPageManagerElementTTL = defaultPageManagerElementTTL; | |
399 | + } | |
400 | +} |
@@ -25,15 +25,14 @@ | ||
25 | 25 | class="org.apache.jetspeed.page.impl.DatabasePageManager"> |
26 | 26 | <!-- OJB configuration file resource path --> |
27 | 27 | <constructor-arg index="0"><value>JETSPEED-INF/ojb/page-manager-repository.xml</value></constructor-arg> |
28 | - <!-- folder/page/link cache size, default=128, min=128 --> | |
29 | - <constructor-arg index="1"><value>128</value></constructor-arg> | |
30 | - <!-- folder/page/link cache expires seconds, default=-1, infinite=0, min=30 --> | |
31 | - <!-- (default is 150 seconds) --> | |
32 | - <constructor-arg index="2"><value>-1</value></constructor-arg> | |
33 | 28 | <!-- permissions security enabled flag, default=false --> |
34 | - <constructor-arg index="3"><value>false</value></constructor-arg> | |
29 | + <constructor-arg index="1"><value>false</value></constructor-arg> | |
35 | 30 | <!-- constraints security enabled flag, default=true --> |
36 | - <constructor-arg index="4"><value>true</value></constructor-arg> | |
31 | + <constructor-arg index="2"><value>true</value></constructor-arg> | |
32 | + <!-- folder/page/link cache --> | |
33 | + <constructor-arg index="3"><ref bean="pageManagerOidCache"/></constructor-arg> | |
34 | + <!-- folder/page/link path cache --> | |
35 | + <constructor-arg index="4"><ref bean="pageManagerPathCache"/></constructor-arg> | |
37 | 36 | </bean> |
38 | 37 | |
39 | 38 | <!-- Transaction Proxying --> |
@@ -18,11 +18,14 @@ | ||
18 | 18 | --> |
19 | 19 | <beans> |
20 | 20 | |
21 | + <!-- Cache Manager --> | |
22 | + <bean id="cacheManagerConfig" class="org.apache.jetspeed.cache.impl.EhCacheConfigResource"> | |
23 | + <property name="defaultConfigResource" value="ehcache.xml"/> | |
24 | + </bean> | |
25 | + | |
21 | 26 | <bean id="cacheManager" |
22 | 27 | class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> |
23 | - <!-- get it through the class path | |
24 | - <property name="configLocation" value="${applicationRoot}/WEB-INF/conf/ehcache.xml"/> | |
25 | - --> | |
28 | + <property name="configLocation" ref="cacheManagerConfig"/> | |
26 | 29 | </bean> |
27 | 30 | |
28 | 31 | <!-- Factory bean used to instantiate a EHCache with the specified name (and corresponding |
@@ -100,7 +103,7 @@ | ||
100 | 103 | <bean id="decorationConfigurationCache" |
101 | 104 | class="org.apache.jetspeed.cache.impl.EhCacheImpl"> |
102 | 105 | <constructor-arg> |
103 | - <ref bean="ehDecorationConfigurationCache" /> | |
106 | + <ref bean="ehDesktopContentCache" /> | |
104 | 107 | </constructor-arg> |
105 | 108 | </bean> |
106 | 109 |
@@ -135,6 +138,14 @@ | ||
135 | 138 | <property name="cacheName" value="portletApplicationNameCache" /> |
136 | 139 | </bean> |
137 | 140 | |
141 | + <bean id="ehDesktopContentCache" | |
142 | + class="org.springframework.cache.ehcache.EhCacheFactoryBean"> | |
143 | + <property name="cacheManager"> | |
144 | + <ref local="cacheManager" /> | |
145 | + </property> | |
146 | + <property name="cacheName" value="desktopContentCache" /> | |
147 | + </bean> | |
148 | + | |
138 | 149 | <bean id="portletApplicationOidCache" |
139 | 150 | class="org.apache.jetspeed.cache.impl.EhCacheImpl"> |
140 | 151 | <constructor-arg> |
@@ -149,6 +160,13 @@ | ||
149 | 160 | </constructor-arg> |
150 | 161 | </bean> |
151 | 162 | |
163 | + <bean id="desktopContentCache" | |
164 | + class="org.apache.jetspeed.cache.impl.EhCacheImpl"> | |
165 | + <constructor-arg> | |
166 | + <ref bean="ehDesktopContentCache" /> | |
167 | + </constructor-arg> | |
168 | + </bean> | |
169 | + | |
152 | 170 | <bean id="ehPortletDefinitionOidCache" |
153 | 171 | class="org.springframework.cache.ehcache.EhCacheFactoryBean"> |
154 | 172 | <property name="cacheManager"> |
@@ -213,30 +231,23 @@ | ||
213 | 231 | </constructor-arg> |
214 | 232 | </bean> |
215 | 233 | |
216 | - <bean id="ehInternalPageFileCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> | |
217 | - <property name="cacheManager"> | |
218 | - <ref local="cacheManager" /> | |
219 | - </property> | |
220 | - <property name="cacheName" value="pageFileCache" /> | |
221 | - </bean> | |
222 | - | |
223 | - <bean id="internalPageFileCache" class="org.apache.jetspeed.cache.impl.EhCacheImpl"> | |
224 | - <constructor-arg> | |
225 | - <ref bean="ehInternalPageFileCache" /> | |
226 | - </constructor-arg> | |
227 | - </bean> | |
228 | - | |
229 | - <bean id="ehInternalImportPageFileCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> | |
230 | - <property name="cacheManager"> | |
231 | - <ref local="cacheManager" /> | |
232 | - </property> | |
233 | - <property name="cacheName" value="importPageFileCache" /> | |
234 | - </bean> | |
235 | - | |
236 | - <bean id="internalImportPageFileCache" class="org.apache.jetspeed.cache.impl.EhCacheImpl"> | |
237 | - <constructor-arg> | |
238 | - <ref bean="ehInternalImportPageFileCache" /> | |
239 | - </constructor-arg> | |
240 | - </bean> | |
241 | - | |
234 | + <!-- Page Manager Caches --> | |
235 | + <bean id="ehPageManagerOidCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> | |
236 | + <property name="cacheManager" ref="cacheManager"/> | |
237 | + <property name="cacheName" value="pageManagerOidCache"/> | |
238 | + </bean> | |
239 | + | |
240 | + <bean id="ehPageManagerPathCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> | |
241 | + <property name="cacheManager" ref="cacheManager"/> | |
242 | + <property name="cacheName" value="pageManagerPathCache"/> | |
243 | + </bean> | |
244 | + | |
245 | + <bean id="pageManagerOidCache" class="org.apache.jetspeed.cache.impl.EhCacheImpl"> | |
246 | + <constructor-arg><ref bean="ehPageManagerOidCache"/></constructor-arg> | |
247 | + </bean> | |
248 | + | |
249 | + <bean id="pageManagerPathCache" class="org.apache.jetspeed.cache.impl.EhCacheDistributedImpl"> | |
250 | + <constructor-arg><ref bean="ehPageManagerPathCache"/></constructor-arg> | |
251 | + </bean> | |
252 | + | |
242 | 253 | </beans> |
@@ -348,6 +348,8 @@ | ||
348 | 348 | file="./src/webapp/WEB-INF/assembly/transaction.xml"/> |
349 | 349 | <copy todir="${maven.build.dir}/classes" |
350 | 350 | file="./src/webapp/WEB-INF/assembly/alternate/interceptors.xml"/> |
351 | + <copy todir="${maven.build.dir}/classes" | |
352 | + file="./src/webapp/WEB-INF/assembly/cache.xml"/> | |
351 | 353 | <java classname="org.apache.jetspeed.page.PageImporter" fork="yes"> |
352 | 354 | <classpath> |
353 | 355 | <path refid="maven.dependency.classpath"/> |
@@ -385,6 +387,8 @@ | ||
385 | 387 | file="./src/webapp/WEB-INF/assembly/transaction.xml"/> |
386 | 388 | <copy todir="${maven.build.dir}/classes" |
387 | 389 | file="./src/webapp/WEB-INF/assembly/alternate/interceptors.xml"/> |
390 | + <copy todir="${maven.build.dir}/classes" | |
391 | + file="./src/webapp/WEB-INF/assembly/cache.xml"/> | |
388 | 392 | <mkdir dir="./target/export/psml"></mkdir> |
389 | 393 | <java classname="org.apache.jetspeed.page.PageImporter" fork="yes"> |
390 | 394 | <classpath> |
@@ -145,4 +145,11 @@ | ||
145 | 145 | * @return the size of the cache |
146 | 146 | */ |
147 | 147 | int getSize(); |
148 | + | |
149 | + /** | |
150 | + * Returns whether this cache is currently part of a distributed cache cluster. | |
151 | + * | |
152 | + * @return distributed flag | |
153 | + */ | |
154 | + boolean isDistributed(); | |
148 | 155 | } |
\ No newline at end of file |
@@ -781,4 +781,13 @@ | ||
781 | 781 | * @return |
782 | 782 | */ |
783 | 783 | public boolean checkConstraint(String securityConstraintName, String actions); |
784 | + | |
785 | + /** | |
786 | + * Returns whether the page manager cache is currently part of a distributed | |
787 | + * cache cluster. | |
788 | + * | |
789 | + * @return distributed flag | |
790 | + */ | |
791 | + public boolean isDistributed(); | |
792 | + | |
784 | 793 | } |
@@ -135,13 +135,7 @@ | ||
135 | 135 | * stashRemoteCachePeers (optional) - specify "true" or "false". Defaults to true. |
136 | 136 | CachePeer objects are stashed for performance. |
137 | 137 | * jndiUrls (mandatory) - specify a pipe separated list of jndiUrls, |
138 | - in the form protocol//hostname:port | |
139 | - | |
140 | - <cacheManagerPeerProviderFactory | |
141 | - class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" | |
142 | - properties="peerDiscovery=automatic, | |
143 | - multicastGroupAddress=230.0.0.1, | |
144 | - multicastGroupPort=4446, timeToLive=1"/> | |
138 | + in the form protocol//hostname:port | |
145 | 139 | --> |
146 | 140 | |
147 | 141 |
@@ -185,9 +179,6 @@ | ||
185 | 179 | net.sf.ehcache.distribution.JNDIManualRMICacheManagerPeerProviderFactoryerFactory. |
186 | 180 | Properties for JNDIRMICacheManagerPeerListenerFactory are the same as |
187 | 181 | RMICacheManagerPeerListenerFactory. |
188 | - | |
189 | - <cacheManagerPeerListenerFactory | |
190 | - class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/> | |
191 | 182 | --> |
192 | 183 | |
193 | 184 |
@@ -332,8 +323,7 @@ | ||
332 | 323 | |
333 | 324 | If there are more than 10000 elements it will overflow to the |
334 | 325 | disk cache, which in this configuration will go to wherever java.io.tmp is |
335 | - defined on your system. On a standard Linux system this will be /tmp" | |
336 | - | |
326 | + defined on your system. On a standard Linux system this will be /tmp | |
337 | 327 | timeToIdleSeconds and timeToLiveSeconds to live are both set at 8 hours (28800) |
338 | 328 | this is the default setting for portlets who set their expiration cache as -1 |
339 | 329 | --> |
@@ -355,13 +345,6 @@ | ||
355 | 345 | timeToIdleSeconds="28800" |
356 | 346 | timeToLiveSeconds="28800" |
357 | 347 | memoryStoreEvictionPolicy="LFU"> |
358 | -<!-- | |
359 | - <cacheEventListenerFactory | |
360 | - class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" | |
361 | - properties="replicateAsynchronously=true, replicatePuts=false, | |
362 | - replicateUpdates=false, replicateUpdatesViaCopy=false, | |
363 | - replicateRemovals=true"/> | |
364 | - --> | |
365 | 348 | </cache> |
366 | 349 | |
367 | 350 |
@@ -383,13 +366,6 @@ | ||
383 | 366 | timeToIdleSeconds="28800" |
384 | 367 | timeToLiveSeconds="28800" |
385 | 368 | memoryStoreEvictionPolicy="LFU"> |
386 | -<!-- | |
387 | - <cacheEventListenerFactory | |
388 | - class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" | |
389 | - properties="replicateAsynchronously=true, replicatePuts=false, | |
390 | - replicateUpdates=false, replicateUpdatesViaCopy=false, | |
391 | - replicateRemovals=true"/> | |
392 | - --> | |
393 | 369 | </cache> |
394 | 370 | |
395 | 371 | <cache name="portletDefinitionOidCache" |
@@ -410,13 +386,6 @@ | ||
410 | 386 | timeToIdleSeconds="28800" |
411 | 387 | timeToLiveSeconds="28800" |
412 | 388 | memoryStoreEvictionPolicy="LFU"> |
413 | - <!-- | |
414 | - <cacheEventListenerFactory | |
415 | - class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" | |
416 | - properties="replicateAsynchronously=true, replicatePuts=false, | |
417 | - replicateUpdates=false, replicateUpdatesViaCopy=false, | |
418 | - replicateRemovals=true"/> | |
419 | - --> | |
420 | 389 | </cache> |
421 | 390 | |
422 | 391 |
@@ -541,4 +510,24 @@ | ||
541 | 510 | memoryStoreEvictionPolicy="LFU" |
542 | 511 | /> |
543 | 512 | |
513 | + <!-- | |
514 | + Jetspeed Page Manager Caches | |
515 | + --> | |
516 | + | |
517 | + <cache name="pageManagerOidCache" | |
518 | + maxElementsInMemory="${org.apache.jetspeed.ehcache.pagemanager.maxelements}" | |
519 | + eternal="false" | |
520 | + overflowToDisk="false" | |
521 | + timeToIdleSeconds="${org.apache.jetspeed.ehcache.pagemanager.element.ttl}" | |
522 | + timeToLiveSeconds="${org.apache.jetspeed.ehcache.pagemanager.element.ttl}" | |
523 | + memoryStoreEvictionPolicy="LFU"/> | |
524 | + | |
525 | + <cache name="pageManagerPathCache" | |
526 | + maxElementsInMemory="${org.apache.jetspeed.ehcache.pagemanager.maxelements}" | |
527 | + eternal="false" | |
528 | + overflowToDisk="false" | |
529 | + timeToIdleSeconds="${org.apache.jetspeed.ehcache.pagemanager.element.ttl}" | |
530 | + timeToLiveSeconds="${org.apache.jetspeed.ehcache.pagemanager.element.ttl}" | |
531 | + memoryStoreEvictionPolicy="LFU"/> | |
532 | + | |
544 | 533 | </ehcache> |
@@ -0,0 +1,543 @@ | ||
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!-- | |
3 | + Licensed to the Apache Software Foundation (ASF) under one or more | |
4 | + contributor license agreements. See the NOTICE file distributed with | |
5 | + this work for additional information regarding copyright ownership. | |
6 | + The ASF licenses this file to You under the Apache License, Version 2.0 | |
7 | + (the "License"); you may not use this file except in compliance with | |
8 | + the License. You may obtain a copy of the License at | |
9 | + | |
10 | + http://www.apache.org/licenses/LICENSE-2.0 | |
11 | + | |
12 | + Unless required by applicable law or agreed to in writing, software | |
13 | + distributed under the License is distributed on an "AS IS" BASIS, | |
14 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 | + See the License for the specific language governing permissions and | |
16 | + limitations under the License. | |
17 | +--> | |
18 | +<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"> | |
19 | + | |
20 | + <!-- | |
21 | + DiskStore configuration | |
22 | + | |
23 | + Sets the path to the directory where cache files are created. | |
24 | + | |
25 | + If the path is a Java System Property it is replaced by its value in the | |
26 | + running VM. | |
27 | + | |
28 | + The following properties are translated: | |
29 | + * user.home - User's home directory | |
30 | + * user.dir - User's current working directory | |
31 | + * java.io.tmpdir - Default temp file path | |
32 | + | |
33 | + Subdirectories can be specified below the property e.g. java.io.tmpdir/one | |
34 | + --> | |
35 | + <diskStore path="java.io.tmpdir"/> | |
36 | + | |
37 | + <!-- | |
38 | + Specifies a CacheManagerEventListenerFactory, be used to create a CacheManagerPeerProvider, | |
39 | + which is notified when Caches are added or removed from the CacheManager. | |
40 | + | |
41 | + The attributes of CacheManagerEventListenerFactory are: | |
42 | + * class - a fully qualified factory class name | |
43 | + * properties - comma separated properties having meaning only to the factory. | |
44 | + | |
45 | + Sets the fully qualified class name to be registered as the CacheManager event listener. | |
46 | + | |
47 | + The events include: | |
48 | + * adding a Cache | |
49 | + * removing a Cache | |
50 | + | |
51 | + Callbacks to listener methods are synchronous and unsynchronized. It is the responsibility | |
52 | + of the implementer to safely handle the potential performance and thread safety issues | |
53 | + depending on what their listener is doing. | |
54 | + | |
55 | + If no class is specified, no listener is created. There is no default. | |
56 | + --> | |
57 | + <cacheManagerEventListenerFactory class="" properties=""/> | |
58 | + | |
59 | + | |
60 | + <!-- | |
61 | + (Enable for distributed operation) | |
62 | + | |
63 | + Specifies a CacheManagerPeerProviderFactory which will be used to create a | |
64 | + CacheManagerPeerProvider, which discovers other CacheManagers in the cluster. | |
65 | + | |
66 | + The attributes of cacheManagerPeerProviderFactory are: | |
67 | + * class - a fully qualified factory class name | |
68 | + * properties - comma separated properties having meaning only to the factory. | |
69 | + | |
70 | + Ehcache comes with a built-in RMI-based distribution system with two means of discovery of | |
71 | + CacheManager peers participating in the cluster: | |
72 | + * automatic, using a multicast group. This one automatically discovers peers and detects | |
73 | + changes such as peers entering and leaving the group | |
74 | + * manual, using manual rmiURL configuration. A hardcoded list of peers is provided at | |
75 | + configuration time. | |
76 | + | |
77 | + Configuring Automatic Discovery: | |
78 | + Automatic discovery is configured as per the following example: | |
79 | + <cacheManagerPeerProviderFactory | |
80 | + class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" | |
81 | + properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1, | |
82 | + multicastGroupPort=4446, timeToLive=32"/> | |
83 | + | |
84 | + Valid properties are: | |
85 | + * peerDiscovery (mandatory) - specify "automatic" | |
86 | + * multicastGroupAddress (mandatory) - specify a valid multicast group address | |
87 | + * multicastGroupPort (mandatory) - specify a dedicated port for the multicast heartbeat | |
88 | + traffic | |
89 | + * timeToLive - specify a value between 0 and 255 which determines how far the packets will propagate. | |
90 | + By convention, the restrictions are: | |
91 | + 0 - the same host | |
92 | + 1 - the same subnet | |
93 | + 32 - the same site | |
94 | + 64 - the same region | |
95 | + 128 - the same continent | |
96 | + 255 - unrestricted | |
97 | + | |
98 | + Configuring Manual Discovery: | |
99 | + Manual discovery is configured as per the following example: | |
100 | + <cacheManagerPeerProviderFactory class= | |
101 | + "net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" | |
102 | + properties="peerDiscovery=manual, | |
103 | + rmiUrls=//server1:40000/sampleCache1|//server2:40000/sampleCache1 | |
104 | + | //server1:40000/sampleCache2|//server2:40000/sampleCache2"/> | |
105 | + | |
106 | + Valid properties are: | |
107 | + * peerDiscovery (mandatory) - specify "manual" | |
108 | + * rmiUrls (mandatory) - specify a pipe separated list of rmiUrls, in the form | |
109 | + //hostname:port | |
110 | + | |
111 | + The hostname is the hostname of the remote CacheManager peer. The port is the listening | |
112 | + port of the RMICacheManagerPeerListener of the remote CacheManager peer. | |
113 | + | |
114 | + An alternate CacheManagerPeerProviderFactory can be used for JNDI discovery of other | |
115 | + CacheManagers in the cluster. Only manual discovery is supported. | |
116 | + | |
117 | + For cacheManagerPeerProviderFactory specify class | |
118 | + net.sf.ehcache.distribution.JNDIManualRMICacheManagerPeerProviderFactoryerFactory. | |
119 | + | |
120 | + Correspondingly for cacheManagerPeerListenerFactory specify class | |
121 | + net.sf.ehcache.distribution.JNDIRMICacheManagerPeerListenerFactoryory. | |
122 | + | |
123 | + Configuring JNDI Manual Discovery: | |
124 | + Manual JNDI discovery is configured as per the following example: | |
125 | + <cacheManagerPeerProviderFactory class= | |
126 | + "net.sf.ehcache.distribution.JNDIManualRMICacheManagerPeerProviderFactoryerFactory" | |
127 | + properties="peerDiscovery=manual, stashContexts=true, stashRemoteCachePeers=true, | |
128 | + jndiUrls=t3//server1:40000/sampleCache1|t3//server2:40000/sampleCache1 | |
129 | + |t3//server1:40000/sampleCache2|t3//server2:40000/sampleCache2"/> | |
130 | + | |
131 | + Valid properties are: | |
132 | + * peerDiscovery (mandatory) - specify "manual" | |
133 | + * stashContexts (optional) - specify "true" or "false". Defaults to true. | |
134 | + java.naming.Context objects are stashed for performance. | |
135 | + * stashRemoteCachePeers (optional) - specify "true" or "false". Defaults to true. | |
136 | + CachePeer objects are stashed for performance. | |
137 | + * jndiUrls (mandatory) - specify a pipe separated list of jndiUrls, | |
138 | + in the form protocol//hostname:port | |
139 | + --> | |
140 | + | |
141 | + <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" | |
142 | + properties="peerDiscovery=automatic, | |
143 | + multicastGroupAddress=${org.apache.jetspeed.ehcache.group.address}, | |
144 | + multicastGroupPort=${org.apache.jetspeed.ehcache.group.port}, | |
145 | + timeToLive=${org.apache.jetspeed.ehcache.group.ttl}"/> | |
146 | + | |
147 | + <!-- | |
148 | + (Enable for distributed operation) | |
149 | + | |
150 | + Specifies a CacheManagerPeerListenerFactory which will be used to create a | |
151 | + CacheManagerPeerListener, which | |
152 | + listens for messages from cache replicators participating in the cluster. | |
153 | + | |
154 | + The attributes of cacheManagerPeerListenerFactory are: | |
155 | + class - a fully qualified factory class name | |
156 | + properties - comma separated properties having meaning only to the factory. | |
157 | + | |
158 | + Ehcache comes with a built-in RMI-based distribution system. The listener component is | |
159 | + RMICacheManagerPeerListener which is configured using | |
160 | + RMICacheManagerPeerListenerFactory. It is configured as per the following example: | |
161 | + | |
162 | + <cacheManagerPeerListenerFactory | |
163 | + class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" | |
164 | + properties="hostName=fully_qualified_hostname_or_ip, | |
165 | + port=40001, | |
166 | + socketTimeoutMillis=120000"/> | |
167 | + | |
168 | + All properties are optional. They are: | |
169 | + * hostName - the hostName of the host the listener is running on. Specify | |
170 | + where the host is multihomed and you want to control the interface over which cluster | |
171 | + messages are received. Defaults to the host name of the default interface if not | |
172 | + specified. | |
173 | + * port - the port the listener listens on. This defaults to a free port if not specified. | |
174 | + * socketTimeoutMillis - the number of ms client sockets will stay open when sending | |
175 | + messages to the listener. This should be long enough for the slowest message. | |
176 | + If not specified it defaults 120000ms. | |
177 | + | |
178 | + | |
179 | + An alternate CacheManagerPeerListenerFactory can be also be used for JNDI binding of | |
180 | + listeners for messages from cache replicators participating in the cluster. For | |
181 | + cacheManagerPeerListenerFactory specify | |
182 | + class net.sf.ehcache.distribution.JNDIRMICacheManagerPeerListenerFactory. | |
183 | + Correspondingly for cacheManagerPeerProviderFactory specify class | |
184 | + net.sf.ehcache.distribution.JNDIManualRMICacheManagerPeerProviderFactoryerFactory. | |
185 | + Properties for JNDIRMICacheManagerPeerListenerFactory are the same as | |
186 | + RMICacheManagerPeerListenerFactory. | |
187 | + --> | |
188 | + | |
189 | + <cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory" | |
190 | + properties="hostName=${org.apache.jetspeed.ehcache.hostname}, | |
191 | + port=${org.apache.jetspeed.ehcache.port}"/> | |
192 | + | |
193 | + <!-- Cache configuration. | |
194 | + | |
195 | + The following attributes are required. | |
196 | + | |
197 | + name: | |
198 | + Sets the name of the cache. This is used to identify the cache. It must be unique. | |
199 | + | |
200 | + maxElementsInMemory: | |
201 | + Sets the maximum number of objects that will be created in memory | |
202 | + | |
203 | + maxElementsOnDisk: | |
204 | + Sets the maximum number of objects that will be maintained in the DiskStore | |
205 | + The default value is zero, meaning unlimited. | |
206 | + | |
207 | + eternal: | |
208 | + Sets whether elements are eternal. If eternal, timeouts are ignored and the | |
209 | + element is never expired. | |
210 | + | |
211 | + overflowToDisk: | |
212 | + Sets whether elements can overflow to disk when the memory store | |
213 | + has reached the maxInMemory limit. | |
214 | + | |
215 | + The following attributes are optional. | |
216 | + | |
217 | + timeToIdleSeconds: | |
218 | + Sets the time to idle for an element before it expires. | |
219 | + i.e. The maximum amount of time between accesses before an element expires | |
220 | + Is only used if the element is not eternal. | |
221 | + Optional attribute. A value of 0 means that an Element can idle for infinity. | |
222 | + The default value is 0. | |
223 | + | |
224 | + timeToLiveSeconds: | |
225 | + Sets the time to live for an element before it expires. | |
226 | + i.e. The maximum time between creation time and when an element expires. | |
227 | + Is only used if the element is not eternal. | |
228 | + Optional attribute. A value of 0 means that and Element can live for infinity. | |
229 | + The default value is 0. | |
230 | + | |
231 | + diskPersistent: | |
232 | + Whether the disk store persists between restarts of the Virtual Machine. | |
233 | + The default value is false. | |
234 | + | |
235 | + diskExpiryThreadIntervalSeconds: | |
236 | + The number of seconds between runs of the disk expiry thread. The default value | |
237 | + is 120 seconds. | |
238 | + | |
239 | + memoryStoreEvictionPolicy: | |
240 | + Policy would be enforced upon reaching the maxElementsInMemory limit. Default | |
241 | + policy is Least Recently Used (specified as LRU). Other policies available - | |
242 | + First In First Out (specified as FIFO) and Less Frequently Used | |
243 | + (specified as LFU) | |
244 | + | |
245 | + Cache elements can also contain sub elements which take the same format of a factory class | |
246 | + and properties. Defined sub-elements are: | |
247 | + | |
248 | + * cacheEventListenerFactory - Enables registration of listeners for cache events, such as | |
249 | + put, remove, update, and expire. | |
250 | + | |
251 | + * bootstrapCacheLoaderFactory - Specifies a BootstrapCacheLoader, which is called by a | |
252 | + cache on initialisation to prepopulate itself. | |
253 | + | |
254 | + Each cache that will be distributed needs to set a cache event listener which replicates | |
255 | + messages to the other CacheManager peers. For the built-in RMI implementation this is done | |
256 | + by adding a cacheEventListenerFactory element of type RMICacheReplicatorFactory to each | |
257 | + distributed cache's configuration as per the following example: | |
258 | + | |
259 | + <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" | |
260 | + properties="replicateAsynchronously=true, | |
261 | + replicatePuts=true, | |
262 | + replicateUpdates=true, | |
263 | + replicateUpdatesViaCopy=true, | |
264 | + replicateRemovals=true "/> | |
265 | + | |
266 | + The RMICacheReplicatorFactory recognises the following properties: | |
267 | + | |
268 | + * replicatePuts=true|false - whether new elements placed in a cache are | |
269 | + replicated to others. Defaults to true. | |
270 | + | |
271 | + * replicateUpdates=true|false - whether new elements which override an | |
272 | + element already existing with the same key are replicated. Defaults to true. | |
273 | + | |
274 | + * replicateRemovals=true - whether element removals are replicated. Defaults to true. | |
275 | + | |
276 | + * replicateAsynchronously=true | false - whether replications are | |
277 | + asynchronous (true) or synchronous (false). Defaults to true. | |
278 | + | |
279 | + * replicateUpdatesViaCopy=true | false - whether the new elements are | |
280 | + copied to other caches (true), or whether a remove message is sent. Defaults to true. | |
281 | + | |
282 | + * asynchronousReplicationIntervalMillis=<number of milliseconds> - The asynchronous | |
283 | + replicator runs at a set interval of milliseconds. The default is 1000. The minimum | |
284 | + is 10. This property is only applicable if replicateAsynchronously=true | |
285 | + | |
286 | + The RMIBootstrapCacheLoader bootstraps caches in clusters where RMICacheReplicators are | |
287 | + used. It is configured as per the following example: | |
288 | + | |
289 | + <bootstrapCacheLoaderFactory | |
290 | + class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory" | |
291 | + properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"/> | |
292 | + | |
293 | + The RMIBootstrapCacheLoaderFactory recognises the following optional properties: | |
294 | + | |
295 | + * bootstrapAsynchronously=true|false - whether the bootstrap happens in the background | |
296 | + after the cache has started. If false, bootstrapping must complete before the cache is | |
297 | + made available. The default value is true. | |
298 | + | |
299 | + * maximumChunkSizeBytes=<integer> - Caches can potentially be very large, larger than the | |
300 | + memory limits of the VM. This property allows the bootstraper to fetched elements in | |
301 | + chunks. The default chunk size is 5000000 (5MB). | |
302 | + | |
303 | + --> | |
304 | + | |
305 | + <!-- | |
306 | + Mandatory Default Cache configuration. These settings will be applied to caches | |
307 | + created programmtically using CacheManager.add(String cacheName) | |
308 | + --> | |
309 | + <defaultCache | |
310 | + maxElementsInMemory="10000" | |
311 | + eternal="false" | |
312 | + timeToIdleSeconds="120" | |
313 | + timeToLiveSeconds="120" | |
314 | + overflowToDisk="true" | |
315 | + maxElementsOnDisk="10000000" | |
316 | + diskPersistent="false" | |
317 | + diskExpiryThreadIntervalSeconds="120" | |
318 | + memoryStoreEvictionPolicy="LRU" | |
319 | + /> | |
320 | + | |
321 | + <!-- | |
322 | + Jetspeed caches. | |
323 | + --> | |
324 | + | |
325 | + <!-- | |
326 | + JSR-168 Portlet Content Cache | |
327 | + This cache implements the JSR-168 caching specification. | |
328 | + The timeToIdle and timeToLive are set to defaults here, but are | |
329 | + always overriden on a per cache-element basis based on the portlet deployment | |
330 | + descriptor value. | |
331 | + | |
332 | + If there are more than 10000 elements it will overflow to the | |
333 | + disk cache, which in this configuration will go to wherever java.io.tmp is | |
334 | + defined on your system. On a standard Linux system this will be /tmp | |
335 | + timeToIdleSeconds and timeToLiveSeconds to live are both set at 8 hours (28800) | |
336 | + this is the default setting for portlets who set their expiration cache as -1 | |
337 | + --> | |
338 | + <cache name="portletContentCache" | |
339 | + maxElementsInMemory="10000" | |
340 | + maxElementsOnDisk="1000" | |
341 | + eternal="false" | |
342 | + overflowToDisk="false" | |
343 | + timeToIdleSeconds="28800" | |
344 | + timeToLiveSeconds="28800" | |
345 | + memoryStoreEvictionPolicy="LFU" | |
346 | + /> | |
347 | + | |
348 | + <cache name="preferencesCache" | |
349 | + maxElementsInMemory="10000" | |
350 | + maxElementsOnDisk="1000" | |
351 | + eternal="false" | |
352 | + overflowToDisk="false" | |
353 | + timeToIdleSeconds="28800" | |
354 | + timeToLiveSeconds="28800" | |
355 | + memoryStoreEvictionPolicy="LFU"> | |
356 | + <cacheEventListenerFactory | |
357 | + class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" | |
358 | + properties="replicateAsynchronously=true, replicatePuts=false, | |
359 | + replicateUpdates=false, replicateUpdatesViaCopy=false, | |
360 | + replicateRemovals=true"/> | |
361 | + </cache> | |
362 | + | |
363 | + | |
364 | + <cache name="portletApplicationOidCache" | |
365 | + maxElementsInMemory="500" | |
366 | + maxElementsOnDisk="1000" | |
367 | + eternal="false" | |
368 | + overflowToDisk="false" | |
369 | + timeToIdleSeconds="28800" | |
370 | + timeToLiveSeconds="28800" | |
371 | + memoryStoreEvictionPolicy="LFU"> | |
372 | + </cache> | |
373 | + | |
374 | + <cache name="portletApplicationNameCache" | |
375 | + maxElementsInMemory="500" | |
376 | + maxElementsOnDisk="1000" | |
377 | + eternal="false" | |
378 | + overflowToDisk="false" | |
379 | + timeToIdleSeconds="28800" | |
380 | + timeToLiveSeconds="28800" | |
381 | + memoryStoreEvictionPolicy="LFU"> | |
382 | + <cacheEventListenerFactory | |
383 | + class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" | |
384 | + properties="replicateAsynchronously=true, replicatePuts=false, | |
385 | + replicateUpdates=false, replicateUpdatesViaCopy=false, | |
386 | + replicateRemovals=true"/> | |
387 | + </cache> | |
388 | + | |
389 | + <cache name="portletDefinitionOidCache" | |
390 | + maxElementsInMemory="2000" | |
391 | + maxElementsOnDisk="1000" | |
392 | + eternal="false" | |
393 | + overflowToDisk="false" | |
394 | + timeToIdleSeconds="28800" | |
395 | + timeToLiveSeconds="28800" | |
396 | + memoryStoreEvictionPolicy="LFU"> | |
397 | + </cache> | |
398 | + | |
399 | + <cache name="portletDefinitionNameCache" | |
400 | + maxElementsInMemory="2000" | |
401 | + maxElementsOnDisk="1000" | |
402 | + eternal="false" | |
403 | + overflowToDisk="false" | |
404 | + timeToIdleSeconds="28800" | |
405 | + timeToLiveSeconds="28800" | |
406 | + memoryStoreEvictionPolicy="LFU"> | |
407 | + <cacheEventListenerFactory | |
408 | + class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" | |
409 | + properties="replicateAsynchronously=true, replicatePuts=false, | |
410 | + replicateUpdates=false, replicateUpdatesViaCopy=false, | |
411 | + replicateRemovals=true"/> | |
412 | + </cache> | |
413 | + | |
414 | + | |
415 | + <cache name="decorationConfigurationCache" | |
416 | + maxElementsInMemory="500" | |
417 | + maxElementsOnDisk="250" | |
418 | + eternal="false" | |
419 | + overflowToDisk="false" | |
420 | + timeToIdleSeconds="3600" | |
421 | + timeToLiveSeconds="3600" | |
422 | + memoryStoreEvictionPolicy="LFU"> | |
423 | + </cache> | |
424 | + | |
425 | + <cache name="desktopContentCache" | |
426 | + maxElementsInMemory="500" | |
427 | + maxElementsOnDisk="250" | |
428 | + eternal="false" | |
429 | + overflowToDisk="false" | |
430 | + timeToIdleSeconds="3600" | |
431 | + timeToLiveSeconds="3600" | |
432 | + memoryStoreEvictionPolicy="LFU"> | |
433 | + </cache> | |
434 | + | |
435 | + <!-- | |
436 | + Sample distributed cache named sampleDistributedCache1. | |
437 | + This cache replicates using defaults. | |
438 | + It also bootstraps from the cluster, using default properties. | |
439 | + <cache name="sampleDistributedCache1" | |
440 | + maxElementsInMemory="10" | |
441 | + eternal="false" | |
442 | + timeToIdleSeconds="100" | |
443 | + timeToLiveSeconds="100" | |
444 | + overflowToDisk="false"> | |
445 | + <cacheEventListenerFactory | |
446 | + class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/> | |
447 | + <bootstrapCacheLoaderFactory | |
448 | + class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/> | |
449 | + </cache> | |
450 | + --> | |
451 | + | |
452 | + | |
453 | + <!-- | |
454 | + Sample distributed cache named sampleDistributedCache2. | |
455 | + This cache replicates using specific properties. | |
456 | + It only replicates updates and does so synchronously via copy | |
457 | + <cache name="sampleDistributedCache2" | |
458 | + maxElementsInMemory="10" | |
459 | + eternal="false" | |
460 | + timeToIdleSeconds="100" | |
461 | + timeToLiveSeconds="100" | |
462 | + overflowToDisk="false"> | |
463 | + <cacheEventListenerFactory | |
464 | + class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" | |
465 | + properties="replicateAsynchronously=false, replicatePuts=false, | |
466 | + replicateUpdates=true, replicateUpdatesViaCopy=true, | |
467 | + replicateRemovals=false"/> | |
468 | + </cache> | |
469 | + --> | |
470 | + | |
471 | + <!-- | |
472 | + Sample distributed cache named sampleDistributedCache3. | |
473 | + This cache replicates using defaults except that the asynchronous replication | |
474 | + interval is set to 200ms. | |
475 | + <cache name="sampleDistributedCache3" | |
476 | + maxElementsInMemory="10" | |
477 | + eternal="false" | |
478 | + timeToIdleSeconds="100" | |
479 | + timeToLiveSeconds="100" | |
480 | + overflowToDisk="false"> | |
481 | + <cacheEventListenerFactory | |
482 | + class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" | |
483 | + properties="asynchronousReplicationIntervalMillis=200"/> | |
484 | + </cache> | |
485 | + --> | |
486 | + | |
487 | + <cache name="authenticationCache" | |
488 | + maxElementsInMemory="1000" | |
489 | + maxElementsOnDisk="1000" | |
490 | + eternal="false" | |
491 | + overflowToDisk="false" | |
492 | + timeToIdleSeconds="30" | |
493 | + timeToLiveSeconds="30" | |
494 | + memoryStoreEvictionPolicy="LFU" | |
495 | + /> | |
496 | + | |
497 | + <cache name="portletWindowCache" | |
498 | + maxElementsInMemory="200" | |
499 | + maxElementsOnDisk="1000" | |
500 | + eternal="false" | |
501 | + overflowToDisk="false" | |
502 | + timeToIdleSeconds="28800" | |
503 | + timeToLiveSeconds="28800" | |
504 | + memoryStoreEvictionPolicy="LFU"/> | |
505 | + | |
506 | + <cache name="decorationContentCache" | |
507 | + maxElementsInMemory="1000" | |
508 | + maxElementsOnDisk="1000" | |
509 | + eternal="false" | |
510 | + overflowToDisk="false" | |
511 | + timeToIdleSeconds="28800" | |
512 | + timeToLiveSeconds="28800" | |
513 | + memoryStoreEvictionPolicy="LFU" | |
514 | + /> | |
515 | + | |
516 | + <!-- | |
517 | + Jetspeed Page Manager Caches | |
518 | + --> | |
519 | + | |
520 | + <cache name="pageManagerOidCache" | |
521 | + maxElementsInMemory="${org.apache.jetspeed.ehcache.pagemanager.maxelements}" | |
522 | + eternal="false" | |
523 | + overflowToDisk="false" | |
524 | + timeToIdleSeconds="${org.apache.jetspeed.ehcache.pagemanager.element.ttl}" | |
525 | + timeToLiveSeconds="${org.apache.jetspeed.ehcache.pagemanager.element.ttl}" | |
526 | + memoryStoreEvictionPolicy="LFU"/> | |
527 | + | |
528 | + <cache name="pageManagerPathCache" | |
529 | + maxElementsInMemory="${org.apache.jetspeed.ehcache.pagemanager.maxelements}" | |
530 | + eternal="false" | |
531 | + overflowToDisk="false" | |
532 | + timeToIdleSeconds="${org.apache.jetspeed.ehcache.pagemanager.element.ttl}" | |
533 | + timeToLiveSeconds="${org.apache.jetspeed.ehcache.pagemanager.element.ttl}" | |
534 | + memoryStoreEvictionPolicy="LFU"> | |
535 | + <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" | |
536 | + properties="replicateAsynchronously=true, | |
537 | + replicatePuts=false, | |
538 | + replicateUpdates=false, | |
539 | + replicateUpdatesViaCopy=false, | |
540 | + replicateRemovals=true"/> | |
541 | + </cache> | |
542 | + | |
543 | +</ehcache> |
@@ -24,14 +24,14 @@ | ||
24 | 24 | class="org.apache.jetspeed.page.impl.DatabasePageManager"> |
25 | 25 | <!-- OJB configuration file resource path --> |
26 | 26 | <constructor-arg index="0"><value>JETSPEED-INF/ojb/page-manager-repository.xml</value></constructor-arg> |
27 | - <!-- folder/page/link cache size, default=128, min=128 --> | |
28 | - <constructor-arg index="1"><value>128</value></constructor-arg> | |
29 | - <!-- folder/page/link cache expires seconds, default=150, infinite=0, min=30 --> | |
30 | - <constructor-arg index="2"><value>0</value></constructor-arg> | |
31 | 27 | <!-- permissions security enabled flag, default=false --> |
32 | - <constructor-arg index="3"><value>false</value></constructor-arg> | |
28 | + <constructor-arg index="1"><value>false</value></constructor-arg> | |
33 | 29 | <!-- constraints security enabled flag, default=true --> |
34 | - <constructor-arg index="4"><value>false</value></constructor-arg> | |
30 | + <constructor-arg index="2"><value>false</value></constructor-arg> | |
31 | + <!-- folder/page/link cache --> | |
32 | + <constructor-arg index="3"><ref bean="pageManagerOidCache"/></constructor-arg> | |
33 | + <!-- folder/page/link path cache --> | |
34 | + <constructor-arg index="4"><ref bean="pageManagerPathCache"/></constructor-arg> | |
35 | 35 | </bean> |
36 | 36 | |
37 | 37 | <!-- Proxying --> |
@@ -89,6 +89,7 @@ | ||
89 | 89 | <include name="etc/db-ojb/*"/> |
90 | 90 | <include name="etc/import/assembly/import-page-manager.xml"/> |
91 | 91 | <include name="etc/import/assembly/repository-datasource-spring.xml"/> |
92 | + <include name="src/webapp/WEB-INF/assembly/cache.xml"/> | |
92 | 93 | <include name="src/webapp/WEB-INF/assembly/transaction.xml"/> |
93 | 94 | <include name="src/webapp/WEB-INF/assembly/alternate/interceptors.xml"/> |
94 | 95 | </fileset> |
@@ -44,14 +44,14 @@ | ||
44 | 44 | class="org.apache.jetspeed.page.impl.DatabasePageManager"> |
45 | 45 | <!-- OJB configuration file resource path --> |
46 | 46 | <constructor-arg index="0"><value>JETSPEED-INF/ojb/page-manager-repository.xml</value></constructor-arg> |
47 | - <!-- folder/page/link cache size, default=128, min=128 --> | |
48 | - <constructor-arg index="1"><value>128</value></constructor-arg> | |
49 | - <!-- folder/page/link cache expires seconds, default=150, infinite=0, min=30 --> | |
50 | - <constructor-arg index="2"><value>0</value></constructor-arg> | |
51 | 47 | <!-- permissions security enabled flag, default=false --> |
52 | - <constructor-arg index="3"><value>false</value></constructor-arg> | |
48 | + <constructor-arg index="1"><value>false</value></constructor-arg> | |
53 | 49 | <!-- constraints security enabled flag, default=true --> |
54 | - <constructor-arg index="4"><value>false</value></constructor-arg> | |
50 | + <constructor-arg index="2"><value>false</value></constructor-arg> | |
51 | + <!-- folder/page/link cache --> | |
52 | + <constructor-arg index="3"><ref bean="pageManagerOidCache"/></constructor-arg> | |
53 | + <!-- folder/page/link path cache --> | |
54 | + <constructor-arg index="4"><ref bean="pageManagerPathCache"/></constructor-arg> | |
55 | 55 | </bean> |
56 | 56 | |
57 | 57 | <!-- Proxying --> |
@@ -343,6 +343,7 @@ | ||
343 | 343 | <fileset dir="${jetspeedWebinfDir}" > |
344 | 344 | <include name="assembly/transaction.xml"/> |
345 | 345 | <include name="assembly/alternate/interceptors.xml"/> |
346 | + <include name="assembly/cache.xml"/> | |
346 | 347 | </fileset> |
347 | 348 | </copy> |
348 | 349 |