/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.gatein.integration.jboss.as7.deployment;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import org.gatein.integration.jboss.as7.GateInConfiguration;
import org.jboss.as.server.deployment.Attachments;
import org.jboss.as.server.deployment.DeploymentPhaseContext;
import org.jboss.as.server.deployment.DeploymentUnit;
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
import org.jboss.as.server.deployment.DeploymentUnitProcessor;
import org.jboss.as.server.deployment.module.ModuleDependency;
import org.jboss.as.server.deployment.module.ModuleSpecification;
import org.jboss.as.web.deployment.WarMetaData;
import org.jboss.as.weld.WeldDeploymentMarker;
import org.jboss.logging.Logger;
import org.jboss.metadata.javaee.spec.ParamValueMetaData;
import org.jboss.metadata.web.jboss.JBossWebMetaData;
import org.jboss.metadata.web.spec.ListenerMetaData;
import org.jboss.metadata.web.spec.WebFragmentMetaData;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoader;
import org.jboss.modules.ResourceLoaderSpec;
import org.jboss.modules.ResourceLoaders;
import org.jboss.portletbridge.listener.PortletBridgeListener;
/**
* @author <a href="mailto:stian@redhat.com">Stian Thorgersen</a>
*/
public class PortletBridgeDependencyProcessor implements DeploymentUnitProcessor {
private static final Logger log = Logger.getLogger(PortletBridgeDependencyProcessor.class);
private static final ModuleIdentifier CDI_PORTLET_INTEGRATION = ModuleIdentifier
.create("org.gatein.cdi-portlet-integration");
private static final ModuleIdentifier COMMONS_FILEUPLOAD = ModuleIdentifier.create("org.apache.commons.fileupload");
private static final ModuleIdentifier JSF_API = ModuleIdentifier.create("javax.faces.api");
private static final ModuleIdentifier JSF_IMPL = ModuleIdentifier.create("com.sun.jsf-impl");
private static final ModuleIdentifier PORTLETBRIDGE_API = ModuleIdentifier.create("org.jboss.portletbridge.api");
private static final ModuleIdentifier PORTLETBRIDGE_IMPL = ModuleIdentifier.create("org.jboss.portletbridge.impl");
private static final String cdiPortletIntegrationVersion = getCdiPortletIntegrationVersion();
private static final String portletBridgeVersion = getPortletBridgeVersion();
private static final String PBR_LISTENER = PortletBridgeListener.class.getName();
public static final String WAR_BUNDLES_PORTLETBRIDGE_PARAM = "org.gatein.portletbridge.WAR_BUNDLES_PORTLETBRIDGE";
public static final String DISABLE_CDI_INTEGRATION_PARAM = "org.gatein.cdi.DISABLE_CDI_INTEGRATION";
private final ListenerMetaData cdiListener;
public PortletBridgeDependencyProcessor() {
cdiListener = new ListenerMetaData();
cdiListener.setListenerClass(PBR_LISTENER);
}
private static String getCdiPortletIntegrationVersion() {
try {
Module module = Module.getBootModuleLoader().loadModule(CDI_PORTLET_INTEGRATION);
Manifest mf = new Manifest(module.getClassLoader().getResourceAsStream("/META-INF/MANIFEST.MF"));
return mf.getMainAttributes().getValue("Implementation-Version");
} catch (Exception e) {
return "";
}
}
private static String getPortletBridgeVersion() {
try {
Module module = Module.getBootModuleLoader().loadModule(PORTLETBRIDGE_IMPL);
Manifest mf = new Manifest(module.getClassLoader().getResourceAsStream("/META-INF/MANIFEST.MF"));
return mf.getMainAttributes().getValue("Implementation-Version");
} catch (Exception e) {
return "";
}
}
private void addCdiPortletIntegration(DeploymentUnit deploymentUnit, ModuleSpecification moduleSpecification,
ModuleLoader moduleLoader) {
ModuleDependency pbr = new ModuleDependency(moduleLoader, CDI_PORTLET_INTEGRATION, false, false, false, false);
moduleSpecification.addSystemDependency(pbr);
}
private void addPortletBridgeApi(DeploymentUnit deploymentUnit, ModuleSpecification moduleSpecification,
ModuleLoader moduleLoader) {
ModuleDependency pbr = new ModuleDependency(moduleLoader, PORTLETBRIDGE_API, false, false, false, false);
moduleSpecification.addSystemDependency(pbr);
}
private void addPortletBridgeDependencies(DeploymentUnit deploymentUnit, ModuleSpecification moduleSpecification,
ModuleLoader moduleLoader) {
ModuleDependency pbr = new ModuleDependency(moduleLoader, COMMONS_FILEUPLOAD, false, false, false, false);
moduleSpecification.addSystemDependency(pbr);
}
private void addPortletBridgeImpl(DeploymentUnit deploymentUnit, ModuleSpecification moduleSpecification,
ModuleLoader moduleLoader) {
try {
Module module = moduleLoader.loadModule(PORTLETBRIDGE_IMPL);
URL url = module.getClassLoader().getResource("org/jboss/portletbridge/PortletBridgeImpl.class");
URLConnection connection = url.openConnection();
if (!(connection instanceof JarURLConnection)) {
throw new RuntimeException("portletbridge-impl not found");
}
JarFile jarFile = ((JarURLConnection) connection).getJarFile();
moduleSpecification.addResourceLoader(ResourceLoaderSpec.createResourceLoaderSpec(ResourceLoaders
.createJarResourceLoader("portletbridge-impl", jarFile)));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
if (!GateInConfiguration.isPortletArchive(deploymentUnit)) {
return;
}
ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
ModuleLoader moduleLoader = Module.getBootModuleLoader();
if (isJsfDependencies(moduleSpecification) && !isPortletBridgeBundled(deploymentUnit)) {
log.infof("Adding JBoss Portlet Bridge %s to \"%s\"", portletBridgeVersion, deploymentUnit.getName());
addPortletBridgeApi(deploymentUnit, moduleSpecification, moduleLoader);
addPortletBridgeImpl(deploymentUnit, moduleSpecification, moduleLoader);
addPortletBridgeDependencies(deploymentUnit, moduleSpecification, moduleLoader);
addPortletBridgeListener(deploymentUnit);
if (isCdiDeployment(deploymentUnit) && !disableCdiIntegration(deploymentUnit)) {
log.infof("Adding CDI Portlet Integration %s to \"%s\"", cdiPortletIntegrationVersion, deploymentUnit.getName());
addCdiPortletIntegration(deploymentUnit, moduleSpecification, moduleLoader);
}
}
}
private void addPortletBridgeListener(DeploymentUnit deploymentUnit) {
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
if (warMetaData == null) {
log.debug("Not installing Portlet Bridge web tier integration as no war metadata found");
return;
}
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
if (webMetaData == null) {
log.debug("Not installing Portlet Bridge web tier integration as no merged web metadata found");
return;
}
List<ListenerMetaData> listeners = webMetaData.getListeners();
if (listeners == null) {
listeners = new ArrayList<ListenerMetaData>();
webMetaData.setListeners(listeners);
} else {
//if the portlet bridge listener is present remove it
//this should allow wars to be portable between AS7 and servlet containers
final ListIterator<ListenerMetaData> iterator = listeners.listIterator();
while (iterator.hasNext()) {
final ListenerMetaData listener = iterator.next();
if (listener.getListenerClass().trim().equals(PBR_LISTENER)) {
log.debugf("Removing portlet bridge listener %s from web config, as it is not needed in EE6 environments", PBR_LISTENER);
iterator.remove();
break;
}
}
}
listeners.add(0, cdiListener);
}
private boolean isCdiDeployment(DeploymentUnit deploymentUnit) {
return WeldDeploymentMarker.isPartOfWeldDeployment(deploymentUnit);
}
private boolean isJsfDependencies(ModuleSpecification moduleSpecification) {
boolean jsfApi = false;
boolean jsfImpl = false;
for (ModuleDependency d : moduleSpecification.getSystemDependencies()) {
if (d.getIdentifier().equals(JSF_API)) {
jsfApi = true;
}
if (d.getIdentifier().equals(JSF_IMPL)) {
jsfImpl = true;
}
}
return jsfApi && jsfImpl;
}
private boolean isPortletBridgeBundled(DeploymentUnit deploymentUnit) {
WarMetaData metaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
if (metaData == null) {
return false;
}
List<ParamValueMetaData> contextParams = new ArrayList<ParamValueMetaData>();
if ((metaData.getWebMetaData() != null) && (metaData.getWebMetaData().getContextParams() != null)) {
contextParams.addAll(metaData.getWebMetaData().getContextParams());
}
if (metaData.getWebFragmentsMetaData() != null) {
for (WebFragmentMetaData fragmentMetaData : metaData.getWebFragmentsMetaData().values()) {
if (fragmentMetaData.getContextParams() != null) {
contextParams.addAll(fragmentMetaData.getContextParams());
}
}
}
for (ParamValueMetaData param : contextParams) {
if ((param.getParamName().equals(WAR_BUNDLES_PORTLETBRIDGE_PARAM) && (param.getParamValue() != null) && (param
.getParamValue().toLowerCase(Locale.ENGLISH).equals("true")))) {
return true;
}
}
return false;
}
private boolean disableCdiIntegration(DeploymentUnit deploymentUnit) {
WarMetaData metaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
if (metaData == null) {
return false;
}
List<ParamValueMetaData> contextParams = new ArrayList<ParamValueMetaData>();
if ((metaData.getWebMetaData() != null) && (metaData.getWebMetaData().getContextParams() != null)) {
contextParams.addAll(metaData.getWebMetaData().getContextParams());
}
if (metaData.getWebFragmentsMetaData() != null) {
for (WebFragmentMetaData fragmentMetaData : metaData.getWebFragmentsMetaData().values()) {
if (fragmentMetaData.getContextParams() != null) {
contextParams.addAll(fragmentMetaData.getContextParams());
}
}
}
for (ParamValueMetaData param : contextParams) {
if ((param.getParamName().equals(DISABLE_CDI_INTEGRATION_PARAM) && (param.getParamValue() != null) && (param
.getParamValue().toLowerCase(Locale.ENGLISH).equals("true")))) {
return true;
}
}
return false;
}
@Override
public void undeploy(DeploymentUnit context) {
}
}