/** * 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.portlet.container; import java.io.Serializable; import java.io.StringWriter; import java.io.Writer; import java.util.List; import javax.portlet.Event; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.namespace.QName; import javax.xml.stream.FactoryConfigurationError; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.pluto.container.EventProvider; import org.apache.pluto.container.PortletContainerException; import org.apache.pluto.container.driver.PortletContextService; 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.apereo.portal.portlet.om.IPortletWindow; /** */ public class EventProviderImpl implements EventProvider { protected final Log logger = LogFactory.getLog(this.getClass()); private final IPortletWindow portletWindow; private final ClassLoader portletClassLoader; public EventProviderImpl( IPortletWindow portletWindow, PortletContextService portletContextService) { this.portletWindow = portletWindow; final PortletDefinition portletDefinition = portletWindow.getPlutoPortletWindow().getPortletDefinition(); final PortletApplicationDefinition application = portletDefinition.getApplication(); final String portletApplicationName = application.getName(); try { this.portletClassLoader = portletContextService.getClassLoader(portletApplicationName); } catch (PortletContainerException e) { throw new IllegalStateException( "Failed to find ClassLoader for portlet applicaiton: " + portletApplicationName, e); } } @Override public Event createEvent(QName qname, Serializable value) throws IllegalArgumentException { if (this.isDeclaredAsPublishingEvent(qname)) { if (value != null && !this.isValueInstanceOfDefinedClass(qname, value)) { throw new IllegalArgumentException( "Payload class (" + value.getClass().getCanonicalName() + ") does not have the right class, check your defined event types in portlet.xml."); } if (value == null) { return new EventImpl(qname); } try { final Thread currentThread = Thread.currentThread(); final ClassLoader cl = currentThread.getContextClassLoader(); final Writer out = new StringWriter(); final Class clazz = value.getClass(); try { currentThread.setContextClassLoader(this.portletClassLoader); final JAXBContext jc = JAXBContext.newInstance(clazz); final Marshaller marshaller = jc.createMarshaller(); final JAXBElement<Serializable> element = new JAXBElement<Serializable>(qname, clazz, value); marshaller.marshal(element, out); } finally { currentThread.setContextClassLoader(cl); } return new EventImpl(qname, out.toString()); } catch (JAXBException e) { // maybe there is no valid jaxb binding // TODO throw exception? logger.error("Event handling failed", e); } catch (FactoryConfigurationError e) { // TODO throw exception? logger.warn(e.getMessage(), e); } } return null; } private boolean isDeclaredAsPublishingEvent(QName qname) { final PortletDefinition portletDescriptor = this.portletWindow.getPlutoPortletWindow().getPortletDefinition(); final List<? extends EventDefinitionReference> events = portletDescriptor.getSupportedPublishingEvents(); if (events == null) { return false; } final PortletApplicationDefinition application = portletDescriptor.getApplication(); final String defaultNamespace = application.getDefaultNamespace(); for (final EventDefinitionReference ref : events) { final QName name = ref.getQualifiedName(defaultNamespace); if (name == null) { continue; } if (qname.equals(name)) { return true; } } return false; } private boolean isValueInstanceOfDefinedClass(QName qname, Serializable value) { final PortletDefinition portletDefinition = this.portletWindow.getPlutoPortletWindow().getPortletDefinition(); final PortletApplicationDefinition app = portletDefinition.getApplication(); final List<? extends EventDefinition> events = app.getEventDefinitions(); if (events == null) { return true; } final String defaultNamespace = app.getDefaultNamespace(); for (final EventDefinition eventDefinition : events) { if (eventDefinition.getQName() != null) { if (eventDefinition.getQName().equals(qname)) { final Class<? extends Serializable> valueClass = value.getClass(); return valueClass.getName().equals(eventDefinition.getValueType()); } } else { final QName tmp = new QName(defaultNamespace, eventDefinition.getName()); if (tmp.equals(qname)) { final Class<? extends Serializable> valueClass = value.getClass(); return valueClass.getName().equals(eventDefinition.getValueType()); } } } // event not declared return true; } }