/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* 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 the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>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.apereo.portal.rendering;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import net.sf.ehcache.Ehcache;
import org.apereo.portal.character.stream.CharacterEventReader;
import org.apereo.portal.character.stream.CharacterEventSource;
import org.apereo.portal.character.stream.PortletContentPlaceholderEventSource;
import org.apereo.portal.character.stream.PortletHeaderPlaceholderEventSource;
import org.apereo.portal.character.stream.PortletHelpPlaceholderEventSource;
import org.apereo.portal.character.stream.PortletTitlePlaceholderEventSource;
import org.apereo.portal.character.stream.events.CharacterDataEventImpl;
import org.apereo.portal.character.stream.events.CharacterEvent;
import org.apereo.portal.character.stream.events.PortletContentPlaceholderEventImpl;
import org.apereo.portal.character.stream.events.PortletHeaderPlaceholderEventImpl;
import org.apereo.portal.character.stream.events.PortletHelpPlaceholderEventImpl;
import org.apereo.portal.character.stream.events.PortletTitlePlaceholderEventImpl;
import org.apereo.portal.portlet.om.IPortletWindow;
import org.apereo.portal.portlet.registry.IPortletWindowRegistry;
import org.apereo.portal.utils.Tuple;
import org.apereo.portal.utils.cache.CacheKey;
import org.apereo.portal.xml.XmlUtilities;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
/**
*/
@RunWith(MockitoJUnitRunner.class)
public class StAXSerializingComponentTest {
@InjectMocks
private StAXSerializingComponent staxSerializingComponent = new StAXSerializingComponent();
@Mock private XmlUtilities xmlUtilities;
@Mock private Ehcache stringCache;
@Test
public void testSerializing() throws Exception {
final MockHttpServletRequest request = new MockHttpServletRequest();
final MockHttpServletResponse response = new MockHttpServletResponse();
final IPortletWindowRegistry portletWindowRegistry = mock(IPortletWindowRegistry.class);
when(xmlUtilities.getHtmlOutputFactory()).thenReturn(XMLOutputFactory.newFactory());
//Setup a simple pass-through parent
staxSerializingComponent.setWrappedComponent(new SimpleStAXSource());
staxSerializingComponent.setXmlUtilities(xmlUtilities);
final IPortletWindow portletWindow = mock(IPortletWindow.class);
when(portletWindowRegistry.getPortletWindow(
Matchers.eq(request), Matchers.any(StartElement.class)))
.thenReturn(new Tuple<IPortletWindow, StartElement>(portletWindow, null));
when(portletWindowRegistry.getOrCreateDefaultPortletWindowByLayoutNodeId(
Matchers.eq(request), Matchers.anyString()))
.thenReturn(portletWindow);
final PortletContentPlaceholderEventSource contentPlaceholderEventSource =
new PortletContentPlaceholderEventSource();
contentPlaceholderEventSource.setPortletWindowRegistry(portletWindowRegistry);
final PortletHeaderPlaceholderEventSource headerPlaceholderEventSource =
new PortletHeaderPlaceholderEventSource();
headerPlaceholderEventSource.setPortletWindowRegistry(portletWindowRegistry);
final PortletTitlePlaceholderEventSource portletTitlePlaceholderEventSource =
new PortletTitlePlaceholderEventSource();
portletTitlePlaceholderEventSource.setPortletWindowRegistry(portletWindowRegistry);
final PortletHelpPlaceholderEventSource portletHelpPlaceholderEventSource =
new PortletHelpPlaceholderEventSource();
portletHelpPlaceholderEventSource.setPortletWindowRegistry(portletWindowRegistry);
final Map<String, CharacterEventSource> chunkingElements =
new LinkedHashMap<String, CharacterEventSource>();
chunkingElements.put("portlet", contentPlaceholderEventSource);
chunkingElements.put("portlet-header", headerPlaceholderEventSource);
staxSerializingComponent.setChunkingElements(chunkingElements);
final Map<String, CharacterEventSource> chunkingPatterns =
new LinkedHashMap<String, CharacterEventSource>();
chunkingPatterns.put(
"\\{up-portlet-title\\(([^\\)]+)\\)\\}", portletTitlePlaceholderEventSource);
chunkingPatterns.put(
"\\{up-portlet-help\\(([^\\)]+)\\)\\}", portletHelpPlaceholderEventSource);
staxSerializingComponent.setChunkingPatterns(chunkingPatterns);
final PipelineEventReader<CharacterEventReader, CharacterEvent> eventReader =
staxSerializingComponent.getEventReader(request, response);
//Expected events structure, leaving the data out to make it at least a little simpler
final List<? extends CharacterEvent> expectedEvents = this.getExpectedEvents();
final Iterator<CharacterEvent> eventItr = eventReader.iterator();
final Iterator<? extends CharacterEvent> expectedEventsItr = expectedEvents.iterator();
int eventCount = 0;
while (expectedEventsItr.hasNext()) {
eventCount++;
assertTrue(
"The number of events returned by the eventReader less than the expected event count of: "
+ expectedEvents.size()
+ " was: "
+ eventCount,
eventItr.hasNext());
final CharacterEvent expectedEvent = expectedEventsItr.next();
final CharacterEvent event = eventItr.next();
assertEquals(
"Events at index "
+ eventCount
+ " do not match\n"
+ expectedEvent
+ "\n"
+ event,
expectedEvent,
event);
}
assertFalse(
"The number of events returned by the eventReader is more than the expected event count of: "
+ expectedEvents.size(),
eventItr.hasNext());
}
private List<? extends CharacterEvent> getExpectedEvents() {
return ImmutableList.<CharacterEvent>builder()
.add(
CharacterDataEventImpl.create(
"<!--\n"
+ "\n"
+ " Licensed to Apereo under one or more contributor license\n"
+ " agreements. See the NOTICE file distributed with this work\n"
+ " for additional information regarding copyright ownership.\n"
+ " Apereo licenses this file to you under the Apache License,\n"
+ " Version 2.0 (the \"License\"); you may not use this file\n"
+ " except in compliance with the License. You may obtain a\n"
+ " copy of the License at the following location:\n"
+ "\n"
+ " http://www.apache.org/licenses/LICENSE-2.0\n"
+ "\n"
+ " Unless required by applicable law or agreed to in writing,\n"
+ " software distributed under the License is distributed on an\n"
+ " \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n"
+ " KIND, either express or implied. See the License for the\n"
+ " specific language governing permissions and limitations\n"
+ " under the License.\n"
+ "\n"
+ "--><layout>\n"
+ " <folder>\n"
+ " "))
.add(new PortletHeaderPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletHeaderPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletHeaderPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletHeaderPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletHeaderPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletHeaderPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletHeaderPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletHeaderPlaceholderEventImpl(null))
.add(
CharacterDataEventImpl.create(
"\n"
+ " </folder>\n"
+ " <folder ID=\"0\" type=\"root\">\n"
+ " <folder ID=\"a\" type=\"header\">\n"
+ " "))
.add(new PortletContentPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletContentPlaceholderEventImpl(null))
.add(
CharacterDataEventImpl.create(
"\n"
+ " </folder>\n"
+ " <folder ID=\"1\" fname=\"my-tab\" type=\"tab\">\n"
+ " <name xml:lang=\"en\">My Tab</name>\n"
+ " <folder ID=\"2\" type=\"column\">\n"
+ " "))
.add(new PortletContentPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletContentPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletContentPlaceholderEventImpl(null))
.add(
CharacterDataEventImpl.create(
"\n"
+ " </folder>\n"
+ " <folder ID=\"6\" type=\"column\">\n"
+ " "))
.add(new PortletContentPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletContentPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletContentPlaceholderEventImpl(null))
.add(
CharacterDataEventImpl.create(
"\n"
+ " </folder>\n"
+ " </folder>\n"
+ " <folder ID=\"11\" fname=\"my-classes\" type=\"tab\">\n"
+ " <name xml:lang=\"en\">My Classes "))
.add(new PortletTitlePlaceholderEventImpl(null))
.add(
CharacterDataEventImpl.create(
"</name>\n" + " <name xml:lang=\"de\">My Classes "))
.add(new PortletTitlePlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("</name>\n" + " <link href=\""))
.add(new PortletHelpPlaceholderEventImpl(null))
.add(
CharacterDataEventImpl.create(
"\">Help Link</link>\n"
+ " <name xml:lang=\"ja\">My Classes "))
.add(new PortletTitlePlaceholderEventImpl(null))
.add(
CharacterDataEventImpl.create(
"</name>\n"
+ " <folder ID=\"12\" type=\"column\">\n"
+ " "))
.add(new PortletContentPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletContentPlaceholderEventImpl(null))
.add(
CharacterDataEventImpl.create(
"\n"
+ " </folder>\n"
+ " <folder ID=\"16\" type=\"column\">\n"
+ " "))
.add(new PortletContentPlaceholderEventImpl(null))
.add(CharacterDataEventImpl.create("\n" + " "))
.add(new PortletContentPlaceholderEventImpl(null))
.add(
CharacterDataEventImpl.create(
"\n"
+ " </folder>\n"
+ " </folder>\n"
+ " </folder>\n"
+ "</layout>"))
.build();
}
private static final class SimpleStAXSource implements StAXPipelineComponent {
@Override
public CacheKey getCacheKey(HttpServletRequest request, HttpServletResponse response) {
return CacheKey.build("SimpleStAXSource", 1);
}
@Override
public PipelineEventReader<XMLEventReader, XMLEvent> getEventReader(
HttpServletRequest request, HttpServletResponse response) {
final XMLInputFactory inputFactory = XMLInputFactory.newInstance();
final XMLEventReader xmlEventReader;
try {
xmlEventReader =
inputFactory.createXMLEventReader(
this.getClass().getResourceAsStream("chunkingTest.xml"));
} catch (XMLStreamException e) {
throw new RuntimeException(e.getMessage(), e);
}
return new PipelineEventReaderImpl<XMLEventReader, XMLEvent>(xmlEventReader);
}
}
}