/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, version 2 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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 General Public License for more details.
*
*
* Copyright 2005 - 2008 Pentaho Corporation. All rights reserved.
*
* @created Jul 11, 2005
* @author James Dixon
*
*/
package org.pentaho.platform.engine.core.output;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.platform.api.engine.IContentOutputHandler;
import org.pentaho.platform.api.engine.IMimeTypeListener;
import org.pentaho.platform.api.engine.IOutputDef;
import org.pentaho.platform.api.engine.IOutputHandler;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.engine.IRuntimeContext;
import org.pentaho.platform.api.repository.IContentItem;
import org.pentaho.platform.engine.core.messages.Messages;
import org.pentaho.platform.engine.core.system.PentahoSystem;
/**
* @author aaron
*
*/
public class SimpleOutputHandler implements IOutputHandler {
private Map<String, Object> responseAttributes;
private IContentItem feedbackContent;
boolean allowFeedback;
private String mimeType;
private int outputType = IOutputHandler.OUTPUT_TYPE_DEFAULT;
private boolean contentGenerated;
private Map<String, IContentItem> outputs;
private IPentahoSession session;
private IMimeTypeListener mimeTypeListener;
protected IRuntimeContext runtimeContext;
private boolean responseExpected;
private static final Log logger = LogFactory.getLog(SimpleOutputHandler.class);
/**
* Creates a {@link SimpleContentItem} copy of an {@link IContentItem}
* @param contentItem provides the underlying outputStream this outputhandler manages.
* Feedback will also be written to this contentItem's output stream if allowFeedback is true
* @param allowFeedback
*/
public SimpleOutputHandler(final IContentItem contentItem, final boolean allowFeedback) {
responseAttributes = new HashMap<String, Object>();
contentGenerated = false;
outputs = new HashMap<String, IContentItem>();
try {
String key = IOutputHandler.RESPONSE + "." + IOutputHandler.CONTENT; //$NON-NLS-1$
outputs.put(key, contentItem);
this.allowFeedback = allowFeedback;
if (allowFeedback) {
feedbackContent = new SimpleContentItem(contentItem.getOutputStream(null));
}
} catch (IOException ioe) {
SimpleOutputHandler.logger.error(null, ioe);
}
}
/**
* Creates a SimpleContentItem from an OutputStream.
* @param outputStream the underlying outputStream this outputhandler manages.
* Feedback will be written to this output stream if allowFeedback is true
* @param allowFeedback
*/
public SimpleOutputHandler(final OutputStream outputStream, final boolean allowFeedback) {
this.allowFeedback = allowFeedback;
if (allowFeedback) {
feedbackContent = new SimpleContentItem(outputStream);
}
responseAttributes = new HashMap<String, Object>();
contentGenerated = false;
outputs = new HashMap<String, IContentItem>();
setOutputStream(outputStream, IOutputHandler.RESPONSE, IOutputHandler.CONTENT);
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#setSession(org.pentaho.platform.api.engine.IPentahoSession)
*/
public void setSession(final IPentahoSession session) {
this.session = session;
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#getSession()
*/
public IPentahoSession getSession() {
return session;
}
public void setOutputStream(final OutputStream outputStream, final String outputName, final String contentName) {
String key = outputName + "." + contentName; //$NON-NLS-1$
SimpleContentItem item = new SimpleContentItem(outputStream);
outputs.put(key, item);
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#setOutputPreference(int)
*/
public void setOutputPreference(final int outputType) {
this.outputType = outputType;
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#contentDone()
*/
public boolean contentDone() {
return contentGenerated;
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#getOutputPreference()
*/
public int getOutputPreference() {
return outputType;
}
public void setMimeType(final String mimeType) {
this.mimeType = mimeType;
}
public String getMimeType() {
return mimeType;
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#allowFeedback()
*/
public boolean allowFeedback() {
return allowFeedback;
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#getOutputDefs()
*/
public Map getOutputDefs() {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#getOutputDef(java.lang.String)
*/
public IOutputDef getOutputDef(final String name) {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#getFeedbackContentItem()
*/
public IContentItem getFeedbackContentItem() {
if (allowFeedback) {
contentGenerated = true;
/*
* if someone is requesting a feedbackContentItem, we can assume they tend to write feedback
* back to the client, so we set the flag here
*/
responseExpected = true;
return feedbackContent;
}
return null;
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#getOutputContentItem(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
*/
public IContentItem getOutputContentItem(final String outputName, final String contentName, final String solution,
final String instanceId, final String localMimeType) {
if(outputName.equals(IOutputHandler.RESPONSE) && contentName.equals(IOutputHandler.CONTENT)) {
responseExpected = true;
}
String key = outputName + "." + contentName; //$NON-NLS-1$
if (outputs.get(key) != null) {
return outputs.get(key);
} else {
IContentOutputHandler output = PentahoSystem.getOutputDestinationFromContentRef(contentName, session);
if (output != null) {
output.setInstanceId(instanceId);
output.setMimeType(localMimeType);
output.setSolutionName(solution);
return output.getFileOutputContentItem();
}
}
return null;
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#getOutputContentItem(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
*/
public IContentItem getOutputContentItem(final String objectName, final String contentName, final String title,
final String url, final String solution, final String instanceId, final String localMimeType) {
return getOutputContentItem(objectName, contentName, solution, instanceId, localMimeType);
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#setContentItem(org.pentaho.platform.api.repository.IContentItem, java.lang.String, java.lang.String)
*/
public void setContentItem(final IContentItem content, final String objectName, final String contentName) {
mimeType = content.getMimeType();
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#setOutput(java.lang.String, java.lang.Object)
*
* This implementation tries to write the data in "value" to the response outputstream managed by this
* output handler, or if "value" is null, adds it to a responseAttributes map for later retrieval.
*/
public void setOutput(final String name, final Object value) {
if (value == null) {
SimpleOutputHandler.logger.info(Messages.getInstance().getString("SimpleOutputHandler.INFO_VALUE_IS_NULL")); //$NON-NLS-1$
return;
}
if (IOutputHandler.CONTENT.equalsIgnoreCase(name)) {
IContentItem response = getOutputContentItem("response", IOutputHandler.CONTENT, null, null, null, null, null); //$NON-NLS-1$
if (response != null) {
try {
//If "value" to set is an IContentItem, then write it to the outputstream
//of the response IContentItem managed by this output handler.
if (value instanceof IContentItem) {
IContentItem content = (IContentItem) value;
// See if we should process the input stream. If it's from
// the content repository, then there's an input stream.
// SimpleContentItem and HttpContentItem both return null from
// getInputStream().
InputStream inStr = content.getInputStream();
if (inStr != null) {
if ((response.getMimeType() == null) || (!response.getMimeType().equalsIgnoreCase(content.getMimeType()))) {
response.setMimeType(content.getMimeType());
}
try {
OutputStream outStr = response.getOutputStream(response.getActionName());
int inCnt = 0;
byte[] buf = new byte[4096];
while (-1 != (inCnt = inStr.read(buf))) {
outStr.write(buf, 0, inCnt);
}
} finally {
try {
inStr.close();
} catch (Exception ignored) {
}
}
contentGenerated = true;
}
} else {
//if "value" is not an IContentItem, assume it is a string and write it out
if (response.getMimeType() == null) {
response.setMimeType("text/html"); //$NON-NLS-1$
}
response.getOutputStream(response.getActionName()).write(value.toString().getBytes());
contentGenerated = true;
}
} catch (IOException ioe) {
//FIXME: do not swallow this exception
SimpleOutputHandler.logger.error(null, ioe);
}
}
} else {
responseAttributes.put(name, value);
}
}
public Map getResponseAttributes() {
return responseAttributes;
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#getMimeTypeListener()
*/
public IMimeTypeListener getMimeTypeListener() {
return mimeTypeListener;
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#setMimeTypeListener(org.pentaho.platform.api.engine.IMimeTypeListener)
*/
public void setMimeTypeListener(final IMimeTypeListener mimeTypeListener) {
this.mimeTypeListener = mimeTypeListener;
}
/* (non-Javadoc)
* @see org.pentaho.platform.api.engine.IOutputHandler#setRuntimeContext(org.pentaho.platform.api.engine.IRuntimeContext)
*/
public void setRuntimeContext(final IRuntimeContext runtimeContext) {
this.runtimeContext = runtimeContext;
}
public boolean isResponseExpected() {
return responseExpected;
}
}