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

com.marklogic.client.io.JacksonParserHandle Maven / Gradle / Ivy

/*
 * Copyright 2012-2016 MarkLogic Corporation
 *
 * 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.marklogic.client.io;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.marklogic.client.MarkLogicIOException;
import com.marklogic.client.impl.JacksonBaseHandle;
import com.marklogic.client.io.marker.BufferableHandle;
import com.marklogic.client.io.marker.ContentHandle;
import com.marklogic.client.io.marker.ContentHandleFactory;
import com.marklogic.client.io.marker.JSONReadHandle;
import com.marklogic.client.io.marker.JSONWriteHandle;
import com.marklogic.client.io.marker.StructureReadHandle;
import com.marklogic.client.io.marker.StructureWriteHandle;
import com.marklogic.client.io.marker.TextReadHandle;
import com.marklogic.client.io.marker.TextWriteHandle;
import com.marklogic.client.io.marker.XMLReadHandle;
import com.marklogic.client.io.marker.XMLWriteHandle;

/**
 * 

An adapter for using the streaming capabilities of the Jackson Open Source library. * Enables low-level efficient reading and writing of JSON documents.

* *

Always call {@link #close} when finished with this handle to release the resources.

* * @see Jackson Streaming API */ public class JacksonParserHandle extends JacksonBaseHandle implements ContentHandle, OutputStreamSender, BufferableHandle, JSONReadHandle, JSONWriteHandle, TextReadHandle, TextWriteHandle, XMLReadHandle, XMLWriteHandle, StructureReadHandle, StructureWriteHandle, Closeable { static final private Logger logger = LoggerFactory.getLogger(JacksonParserHandle.class); private JsonParser parser = null; private InputStream content = null; private boolean closed = false; final static private int BUFFER_SIZE = 8192; /** * Creates a factory to create a JacksonParserHandle instance for a JsonParser. * @return the factory */ static public ContentHandleFactory newFactory() { return new ContentHandleFactory() { @Override public Class[] getHandledClasses() { return new Class[]{ JsonParser.class }; } @Override public boolean isHandled(Class type) { return JsonParser.class.isAssignableFrom(type); } @Override public ContentHandle newHandle(Class type) { @SuppressWarnings("unchecked") ContentHandle handle = isHandled(type) ? (ContentHandle) new JacksonParserHandle() : null; return handle; } }; } public JacksonParserHandle() { super(); setFormat(Format.JSON); setResendable(false); } /** * Specifies the format of the content and returns the handle * as a fluent convenience. * @param format the format of the content * @return this handle */ public JacksonParserHandle withFormat(Format format) { setFormat(format); return this; } /** * JsonParser allows streaming access to content as it arrives. * @return the JsonParser over the content (usually received from the server) */ public JsonParser get() { if ( parser == null ) { if ( content == null ) { throw new IllegalStateException("Handle is not yet populated with content"); } try { parser = getMapper().getFactory().createParser(content); } catch (JsonParseException e) { throw new MarkLogicIOException(e); } catch (IOException e) { throw new MarkLogicIOException(e); } } return parser; } /** * Available for the edge case that content from a JsonParser must be written. */ public void set(JsonParser parser) { this.parser = parser; if ( parser == null ) { content = null; } else if ( parser.getInputSource() instanceof InputStream ) { content = (InputStream) parser.getInputSource(); } } /** * Provides access to the ObjectMapper used internally so you can configure * it to fit your JSON. * @return the ObjectMapper instance */ @Override public ObjectMapper getMapper() { return super.getMapper(); } /** * Enables clients to specify their own ObjectMapper instance, including databinding mappers * for formats other than JSON. * For example:
{@code
     *ObjectMapper mapper = new CsvMapper();
     *mapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
     *mapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false);
     *handle.setMapper(mapper);
     * }
* * Use at your own risk! Note that you most likely want to set to false the two options we * demonstrate above (JsonGenerator.Feature.AUTO_CLOSE_TARGET and JsonParser.Feature.AUTO_CLOSE_SOURCE) * as we do so your mapper will not close streams which we may need to reuse if we have to * resend a network request. **/ @Override public void setMapper(ObjectMapper mapper) { super.setMapper(mapper); } @Override protected void receiveContent(InputStream content) { this.content = content; if (content == null) parser = null; } protected boolean hasContent() { return content != null || parser != null; } @Override public void write(OutputStream out) throws IOException { try { if ( parser != null && parser.nextToken() != null ) { JsonGenerator generator = getMapper().getFactory().createGenerator(out); generator.copyCurrentStructure(parser); generator.close(); } else if (content != null) { byte[] b = new byte[BUFFER_SIZE]; int len = 0; while ((len = content.read(b)) != -1) { out.write(b, 0, len); } content.close(); closed = true; } } catch (IOException e) { throw new MarkLogicIOException(e); } } /** Always call close() when finished with this handle -- it closes the underlying InputStream. */ public void close() { if ( content != null && closed != true ) { try { content.close(); } catch (IOException e) { logger.error("Failed to close underlying InputStream",e); throw new MarkLogicIOException(e); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy