/**
* 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.verify.extender.internal.osgi.commands;
import com.liferay.counter.kernel.service.CounterLocalService;
import com.liferay.osgi.service.tracker.collections.map.PropertyServiceReferenceComparator;
import com.liferay.osgi.service.tracker.collections.map.PropertyServiceReferenceMapper;
import com.liferay.osgi.service.tracker.collections.map.ServiceTrackerMap;
import com.liferay.osgi.service.tracker.collections.map.ServiceTrackerMapFactory;
import com.liferay.osgi.service.tracker.collections.map.ServiceTrackerMapListener;
import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.Release;
import com.liferay.portal.kernel.module.framework.ModuleServiceLifecycle;
import com.liferay.portal.kernel.service.ReleaseLocalService;
import com.liferay.portal.kernel.util.HashMapDictionary;
import com.liferay.portal.kernel.util.NotificationThreadLocal;
import com.liferay.portal.kernel.workflow.WorkflowThreadLocal;
import com.liferay.portal.output.stream.container.OutputStreamContainer;
import com.liferay.portal.output.stream.container.OutputStreamContainerFactory;
import com.liferay.portal.output.stream.container.OutputStreamContainerFactoryTracker;
import com.liferay.portal.search.index.IndexStatusManager;
import com.liferay.portal.verify.VerifyException;
import com.liferay.portal.verify.VerifyProcess;
import com.liferay.portal.verify.extender.internal.configuration.VerifyProcessTrackerConfiguration;
import com.liferay.portal.verify.extender.marker.VerifyProcessCompletionMarker;
import com.liferay.portlet.exportimport.staging.StagingAdvicesThreadLocal;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Dictionary;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
/**
* @author Miguel Pastor
* @author Raymond Augé
* @author Carlos Sierra Andrés
*/
@Component(
configurationPid = "com.liferay.portal.verify.extender.internal.configuration.VerifyProcessTrackerConfiguration",
configurationPolicy = ConfigurationPolicy.OPTIONAL, immediate = true,
property = {
"osgi.command.function=execute", "osgi.command.function=executeAll",
"osgi.command.function=list", "osgi.command.function=show",
"osgi.command.function=showReports", "osgi.command.scope=verify"
},
service = {VerifyProcessTrackerOSGiCommands.class}
)
public class VerifyProcessTrackerOSGiCommands {
public void execute(final String verifyProcessName) {
executeVerifyProcesses(
verifyProcessName, null, "verify-" + verifyProcessName);
}
public void execute(
String verifyProcessName, String outputStreamContainerFactoryName) {
executeVerifyProcesses(
verifyProcessName, outputStreamContainerFactoryName,
"verify-" + verifyProcessName);
}
public void executeAll() {
OutputStreamContainerFactory outputStreamContainerFactory =
outputStreamContainerFactoryTracker.
getOutputStreamContainerFactory();
_runAllVerifiersWithFactory(outputStreamContainerFactory);
}
public void executeAll(String outputStreamContainerFactoryName) {
OutputStreamContainerFactory outputStreamContainerFactory =
outputStreamContainerFactoryTracker.getOutputStreamContainerFactory(
outputStreamContainerFactoryName);
_runAllVerifiersWithFactory(outputStreamContainerFactory);
}
public void list() {
for (String verifyProcessName : _verifyProcesses.keySet()) {
show(verifyProcessName);
}
}
public void show(String verifyProcessName) {
try {
getVerifyProcesses(verifyProcessName);
}
catch (IllegalArgumentException iae) {
System.out.println(
"No verify process with name " + verifyProcessName);
return;
}
System.out.println("Registered verify process " + verifyProcessName);
}
public void showReports() {
Set<String> outputStreamContainerFactoryNames =
outputStreamContainerFactoryTracker.
getOutputStreamContainerFactoryNames();
for (String outputStreamContainerFactoryName :
outputStreamContainerFactoryNames) {
System.out.println(outputStreamContainerFactoryName);
}
}
@Activate
protected void activate(
BundleContext bundleContext, Map<String, Object> properties) {
_bundleContext = bundleContext;
_verifyProcessTrackerConfiguration =
ConfigurableUtil.createConfigurable(
VerifyProcessTrackerConfiguration.class, properties);
ServiceTrackerMapListener<String, VerifyProcess, List<VerifyProcess>>
verifyServiceTrackerMapListener = null;
if (_verifyProcessTrackerConfiguration.autoVerify()) {
verifyServiceTrackerMapListener =
new VerifyServiceTrackerMapListener();
}
_serviceRegistrations = new ConcurrentHashMap<>();
_verifyProcesses = ServiceTrackerMapFactory.multiValueMap(
_bundleContext, VerifyProcess.class, null,
new PropertyServiceReferenceMapper<String, VerifyProcess>(
"verify.process.name"),
new PropertyServiceReferenceComparator("service.ranking"),
verifyServiceTrackerMapListener);
_verifyProcesses.open();
}
protected void close(OutputStream outputStream) {
try {
outputStream.close();
}
catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
@Deactivate
protected void deactivate() {
_verifyProcesses.close();
for (Map.Entry
<String, ServiceRegistration<VerifyProcessCompletionMarker>>
serviceRegistrationEntry :
_serviceRegistrations.entrySet()) {
ServiceRegistration<VerifyProcessCompletionMarker>
serviceRegistration = serviceRegistrationEntry.getValue();
serviceRegistration.unregister();
}
_serviceRegistrations = null;
}
protected void executeVerifyProcesses(
String verifyProcessName, OutputStream outputStream) {
PrintWriter printWriter = new PrintWriter(outputStream, true);
List<VerifyProcess> verifyProcesses = getVerifyProcesses(
verifyProcessName);
boolean indexReadOnly = indexStatusManager.isIndexReadOnly();
indexStatusManager.setIndexReadOnly(
_verifyProcessTrackerConfiguration.indexReadOnly());
NotificationThreadLocal.setEnabled(false);
StagingAdvicesThreadLocal.setEnabled(false);
WorkflowThreadLocal.setEnabled(false);
try {
Release release = releaseLocalService.fetchRelease(
verifyProcessName);
if ((release != null) && release.isVerified()) {
if (!_serviceRegistrations.containsKey(verifyProcessName)) {
_registerVerifyProcessCompletionMarker(verifyProcessName);
}
return;
}
if (release == null) {
// Verification state must be persisted even though not all
// verifiers are associated with a database service
release = releaseLocalService.createRelease(
counterLocalService.increment());
release.setServletContextName(verifyProcessName);
release.setVerified(false);
}
printWriter.println(
"Executing verifiers registered for " + verifyProcessName);
VerifyException verifyException = null;
for (VerifyProcess verifyProcess : verifyProcesses) {
try {
verifyProcess.verify();
}
catch (VerifyException ve) {
_log.error(ve, ve);
verifyException = ve;
}
}
if (verifyException == null) {
release.setVerified(true);
releaseLocalService.updateRelease(release);
_registerVerifyProcessCompletionMarker(verifyProcessName);
}
}
finally {
indexStatusManager.setIndexReadOnly(indexReadOnly);
NotificationThreadLocal.setEnabled(true);
StagingAdvicesThreadLocal.setEnabled(true);
WorkflowThreadLocal.setEnabled(true);
}
}
protected void executeVerifyProcesses(
final String verifyProcessName, String outputStreamContainerFactoryName,
String outputStreamName) {
OutputStreamContainerFactory outputStreamContainerFactory;
if (outputStreamContainerFactoryName != null) {
outputStreamContainerFactory =
outputStreamContainerFactoryTracker.
getOutputStreamContainerFactory(
outputStreamContainerFactoryName);
}
else {
outputStreamContainerFactory =
outputStreamContainerFactoryTracker.
getOutputStreamContainerFactory();
}
OutputStreamContainer outputStreamContainer =
outputStreamContainerFactory.create(outputStreamName);
final OutputStream outputStream =
outputStreamContainer.getOutputStream();
outputStreamContainerFactoryTracker.runWithSwappedLog(
new Runnable() {
@Override
public void run() {
executeVerifyProcesses(verifyProcessName, outputStream);
}
},
outputStreamName, outputStream);
close(outputStream);
}
protected List<VerifyProcess> getVerifyProcesses(String verifyProcessName) {
List<VerifyProcess> verifyProcesses = _verifyProcesses.getService(
verifyProcessName);
if (verifyProcesses == null) {
throw new IllegalArgumentException(
"No verify processes with name " + verifyProcessName);
}
return verifyProcesses;
}
@Reference(target = ModuleServiceLifecycle.PORTAL_INITIALIZED, unbind = "-")
protected void setModuleServiceLifecycle(
ModuleServiceLifecycle moduleServiceLifecycle) {
}
@Reference
protected CounterLocalService counterLocalService;
@Reference
protected IndexStatusManager indexStatusManager;
@Reference
protected OutputStreamContainerFactoryTracker
outputStreamContainerFactoryTracker;
@Reference
protected ReleaseLocalService releaseLocalService;
private void _registerVerifyProcessCompletionMarker(
String verifyProcessName) {
Dictionary<String, String> dictionary = new HashMapDictionary<>();
dictionary.put("verify.process.name", verifyProcessName);
ServiceRegistration<VerifyProcessCompletionMarker> serviceRegistration =
_bundleContext.registerService(
VerifyProcessCompletionMarker.class,
new VerifyProcessCompletionMarker() {}, dictionary);
_serviceRegistrations.put(verifyProcessName, serviceRegistration);
}
private void _runAllVerifiersWithFactory(
OutputStreamContainerFactory outputStreamContainerFactory) {
OutputStreamContainer outputStreamContainer =
outputStreamContainerFactory.create("all-verifiers");
final OutputStream outputStream =
outputStreamContainer.getOutputStream();
outputStreamContainerFactoryTracker.runWithSwappedLog(
new AllVerifiersRunnable(outputStream),
outputStreamContainer.getDescription(), outputStream);
}
private static final Log _log = LogFactoryUtil.getLog(
VerifyProcessTrackerOSGiCommands.class);
private BundleContext _bundleContext;
private Map<String, ServiceRegistration<VerifyProcessCompletionMarker>>
_serviceRegistrations;
private ServiceTrackerMap<String, List<VerifyProcess>> _verifyProcesses;
private VerifyProcessTrackerConfiguration
_verifyProcessTrackerConfiguration;
private class AllVerifiersRunnable implements Runnable {
public AllVerifiersRunnable(OutputStream outputStream) {
_outputStream = outputStream;
}
@Override
public void run() {
Set<String> verifyProcessNames = _verifyProcesses.keySet();
for (String verifyProcessName : verifyProcessNames) {
executeVerifyProcesses(verifyProcessName, _outputStream);
}
}
private final OutputStream _outputStream;
}
private class VerifyServiceTrackerMapListener
implements ServiceTrackerMapListener
<String, VerifyProcess, List<VerifyProcess>> {
@Override
public void keyEmitted(
ServiceTrackerMap<String, List<VerifyProcess>>
verifyProcessTrackerMap,
String key, VerifyProcess serviceVerifyProcess,
List<VerifyProcess> contentVerifyProcesses) {
execute(key);
}
@Override
public void keyRemoved(
ServiceTrackerMap<String, List<VerifyProcess>> serviceTrackerMap,
String key, VerifyProcess serviceVerifyProcess,
List<VerifyProcess> contentVerifyProcess) {
}
}
}