/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library 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 library 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.
*/
package com.liferay.portal.osgi.web.portlet.tracker.internal;
import com.liferay.osgi.util.ServiceTrackerFactory;
import com.liferay.osgi.util.StringPlus;
import com.liferay.portal.kernel.application.type.ApplicationType;
import com.liferay.portal.kernel.bean.BeanPropertiesUtil;
import com.liferay.portal.kernel.configuration.Configuration;
import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.Company;
import com.liferay.portal.kernel.model.CompanyConstants;
import com.liferay.portal.kernel.model.EventDefinition;
import com.liferay.portal.kernel.model.PortletApp;
import com.liferay.portal.kernel.model.PortletCategory;
import com.liferay.portal.kernel.model.PortletInfo;
import com.liferay.portal.kernel.model.PortletInstance;
import com.liferay.portal.kernel.model.PublicRenderParameter;
import com.liferay.portal.kernel.module.framework.ModuleServiceLifecycle;
import com.liferay.portal.kernel.portlet.InvokerPortlet;
import com.liferay.portal.kernel.portlet.LiferayWindowState;
import com.liferay.portal.kernel.portlet.PortletInstanceFactory;
import com.liferay.portal.kernel.security.permission.ResourceActions;
import com.liferay.portal.kernel.security.permission.ResourceActionsUtil;
import com.liferay.portal.kernel.service.CompanyLocalService;
import com.liferay.portal.kernel.service.PortletLocalService;
import com.liferay.portal.kernel.service.ResourceActionLocalService;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.ContentTypes;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.Portal;
import com.liferay.portal.kernel.util.PortletKeys;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.SetUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.kernel.xml.QName;
import com.liferay.portal.kernel.xml.SAXReader;
import com.liferay.portal.model.impl.PublicRenderParameterImpl;
import com.liferay.portal.osgi.web.servlet.context.helper.ServletContextHelperFactory;
import com.liferay.portal.osgi.web.servlet.context.helper.ServletContextHelperRegistration;
import com.liferay.portal.util.WebAppPool;
import com.liferay.portlet.PortletBagFactory;
import com.liferay.portlet.PortletContextBag;
import com.liferay.portlet.PortletContextBagPool;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.portlet.Portlet;
import javax.portlet.PortletMode;
import javax.portlet.WindowState;
import javax.servlet.ServletContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.http.runtime.HttpServiceRuntime;
import org.osgi.service.http.runtime.HttpServiceRuntimeConstants;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
/**
* @author Raymond Augé
*/
@Component(immediate = true, service = PortletTracker.class)
public class PortletTracker
implements
ServiceTrackerCustomizer
<Portlet, com.liferay.portal.kernel.model.Portlet> {
@Override
public com.liferay.portal.kernel.model.Portlet addingService(
ServiceReference<Portlet> serviceReference) {
Portlet portlet = _bundleContext.getService(serviceReference);
String portletName = (String)serviceReference.getProperty(
"javax.portlet.name");
if (Validator.isNull(portletName)) {
Class<?> clazz = portlet.getClass();
portletName = clazz.getName();
}
String portletId = StringUtil.replace(
portletName, new char[] {'.', '$'}, new char[] {'_', '_'});
portletId = _portal.getJsSafePortletId(portletId);
if (portletId.length() >
PortletInstance.PORTLET_INSTANCE_KEY_MAX_LENGTH) {
_log.error(
"Portlet ID " + portletId + " has more than " +
PortletInstance.PORTLET_INSTANCE_KEY_MAX_LENGTH +
" characters");
_bundleContext.ungetService(serviceReference);
return null;
}
com.liferay.portal.kernel.model.Portlet portletModel =
_portletLocalService.getPortletById(portletId);
if (portletModel != null) {
_log.error("Portlet id " + portletId + " is already in use");
_bundleContext.ungetService(serviceReference);
return null;
}
if (_log.isInfoEnabled()) {
_log.info("Adding " + serviceReference);
}
portletModel = addingPortlet(
serviceReference, portlet, portletName, portletId);
if (portletModel == null) {
_bundleContext.ungetService(serviceReference);
}
return portletModel;
}
@Override
public void modifiedService(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
removedService(serviceReference, portletModel);
com.liferay.portal.kernel.model.Portlet newPortletModel = addingService(
serviceReference);
BeanPropertiesUtil.copyProperties(newPortletModel, portletModel);
}
@Override
public void removedService(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
portletModel.unsetReady();
ServiceRegistrations serviceRegistrations = _serviceRegistrations.get(
(Long)serviceReference.getProperty(Constants.SERVICE_BUNDLEID));
if (serviceRegistrations == null) {
return;
}
BundlePortletApp bundlePortletApp =
serviceRegistrations.getBundlePortletApp();
bundlePortletApp.removePortlet(portletModel);
try {
_bundleContext.ungetService(serviceReference);
}
catch (IllegalStateException ise) {
// We still need to remove the service so we can ignore this and
// keep going
}
_portletInstanceFactory.destroy(portletModel);
List<Company> companies = _companyLocalService.getCompanies();
for (Company company : companies) {
PortletCategory portletCategory = (PortletCategory)WebAppPool.get(
company.getCompanyId(), WebKeys.PORTLET_CATEGORY);
portletCategory.separate(portletModel.getRootPortletId());
}
serviceRegistrations.removeServiceReference(serviceReference);
}
@Activate
@Modified
protected void activate(BundleContext bundleContext) {
if (_serviceTracker != null) {
_serviceTracker.close();
}
_bundleContext = bundleContext;
_serviceTracker = ServiceTrackerFactory.open(
_bundleContext, Portlet.class, this);
if (_log.isInfoEnabled()) {
_log.info("Activated");
}
}
protected com.liferay.portal.kernel.model.Portlet addingPortlet(
ServiceReference<Portlet> serviceReference, Portlet portlet,
String portletName, String portletId) {
_warnPorletProperties(portletName, serviceReference);
Bundle bundle = serviceReference.getBundle();
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
ClassLoader bundleClassLoader = bundleWiring.getClassLoader();
Thread thread = Thread.currentThread();
ClassLoader contextClassLoader = thread.getContextClassLoader();
thread.setContextClassLoader(bundleWiring.getClassLoader());
ServiceRegistrations serviceRegistrations = getServiceRegistrations(
bundle.getBundleId());
try {
BundlePortletApp bundlePortletApp = createBundlePortletApp(
bundle, bundleClassLoader, serviceRegistrations);
com.liferay.portal.kernel.model.Portlet portletModel =
buildPortletModel(bundlePortletApp, portletId);
portletModel.setPortletName(portletName);
String displayName = GetterUtil.getString(
serviceReference.getProperty("javax.portlet.display-name"),
portletName);
portletModel.setDisplayName(displayName);
Class<?> portletClazz = portlet.getClass();
portletModel.setPortletClass(portletClazz.getName());
collectJxPortletFeatures(serviceReference, portletModel);
collectLiferayFeatures(serviceReference, portletModel);
PortletContextBag portletContextBag = new PortletContextBag(
bundlePortletApp.getServletContextName());
PortletContextBagPool.put(
bundlePortletApp.getServletContextName(), portletContextBag);
PortletBagFactory portletBagFactory = new BundlePortletBagFactory(
portlet);
portletBagFactory.setClassLoader(bundleClassLoader);
portletBagFactory.setServletContext(
bundlePortletApp.getServletContext());
portletBagFactory.setWARFile(true);
portletBagFactory.create(portletModel, true);
List<Company> companies = _companyLocalService.getCompanies();
deployPortlet(serviceReference, portletModel, companies);
portletModel.setReady(true);
if (_log.isInfoEnabled()) {
_log.info("Added " + serviceReference);
}
serviceRegistrations.addServiceReference(serviceReference);
return portletModel;
}
catch (Exception e) {
_log.error(
"Portlet " + portletId + " from " + bundle +
" failed to initialize",
e);
return null;
}
finally {
thread.setContextClassLoader(contextClassLoader);
}
}
protected com.liferay.portal.kernel.model.Portlet buildPortletModel(
BundlePortletApp bundlePortletApp, String portletId) {
com.liferay.portal.kernel.model.Portlet portletModel =
_portletLocalService.createPortlet(0);
portletModel.setPortletId(portletId);
portletModel.setCompanyId(CompanyConstants.SYSTEM);
portletModel.setPluginPackage(bundlePortletApp.getPluginPackage());
portletModel.setPortletApp(bundlePortletApp);
portletModel.setRoleMappers(bundlePortletApp.getRoleMappers());
portletModel.setStrutsPath(portletId);
return portletModel;
}
protected void collectApplicationTypes(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
Set<ApplicationType> applicationTypes = new HashSet<>();
List<String> applicationTypeValues = StringPlus.asList(
get(serviceReference, "application-type"));
for (String applicationTypeValue : applicationTypeValues) {
try {
ApplicationType applicationType = ApplicationType.parse(
applicationTypeValue);
applicationTypes.add(applicationType);
}
catch (IllegalArgumentException iae) {
_log.error("Application type " + applicationTypeValue);
continue;
}
}
if (applicationTypes.isEmpty()) {
applicationTypes.add(ApplicationType.WIDGET);
}
portletModel.setApplicationTypes(applicationTypes);
}
protected void collectCacheScope(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
}
protected void collectExpirationCache(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
int expirationCache = GetterUtil.getInteger(
serviceReference.getProperty("javax.portlet.expiration-cache"));
portletModel.setExpCache(expirationCache);
}
protected void collectInitParams(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
Map<String, String> initParams = new HashMap<>();
for (String initParamKey : serviceReference.getPropertyKeys()) {
if (!initParamKey.startsWith("javax.portlet.init-param.")) {
continue;
}
initParams.put(
initParamKey.substring("javax.portlet.init-param.".length()),
GetterUtil.getString(
serviceReference.getProperty(initParamKey)));
}
initParams.put(
InvokerPortlet.INIT_INVOKER_PORTLET_NAME, "portlet-servlet");
portletModel.setInitParams(initParams);
}
protected void collectJxPortletFeatures(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
collectApplicationTypes(serviceReference, portletModel);
collectCacheScope(serviceReference, portletModel);
collectExpirationCache(serviceReference, portletModel);
collectInitParams(serviceReference, portletModel);
collectPortletInfo(serviceReference, portletModel);
collectPortletModes(serviceReference, portletModel);
collectPortletPreferences(serviceReference, portletModel);
collectResourceBundle(serviceReference, portletModel);
collectSecurityRoleRefs(serviceReference, portletModel);
collectSupportedProcessingEvents(serviceReference, portletModel);
collectSupportedPublicRenderParameters(serviceReference, portletModel);
collectSupportedPublishingEvents(serviceReference, portletModel);
collectWindowStates(serviceReference, portletModel);
}
protected void collectLiferayFeatures(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
portletModel.setActionTimeout(
GetterUtil.getInteger(
get(serviceReference, "action-timeout"),
portletModel.getActionTimeout()));
portletModel.setActionURLRedirect(
GetterUtil.getBoolean(
get(serviceReference, "action-url-redirect"),
portletModel.getActionURLRedirect()));
portletModel.setActive(
GetterUtil.getBoolean(
get(serviceReference, "active"), portletModel.isActive()));
portletModel.setAddDefaultResource(
GetterUtil.getBoolean(
get(serviceReference, "add-default-resource"),
portletModel.isAddDefaultResource()));
portletModel.setAjaxable(
GetterUtil.getBoolean(
get(serviceReference, "ajaxable"), portletModel.isAjaxable()));
Set<String> autopropagatedParameters = SetUtil.fromCollection(
StringPlus.asList(
get(serviceReference, "autopropagated-parameters")));
portletModel.setAutopropagatedParameters(autopropagatedParameters);
portletModel.setControlPanelEntryWeight(
GetterUtil.getDouble(
get(serviceReference, "control-panel-entry-weight"),
portletModel.getControlPanelEntryWeight()));
portletModel.setCssClassWrapper(
GetterUtil.getString(
get(serviceReference, "css-class-wrapper"),
portletModel.getCssClassWrapper()));
portletModel.setFooterPortalCss(
StringPlus.asList(get(serviceReference, "footer-portal-css")));
portletModel.setFooterPortalJavaScript(
StringPlus.asList(
get(serviceReference, "footer-portal-javascript")));
portletModel.setFooterPortletCss(
StringPlus.asList(get(serviceReference, "footer-portlet-css")));
portletModel.setFooterPortletJavaScript(
StringPlus.asList(
get(serviceReference, "footer-portlet-javascript")));
portletModel.setFriendlyURLMapping(
GetterUtil.getString(
get(serviceReference, "friendly-url-mapping"),
portletModel.getFriendlyURLMapping()));
portletModel.setFriendlyURLRoutes(
GetterUtil.getString(
get(serviceReference, "friendly-url-routes"),
portletModel.getFriendlyURLRoutes()));
portletModel.setHeaderPortalCss(
StringPlus.asList(get(serviceReference, "header-portal-css")));
portletModel.setHeaderPortalJavaScript(
StringPlus.asList(
get(serviceReference, "header-portal-javascript")));
portletModel.setHeaderPortletCss(
StringPlus.asList(get(serviceReference, "header-portlet-css")));
portletModel.setHeaderPortletJavaScript(
StringPlus.asList(
get(serviceReference, "header-portlet-javascript")));
portletModel.setIcon(
GetterUtil.getString(
get(serviceReference, "icon"), portletModel.getIcon()));
portletModel.setInclude(
GetterUtil.getBoolean(
get(serviceReference, "include"), portletModel.isInclude()));
portletModel.setInstanceable(
GetterUtil.getBoolean(
get(serviceReference, "instanceable"),
portletModel.isInstanceable()));
portletModel.setLayoutCacheable(
GetterUtil.getBoolean(
get(serviceReference, "layout-cacheable"),
portletModel.isLayoutCacheable()));
portletModel.setMaximizeEdit(
GetterUtil.getBoolean(
get(serviceReference, "maximize-edit"),
portletModel.isMaximizeEdit()));
portletModel.setMaximizeHelp(
GetterUtil.getBoolean(
get(serviceReference, "maximize-help"),
portletModel.isMaximizeHelp()));
portletModel.setParentStrutsPath(
GetterUtil.getString(
get(serviceReference, "parent-struts-path"),
portletModel.getParentStrutsPath()));
portletModel.setPopUpPrint(
GetterUtil.getBoolean(
get(serviceReference, "pop-up-print"),
portletModel.isPopUpPrint()));
portletModel.setPreferencesCompanyWide(
GetterUtil.getBoolean(
get(serviceReference, "preferences-company-wide"),
portletModel.isPreferencesCompanyWide()));
portletModel.setPreferencesOwnedByGroup(
GetterUtil.getBoolean(
get(serviceReference, "preferences-owned-by-group"),
portletModel.isPreferencesOwnedByGroup()));
portletModel.setPreferencesUniquePerLayout(
GetterUtil.getBoolean(
get(serviceReference, "preferences-unique-per-layout"),
portletModel.isPreferencesUniquePerLayout()));
portletModel.setPrivateRequestAttributes(
GetterUtil.getBoolean(
get(serviceReference, "private-request-attributes"),
portletModel.isPrivateRequestAttributes()));
portletModel.setPrivateSessionAttributes(
GetterUtil.getBoolean(
get(serviceReference, "private-session-attributes"),
portletModel.isPrivateSessionAttributes()));
portletModel.setRemoteable(
GetterUtil.getBoolean(
get(serviceReference, "remoteable"),
portletModel.isRemoteable()));
portletModel.setRenderTimeout(
GetterUtil.getInteger(
get(serviceReference, "render-timeout"),
portletModel.getRenderTimeout()));
portletModel.setRenderWeight(
GetterUtil.getInteger(
get(serviceReference, "render-weight"),
portletModel.getRenderWeight()));
if (!portletModel.isAjaxable() &&
(portletModel.getRenderWeight() < 1)) {
portletModel.setRenderWeight(1);
}
boolean defaultRequiresNamespacedParameters = GetterUtil.getBoolean(
get(serviceReference, "requires-namespaced-parameters"),
portletModel.isRequiresNamespacedParameters());
portletModel.setRequiresNamespacedParameters(
GetterUtil.getBoolean(
serviceReference.getProperty("requires-namespaced-parameters"),
defaultRequiresNamespacedParameters));
portletModel.setRestoreCurrentView(
GetterUtil.getBoolean(
get(serviceReference, "restore-current-view"),
portletModel.isRestoreCurrentView()));
portletModel.setScopeable(
GetterUtil.getBoolean(
get(serviceReference, "scopeable"),
portletModel.isScopeable()));
portletModel.setShowPortletAccessDenied(
GetterUtil.getBoolean(
get(serviceReference, "show-portlet-access-denied"),
portletModel.isShowPortletAccessDenied()));
portletModel.setShowPortletInactive(
GetterUtil.getBoolean(
get(serviceReference, "show-portlet-inactive"),
portletModel.isShowPortletInactive()));
portletModel.setSinglePageApplication(
GetterUtil.getBoolean(
get(serviceReference, "single-page-application"),
portletModel.isSinglePageApplication()));
portletModel.setStrutsPath(
GetterUtil.getString(
get(serviceReference, "struts-path"),
portletModel.getStrutsPath()));
portletModel.setSystem(
GetterUtil.getBoolean(
get(serviceReference, "system"), portletModel.isSystem()));
portletModel.setUseDefaultTemplate(
GetterUtil.getBoolean(
get(serviceReference, "use-default-template"),
portletModel.isUseDefaultTemplate()));
portletModel.setUserPrincipalStrategy(
GetterUtil.getString(
get(serviceReference, "user-principal-strategy"),
portletModel.getUserPrincipalStrategy()));
portletModel.setVirtualPath(
GetterUtil.getString(
get(serviceReference, "virtual-path"),
portletModel.getVirtualPath()));
}
protected void collectPortletInfo(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
String portletInfoTitle = GetterUtil.getString(
serviceReference.getProperty("javax.portlet.info.title"));
String portletDisplayName = GetterUtil.getString(
serviceReference.getProperty("javax.portlet.display-name"),
portletInfoTitle);
String portletInfoShortTitle = GetterUtil.getString(
serviceReference.getProperty("javax.portlet.info.short-title"));
String portletInfoKeyWords = GetterUtil.getString(
serviceReference.getProperty("javax.portlet.info.keywords"));
String portletDescription = GetterUtil.getString(
serviceReference.getProperty("javax.portlet.description"));
PortletInfo portletInfo = new PortletInfo(
portletDisplayName, portletInfoShortTitle, portletInfoKeyWords,
portletDescription);
portletModel.setPortletInfo(portletInfo);
}
protected void collectPortletModes(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
Map<String, Set<String>> portletModes = new HashMap<>();
portletModes.put(
ContentTypes.TEXT_HTML,
SetUtil.fromArray(new String[] {toLowerCase(PortletMode.VIEW)}));
List<String> portletModesStrings = StringPlus.asList(
serviceReference.getProperty("javax.portlet.portlet-mode"));
for (String portletModesString : portletModesStrings) {
String[] portletModesStringParts = StringUtil.split(
portletModesString, CharPool.SEMICOLON);
if (portletModesStringParts.length != 2) {
continue;
}
String mimeType = portletModesStringParts[0];
Set<String> mimeTypePortletModes = new HashSet<>();
mimeTypePortletModes.add(toLowerCase(PortletMode.VIEW));
mimeTypePortletModes.addAll(
toLowerCaseSet(portletModesStringParts[1]));
portletModes.put(mimeType, mimeTypePortletModes);
}
portletModel.setPortletModes(portletModes);
}
protected void collectPortletPreferences(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
String defaultPreferences = GetterUtil.getString(
serviceReference.getProperty("javax.portlet.preferences"));
if ((defaultPreferences != null) &&
defaultPreferences.startsWith("classpath:")) {
Bundle bundle = serviceReference.getBundle();
URL url = bundle.getResource(
defaultPreferences.substring("classpath:".length()));
if (url != null) {
try {
defaultPreferences = StringUtil.read(url.openStream());
}
catch (IOException ioe) {
_log.error(ioe, ioe);
}
}
}
portletModel.setDefaultPreferences(defaultPreferences);
}
protected void collectResourceBundle(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
String resourceBundle = GetterUtil.getString(
serviceReference.getProperty("javax.portlet.resource-bundle"),
portletModel.getResourceBundle());
portletModel.setResourceBundle(resourceBundle);
}
protected void collectSecurityRoleRefs(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
Set<String> unlinkedRoles = new HashSet<>();
List<String> roleRefs = StringPlus.asList(
serviceReference.getProperty("javax.portlet.security-role-ref"));
if (roleRefs.isEmpty()) {
roleRefs.add("administrator");
roleRefs.add("guest");
roleRefs.add("power-user");
roleRefs.add("user");
}
for (String roleRef : roleRefs) {
for (String curRoleRef : StringUtil.split(roleRef)) {
unlinkedRoles.add(curRoleRef);
}
}
portletModel.setUnlinkedRoles(unlinkedRoles);
portletModel.linkRoles();
}
protected void collectSupportedProcessingEvents(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
Set<QName> processingEvents = new HashSet<>();
PortletApp portletApp = portletModel.getPortletApp();
List<String> supportedProcessingEvents = StringPlus.asList(
serviceReference.getProperty(
"javax.portlet.supported-processing-event"));
for (String supportedProcessingEvent : supportedProcessingEvents) {
String name = supportedProcessingEvent;
String qname = null;
String[] parts = StringUtil.split(
supportedProcessingEvent, StringPool.SEMICOLON);
if (parts.length == 2) {
name = parts[0];
qname = parts[1];
}
QName qName = getQName(
name, qname, portletApp.getDefaultNamespace());
processingEvents.add(qName);
Set<EventDefinition> eventDefinitions =
portletApp.getEventDefinitions();
for (EventDefinition eventDefinition : eventDefinitions) {
Set<QName> qNames = eventDefinition.getQNames();
if (qNames.contains(qName)) {
processingEvents.addAll(qNames);
}
}
}
portletModel.setProcessingEvents(processingEvents);
}
protected void collectSupportedPublicRenderParameters(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
Set<PublicRenderParameter> publicRenderParameters = new HashSet<>();
PortletApp portletApp = portletModel.getPortletApp();
List<String> supportedPublicRenderParameters = StringPlus.asList(
serviceReference.getProperty(
"javax.portlet.supported-public-render-parameter"));
for (String supportedPublicRenderParameter :
supportedPublicRenderParameters) {
String name = supportedPublicRenderParameter;
String qname = null;
String[] parts = StringUtil.split(
supportedPublicRenderParameter, StringPool.SEMICOLON);
if (parts.length == 2) {
name = parts[0];
qname = parts[1];
}
QName qName = getQName(
name, qname, portletApp.getDefaultNamespace());
PublicRenderParameter publicRenderParameter =
new PublicRenderParameterImpl(name, qName, portletApp);
publicRenderParameters.add(publicRenderParameter);
}
portletModel.setPublicRenderParameters(publicRenderParameters);
}
protected void collectSupportedPublishingEvents(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
Set<QName> publishingEvents = new HashSet<>();
PortletApp portletApp = portletModel.getPortletApp();
List<String> supportedPublishingEvents = StringPlus.asList(
serviceReference.getProperty(
"javax.portlet.supported-publishing-event"));
for (String supportedPublishingEvent : supportedPublishingEvents) {
String name = supportedPublishingEvent;
String qname = null;
String[] parts = StringUtil.split(
supportedPublishingEvent, StringPool.SEMICOLON);
if (parts.length == 2) {
name = parts[0];
qname = parts[1];
}
QName qName = getQName(
name, qname, portletApp.getDefaultNamespace());
publishingEvents.add(qName);
}
portletModel.setPublishingEvents(publishingEvents);
}
protected void collectWindowStates(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel) {
Map<String, Set<String>> windowStates = new HashMap<>();
windowStates.put(
ContentTypes.TEXT_HTML,
SetUtil.fromArray(
new String[] {
toLowerCase(LiferayWindowState.EXCLUSIVE),
toLowerCase(LiferayWindowState.POP_UP),
toLowerCase(WindowState.MAXIMIZED),
toLowerCase(WindowState.MINIMIZED),
toLowerCase(WindowState.NORMAL)
}));
List<String> windowStatesStrings = StringPlus.asList(
serviceReference.getProperty("javax.portlet.window-state"));
for (String windowStatesString : windowStatesStrings) {
String[] windowStatesStringParts = StringUtil.split(
windowStatesString, CharPool.SEMICOLON);
if (windowStatesStringParts.length != 2) {
continue;
}
String mimeType = windowStatesStringParts[0];
Set<String> mimeTypeWindowStates = new HashSet<>();
mimeTypeWindowStates.add(toLowerCase(WindowState.NORMAL));
Set<String> windowStatesSet = toLowerCaseSet(
windowStatesStringParts[1]);
if (windowStatesSet.isEmpty()) {
mimeTypeWindowStates.add(
toLowerCase(LiferayWindowState.EXCLUSIVE));
mimeTypeWindowStates.add(
toLowerCase(LiferayWindowState.POP_UP));
mimeTypeWindowStates.add(toLowerCase(WindowState.MAXIMIZED));
mimeTypeWindowStates.add(toLowerCase(WindowState.MINIMIZED));
}
else {
mimeTypeWindowStates.addAll(windowStatesSet);
}
windowStates.put(mimeType, mimeTypeWindowStates);
}
portletModel.setWindowStates(windowStates);
}
protected BundlePortletApp createBundlePortletApp(
Bundle bundle, ClassLoader classLoader,
ServiceRegistrations serviceRegistrations) {
BundlePortletApp bundlePortletApp =
serviceRegistrations.getBundlePortletApp();
if (bundlePortletApp != null) {
return bundlePortletApp;
}
com.liferay.portal.kernel.model.Portlet portalPortletModel =
_portletLocalService.getPortletById(
CompanyConstants.SYSTEM, PortletKeys.PORTAL);
ServiceTracker<ServletContextHelperRegistration, ServletContext>
serviceTracker = getServletContextHelperRegistrationServiceTracker(
bundle, serviceRegistrations);
serviceRegistrations.setServiceTracker(serviceTracker);
bundlePortletApp = new BundlePortletApp(
bundle, portalPortletModel, serviceTracker);
serviceRegistrations.setBundlePortletApp(bundlePortletApp);
serviceRegistrations.doConfiguration(classLoader);
return bundlePortletApp;
}
@Deactivate
protected void deactivate() {
_serviceTracker.close();
if (_log.isInfoEnabled()) {
_log.info("Deactivated");
}
}
protected void deployPortlet(
ServiceReference<Portlet> serviceReference,
com.liferay.portal.kernel.model.Portlet portletModel,
List<Company> companies)
throws PortalException {
List<String> categoryNames = StringPlus.asList(
get(serviceReference, "display-category"));
if (categoryNames.isEmpty()) {
categoryNames.add("category.undefined");
}
String[] categoryNamesArray = ArrayUtil.toStringArray(categoryNames);
for (Company company : companies) {
com.liferay.portal.kernel.model.Portlet companyPortletModel =
(com.liferay.portal.kernel.model.Portlet)portletModel.clone();
companyPortletModel.setCompanyId(company.getCompanyId());
_portletLocalService.deployRemotePortlet(
companyPortletModel, categoryNamesArray, false);
}
}
protected Object get(
ServiceReference<Portlet> serviceReference, String property) {
return serviceReference.getProperty(_NAMESPACE + property);
}
protected QName getQName(String name, String uri, String defaultNamespace) {
if (Validator.isNull(name) && Validator.isNull(uri)) {
return null;
}
if (Validator.isNull(uri)) {
return _saxReader.createQName(
name, _saxReader.createNamespace(defaultNamespace));
}
return _saxReader.createQName(name, _saxReader.createNamespace(uri));
}
protected ServiceRegistrations getServiceRegistrations(Long bundleId) {
ServiceRegistrations serviceRegistrations = _serviceRegistrations.get(
bundleId);
if (serviceRegistrations == null) {
serviceRegistrations = new ServiceRegistrations(bundleId);
ServiceRegistrations oldServiceRegistrations =
_serviceRegistrations.putIfAbsent(
bundleId, serviceRegistrations);
if (oldServiceRegistrations != null) {
serviceRegistrations = oldServiceRegistrations;
}
}
return serviceRegistrations;
}
protected ServiceTracker<ServletContextHelperRegistration, ServletContext>
getServletContextHelperRegistrationServiceTracker(
Bundle bundle, ServiceRegistrations serviceRegistrations) {
BundleContext bundleContext = bundle.getBundleContext();
ServiceTracker<ServletContextHelperRegistration, ServletContext>
serviceTracker = new ServiceTracker<>(
bundleContext, ServletContextHelperRegistration.class,
new ServletContextServiceTrackerCustomizer(bundleContext));
serviceTracker.open();
return serviceTracker;
}
protected void readResourceActions(
Configuration configuration, String servletContextName,
ClassLoader classLoader) {
if (configuration == null) {
return;
}
Properties properties = configuration.getProperties();
try {
ResourceActionsUtil.read(
null, classLoader,
StringUtil.split(
properties.getProperty(
PropsKeys.RESOURCE_ACTIONS_CONFIGS)));
}
catch (Exception e) {
_log.error(e, e);
}
}
@Reference(unbind = "-")
protected void setHttpServiceRuntime(
HttpServiceRuntime httpServiceRuntime, Map<String, Object> properties) {
List<String> httpServiceEndpoints = StringPlus.asList(
properties.get(HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT));
if (!httpServiceEndpoints.isEmpty()) {
_httpServiceEndpoint = httpServiceEndpoints.get(0);
}
if ((_httpServiceEndpoint.length() > 0) &&
_httpServiceEndpoint.endsWith("/")) {
_httpServiceEndpoint = _httpServiceEndpoint.substring(
0, _httpServiceEndpoint.length() - 1);
}
}
protected String toLowerCase(Object object) {
String string = String.valueOf(object);
return StringUtil.toLowerCase(string.trim());
}
protected Set<String> toLowerCaseSet(String string) {
String[] array = StringUtil.split(string);
for (int i = 0; i < array.length; i++) {
array[i] = toLowerCase(array[i]);
}
return SetUtil.fromArray(array);
}
private void _warnPorletProperties(
String portletName, ServiceReference<Portlet> serviceReference) {
if (!_log.isWarnEnabled()) {
return;
}
List<String> invalidKeys = _portletPropertyValidator.validate(
serviceReference.getPropertyKeys());
for (String invalidKey : invalidKeys) {
_log.warn(
"Invalid property " + invalidKey + " for portlet " +
portletName);
}
}
private static final String _NAMESPACE = "com.liferay.portlet.";
private static final Log _log = LogFactoryUtil.getLog(PortletTracker.class);
private BundleContext _bundleContext;
@Reference
private CompanyLocalService _companyLocalService;
private String _httpServiceEndpoint = StringPool.BLANK;
@Reference(target = ModuleServiceLifecycle.PORTAL_INITIALIZED, unbind = "-")
private ModuleServiceLifecycle _moduleServiceLifecycle;
@Reference
private Portal _portal;
@Reference
private PortletInstanceFactory _portletInstanceFactory;
@Reference
private PortletLocalService _portletLocalService;
private final PortletPropertyValidator _portletPropertyValidator =
new PortletPropertyValidator();
@Reference
private ResourceActionLocalService _resourceActionLocalService;
@Reference
private ResourceActions _resourceActions;
@Reference
private SAXReader _saxReader;
private final ConcurrentMap<Long, ServiceRegistrations>
_serviceRegistrations = new ConcurrentHashMap<>();
private ServiceTracker<Portlet, com.liferay.portal.kernel.model.Portlet>
_serviceTracker;
@Reference
private ServletContextHelperFactory _servletContextHelperFactory;
private class ServiceRegistrations {
public ServiceRegistrations(Long bundleId) {
_bundleId = bundleId;
}
public synchronized void addServiceReference(
ServiceReference<Portlet> serviceReference) {
_serviceReferences.add(serviceReference);
}
public synchronized void removeServiceReference(
ServiceReference<Portlet> serviceReference) {
_serviceReferences.remove(serviceReference);
if (!_serviceReferences.isEmpty()) {
return;
}
_serviceReferences.clear();
_bundlePortletApp = null;
_serviceRegistrations.remove(_bundleId);
_serviceTracker.close();
}
public synchronized void setBundlePortletApp(
BundlePortletApp bundlePortletApp) {
_bundlePortletApp = bundlePortletApp;
}
public synchronized void setServiceTracker(
ServiceTracker<ServletContextHelperRegistration, ServletContext>
serviceTracker) {
_serviceTracker = serviceTracker;
}
protected synchronized void doConfiguration(ClassLoader classLoader) {
try {
_configuration = ConfigurationFactoryUtil.getConfiguration(
classLoader, "portlet");
}
catch (Exception e) {
}
readResourceActions(
_configuration, _bundlePortletApp.getServletContextName(),
classLoader);
}
protected synchronized BundlePortletApp getBundlePortletApp() {
return _bundlePortletApp;
}
private final Long _bundleId;
private BundlePortletApp _bundlePortletApp;
private Configuration _configuration;
private final List<ServiceReference<Portlet>> _serviceReferences =
new ArrayList<>();
private ServiceTracker<ServletContextHelperRegistration, ServletContext>
_serviceTracker;
}
private class ServletContextServiceTrackerCustomizer
implements ServiceTrackerCustomizer
<ServletContextHelperRegistration, ServletContext> {
public ServletContextServiceTrackerCustomizer(
BundleContext bundleContext) {
_bundleContext = bundleContext;
}
@Override
public ServletContext addingService(
ServiceReference<ServletContextHelperRegistration> reference) {
ServletContextHelperRegistration service =
_bundleContext.getService(reference);
return service.getServletContext();
}
@Override
public void modifiedService(
ServiceReference<ServletContextHelperRegistration> reference,
ServletContext servletContext) {
}
@Override
public void removedService(
ServiceReference<ServletContextHelperRegistration> reference,
ServletContext servletContext) {
try {
_bundleContext.ungetService(reference);
}
catch (IllegalStateException ise) {
// Ignore this because the service is already ungotten
}
}
private final BundleContext _bundleContext;
}
}