Package com.google.enterprise.connector.db

Source Code of com.google.enterprise.connector.db.InputStreamFactories

// Copyright 2012 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.enterprise.connector.db;

import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import com.google.common.io.FileBackedOutputStream;
import com.google.common.io.InputSupplier;
import com.google.enterprise.connector.spi.RepositoryDocumentException;
import com.google.enterprise.connector.spi.Value;
import com.google.enterprise.connector.spiimpl.BinaryValue;
import com.google.enterprise.connector.util.Base64;
import com.google.enterprise.connector.util.Base64DecoderException;
import com.google.enterprise.connector.util.Base64FilterInputStream;
import com.google.enterprise.connector.util.InputStreamFactory;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.logging.Level;
import java.util.logging.Logger;

/** A factory and utility class for {@code InputStreamFactory}. */
/* TODO(jlacey): Move this to CM util package if another connector wants it. */
public class InputStreamFactories {
  private static final Logger LOG =
      Logger.getLogger(InputStreamFactories.class.getName());

  /**
   * Gets an {@code InputStreamFactory} that tries not to consume large
   * amounts of memory, no matter how large the given byte array is.
   *
   * @param data a byte array
   */
  public static final InputStreamFactory newInstance(byte[] data) {
    if (data == null) {
      return null;
    }
    try {
      return new FileBackedInputStreamFactory(data);
    } catch (IOException e) {
      if (LOG.isLoggable(Level.FINEST)) {
        LOG.log(Level.WARNING, "Failed to cache document content.", e);
      } else {
        LOG.warning("Failed to cache document content:\n" + e.toString());
      }
      // Resort to holding the binary data in memory, rather than on disk.
      return new ByteArrayInputStreamFactory(data);
    }
  }

  /**
   * Gets an {@code InputStreamFactory} for a Base64-encoded string.
   * If the input is not Base64-encoded, it is converted to bytes
   * using UTF-8.
   */
  public static final InputStreamFactory fromBase64String(String content) {
    byte[] bytes = content.getBytes(Charsets.UTF_8);
    byte[] decodedBytes;
    try {
      decodedBytes = Base64.decode(bytes);
    } catch (Base64DecoderException e) {
      // Just leave the data as-is.
      decodedBytes = bytes;
    }
    return newInstance(decodedBytes);
  }

  /** Fully reads an input stream from the factory and Base64 encodes it. */
  public static final String toBase64String(InputStreamFactory factory)
      throws IOException {
    return CharStreams.toString(new InputStreamReader(
            new Base64FilterInputStream(factory.getInputStream()),
            Charsets.UTF_8));
  }

  /** Fully reads an input stream from the value and Base64 encodes it. */
  public static final String toString(Value binaryValue)
      throws IOException, RepositoryDocumentException {
    return CharStreams.toString(new InputStreamReader(
            ((BinaryValue) binaryValue).getInputStream(),
            Charsets.UTF_8));
  }

  public static interface ContentLengthInputStreamFactory
      extends InputStreamFactory {
    /**
     * Returns the number of bytes of content that will be returned by the
     * InputStream, or -1 if the length is not known.
     */
    public long length();
  }

  /** An InputStreamFactory backed by a FileBackedOutputStream. */
  private static class FileBackedInputStreamFactory
      implements ContentLengthInputStreamFactory {
    private static final int IN_MEMORY_THRESHOLD = 32 * 1024;

    /**
     * We hold onto a single supplier, because when that gets finalized,
     * the backing file will get deleted.
     */
    private final InputSupplier<InputStream> supplier;
    private final long length;

    FileBackedInputStreamFactory(byte[] data) throws IOException {
      FileBackedOutputStream out =
          new FileBackedOutputStream(IN_MEMORY_THRESHOLD, true);
      length = data.length;
      out.write(data);
      out.close();
      supplier = out.getSupplier();
    }

    @Override
    public InputStream getInputStream() throws IOException {
      return supplier.getInput();
    }

    @Override
    public long length() {
      return length;
    }
  }

  /** An InputStreamFactory backed by a byte array. */
  private static class ByteArrayInputStreamFactory
      implements ContentLengthInputStreamFactory {
    private final byte[] data;

    ByteArrayInputStreamFactory(byte[] data) {
      // TODO(jlacey): Make a defensive copy of the array?
      this.data = data;
    }

    @Override
    public InputStream getInputStream() {
      return new ByteArrayInputStream(data);
    }

    @Override
    public long length() {
      return data.length;
    }
  }

  /** This class should not be instantiated. */
  private InputStreamFactories() {
    throw new AssertionError();
  }
}
TOP

Related Classes of com.google.enterprise.connector.db.InputStreamFactories

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.