/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* 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.xwiki.filter.xar.internal.input;
import java.io.IOException;
import java.io.InputStream;
import javax.inject.Inject;
import javax.inject.Provider;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.xwiki.component.annotation.Component;
import org.xwiki.component.annotation.InstantiationStrategy;
import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
import org.xwiki.filter.FilterEventParameters;
import org.xwiki.filter.FilterException;
import org.xwiki.filter.input.AbstractBeanInputFilterStream;
import org.xwiki.filter.input.InputSource;
import org.xwiki.filter.input.InputStreamInputSource;
import org.xwiki.filter.input.ReaderInputSource;
import org.xwiki.filter.xar.input.XARInputProperties;
import org.xwiki.filter.xar.internal.XARFilterUtils;
import org.xwiki.filter.xml.input.SourceInputSource;
import org.xwiki.model.reference.EntityReference;
/**
* @version $Id: c3cf3885cea5fdc5812de89053f694fe7b97c4e5 $
* @since 6.2M1
*/
@Component(hints = {XARFilterUtils.ROLEHINT_13, XARFilterUtils.ROLEHINT_12, XARFilterUtils.ROLEHINT_11})
@InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
public class XARInputFilterStream extends AbstractBeanInputFilterStream<XARInputProperties, XARInputFilter>
{
@Inject
private Provider<WikiReader> wikiReaderProvider;
@Inject
private Provider<DocumentLocaleReader> documentLocaleReaderProvider;
@Override
public void close() throws IOException
{
this.properties.getSource().close();
}
@Override
protected void read(Object filter, XARInputFilter proxyFilter) throws FilterException
{
InputSource inputSource = this.properties.getSource();
if (this.properties.isForceDocument() || inputSource instanceof ReaderInputSource
|| inputSource instanceof SourceInputSource) {
readDocument(filter, proxyFilter);
} else if (inputSource instanceof InputStreamInputSource) {
InputStream stream;
try {
stream = ((InputStreamInputSource) inputSource).getInputStream();
} catch (IOException e) {
throw new FilterException("Failed to get input stream", e);
}
Boolean iszip;
try {
iszip = isZip(stream);
} catch (IOException e) {
throw new FilterException("Failed to read input stream", e);
} finally {
try {
inputSource.close();
} catch (IOException e) {
throw new FilterException("Failed to close the source", e);
}
}
if (iszip == Boolean.FALSE) {
readDocument(filter, proxyFilter);
} else {
readXAR(filter, proxyFilter);
}
} else {
throw new FilterException(String.format("Unsupported input source of type [%s]", inputSource.getClass()));
}
}
private void readXAR(Object filter, XARInputFilter proxyFilter) throws FilterException
{
WikiReader wikiReader = this.wikiReaderProvider.get();
wikiReader.setProperties(this.properties);
try {
wikiReader.read(filter, proxyFilter);
} catch (Exception e) {
throw new FilterException("Failed to read XAR package", e);
}
}
protected void readDocument(Object filter, XARInputFilter proxyFilter) throws FilterException
{
DocumentLocaleReader documentReader = documentLocaleReaderProvider.get();
documentReader.setProperties(this.properties);
try {
documentReader.read(filter, proxyFilter);
} catch (Exception e) {
throw new FilterException("Failed to read XAR XML document", e);
}
// Close remaining opened spaces
if (documentReader.getSentSpaceReference() != null) {
for (EntityReference space = documentReader.getSentSpaceReference(); space != null; space =
space.getParent()) {
proxyFilter.endWikiSpace(space.getName(), FilterEventParameters.EMPTY);
}
}
}
private Boolean isZip(InputStream stream) throws IOException
{
if (!stream.markSupported()) {
// ZIP by default
return null;
}
final byte[] signature = new byte[12];
stream.mark(signature.length);
int signatureLength = stream.read(signature);
stream.reset();
return ZipArchiveInputStream.matches(signature, signatureLength);
}
}