/**
* 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.output.stream.container;
import com.liferay.osgi.service.tracker.collections.map.ServiceTrackerMap;
import com.liferay.osgi.service.tracker.collections.map.ServiceTrackerMapFactory;
import com.liferay.portal.kernel.module.framework.ModuleServiceLifecycle;
import com.liferay.portal.output.stream.container.internal.ConsoleOutputStreamContainerFactory;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Set;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;
import org.apache.log4j.WriterAppender;
import org.osgi.framework.BundleContext;
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.Reference;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
/**
* @author Carlos Sierra Andrés
*/
@Component(
immediate = true, service = OutputStreamContainerFactoryTracker.class
)
public class OutputStreamContainerFactoryTracker {
public OutputStreamContainerFactory getOutputStreamContainerFactory() {
return _outputStreamContainerFactory;
}
public OutputStreamContainerFactory getOutputStreamContainerFactory(
String outputStreamContainerFactoryName) {
OutputStreamContainerFactory outputStreamContainerFactory =
_outputStreamContainerFactories.getService(
outputStreamContainerFactoryName);
if (outputStreamContainerFactory == null) {
throw new IllegalArgumentException(
"No output stream container factory registered with name " +
outputStreamContainerFactoryName);
}
return outputStreamContainerFactory;
}
public Set<String> getOutputStreamContainerFactoryNames() {
return _outputStreamContainerFactories.keySet();
}
public void runWithSwappedLog(Runnable runnable, String outputStreamHint) {
OutputStreamContainer outputStreamContainer =
_outputStreamContainerFactory.create(outputStreamHint);
runWithSwappedLog(
runnable, outputStreamContainer.getDescription(),
outputStreamContainer.getOutputStream());
}
public void runWithSwappedLog(
Runnable runnable, String outputStreamName, OutputStream outputStream) {
_logger.log(
org.apache.felix.utils.log.Logger.LOG_INFO,
"Using " + outputStreamName + " as output");
Writer writer = _writerThreadLocal.get();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(
outputStream, Charset.forName("UTF-8"));
_writerThreadLocal.set(outputStreamWriter);
try {
runnable.run();
outputStreamWriter.flush();
}
catch (IOException ioe) {
_logger.log(
org.apache.felix.utils.log.Logger.LOG_ERROR,
ioe.getLocalizedMessage());
}
finally {
_writerThreadLocal.set(writer);
}
}
public void runWithSwappedLog(
Runnable runnable, String outputStreamHint,
String outputStreamContainerName) {
OutputStreamContainerFactory outputStreamContainerFactory =
_outputStreamContainerFactories.getService(
outputStreamContainerName);
if (outputStreamContainerFactory == null) {
runWithSwappedLog(runnable, outputStreamHint);
return;
}
OutputStreamContainer outputStreamContainer =
outputStreamContainerFactory.create(outputStreamHint);
runWithSwappedLog(
runnable, outputStreamContainer.getDescription(),
outputStreamContainer.getOutputStream());
}
@Activate
protected void activate(BundleContext bundleContext) {
_logger = new org.apache.felix.utils.log.Logger(bundleContext);
Logger rootLogger = Logger.getRootLogger();
_writerAppender = new WriterAppender(
new SimpleLayout(), new ThreadLocalWriter());
_writerAppender.setThreshold(Level.ALL);
_writerAppender.activateOptions();
rootLogger.addAppender(_writerAppender);
_outputStreamContainerFactories =
ServiceTrackerMapFactory.openSingleValueMap(
bundleContext, OutputStreamContainerFactory.class, "name");
}
@Deactivate
protected void deactivate() {
Logger rootLogger = Logger.getRootLogger();
if (_outputStreamContainerFactory != null) {
_outputStreamContainerFactories.close();
}
if (rootLogger != null) {
rootLogger.removeAppender(_writerAppender);
}
}
@Reference(target = ModuleServiceLifecycle.PORTAL_INITIALIZED, unbind = "-")
protected void setModuleServiceLifecycle(
ModuleServiceLifecycle moduleServiceLifecycle) {
}
@Reference(
policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY
)
protected void setOutputStreamContainerFactory(
OutputStreamContainerFactory outputStreamContainerFactory) {
_outputStreamContainerFactory = outputStreamContainerFactory;
}
protected void unsetOutputStreamContainerFactory(
OutputStreamContainerFactory outputStreamContainerFactory) {
_outputStreamContainerFactory = _consoleOutputStreamContainerFactory;
}
private final OutputStreamContainerFactory
_consoleOutputStreamContainerFactory =
new ConsoleOutputStreamContainerFactory();
private org.apache.felix.utils.log.Logger _logger;
private ServiceTrackerMap<String, OutputStreamContainerFactory>
_outputStreamContainerFactories;
private OutputStreamContainerFactory _outputStreamContainerFactory;
private WriterAppender _writerAppender;
private final ThreadLocal<Writer> _writerThreadLocal = new ThreadLocal<>();
private class ThreadLocalWriter extends Writer {
@Override
public void close() throws IOException {
Writer writer = _writerThreadLocal.get();
if (writer != null) {
writer.close();
}
}
@Override
public void flush() throws IOException {
Writer writer = _writerThreadLocal.get();
if (writer != null) {
writer.flush();
}
}
@Override
public void write(char[] chars, int offset, int length)
throws IOException {
Writer writer = _writerThreadLocal.get();
if (writer != null) {
writer.write(chars, offset, length);
}
}
}
}