All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gc.iotools.fmt.GuessInputStream Maven / Gradle / Ivy

package com.gc.iotools.fmt;

/*
 * Copyright (c) 2008, Davide Simonetti
 * All rights reserved.
 * Redistribution and use in source and binary forms, 
 * with or without modification, are permitted provided that the following 
 * conditions are met:
 *  * Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution.
 *  * Neither the name of Davide Simonetti nor the names of its contributors may
 *    be used to endorse or promote products derived from this software without 
 *    specific prior written permission.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;

import com.gc.iotools.fmt.base.Decoder;
import com.gc.iotools.fmt.base.DetectionLibrary;
import com.gc.iotools.fmt.base.FormatEnum;
import com.gc.iotools.fmt.base.FormatId;
import com.gc.iotools.fmt.base.ResettableInputStream;
import com.gc.iotools.fmt.decoders.Base64Decoder;
import com.gc.iotools.fmt.decoders.GzipDecoder;
import com.gc.iotools.fmt.decoders.Pkcs7Decoder;
import com.gc.iotools.fmt.detect.droid.DroidDetectorImpl;
import com.gc.iotools.fmt.detect.wzf.StreamDetectorImpl;
import com.gc.iotools.stream.is.RandomAccessInputStream;

/**
 * InputStream that wraps the original InputStream and guess the format.
 * 
 * To support a new format:
 * 
    *
  • implement a new DetectorModule. The metod parse(bytes[]) should return * true when the format is recognized
  • *
  • Extend the enum FormatEnum to provide the new name for the format.
  • *
  • Either register it statically in GuessFormatInputStream with the method * addDetector or pass an instance in the constructor.
  • *
* */ public class GuessInputStream extends InputStream { public static final Collection DEFAULT_DECODERS = new HashSet(); static { DEFAULT_DECODERS.add(new Base64Decoder()); DEFAULT_DECODERS.add(new GzipDecoder()); DEFAULT_DECODERS.add(new Pkcs7Decoder()); } public static void addDefaultDecoder(final Decoder decoder) { if (decoder == null) { throw new IllegalArgumentException("decoder is null"); } DEFAULT_DECODERS.add(decoder); } public static void addDefaultDecoders(final Decoder[] decoders) { if (decoders == null) { throw new IllegalArgumentException("decoders array is null"); } DEFAULT_DECODERS.addAll(Arrays.asList(decoders)); } public static GuessInputStream getInstance(final InputStream istream) throws IOException { return getInstance(istream, FormatEnum.values(), 0); } public static GuessInputStream getInstance(final InputStream istream, final Class clazz, final String droidSignatureFile, String streamConfigFile) throws IOException { if (droidSignatureFile == null && streamConfigFile == null) { throw new IllegalArgumentException( "both configuration files are null."); } Collection detectionLibraries = new HashSet(); if (streamConfigFile != null) { DetectionLibrary stream = new StreamDetectorImpl(streamConfigFile, clazz); detectionLibraries.add(stream); } if (droidSignatureFile != null) { DetectionLibrary stream = new DroidDetectorImpl(); detectionLibraries.add(stream); } return getInstance(istream, null, detectionLibraries.toArray(new DetectionLibrary[0]), DEFAULT_DECODERS.toArray(new Decoder[0]), 0); } // private static final Loggerger LOGGER = Loggerger // .getLoggerger(GuessFormatInputStream.class); // Should become a collection to support multiple detectors per format // private final Set definiteLength = new // HashSet(); public static GuessInputStream getInstance(final InputStream source, final FormatEnum[] enabledFormats) throws IOException { return getInstance(source, enabledFormats, 0); } /** * This method creates an instance of the GuessInputStream. It checks if the * InputStream is already an instance of GuessInputStream and do * optimizations if possible. * * @param source * Source stream to be wrapped. * @return Instance of the newly created GuessInputStream */ public static GuessInputStream getInstance(final InputStream source, final FormatEnum[] enabledFormats, int recursionLevel) throws IOException { Collection detectionLibraries = new ArrayList(); detectionLibraries.add(new StreamDetectorImpl()); detectionLibraries.add(new DroidDetectorImpl()); return getInstance(source, enabledFormats, detectionLibraries .toArray(new DetectionLibrary[0]), DEFAULT_DECODERS .toArray(new Decoder[0]), recursionLevel); } public static GuessInputStream getInstance(final InputStream stream, final FormatEnum[] enabledFormats, final DetectionLibrary[] detectors, final Decoder[] decoders, int recursionLevel) throws IOException { if (stream == null) { throw new IllegalArgumentException("Parameter stream==null"); } GuessInputStream result; ResettableStreamRASAdapter ris; if (stream instanceof GuessInputStream) { final GuessInputStream gis = (GuessInputStream) stream; ris = gis.baseStream; } else { ris = new ResettableStreamRASAdapter(new RandomAccessInputStream( stream)); } ris.enable(true); DetectionStrategy ds = new DetectionStrategy(detectors, decoders, enabledFormats, ris, recursionLevel); result = new GuessInputStream(enabledFormats, ds.getFormats(), ris, ds.getStream()); ris.enable(false); return result; } private final ResettableStreamRASAdapter baseStream; private final ResettableInputStream decodedStream; private final FormatId[] detectedFormats; private final Collection enabledFormats; private InputStreamStatusEnum status = InputStreamStatusEnum.NOT_INITIALIZED; private boolean decode = false; protected GuessInputStream(final FormatEnum[] enabledFormats, FormatId[] detected, ResettableStreamRASAdapter baseStream, ResettableInputStream decodedStream) { this.enabledFormats = Collections.unmodifiableCollection(Arrays .asList(enabledFormats)); this.baseStream = baseStream; this.decodedStream = decodedStream; this.detectedFormats = detected; } public void setDecode(boolean decode) { if (status.equals(InputStreamStatusEnum.READING_DATA) && (decode != this.decode)) { throw new IllegalStateException("Some byte has been " + " read already from the underlying stream. " + "It is not possible " + "to change the decoding behaviour now. " + "Decoding behaviour set [" + this.decode + "] decoding wanted[" + decode + "]"); } this.decode = decode; } @Override public int available() throws IOException { return getStream().available(); } public final boolean canDetect(final FormatEnum formatEnum) { if (formatEnum == null) { throw new IllegalArgumentException("Parameter formatEnum is null"); } return this.enabledFormats.contains(formatEnum); } public final boolean canDetectAll(final FormatEnum[] formatEnums) { if (formatEnums == null) { throw new IllegalArgumentException( "Parameter formatEnums is null"); } boolean result = true; for (int i = 0; i < formatEnums.length && result; i++) { FormatEnum formatEnum = formatEnums[i]; result &= this.enabledFormats.contains(formatEnum); } return result; } @Override public void close() throws IOException { status = InputStreamStatusEnum.READING_DATA; getStream().close(); } public FormatId[] getDetectedFormatsId() { return detectedFormats; } public final FormatEnum getFormat() { return getFormatId().format; } public final FormatId getFormatId() { return getDetectedFormatsId()[0]; } public final FormatEnum[] getFormats() { FormatId[] formats = getDetectedFormatsId(); Collection result = new ArrayList(); for (FormatId formatId : formats) { result.add(formatId.format); } return result.toArray(new FormatEnum[0]); } @Override public boolean markSupported() { return false; } @Override public int read() throws IOException { status = InputStreamStatusEnum.READING_DATA; return getStream().read(); } @Override public int read(byte[] b) throws IOException { status = InputStreamStatusEnum.READING_DATA; return getStream().read(b); } @Override public int read(byte[] b, int off, int len) throws IOException { status = InputStreamStatusEnum.READING_DATA; return getStream().read(b, off, len); } @Override public long skip(long n) throws IOException { status = InputStreamStatusEnum.READING_DATA; return getStream().skip(n); } private InputStream getStream() { return (decode ? decodedStream : baseStream); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy