/* | |
* 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.pluto.driver.services.container; | |
import java.io.IOException; | |
import java.io.Serializable; | |
import java.io.StringReader; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.HashSet; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.Set; | |
import javax.portlet.Event; | |
import javax.portlet.PortletException; | |
import javax.servlet.ServletContext; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import javax.xml.bind.JAXBContext; | |
import javax.xml.bind.JAXBElement; | |
import javax.xml.bind.JAXBException; | |
import javax.xml.bind.Unmarshaller; | |
import javax.xml.namespace.QName; | |
import javax.xml.parsers.FactoryConfigurationError; | |
import javax.xml.stream.XMLInputFactory; | |
import javax.xml.stream.XMLStreamException; | |
import javax.xml.stream.XMLStreamReader; | |
import org.apache.pluto.container.EventCoordinationService; | |
import org.apache.pluto.container.PortletContainer; | |
import org.apache.pluto.container.PortletContainerException; | |
import org.apache.pluto.container.PortletWindow; | |
import org.apache.pluto.container.bean.processor.CDIEventStore; | |
import org.apache.pluto.container.bean.processor.CrossContextCDIEvent; | |
import org.apache.pluto.container.driver.PortletContextService; | |
import org.apache.pluto.container.driver.PortletRegistryService; | |
import org.apache.pluto.container.om.portlet.EventDefinition; | |
import org.apache.pluto.container.om.portlet.EventDefinitionReference; | |
import org.apache.pluto.container.om.portlet.PortletApplicationDefinition; | |
import org.apache.pluto.container.om.portlet.PortletDefinition; | |
import org.apache.pluto.driver.AttributeKeys; | |
import org.apache.pluto.driver.config.DriverConfiguration; | |
import org.apache.pluto.driver.core.PortalRequestContext; | |
import org.apache.pluto.driver.core.PortletWindowImpl; | |
import org.apache.pluto.driver.services.portal.PageConfig; | |
import org.apache.pluto.driver.services.portal.PortletWindowConfig; | |
import org.apache.pluto.driver.url.PortalURL; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import static org.apache.pluto.container.bean.processor.CDIEventStore.CDI_EVENT_QNAME; | |
public class EventCoordinationServiceImpl implements EventCoordinationService { | |
/** Logger. */ | |
private static final Logger LOG = LoggerFactory | |
.getLogger(EventCoordinationServiceImpl.class); | |
/** PortletRegistryService used to obtain PortletApplicationConfig objects */ | |
private final PortletRegistryService portletRegistry; | |
/** PortletContextService used to obtain PortletContext objects */ | |
private final PortletContextService portletContextService; | |
public EventCoordinationServiceImpl(PortletRegistryService portletRegistry, | |
PortletContextService portletContextService) { | |
this.portletRegistry = portletRegistry; | |
this.portletContextService = portletContextService; | |
} | |
public void processEvents(PortletContainer container, | |
PortletWindow portletWindow, HttpServletRequest request, | |
HttpServletResponse response, List<Event> events) { | |
ServletContext containerServletContext = PortalRequestContext.getContext( | |
request).getServletContext(); | |
DriverConfiguration driverConfig = (DriverConfiguration) containerServletContext | |
.getAttribute(AttributeKeys.DRIVER_CONFIG); | |
// PortalURL portalURL = PortalURLParserImpl.getParser().parse(request); | |
PortalURL portalURL = PortalRequestContext.getContext(request) | |
.createPortalURL(); | |
// Map<String, PortletWindowThread> portletWindowThreads = new | |
// HashMap<String, PortletWindowThread>(); | |
// ThreadGroup threadGroup = new ThreadGroup("FireEventThreads"); | |
List<Event> cdiEvents = new ArrayList<Event>(); | |
List<Event> portletEvents = new ArrayList<Event>(); | |
for(Event event : events){ | |
if(event.getQName().equals(CDI_EVENT_QNAME)){ | |
cdiEvents.add(event); | |
} else { | |
portletEvents.add(event); | |
} | |
} | |
events.clear(); | |
events.addAll(cdiEvents); | |
events.addAll(portletEvents); | |
for (Event event : events) { | |
List<String> portletNames = getAllPortletsRegisteredForEvent(event, | |
driverConfig, containerServletContext, portalURL); | |
// Deliver events to all portlets in the portal | |
// Collection<PortletWindowConfig> portlets = | |
// getAllPortlets(driverConfig); | |
// Limit event delivery to portlets that are on the current page | |
Collection<PortletWindowConfig> portlets = new ArrayList<PortletWindowConfig>(); | |
for (String pid : portalURL.getPortletIds()) { | |
portlets.add(PortletWindowConfig.fromId(pid)); | |
} | |
// iterate all portlets in the portal | |
for (PortletWindowConfig config : portlets) { | |
PortletWindow window = new PortletWindowImpl(container, config, | |
portalURL); | |
if (portletNames != null) { | |
for (String portlet : portletNames) { | |
if (portlet.equals(config.getId())) { | |
/* | |
* PLUTO-569: multi-threaded (event) request processing | |
* isn't thread save with the Pluto Portal Driver handling | |
* of request attributes as they all are stored/managed | |
* within the single underlying HttpServletRequest. | |
* Providing proper thread save parallel request processing | |
* would require extensive enhancements to the Pluto Portal | |
* Driver and as such is out-of-scope for the purpose of | |
* the Portal Driver itself. | |
* | |
* // the thread now is a new one, with possible // | |
* waiting, // for the old to exit | |
* | |
* | |
* PortletWindowThread portletWindowThread = | |
* getPortletWindowThread(portletWindowThreads, | |
* threadGroup, container, config, window, request, | |
* response, containerServletContext); | |
* | |
* // is this event portletWindowThread.addEvent(event); | |
* | |
* portletWindowThread.start(); | |
* | |
* } } } } waitForEventExecution(threadGroup); try { | |
* Thread.sleep(WAITING_CYCLE); } catch | |
* (InterruptedException e) { LOG.warn(e.getMessage(),e); } | |
* } waitForEventExecution(threadGroup); | |
*/ | |
doEvent(container, window, event, request, response); | |
} | |
} | |
} | |
} | |
for(CrossContextCDIEvent portletCDIEvent : CDIEventStore.CDIEventBus){ | |
if(event.getQName().equals(CDI_EVENT_QNAME) && event.getValue().equals(portletCDIEvent.getData()) && portletCDIEvent.isProcessing()){ | |
CDIEventStore.CDIEventBus.remove(portletCDIEvent); | |
break; | |
} | |
} | |
} | |
} | |
@SuppressWarnings("rawtypes") | |
protected void doEvent(PortletContainer container, | |
PortletWindow portletWindow, Event event, HttpServletRequest request, | |
HttpServletResponse response) { | |
try { | |
Object value = event.getValue(); | |
XMLStreamReader xml = null; | |
try { | |
if (value instanceof String) { | |
String in = (String) value; | |
xml = XMLInputFactory.newInstance().createXMLStreamReader( | |
new StringReader(in)); | |
} | |
} catch (XMLStreamException e1) { | |
throw new IllegalStateException(e1); | |
} catch (FactoryConfigurationError e1) { | |
throw new IllegalStateException(e1); | |
} | |
if (xml != null) { | |
// XMLStreamReader xml = (XMLStreamReader) event.getValue(); | |
// provider.getEventDefinition(event.getQName()); | |
if(!event.getQName().equals(CDI_EVENT_QNAME)){ | |
try { | |
// now test if object is jaxb | |
EventDefinition eventDefinitionDD = getEventDefintion( | |
portletWindow, event.getQName()); | |
ClassLoader loader = portletContextService | |
.getClassLoader(portletWindow.getPortletDefinition() | |
.getApplication().getName()); | |
Class<? extends Serializable> clazz = loader.loadClass( | |
eventDefinitionDD.getValueType()).asSubclass( | |
Serializable.class); | |
JAXBContext jc = JAXBContext.newInstance(clazz); | |
Unmarshaller unmarshaller = jc.createUnmarshaller(); | |
// unmarshaller.setEventHandler(new | |
// javax.xml.bind.helpers.DefaultValidationEventHandler()); | |
JAXBElement result = unmarshaller.unmarshal(xml, clazz); | |
event = new EventImpl(event.getQName(), | |
(Serializable) result.getValue()); | |
} catch (JAXBException e) { | |
System.out.println(e.toString()); | |
throw new IllegalStateException(e); | |
} catch (ClassCastException e) { | |
System.out.println(e.toString()); | |
throw new IllegalStateException(e); | |
} catch (ClassNotFoundException e) { | |
System.out.println(e.toString()); | |
throw new IllegalStateException(e); | |
} catch (PortletContainerException e) { | |
System.out.println(e.toString()); | |
throw new IllegalStateException(e); | |
} | |
} | |
} | |
container.doEvent(portletWindow, request, response, event); | |
} catch (PortletException e) { | |
LOG.warn(e.getMessage(), e); | |
} catch (IOException e) { | |
LOG.warn(e.getMessage(), e); | |
} catch (PortletContainerException e) { | |
LOG.warn(e.getMessage(), e); | |
} | |
} | |
private EventDefinition getEventDefintion(PortletWindow portletWindow, QName name) { | |
PortletApplicationDefinition appDD = portletWindow.getPortletDefinition().getApplication(); | |
for (EventDefinition def : appDD.getEventDefinitions()) { | |
if (def.getQName().equals(name)) { | |
return def; | |
} | |
} | |
throw new IllegalStateException(); | |
} | |
private List<String> getAllPortletsRegisteredForEvent(Event event, | |
DriverConfiguration driverConfig, | |
ServletContext containerServletContext, PortalURL portalURL) { | |
Set<String> resultSet = new HashSet<String>(); | |
List<String> resultList = new ArrayList<String>(); | |
QName eventName = event.getQName(); | |
// Collection<PortletWindowConfig> portlets = getAllPortlets(driverConfig); | |
// limit event processing to those portlets on the page | |
Collection<PortletWindowConfig> portlets = new ArrayList<PortletWindowConfig>(); | |
for (String pid : portalURL.getPortletIds()) { | |
portlets.add(PortletWindowConfig.fromId(pid)); | |
} | |
for (PortletWindowConfig portlet : portlets) { | |
String contextPath = portlet.getContextPath(); | |
String applicationName = contextPath; | |
PortletApplicationDefinition portletAppDD = null; | |
try { | |
portletAppDD = portletRegistry | |
.getPortletApplication(applicationName); | |
List<? extends PortletDefinition> portletDDs = portletAppDD | |
.getPortlets(); | |
List<QName> aliases = getAllAliases(eventName, portletAppDD); | |
for (PortletDefinition portletDD : portletDDs) { | |
List<? extends EventDefinitionReference> processingEvents = portletDD | |
.getSupportedProcessingEvents(); | |
if (isEventSupported(processingEvents, eventName, | |
portletAppDD.getDefaultNamespace())) { | |
if (portletDD.getPortletName().equals( | |
portlet.getPortletName())) { | |
resultSet.add(portlet.getId()); | |
} | |
} else { | |
if (processingEvents != null) { | |
for (EventDefinitionReference ref : processingEvents) { | |
QName name = ref.getQualifiedName(); | |
if (name == null) { | |
continue; | |
} | |
// add also grouped portlets, that ends with "." | |
if (name.toString().endsWith(".") | |
&& eventName.toString().startsWith( | |
name.toString()) | |
&& portletDD.getPortletName().equals( | |
portlet.getPortletName())) { | |
resultSet.add(portlet.getId()); | |
} | |
// also look for alias names: | |
if (aliases != null) { | |
for (QName alias : aliases) { | |
if (alias.toString().equals(name.toString()) | |
&& portletDD.getPortletName().equals( | |
portlet.getPortletName())) { | |
resultSet.add(portlet.getId()); | |
} | |
} | |
} | |
// also look for default namespaced events | |
if (name.getNamespaceURI() == null | |
|| name.getNamespaceURI().equals("")) { | |
String defaultNamespace = portletAppDD | |
.getDefaultNamespace(); | |
QName qname = new QName(defaultNamespace, | |
name.getLocalPart()); | |
if (eventName.toString().equals(qname.toString()) | |
&& portletDD.getPortletName().equals( | |
portlet.getPortletName())) { | |
resultSet.add(portlet.getId()); | |
} | |
} | |
} | |
} | |
} | |
} | |
} catch (PortletContainerException e) { | |
LOG.warn(e.getMessage(), e); | |
} | |
} | |
// make list | |
for (String name : resultSet) { | |
resultList.add(name); | |
} | |
return resultList; | |
} | |
private boolean isEventSupported( | |
List<? extends EventDefinitionReference> supportedEvents, | |
QName eventName, String defaultNamespace) { | |
if (supportedEvents != null) { | |
for (EventDefinitionReference ref : supportedEvents) { | |
QName refQName = ref.getQualifiedName(); | |
if (refQName != null && refQName.equals(eventName)) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
private List<QName> getAllAliases(QName eventName, | |
PortletApplicationDefinition portletAppDD) { | |
if (portletAppDD.getEventDefinitions() != null) { | |
for (EventDefinition def : portletAppDD.getEventDefinitions()) { | |
QName defQName = def.getQName(); | |
if (defQName != null && defQName.equals(eventName)) { | |
return def.getAliases(); | |
} | |
} | |
} | |
return null; | |
} | |
/** | |
* | |
*/ | |
@SuppressWarnings("unused") | |
private Collection<PortletWindowConfig> getAllPortlets( | |
DriverConfiguration driverConfig) { | |
Collection<PortletWindowConfig> portlets = new ArrayList<PortletWindowConfig>(); | |
Collection<PageConfig> pages = driverConfig.getPages(); | |
if (pages != null) { | |
Iterator<PageConfig> iPages = pages.iterator(); | |
while (iPages.hasNext()) { | |
PageConfig pageConfig = (PageConfig) iPages.next(); | |
Collection<String> portletIDs = pageConfig.getPortletIds(); | |
if (portletIDs != null) { | |
Iterator<String> iPortletIDs = portletIDs.iterator(); | |
while (iPortletIDs.hasNext()) { | |
portlets.add(PortletWindowConfig.fromId(iPortletIDs.next() | |
.toString())); | |
} | |
} | |
} | |
} | |
return portlets; | |
} | |
} |