You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rave.apache.org by ca...@apache.org on 2012/03/07 18:09:35 UTC
svn commit: r1298022 - in /incubator/rave/trunk:
rave-components/rave-commons/
rave-components/rave-commons/src/main/java/org/apache/rave/model/
rave-components/rave-commons/src/main/java/org/apache/rave/service/
rave-components/rave-commons/src/main/j...
Author: carlucci
Date: Wed Mar 7 17:09:34 2012
New Revision: 1298022
URL: http://svn.apache.org/viewvc?rev=1298022&view=rev
Log:
RAVE-506: Static Content Fetcher
Added:
incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/model/
incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/model/StaticContent.java
incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/service/StaticContentFetcherService.java
incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/service/impl/DefaultStaticContentFetcherService.java
incubator/rave/trunk/rave-components/rave-commons/src/test/java/org/apache/rave/service/impl/DefaultStaticContentFetcherServiceTest.java
incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/tag/StaticContentTag.java
- copied, changed from r1297542, incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/tag/RegionWidgetTag.java
incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/tag/StaticContentTagTest.java
Modified:
incubator/rave/trunk/rave-components/rave-commons/pom.xml
incubator/rave/trunk/rave-components/rave-core/src/main/resources/org/apache/rave/core-applicationContext.xml
incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/interceptors/CommonModelHandlerInterceptor.java
incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/util/ModelKeys.java
incubator/rave/trunk/rave-components/rave-web/src/main/resources/META-INF/rave.tld
incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/interceptors/CommonModelHandlerInterceptorTest.java
incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/common/header.jsp
Modified: incubator/rave/trunk/rave-components/rave-commons/pom.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-commons/pom.xml?rev=1298022&r1=1298021&r2=1298022&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-commons/pom.xml (original)
+++ incubator/rave/trunk/rave-components/rave-commons/pom.xml Wed Mar 7 17:09:34 2012
@@ -61,6 +61,10 @@
</dependency>
<dependency>
<groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
</dependency>
<dependency>
@@ -106,6 +110,11 @@
<artifactId>aspectjweaver</artifactId>
<version>1.6.9</version>
</dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
Added: incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/model/StaticContent.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/model/StaticContent.java?rev=1298022&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/model/StaticContent.java (added)
+++ incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/model/StaticContent.java Wed Mar 7 17:09:34 2012
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.rave.model;
+
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * POJO representing a static content artifact
+ */
+public class StaticContent {
+ private String id;
+ private URI location;
+ private String content;
+ // replacementTokens can be used when the static content artifact is a template and needs some
+ // environment specific tokens to be replaced
+ private Map<String, String> replacementTokens;
+
+ public StaticContent(String id, URI location, Map<String, String> replacementTokens) {
+ this.id = id;
+ this.location = location;
+ this.replacementTokens = replacementTokens == null ? new HashMap<String, String>() : replacementTokens;
+ this.content = "";
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public URI getLocation() {
+ return location;
+ }
+
+ public Map<String, String> getReplacementTokens() {
+ return replacementTokens;
+ }
+
+ @Override
+ public String toString() {
+ return "StaticContent{" + "id=" + id + ", location=" + location + "}";
+ }
+}
Added: incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/service/StaticContentFetcherService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/service/StaticContentFetcherService.java?rev=1298022&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/service/StaticContentFetcherService.java (added)
+++ incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/service/StaticContentFetcherService.java Wed Mar 7 17:09:34 2012
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.rave.service;
+
+/**
+ * Interface for dealing with remote Static Content (such as HTML or JavaScript fragments) so that
+ * Rave can render them directly on pages and improve performance by internally caching the content
+ */
+public interface StaticContentFetcherService {
+ /**
+ * Returns the content from the cache for the supplied key
+ *
+ * @param key the cache key of the content artifact to lookup
+ * @return String representing the static content
+ */
+ String getContent(String key);
+
+ /**
+ * Refreshes all of the cached StaticContent artifacts currently in the cache
+ */
+ void refreshAll();
+
+ /**
+ * Refresh a single StaticContent artifact in the cache based on the supplied key
+ * @param key the cache key of the content artifact to refresh
+ */
+ void refresh(String key);
+}
Added: incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/service/impl/DefaultStaticContentFetcherService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/service/impl/DefaultStaticContentFetcherService.java?rev=1298022&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/service/impl/DefaultStaticContentFetcherService.java (added)
+++ incubator/rave/trunk/rave-components/rave-commons/src/main/java/org/apache/rave/service/impl/DefaultStaticContentFetcherService.java Wed Mar 7 17:09:34 2012
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.rave.service.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.rave.model.StaticContent;
+import org.apache.rave.service.StaticContentFetcherService;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class DefaultStaticContentFetcherService implements StaticContentFetcherService {
+ private static final Log log = LogFactory.getLog(DefaultStaticContentFetcherService.class);
+ private Map<String, StaticContent> contentMap;
+ private RestTemplate restTemplate;
+
+ public DefaultStaticContentFetcherService(RestTemplate restTemplate, List<StaticContent> contentObjects) {
+ this.restTemplate = restTemplate;
+ contentMap = new HashMap<String, StaticContent>();
+ for (StaticContent contentObject : contentObjects) {
+ contentMap.put(contentObject.getId(), contentObject);
+ }
+ }
+
+ @Override
+ public String getContent(String key) {
+ log.debug("getContent(" + key + ")");
+ StaticContent content = contentMap.get(key);
+ if (content == null) {
+ throw new IllegalArgumentException("Invalid content key: " + key);
+ }
+ return content.getContent();
+ }
+
+ @Override
+ public void refreshAll() {
+ log.debug("refreshAll()");
+ for (StaticContent curEntry : contentMap.values()) {
+ refreshFromLocation(curEntry);
+ }
+ }
+
+ @Override
+ public void refresh(String key) {
+ log.debug("refresh(" + key + ")");
+ //if the key exists in the content map, refresh it
+ StaticContent item = contentMap.get(key);
+ if (item != null) {
+ refreshFromLocation(item);
+ }
+ }
+
+ private void refreshFromLocation(StaticContent staticContent) {
+ log.debug("refreshFromLocation() - for " + staticContent);
+ try {
+ //We need an intermediate temp content string here so we don't even accidentally hand out a reference to
+ //a not-fully-token-replaced piece of content. Very unlikely, but could happen.
+ String tempContent = restTemplate.getForObject(staticContent.getLocation(), String.class);
+ for (Map.Entry<String, String> replacementTokenEntry : staticContent.getReplacementTokens().entrySet()) {
+ tempContent = tempContent.replaceAll(replacementTokenEntry.getKey(), replacementTokenEntry.getValue());
+ }
+ staticContent.setContent(tempContent);
+ } catch (RestClientException e) {
+ //RestClientException handles server errors 5xx, client errors 4xx, and IO errors
+ log.error("Unable to process {" + staticContent.getLocation() + "}", e);
+ }
+ }
+}
Added: incubator/rave/trunk/rave-components/rave-commons/src/test/java/org/apache/rave/service/impl/DefaultStaticContentFetcherServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-commons/src/test/java/org/apache/rave/service/impl/DefaultStaticContentFetcherServiceTest.java?rev=1298022&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-commons/src/test/java/org/apache/rave/service/impl/DefaultStaticContentFetcherServiceTest.java (added)
+++ incubator/rave/trunk/rave-components/rave-commons/src/test/java/org/apache/rave/service/impl/DefaultStaticContentFetcherServiceTest.java Wed Mar 7 17:09:34 2012
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.rave.service.impl;
+
+import org.apache.rave.model.StaticContent;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class DefaultStaticContentFetcherServiceTest {
+ private RestTemplate restTemplate;
+
+ private final String VALID_URL1 = "http://www.google.com/";
+ private final String VALID_URL1_ID = "google";
+ private final String VALID_URL1_CONTENT = "Bogus www.google.page";
+ private StaticContent VALID_CONTENT_1;
+
+ private final String VALID_URL2 = "http://www.yahoo.com/";
+ private final String VALID_URL2_ID = "yahoo";
+ private final String VALID_URL2_CONTENT = "Bogus www.yahoo.page";
+ private StaticContent VALID_CONTENT_2;
+
+ private final String VALID_URL3 = "http://www.bing.com/";
+ private final String VALID_URL3_ID = "bing";
+ private final String VALID_URL3_CONTENT = "Bogus www.bing.page with replacement tokens: {token1} && {token2}";
+ private final String VALID_URL3_TOKEN_1 = "\\{token1\\}";
+ private final String VALID_URL3_TOKEN_2 = "\\{token2\\}";
+ private final String VALID_URL3_TOKEN_1_REPLACEMENT = "token-1-value";
+ private final String VALID_URL3_TOKEN_2_REPLACEMENT = "token-2-value";
+ private final String VALID_URL3_CONTENT_WITH_REPLACEMENTS = VALID_URL3_CONTENT
+ .replaceAll(VALID_URL3_TOKEN_1, VALID_URL3_TOKEN_1_REPLACEMENT)
+ .replaceAll(VALID_URL3_TOKEN_2, VALID_URL3_TOKEN_2_REPLACEMENT);
+ private StaticContent VALID_CONTENT_3;
+
+ @Before
+ public void setUp() throws URISyntaxException {
+ VALID_CONTENT_1 = new StaticContent(VALID_URL1_ID, new URI(VALID_URL1), null);
+ VALID_CONTENT_2 = new StaticContent(VALID_URL2_ID, new URI(VALID_URL2), null);
+ VALID_CONTENT_3 = new StaticContent(VALID_URL3_ID, new URI(VALID_URL3), null);
+
+ restTemplate = createNiceMock(RestTemplate.class);
+ }
+
+ @Test
+ public void getContent_validId() throws URISyntaxException {
+ DefaultStaticContentFetcherService service = new DefaultStaticContentFetcherService(restTemplate, Arrays.asList(VALID_CONTENT_1, VALID_CONTENT_2, VALID_CONTENT_3));
+ expectAllRestTemplateGetForObject();
+ replay(restTemplate);
+
+ //Initially all content will be blank
+ assertBlankInitialContent(service);
+
+ service.refreshAll();
+
+ //Now that the content has been refreshed we should get a valid value
+ assertThat(service.getContent(VALID_URL1_ID), is(VALID_URL1_CONTENT));
+
+ verify(restTemplate);
+ }
+
+ @Test
+ public void getContent_validIdsWithReplacementTokens() throws URISyntaxException {
+ //Setup our third content object to use the replacement feature and test for it
+ Map<String, String> tokenReplacements = new HashMap<String, String>();
+ tokenReplacements.put(VALID_URL3_TOKEN_1, VALID_URL3_TOKEN_1_REPLACEMENT);
+ tokenReplacements.put(VALID_URL3_TOKEN_2, VALID_URL3_TOKEN_2_REPLACEMENT);
+ VALID_CONTENT_3 = new StaticContent(VALID_URL3_ID, new URI(VALID_URL3), tokenReplacements);
+
+ expectAllRestTemplateGetForObject();
+ replay(restTemplate);
+
+ DefaultStaticContentFetcherService service = new DefaultStaticContentFetcherService(restTemplate, Arrays.asList(VALID_CONTENT_1, VALID_CONTENT_2, VALID_CONTENT_3));
+
+ service.refreshAll();
+
+ assertThat(service.getContent(VALID_URL1_ID), is(VALID_URL1_CONTENT));
+ assertThat(service.getContent(VALID_URL2_ID), is(VALID_URL2_CONTENT));
+ assertThat(service.getContent(VALID_URL3_ID), is(VALID_URL3_CONTENT_WITH_REPLACEMENTS));
+
+ verify(restTemplate);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void getContent_invalidId() {
+ DefaultStaticContentFetcherService service = new DefaultStaticContentFetcherService(restTemplate, Arrays.asList(VALID_CONTENT_1, VALID_CONTENT_2, VALID_CONTENT_3));
+ service.getContent("INVALID");
+ }
+
+ @Test
+ public void refreshAll() throws URISyntaxException {
+ DefaultStaticContentFetcherService service = new DefaultStaticContentFetcherService(restTemplate, Arrays.asList(VALID_CONTENT_1, VALID_CONTENT_2, VALID_CONTENT_3));
+
+ assertBlankInitialContent(service);
+
+ expectAllRestTemplateGetForObject();
+ replay(restTemplate);
+
+ service.refreshAll();
+
+ //Now that the content has been refreshed we should get a valid value
+ assertThat(service.getContent(VALID_URL1_ID), is(VALID_URL1_CONTENT));
+ assertThat(service.getContent(VALID_URL2_ID), is(VALID_URL2_CONTENT));
+ assertThat(service.getContent(VALID_URL3_ID), is(VALID_URL3_CONTENT));
+ }
+
+ @Test
+ public void refresh_invalidKey() throws URISyntaxException {
+ DefaultStaticContentFetcherService service = new DefaultStaticContentFetcherService(restTemplate, Arrays.asList(VALID_CONTENT_1, VALID_CONTENT_2, VALID_CONTENT_3));
+
+ assertBlankInitialContent(service);
+
+ expectAllRestTemplateGetForObject();
+ replay(restTemplate);
+
+ service.refresh("INVALID_CACHE_KEY");
+
+ //Now that the content has been refreshed we should get a valid value
+ assertThat(service.getContent(VALID_URL1_ID), is(""));
+ assertThat(service.getContent(VALID_URL2_ID), is(""));
+ assertThat(service.getContent(VALID_URL3_ID), is(""));
+ }
+
+ @Test
+ public void refresh_validKey() throws URISyntaxException {
+ DefaultStaticContentFetcherService service = new DefaultStaticContentFetcherService(restTemplate, Arrays.asList(VALID_CONTENT_1, VALID_CONTENT_2, VALID_CONTENT_3));
+
+ assertBlankInitialContent(service);
+
+ expectAllRestTemplateGetForObject();
+ replay(restTemplate);
+
+ service.refresh(VALID_URL2_ID);
+
+ //Now that the content has been refreshed we should get a valid value
+ assertThat(service.getContent(VALID_URL1_ID), is(""));
+ assertThat(service.getContent(VALID_URL2_ID), is(VALID_URL2_CONTENT));
+ assertThat(service.getContent(VALID_URL3_ID), is(""));
+ }
+
+ @Test
+ public void refresh_fetchErrorExistingValidContentPreserved() throws URISyntaxException {
+ //Create the fetcher, refresh the content and then validate that we have the expected content
+ DefaultStaticContentFetcherService service = new DefaultStaticContentFetcherService(restTemplate, Arrays.asList(VALID_CONTENT_1, VALID_CONTENT_2, VALID_CONTENT_3));
+
+ expectAllRestTemplateGetForObject();
+ replay(restTemplate);
+
+ service.refreshAll();
+
+ assertThat(service.getContent(VALID_URL1_ID), is(VALID_URL1_CONTENT));
+ assertThat(service.getContent(VALID_URL2_ID), is(VALID_URL2_CONTENT));
+ assertThat(service.getContent(VALID_URL3_ID), is(VALID_URL3_CONTENT));
+
+ //Now create a new RestTemplate mock and have it return new content for two of the items and throw an exception
+ //for the third -- in this case the two items should have the new content but the third with the exception should
+ //retain the old good cached content.
+ String newContent = "new content from refresh";
+ restTemplate = createNiceMock(RestTemplate.class);
+ expect(restTemplate.getForObject(new URI(VALID_URL1), String.class)).andReturn(newContent);
+ expect(restTemplate.getForObject(new URI(VALID_URL2), String.class)).andThrow(new RestClientException("Boom"));
+ expect(restTemplate.getForObject(new URI(VALID_URL3), String.class)).andReturn(newContent);
+ replay(restTemplate);
+ //Use reflection to stuff the new RestTemplate instance into our existing content fetcher instance
+ ReflectionTestUtils.setField(service, "restTemplate", restTemplate);
+
+ service.refreshAll();
+
+ assertThat(service.getContent(VALID_URL1_ID), is(newContent));
+ assertThat(service.getContent(VALID_URL2_ID), is(VALID_URL2_CONTENT));
+ assertThat(service.getContent(VALID_URL3_ID), is(newContent));
+ }
+
+ private void expectAllRestTemplateGetForObject() throws URISyntaxException {
+ expect(restTemplate.getForObject(new URI(VALID_URL1), String.class)).andReturn(VALID_URL1_CONTENT);
+ expect(restTemplate.getForObject(new URI(VALID_URL2), String.class)).andReturn(VALID_URL2_CONTENT);
+ expect(restTemplate.getForObject(new URI(VALID_URL3), String.class)).andReturn(VALID_URL3_CONTENT);
+ }
+
+ private void assertBlankInitialContent(DefaultStaticContentFetcherService service) {
+ assertThat(service.getContent(VALID_URL1_ID), is(""));
+ assertThat(service.getContent(VALID_URL2_ID), is(""));
+ assertThat(service.getContent(VALID_URL3_ID), is(""));
+ }
+}
Modified: incubator/rave/trunk/rave-components/rave-core/src/main/resources/org/apache/rave/core-applicationContext.xml
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/resources/org/apache/rave/core-applicationContext.xml?rev=1298022&r1=1298021&r2=1298022&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/resources/org/apache/rave/core-applicationContext.xml (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/resources/org/apache/rave/core-applicationContext.xml Wed Mar 7 17:09:34 2012
@@ -124,13 +124,13 @@
</property>-->
</bean>
<!--
- NOTE: to use mail session you'll need to configure following within catalina_home/conf/context.xml
- <Resource name="mail/Session" auth="Container" type="javax.mail.Session" mail.smtp.host="my.mail.host"/>
+ NOTE: to use mail session you'll need to configure following within catalina_home/conf/context.xml
+ <Resource name="mail/Session" auth="Container" type="javax.mail.Session" mail.smtp.host="my.mail.host"/>
- Further, activation & mail jars needs to be placed within catalina_home/lib folder
- -->
- <!--
- <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
+ Further, activation & mail jars needs to be placed within catalina_home/lib folder
+ -->
+ <!--
+ <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="session" ref="mailSession"/>
</bean>
<bean id="mailSession" class="org.springframework.jndi.JndiObjectFactoryBean">
@@ -138,4 +138,53 @@
</bean>
-->
+ <bean id="restTemplate" class="org.springframework.web.client.RestTemplate" />
+
+ <bean id="staticContentCache" class="org.apache.rave.service.impl.DefaultStaticContentFetcherService">
+ <constructor-arg ref="restTemplate"/>
+ <constructor-arg>
+ <list>
+ <!-- example of a Static Content source that doesn't have any string token placeholders in its content body
+ <bean class="org.apache.rave.model.StaticContent">
+ <constructor-arg index="0" value="standardCompanyHeader"/>
+ <constructor-arg index="1" value="${company.header.host}/content/standard_header.html"/>
+ <constructor-arg index="2">
+ <null/>
+ </constructor-arg>
+ </bean>
+ -->
+ <!-- example of a Static Content source that has string token placeholders
+ <bean class="org.apache.rave.model.StaticContent">
+ <constructor-arg index="0" value="environmentSpecificContent"/>
+ <constructor-arg index="1" value="${company.header.host}/content/footer.html"/>
+ <constructor-arg index="2">
+ <map>
+ <entry key="\{supportEmail\}" value="${raveproperty.supportemail}"/>
+ <entry key="\{productVersion\}" value="${raveproperty.version}"/>
+ </map>
+ </constructor-arg>
+ </bean>
+ -->
+ </list>
+ </constructor-arg>
+ </bean>
+
+ <!-- example on how to setup a Spring Timer to refresh the Static Content cache at a fixed interval
+ <bean id="refreshStaticContentCacheScheduledTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
+ <property name="delay" value="5000"/>
+ <property name="period" value="300000"/>
+ <property name="timerTask">
+ <bean class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean"
+ p:targetObject-ref="staticContentCache" p:targetMethod="refreshAll"/>
+ </property>
+ </bean>
+ <bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
+ <property name="daemon" value="true"/>
+ <property name="scheduledTimerTasks">
+ <list>
+ <ref local="refreshStaticContentCacheScheduledTask"/>
+ </list>
+ </property>
+ </bean>
+ -->
</beans>
\ No newline at end of file
Modified: incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/interceptors/CommonModelHandlerInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/interceptors/CommonModelHandlerInterceptor.java?rev=1298022&r1=1298021&r2=1298022&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/interceptors/CommonModelHandlerInterceptor.java (original)
+++ incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/interceptors/CommonModelHandlerInterceptor.java Wed Mar 7 17:09:34 2012
@@ -21,6 +21,7 @@ package org.apache.rave.portal.web.inter
import org.apache.rave.portal.service.PortalPreferenceService;
import org.apache.rave.portal.web.util.ModelKeys;
+import org.apache.rave.service.StaticContentFetcherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.ui.ModelMap;
@@ -36,10 +37,12 @@ import javax.servlet.http.HttpServletRes
public class CommonModelHandlerInterceptor extends HandlerInterceptorAdapter {
private final PortalPreferenceService preferenceService;
+ private final StaticContentFetcherService staticContentFetcherService;
@Autowired
- public CommonModelHandlerInterceptor(PortalPreferenceService preferenceService) {
+ public CommonModelHandlerInterceptor(PortalPreferenceService preferenceService, StaticContentFetcherService staticContentFetcherService) {
this.preferenceService = preferenceService;
+ this.staticContentFetcherService = staticContentFetcherService;
}
@Override
@@ -47,6 +50,7 @@ public class CommonModelHandlerIntercept
if (modelAndView != null) {
ModelMap map = modelAndView.getModelMap();
map.addAttribute(ModelKeys.PORTAL_SETTINGS, preferenceService.getPreferencesAsMap());
+ map.addAttribute(ModelKeys.STATIC_CONTENT_CACHE, staticContentFetcherService);
}
super.postHandle(request, response, handler, modelAndView);
}
Copied: incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/tag/StaticContentTag.java (from r1297542, incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/tag/RegionWidgetTag.java)
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/tag/StaticContentTag.java?p2=incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/tag/StaticContentTag.java&p1=incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/tag/RegionWidgetTag.java&r1=1297542&r2=1298022&rev=1298022&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/tag/RegionWidgetTag.java (original)
+++ incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/tag/StaticContentTag.java Wed Mar 7 17:09:34 2012
@@ -16,73 +16,40 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.rave.portal.web.tag;
-import org.apache.commons.lang.StringEscapeUtils;
-import org.apache.rave.portal.model.RegionWidget;
-import org.apache.rave.portal.web.renderer.RenderScope;
-import org.apache.rave.portal.web.renderer.RenderService;
-import org.apache.rave.portal.web.renderer.ScriptLocation;
-import org.apache.rave.portal.web.renderer.ScriptManager;
-
+import org.apache.rave.service.StaticContentFetcherService;
import javax.servlet.jsp.JspException;
/**
- * JSP tag that renders a RegionWidget
+ * JSP tag that renders a block of static content from the StaticContentFetcherService cache
*/
-public class RegionWidgetTag extends AbstractContextAwareSingletonBeanDependentTag<RenderService> {
-
- private RegionWidget regionWidget;
+public class StaticContentTag extends AbstractContextAwareSingletonBeanDependentTag<StaticContentFetcherService> {
+ private String contentKey;
- // Script block for disabled gadget
- private static final String DISABLED_SCRIPT_BLOCK =
- "<script>rave.registerWidget(widgetsByRegionIdMap, %1$s, {type: 'DISABLED'," +
- " regionWidgetId: %2$s," +
- " disabledMessage: '%3$s'," +
- " collapsed: %4$s," +
- " widgetId: %5$s});</script>";
-
- public RegionWidgetTag() {
- super(RenderService.class);
+ public StaticContentTag() {
+ super(StaticContentFetcherService.class);
}
- public RegionWidget getRegionWidget() {
- return regionWidget;
+ public String getContentKey() {
+ return contentKey;
}
- public void setRegionWidget(RegionWidget regionWidget) {
- this.regionWidget = regionWidget;
+ public void setContentKey(String contentKey) {
+ this.contentKey = contentKey;
}
- /**
- * Delegates rendering of the RegionWidget to the RenderService
- *
- * @return EVAL_BODY_INCLUDE if no exception is thrown
- * @throws JspException if the regionWidget is not set or is not supported by the renderService.
- */
@Override
public int doStartTag() throws JspException {
-
- if (regionWidget != null && getBean().getSupportedWidgetTypes().contains(regionWidget.getWidget().getType()) ) {
- if ( regionWidget.getWidget().isDisableRendering() ) {
- ScriptManager scriptManager = getBeanFromContext(ScriptManager.class);
- String widgetScript = String.format(DISABLED_SCRIPT_BLOCK, regionWidget.getRegion().getEntityId(),
- regionWidget.getEntityId(),
- StringEscapeUtils.escapeJavaScript(regionWidget.getWidget().getDisableRenderingMessage()),
- regionWidget.isCollapsed(),
- regionWidget.getWidget().getEntityId());
- scriptManager.registerScriptBlock(widgetScript, ScriptLocation.AFTER_RAVE, RenderScope.CURRENT_REQUEST, getContext());
- } else {
- writeString(getBean().render(regionWidget, getContext()));
- }
+ if (contentKey != null) {
+ writeString(getBean().getContent(contentKey));
}
else {
- throw new JspException("Unsupported regionWidget type or regionWidget not set: " + regionWidget);
+ throw new JspException("contentKey can't be null");
}
- //Certain JSP implementations use tag pools. Setting the regionWidget to null ensures that there is no chance a given tag
- //will accidentally re-use a region widget if the attribute in the JSP is empty
- regionWidget = null;
+ //Certain JSP implementations use tag pools. Setting the contentKey to null ensures that there is no chance a given tag
+ //will accidentally re-use a contentKey if the attribute in the JSP is empty
+ contentKey = null;
return EVAL_BODY_INCLUDE;
}
-}
+}
\ No newline at end of file
Modified: incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/util/ModelKeys.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/util/ModelKeys.java?rev=1298022&r1=1298021&r2=1298022&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/util/ModelKeys.java (original)
+++ incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/util/ModelKeys.java Wed Mar 7 17:09:34 2012
@@ -51,4 +51,5 @@ public class ModelKeys {
public static final String DEFAULT_TAG_PAGE = "defaultTagPage";
public static final String CAPTCHA_HTML = "captchaHtml";
public static final String REDIRECT_MESSAGE = "message";
+ public static final String STATIC_CONTENT_CACHE = "staticContentCache";
}
\ No newline at end of file
Modified: incubator/rave/trunk/rave-components/rave-web/src/main/resources/META-INF/rave.tld
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/main/resources/META-INF/rave.tld?rev=1298022&r1=1298021&r2=1298022&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/main/resources/META-INF/rave.tld (original)
+++ incubator/rave/trunk/rave-components/rave-web/src/main/resources/META-INF/rave.tld Wed Mar 7 17:09:34 2012
@@ -50,4 +50,18 @@
<type>org.apache.rave.portal.web.renderer.ScriptLocation</type>
</attribute>
</tag>
+ <tag>
+ <description>Renders a static content fragment based on the cache key</description>
+ <name>render-static-content</name>
+ <tag-class>org.apache.rave.portal.web.tag.StaticContentTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>The cache key of the static content to render</description>
+ <name>contentKey</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ </tag>
+
</taglib>
Modified: incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/interceptors/CommonModelHandlerInterceptorTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/interceptors/CommonModelHandlerInterceptorTest.java?rev=1298022&r1=1298021&r2=1298022&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/interceptors/CommonModelHandlerInterceptorTest.java (original)
+++ incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/interceptors/CommonModelHandlerInterceptorTest.java Wed Mar 7 17:09:34 2012
@@ -22,6 +22,7 @@ package org.apache.rave.portal.web.inter
import org.apache.rave.portal.model.PortalPreference;
import org.apache.rave.portal.service.PortalPreferenceService;
import org.apache.rave.portal.web.util.ModelKeys;
+import org.apache.rave.service.StaticContentFetcherService;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
@@ -31,12 +32,9 @@ import org.springframework.web.servlet.M
import java.util.HashMap;
import java.util.Map;
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.assertTrue;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.*;
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.CoreMatchers.*;
/**
* Test for {@link CommonModelHandlerInterceptor}
@@ -45,11 +43,14 @@ public class CommonModelHandlerIntercept
CommonModelHandlerInterceptor interceptor;
PortalPreferenceService portalPreferenceService;
+ StaticContentFetcherService staticContentFetcherService;
@Before
public void setUp() throws Exception {
portalPreferenceService = createMock(PortalPreferenceService.class);
- interceptor = new CommonModelHandlerInterceptor(portalPreferenceService);
+ staticContentFetcherService = createMock(StaticContentFetcherService.class);
+
+ interceptor = new CommonModelHandlerInterceptor(portalPreferenceService, staticContentFetcherService);
}
@Test
@@ -66,7 +67,9 @@ public class CommonModelHandlerIntercept
interceptor.postHandle(request, response, handler, modelAndView);
verify(portalPreferenceService);
- assertTrue(modelAndView.getModelMap().containsKey(ModelKeys.PORTAL_SETTINGS));
+ Map<String, Object> modelMap = modelAndView.getModelMap();
+ assertThat((Map<String, PortalPreference>) modelMap.get(ModelKeys.PORTAL_SETTINGS), sameInstance(preferenceMap));
+ assertThat((StaticContentFetcherService) modelMap.get(ModelKeys.STATIC_CONTENT_CACHE), sameInstance(staticContentFetcherService));
}
@Test
public void testPostHandle_noModelAndView() throws Exception {
@@ -76,6 +79,6 @@ public class CommonModelHandlerIntercept
ModelAndView modelAndView = null;
interceptor.postHandle(request, response, handler, modelAndView);
- assertNull(modelAndView);
+ assertThat(modelAndView, is(nullValue(ModelAndView.class)));
}
}
Added: incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/tag/StaticContentTagTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/tag/StaticContentTagTest.java?rev=1298022&view=auto
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/tag/StaticContentTagTest.java (added)
+++ incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/tag/StaticContentTagTest.java Wed Mar 7 17:09:34 2012
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.rave.portal.web.tag;
+
+
+import org.apache.rave.service.StaticContentFetcherService;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.web.context.WebApplicationContext;
+
+import javax.servlet.ServletContext;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.JspWriter;
+import javax.servlet.jsp.PageContext;
+import java.io.IOException;
+
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class StaticContentTagTest {
+ private StaticContentFetcherService service;
+ private StaticContentTag tag;
+ private WebApplicationContext wContext;
+ private PageContext pageContext;
+ private ServletContext servletContext;
+ private JspWriter writer;
+
+ private final String VALID_CACHE_KEY = "myCacheKey";
+ private final String VALID_STATIC_CONTENT = "the content of the static content artifact";
+
+ @Before
+ public void setup() throws JspException {
+ service = createMock(StaticContentFetcherService.class);
+ wContext = createNiceMock(WebApplicationContext.class);
+ pageContext = createNiceMock(PageContext.class);
+ servletContext = createNiceMock(ServletContext.class);
+ writer = createNiceMock(JspWriter.class);
+
+ tag = new StaticContentTag();
+ tag.setPageContext(pageContext);
+ }
+
+ @Test
+ public void doStartTag_validKey() throws IOException, JspException {
+ tag.setContentKey(VALID_CACHE_KEY);
+
+ expect(service.getContent(VALID_CACHE_KEY)).andReturn(VALID_STATIC_CONTENT);
+ expect(pageContext.getServletContext()).andReturn(servletContext).anyTimes();
+ expect(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)).andReturn(wContext).anyTimes();
+ expect(wContext.getBean(StaticContentFetcherService.class)).andReturn(service).anyTimes();
+ expect(pageContext.getOut()).andReturn(writer);
+ replay(service, pageContext, servletContext, wContext, writer);
+
+ int result = tag.doStartTag();
+
+ assertThat(result, is(javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE));
+ verify(service, pageContext, servletContext, wContext, writer);
+ }
+
+ @Test(expected = JspException.class)
+ public void doStartTag_nullKey() throws IOException, JspException {
+ tag.setContentKey(null);
+ tag.doStartTag();
+ }
+
+ @Test
+ public void getCacheKey() {
+ assertThat(tag.getContentKey(), is(nullValue(String.class)));
+ tag.setContentKey(VALID_CACHE_KEY);
+ assertThat(tag.getContentKey(), is(VALID_CACHE_KEY));
+ }
+}
Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/common/header.jsp
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/common/header.jsp?rev=1298022&r1=1298021&r2=1298022&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/common/header.jsp (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/common/header.jsp Wed Mar 7 17:09:34 2012
@@ -16,4 +16,9 @@ KIND, either express or implied. See th
specific language governing permissions and limitations
under the License.
--%>
-<%-- Common header will go here... --%>
\ No newline at end of file
+<%-- Common header will go here... --%>
+
+<%-- example on how to render static content from the cache using the tag library
+<%@ include file="/WEB-INF/jsp/includes/taglibs.jsp" %>
+<portal:render-static-content contentKey="standardCompanyHeader" />
+--%>
\ No newline at end of file