[OLINGO-832] Merge branch 'OLINGO-832_StreamSerializerPoC'
This commit is contained in:
commit
47bc730a89
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.olingo.fit.tecsvc.http;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.olingo.client.api.ODataClient;
|
||||||
|
import org.apache.olingo.commons.api.format.ContentType;
|
||||||
|
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||||
|
import org.apache.olingo.commons.api.http.HttpMethod;
|
||||||
|
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
||||||
|
import org.apache.olingo.fit.AbstractBaseTestITCase;
|
||||||
|
import org.apache.olingo.fit.tecsvc.TecSvcConst;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class BasicStreamITCase extends AbstractBaseTestITCase {
|
||||||
|
|
||||||
|
private static final String SERVICE_URI = TecSvcConst.BASE_URI + "/";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void streamAllPrim() throws Exception {
|
||||||
|
URL url = new URL(SERVICE_URI + "ESAllPrim?$format=json");
|
||||||
|
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
connection.setRequestMethod(HttpMethod.GET.name());
|
||||||
|
connection.setRequestProperty("odata.streaming", "true");
|
||||||
|
connection.connect();
|
||||||
|
|
||||||
|
assertEquals(HttpStatusCode.OK.getStatusCode(), connection.getResponseCode());
|
||||||
|
assertEquals(ContentType.JSON, ContentType.create(connection.getHeaderField(HttpHeader.CONTENT_TYPE)));
|
||||||
|
|
||||||
|
final String content = IOUtils.toString(connection.getInputStream());
|
||||||
|
|
||||||
|
assertTrue(content.contains("\"PropertyString\":\"First Resource - positive values->streamed\""));
|
||||||
|
assertTrue(content.contains("\"PropertyString\":\"Second Resource - negative values->streamed\""));
|
||||||
|
assertTrue(content.contains("\"PropertyString\":\"->streamed\""));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ODataClient getClient() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -525,7 +525,7 @@ public class AtomSerializer extends AbstractAtomDealer implements ODataSerialize
|
||||||
|
|
||||||
common(writer, entitySet);
|
common(writer, entitySet);
|
||||||
|
|
||||||
for (Entity entity : entitySet.getEntities()) {
|
for (Entity entity : entitySet) {
|
||||||
if (entity.getType() == null && entity.getProperties().isEmpty()) {
|
if (entity.getType() == null && entity.getProperties().isEmpty()) {
|
||||||
entityRef(writer, entity);
|
entityRef(writer, entity);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.olingo.commons.api.data;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public abstract class AbstractEntityCollection extends AbstractODataObject implements Iterable<Entity> {
|
||||||
|
public abstract Integer getCount();
|
||||||
|
|
||||||
|
public abstract URI getNext();
|
||||||
|
|
||||||
|
public abstract URI getDeltaLink();
|
||||||
|
}
|
|
@ -20,12 +20,13 @@ package org.apache.olingo.commons.api.data;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data representation for a collection of single entities.
|
* Data representation for a collection of single entities.
|
||||||
*/
|
*/
|
||||||
public class EntityCollection extends AbstractODataObject {
|
public class EntityCollection extends AbstractEntityCollection {
|
||||||
|
|
||||||
private final List<Entity> entities = new ArrayList<Entity>();
|
private final List<Entity> entities = new ArrayList<Entity>();
|
||||||
private Integer count;
|
private Integer count;
|
||||||
|
@ -46,6 +47,7 @@ public class EntityCollection extends AbstractODataObject {
|
||||||
*
|
*
|
||||||
* @return number of entries into the entity set.
|
* @return number of entries into the entity set.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Integer getCount() {
|
public Integer getCount() {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -73,6 +75,7 @@ public class EntityCollection extends AbstractODataObject {
|
||||||
*
|
*
|
||||||
* @return next link if exists; null otherwise.
|
* @return next link if exists; null otherwise.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public URI getNext() {
|
public URI getNext() {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
@ -82,6 +85,7 @@ public class EntityCollection extends AbstractODataObject {
|
||||||
*
|
*
|
||||||
* @return delta link if exists; null otherwise.
|
* @return delta link if exists; null otherwise.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public URI getDeltaLink() {
|
public URI getDeltaLink() {
|
||||||
return deltaLink;
|
return deltaLink;
|
||||||
}
|
}
|
||||||
|
@ -95,6 +99,11 @@ public class EntityCollection extends AbstractODataObject {
|
||||||
this.deltaLink = deltaLink;
|
this.deltaLink = deltaLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Entity> iterator() {
|
||||||
|
return this.entities.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object o) {
|
public boolean equals(final Object o) {
|
||||||
if (!super.equals(o)) {
|
if (!super.equals(o)) {
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.olingo.commons.api.data;
|
||||||
|
|
||||||
|
import org.apache.olingo.commons.api.ex.ODataNotSupportedException;
|
||||||
|
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
|
||||||
|
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data representation for a collection of single entities.
|
||||||
|
*/
|
||||||
|
public abstract class EntityIterator extends AbstractEntityCollection implements Iterator<Entity> {
|
||||||
|
|
||||||
|
public abstract boolean hasNext();
|
||||||
|
public abstract Entity next();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
//"Remove is not supported for iteration over Entities."
|
||||||
|
throw new ODataNotSupportedException("Entity Iterator does not support remove()");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Entity> iterator() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCount() {
|
||||||
|
throw new ODataNotSupportedException("Entity Iterator does not support getCount()");
|
||||||
|
}
|
||||||
|
|
||||||
|
public URI getNext() {
|
||||||
|
throw new ODataNotSupportedException("Entity Iterator does not support getNext()");
|
||||||
|
}
|
||||||
|
|
||||||
|
public URI getDeltaLink() {
|
||||||
|
throw new ODataNotSupportedException("Entity Iterator does not support getDeltaLink()");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.olingo.commons.api.ex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core runtime exception for OData.
|
||||||
|
*/
|
||||||
|
public class ODataNotSupportedException extends ODataRuntimeException {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 42L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create with <code>message</code>.
|
||||||
|
*
|
||||||
|
* @param msg message text for exception
|
||||||
|
*/
|
||||||
|
public ODataNotSupportedException(final String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create with <code>message</code> for and <code>cause</code> of exception.
|
||||||
|
*
|
||||||
|
* @param msg message text for exception
|
||||||
|
* @param cause cause of exception
|
||||||
|
*/
|
||||||
|
public ODataNotSupportedException(final String msg, final Exception cause) {
|
||||||
|
super(msg, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create with <code>cause</code> of exception.
|
||||||
|
*
|
||||||
|
* @param cause cause of exception
|
||||||
|
*/
|
||||||
|
public ODataNotSupportedException(final Exception cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.olingo.server.api;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.channels.WritableByteChannel;
|
||||||
|
|
||||||
|
public interface ODataContent {
|
||||||
|
void write(WritableByteChannel channel);
|
||||||
|
|
||||||
|
void write(OutputStream stream);
|
||||||
|
}
|
|
@ -18,12 +18,12 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.olingo.server.api;
|
package org.apache.olingo.server.api;
|
||||||
|
|
||||||
|
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.olingo.commons.api.http.HttpStatusCode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response object to carry OData-relevant HTTP information (status code, response headers, and content).
|
* Response object to carry OData-relevant HTTP information (status code, response headers, and content).
|
||||||
*/
|
*/
|
||||||
|
@ -131,4 +131,13 @@ public class ODataResponse {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ODataContent odataContent;
|
||||||
|
|
||||||
|
public void setODataContent(ODataContent result) {
|
||||||
|
odataContent = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ODataContent getODataContent() {
|
||||||
|
return odataContent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.olingo.server.api;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.channels.WritableByteChannel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The WriteContentErrorCallback is called when during the {@link ODataContent#write(OutputStream)}
|
||||||
|
* or the {@link ODataContent#write(WritableByteChannel)} an error occurs.
|
||||||
|
*/
|
||||||
|
public interface WriteContentErrorCallback {
|
||||||
|
void handleError(WriteContentErrorContext context, WritableByteChannel channel);
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.olingo.server.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The WriteContentErrorErrorContext is the parameter for the WriteContentErrorCallback.
|
||||||
|
*/
|
||||||
|
public interface WriteContentErrorContext {
|
||||||
|
Exception getException();
|
||||||
|
ODataLibraryException getODataLibraryException();
|
||||||
|
}
|
|
@ -19,6 +19,7 @@
|
||||||
package org.apache.olingo.server.api.serializer;
|
package org.apache.olingo.server.api.serializer;
|
||||||
|
|
||||||
import org.apache.olingo.commons.api.data.ContextURL;
|
import org.apache.olingo.commons.api.data.ContextURL;
|
||||||
|
import org.apache.olingo.server.api.WriteContentErrorCallback;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.CountOption;
|
import org.apache.olingo.server.api.uri.queryoption.CountOption;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
|
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
|
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
|
||||||
|
@ -32,6 +33,7 @@ public class EntityCollectionSerializerOptions {
|
||||||
private SelectOption select;
|
private SelectOption select;
|
||||||
private boolean writeOnlyReferences;
|
private boolean writeOnlyReferences;
|
||||||
private String id;
|
private String id;
|
||||||
|
private WriteContentErrorCallback writeContentErrorCallback;
|
||||||
private String xml10InvalidCharReplacement;
|
private String xml10InvalidCharReplacement;
|
||||||
|
|
||||||
/** Gets the {@link ContextURL}. */
|
/** Gets the {@link ContextURL}. */
|
||||||
|
@ -64,6 +66,17 @@ public class EntityCollectionSerializerOptions {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the callback which is used in case of an exception during
|
||||||
|
* write of the content (in case the content will be written/streamed
|
||||||
|
* in the future)
|
||||||
|
* @return callback which is used in case of an exception during
|
||||||
|
* write of the content
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public WriteContentErrorCallback getWriteContentErrorCallback() {
|
||||||
|
return writeContentErrorCallback;
|
||||||
|
}
|
||||||
/** Gets the replacement string for unicode characters, that is not allowed in XML 1.0 */
|
/** Gets the replacement string for unicode characters, that is not allowed in XML 1.0 */
|
||||||
public String xml10InvalidCharReplacement() {
|
public String xml10InvalidCharReplacement() {
|
||||||
return xml10InvalidCharReplacement;
|
return xml10InvalidCharReplacement;
|
||||||
|
@ -119,6 +132,18 @@ public class EntityCollectionSerializerOptions {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the callback which is used in case of an exception during
|
||||||
|
* write of the content.
|
||||||
|
*
|
||||||
|
* @param writeContentErrorCallback the callback
|
||||||
|
* @return the builder
|
||||||
|
*/
|
||||||
|
public Builder writeContentErrorCallback(WriteContentErrorCallback writeContentErrorCallback) {
|
||||||
|
options.writeContentErrorCallback = writeContentErrorCallback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/** set the replacement String for xml 1.0 unicode controlled characters that are not allowed */
|
/** set the replacement String for xml 1.0 unicode controlled characters that are not allowed */
|
||||||
public Builder xml10InvalidCharReplacement(final String replacement) {
|
public Builder xml10InvalidCharReplacement(final String replacement) {
|
||||||
options.xml10InvalidCharReplacement = replacement;
|
options.xml10InvalidCharReplacement = replacement;
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
package org.apache.olingo.server.api.serializer;
|
package org.apache.olingo.server.api.serializer;
|
||||||
|
|
||||||
import org.apache.olingo.commons.api.data.Entity;
|
import org.apache.olingo.commons.api.data.Entity;
|
||||||
import org.apache.olingo.commons.api.data.EntityCollection;
|
import org.apache.olingo.commons.api.data.AbstractEntityCollection;
|
||||||
|
import org.apache.olingo.commons.api.data.EntityIterator;
|
||||||
import org.apache.olingo.commons.api.data.Property;
|
import org.apache.olingo.commons.api.data.Property;
|
||||||
import org.apache.olingo.commons.api.edm.EdmComplexType;
|
import org.apache.olingo.commons.api.edm.EdmComplexType;
|
||||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
||||||
|
@ -61,7 +62,17 @@ public interface ODataSerializer {
|
||||||
* @param options options for the serializer
|
* @param options options for the serializer
|
||||||
*/
|
*/
|
||||||
SerializerResult entityCollection(ServiceMetadata metadata, EdmEntityType entityType,
|
SerializerResult entityCollection(ServiceMetadata metadata, EdmEntityType entityType,
|
||||||
EntityCollection entitySet, EntityCollectionSerializerOptions options) throws SerializerException;
|
AbstractEntityCollection entitySet, EntityCollectionSerializerOptions options) throws SerializerException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes entity-collection data into an InputStream.
|
||||||
|
* @param metadata metadata for the service
|
||||||
|
* @param entityType the {@link EdmEntityType}
|
||||||
|
* @param entities the data of the entity set
|
||||||
|
* @param options options for the serializer
|
||||||
|
*/
|
||||||
|
SerializerStreamResult entityCollectionStreamed(ServiceMetadata metadata, EdmEntityType entityType,
|
||||||
|
EntityIterator entities, EntityCollectionSerializerOptions options) throws SerializerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes entity data into an InputStream.
|
* Writes entity data into an InputStream.
|
||||||
|
@ -128,8 +139,9 @@ public interface ODataSerializer {
|
||||||
* @param metadata metadata for the service
|
* @param metadata metadata for the service
|
||||||
* @param edmEntitySet {@link EdmEntitySet}
|
* @param edmEntitySet {@link EdmEntitySet}
|
||||||
* @param entityCollection data of the entity collection
|
* @param entityCollection data of the entity collection
|
||||||
* @param ReferenceCollectionSerializerOptions {@link ReferenceCollectionSerializerOptions}
|
* @param options {@link ReferenceCollectionSerializerOptions}
|
||||||
*/
|
*/
|
||||||
SerializerResult referenceCollection(ServiceMetadata metadata, EdmEntitySet edmEntitySet,
|
SerializerResult referenceCollection(ServiceMetadata metadata, EdmEntitySet edmEntitySet,
|
||||||
EntityCollection entityCollection, ReferenceCollectionSerializerOptions options) throws SerializerException;
|
AbstractEntityCollection entityCollection, ReferenceCollectionSerializerOptions options)
|
||||||
|
throws SerializerException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.olingo.server.api.serializer;
|
||||||
|
|
||||||
|
import org.apache.olingo.server.api.ODataContent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result type for {@link ODataSerializer} methods
|
||||||
|
* which supports stream/write in the future
|
||||||
|
*/
|
||||||
|
public interface SerializerStreamResult {
|
||||||
|
/**
|
||||||
|
* Returns the content as ODataContent
|
||||||
|
* @return content
|
||||||
|
*/
|
||||||
|
ODataContent getODataContent();
|
||||||
|
}
|
|
@ -19,6 +19,7 @@
|
||||||
package org.apache.olingo.server.core;
|
package org.apache.olingo.server.core;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.Channel;
|
import java.nio.channels.Channel;
|
||||||
import java.nio.channels.Channels;
|
import java.nio.channels.Channels;
|
||||||
|
@ -38,6 +39,7 @@ import org.apache.olingo.commons.api.ex.ODataRuntimeException;
|
||||||
import org.apache.olingo.commons.api.http.HttpHeader;
|
import org.apache.olingo.commons.api.http.HttpHeader;
|
||||||
import org.apache.olingo.commons.api.http.HttpMethod;
|
import org.apache.olingo.commons.api.http.HttpMethod;
|
||||||
import org.apache.olingo.server.api.OData;
|
import org.apache.olingo.server.api.OData;
|
||||||
|
import org.apache.olingo.server.api.ODataContent;
|
||||||
import org.apache.olingo.server.api.ODataHttpHandler;
|
import org.apache.olingo.server.api.ODataHttpHandler;
|
||||||
import org.apache.olingo.server.api.ODataLibraryException;
|
import org.apache.olingo.server.api.ODataLibraryException;
|
||||||
import org.apache.olingo.server.api.ODataRequest;
|
import org.apache.olingo.server.api.ODataRequest;
|
||||||
|
@ -149,22 +151,35 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (odResponse.getContent() != null) {
|
if (odResponse.getContent() != null ) {
|
||||||
copyContent(odResponse, response);
|
copyContent(odResponse.getContent(), response);
|
||||||
|
} else if(odResponse.getODataContent() != null) {
|
||||||
|
writeContent(odResponse, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyContent(final ODataResponse odataResponse, final HttpServletResponse servletResponse) {
|
static void writeContent(final ODataResponse odataResponse, final HttpServletResponse servletResponse) {
|
||||||
ReadableByteChannel input = null;
|
try {
|
||||||
|
ODataContent res = odataResponse.getODataContent();
|
||||||
|
res.write(Channels.newChannel(servletResponse.getOutputStream()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ODataRuntimeException("Error on reading request content", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copyContent(final InputStream inputStream, final HttpServletResponse servletResponse) {
|
||||||
|
copyContent(Channels.newChannel(inputStream), servletResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copyContent(final ReadableByteChannel input, final HttpServletResponse servletResponse) {
|
||||||
WritableByteChannel output = null;
|
WritableByteChannel output = null;
|
||||||
try {
|
try {
|
||||||
ByteBuffer inBuffer = ByteBuffer.allocate(COPY_BUFFER_SIZE);
|
ByteBuffer inBuffer = ByteBuffer.allocate(COPY_BUFFER_SIZE);
|
||||||
output = Channels.newChannel(servletResponse.getOutputStream());
|
output = Channels.newChannel(servletResponse.getOutputStream());
|
||||||
input = Channels.newChannel(odataResponse.getContent());
|
|
||||||
while (input.read(inBuffer) > 0) {
|
while (input.read(inBuffer) > 0) {
|
||||||
inBuffer.flip();
|
inBuffer.flip();
|
||||||
output.write(inBuffer);
|
output.write(inBuffer);
|
||||||
inBuffer.rewind();
|
inBuffer.clear();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ODataRuntimeException("Error on reading request content", e);
|
throw new ODataRuntimeException("Error on reading request content", e);
|
||||||
|
|
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.olingo.server.core;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.channels.Channels;
|
||||||
|
import java.nio.channels.WritableByteChannel;
|
||||||
|
|
||||||
|
import org.apache.olingo.commons.api.data.EntityIterator;
|
||||||
|
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
||||||
|
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
|
||||||
|
import org.apache.olingo.server.api.ODataContent;
|
||||||
|
import org.apache.olingo.server.api.ODataLibraryException;
|
||||||
|
import org.apache.olingo.server.api.ServiceMetadata;
|
||||||
|
import org.apache.olingo.server.api.WriteContentErrorCallback;
|
||||||
|
import org.apache.olingo.server.api.WriteContentErrorContext;
|
||||||
|
import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
|
||||||
|
import org.apache.olingo.server.api.serializer.ODataSerializer;
|
||||||
|
import org.apache.olingo.server.api.serializer.SerializerException;
|
||||||
|
import org.apache.olingo.server.api.serializer.SerializerStreamResult;
|
||||||
|
import org.apache.olingo.server.core.serializer.SerializerStreamResultImpl;
|
||||||
|
import org.apache.olingo.server.core.serializer.json.ODataJsonSerializer;
|
||||||
|
import org.apache.olingo.server.core.serializer.xml.ODataXmlSerializer;
|
||||||
|
|
||||||
|
public class ODataWritableContent implements ODataContent {
|
||||||
|
private StreamContent streamContent;
|
||||||
|
|
||||||
|
private static abstract class StreamContent {
|
||||||
|
protected ODataSerializer serializer;
|
||||||
|
protected EntityIterator iterator;
|
||||||
|
protected ServiceMetadata metadata;
|
||||||
|
protected EdmEntityType entityType;
|
||||||
|
protected EntityCollectionSerializerOptions options;
|
||||||
|
|
||||||
|
public StreamContent(EntityIterator iterator, EdmEntityType entityType,
|
||||||
|
ODataSerializer serializer, ServiceMetadata metadata,
|
||||||
|
EntityCollectionSerializerOptions options) {
|
||||||
|
this.iterator = iterator;
|
||||||
|
this.entityType = entityType;
|
||||||
|
this.serializer = serializer;
|
||||||
|
this.metadata = metadata;
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void writeEntity(EntityIterator entity, OutputStream outputStream) throws SerializerException;
|
||||||
|
|
||||||
|
public void write(OutputStream out) {
|
||||||
|
try {
|
||||||
|
writeEntity(iterator, out);
|
||||||
|
} catch (SerializerException e) {
|
||||||
|
final WriteContentErrorCallback errorCallback = options.getWriteContentErrorCallback();
|
||||||
|
if(errorCallback != null) {
|
||||||
|
final ErrorContext errorContext = new ErrorContext(e);
|
||||||
|
errorCallback.handleError(errorContext, Channels.newChannel(out));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StreamContentForJson extends StreamContent {
|
||||||
|
private ODataJsonSerializer jsonSerializer;
|
||||||
|
|
||||||
|
public StreamContentForJson(EntityIterator iterator, EdmEntityType entityType,
|
||||||
|
ODataJsonSerializer jsonSerializer, ServiceMetadata metadata,
|
||||||
|
EntityCollectionSerializerOptions options) {
|
||||||
|
super(iterator, entityType, jsonSerializer, metadata, options);
|
||||||
|
|
||||||
|
this.jsonSerializer = jsonSerializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeEntity(EntityIterator entity, OutputStream outputStream) throws SerializerException {
|
||||||
|
try {
|
||||||
|
jsonSerializer.entityCollectionIntoStream(metadata, entityType, entity, options, outputStream);
|
||||||
|
outputStream.flush();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
throw new ODataRuntimeException("Failed entity serialization");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StreamContentForXml extends StreamContent {
|
||||||
|
private ODataXmlSerializer xmlSerializer;
|
||||||
|
|
||||||
|
public StreamContentForXml(EntityIterator iterator, EdmEntityType entityType,
|
||||||
|
ODataXmlSerializer xmlSerializer, ServiceMetadata metadata,
|
||||||
|
EntityCollectionSerializerOptions options) {
|
||||||
|
super(iterator, entityType, xmlSerializer, metadata, options);
|
||||||
|
|
||||||
|
this.xmlSerializer = xmlSerializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeEntity(EntityIterator entity, OutputStream outputStream) throws SerializerException {
|
||||||
|
try {
|
||||||
|
xmlSerializer.entityCollectionIntoStream(metadata, entityType, entity, options, outputStream);
|
||||||
|
outputStream.flush();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
throw new ODataRuntimeException("Failed entity serialization");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(WritableByteChannel writeChannel) {
|
||||||
|
this.streamContent.write(Channels.newOutputStream(writeChannel));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(OutputStream stream) {
|
||||||
|
write(Channels.newChannel(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ODataWritableContent(StreamContent streamContent) {
|
||||||
|
this.streamContent = streamContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ODataWritableContentBuilder with(EntityIterator iterator, EdmEntityType entityType,
|
||||||
|
ODataSerializer serializer, ServiceMetadata metadata,
|
||||||
|
EntityCollectionSerializerOptions options) {
|
||||||
|
return new ODataWritableContentBuilder(iterator, entityType, serializer, metadata, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ErrorContext implements WriteContentErrorContext {
|
||||||
|
private ODataLibraryException exception;
|
||||||
|
public ErrorContext(ODataLibraryException exception) {
|
||||||
|
this.exception = exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Exception getException() {
|
||||||
|
return exception;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public ODataLibraryException getODataLibraryException() {
|
||||||
|
return exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ODataWritableContentBuilder {
|
||||||
|
private ODataSerializer serializer;
|
||||||
|
private EntityIterator entities;
|
||||||
|
private ServiceMetadata metadata;
|
||||||
|
private EdmEntityType entityType;
|
||||||
|
private EntityCollectionSerializerOptions options;
|
||||||
|
|
||||||
|
public ODataWritableContentBuilder(EntityIterator entities, EdmEntityType entityType,
|
||||||
|
ODataSerializer serializer,
|
||||||
|
ServiceMetadata metadata, EntityCollectionSerializerOptions options) {
|
||||||
|
this.entities = entities;
|
||||||
|
this.entityType = entityType;
|
||||||
|
this.serializer = serializer;
|
||||||
|
this.metadata = metadata;
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ODataContent buildContent() {
|
||||||
|
if(serializer instanceof ODataJsonSerializer) {
|
||||||
|
StreamContent input = new StreamContentForJson(entities, entityType,
|
||||||
|
(ODataJsonSerializer) serializer, metadata, options);
|
||||||
|
return new ODataWritableContent(input);
|
||||||
|
} else if(serializer instanceof ODataXmlSerializer) {
|
||||||
|
StreamContentForXml input = new StreamContentForXml(entities, entityType,
|
||||||
|
(ODataXmlSerializer) serializer, metadata, options);
|
||||||
|
return new ODataWritableContent(input);
|
||||||
|
}
|
||||||
|
throw new ODataRuntimeException("No suitable serializer found");
|
||||||
|
}
|
||||||
|
public SerializerStreamResult build() {
|
||||||
|
return SerializerStreamResultImpl.with().content(buildContent()).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ package org.apache.olingo.server.core.serializer;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.apache.olingo.server.api.ODataContent;
|
||||||
import org.apache.olingo.server.api.serializer.SerializerResult;
|
import org.apache.olingo.server.api.serializer.SerializerResult;
|
||||||
|
|
||||||
public class SerializerResultImpl implements SerializerResult {
|
public class SerializerResultImpl implements SerializerResult {
|
||||||
|
@ -30,23 +31,34 @@ public class SerializerResultImpl implements SerializerResult {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public ReadableByteChannel getChannel() {
|
||||||
|
// return Channels.newChannel(getContent());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void write(WritableByteChannel channel) {
|
||||||
|
// ResultHelper.copy(Channels.newChannel(content), channel);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public boolean isWriteSupported() {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
public static SerializerResultBuilder with() {
|
public static SerializerResultBuilder with() {
|
||||||
return new SerializerResultBuilder();
|
return new SerializerResultBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SerializerResultBuilder {
|
public static class SerializerResultBuilder {
|
||||||
private InputStream content;
|
private SerializerResultImpl result = new SerializerResultImpl();
|
||||||
|
|
||||||
public SerializerResultBuilder content(final InputStream input) {
|
public SerializerResultBuilder content(final InputStream input) {
|
||||||
content = input;
|
result.content = input;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SerializerResult build() {
|
public SerializerResult build() {
|
||||||
SerializerResultImpl result = new SerializerResultImpl();
|
|
||||||
result.content = content;
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.olingo.server.core.serializer;
|
||||||
|
|
||||||
|
import org.apache.olingo.server.api.ODataContent;
|
||||||
|
import org.apache.olingo.server.api.serializer.SerializerStreamResult;
|
||||||
|
|
||||||
|
public class SerializerStreamResultImpl implements SerializerStreamResult {
|
||||||
|
private ODataContent oDataContent;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ODataContent getODataContent() {
|
||||||
|
return oDataContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SerializerResultBuilder with() {
|
||||||
|
return new SerializerResultBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SerializerResultBuilder {
|
||||||
|
private SerializerStreamResultImpl result = new SerializerStreamResultImpl();
|
||||||
|
|
||||||
|
public SerializerResultBuilder content(final ODataContent content) {
|
||||||
|
result.oDataContent = content;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SerializerStreamResult build() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,8 @@ import org.apache.olingo.commons.api.Constants;
|
||||||
import org.apache.olingo.commons.api.data.ComplexValue;
|
import org.apache.olingo.commons.api.data.ComplexValue;
|
||||||
import org.apache.olingo.commons.api.data.ContextURL;
|
import org.apache.olingo.commons.api.data.ContextURL;
|
||||||
import org.apache.olingo.commons.api.data.Entity;
|
import org.apache.olingo.commons.api.data.Entity;
|
||||||
import org.apache.olingo.commons.api.data.EntityCollection;
|
import org.apache.olingo.commons.api.data.AbstractEntityCollection;
|
||||||
|
import org.apache.olingo.commons.api.data.EntityIterator;
|
||||||
import org.apache.olingo.commons.api.data.Link;
|
import org.apache.olingo.commons.api.data.Link;
|
||||||
import org.apache.olingo.commons.api.data.Linked;
|
import org.apache.olingo.commons.api.data.Linked;
|
||||||
import org.apache.olingo.commons.api.data.Property;
|
import org.apache.olingo.commons.api.data.Property;
|
||||||
|
@ -57,11 +58,13 @@ import org.apache.olingo.server.api.serializer.ReferenceCollectionSerializerOpti
|
||||||
import org.apache.olingo.server.api.serializer.ReferenceSerializerOptions;
|
import org.apache.olingo.server.api.serializer.ReferenceSerializerOptions;
|
||||||
import org.apache.olingo.server.api.serializer.SerializerException;
|
import org.apache.olingo.server.api.serializer.SerializerException;
|
||||||
import org.apache.olingo.server.api.serializer.SerializerResult;
|
import org.apache.olingo.server.api.serializer.SerializerResult;
|
||||||
|
import org.apache.olingo.server.api.serializer.SerializerStreamResult;
|
||||||
import org.apache.olingo.server.api.uri.UriHelper;
|
import org.apache.olingo.server.api.uri.UriHelper;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
|
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
|
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
|
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
|
||||||
import org.apache.olingo.server.core.serializer.AbstractODataSerializer;
|
import org.apache.olingo.server.core.serializer.AbstractODataSerializer;
|
||||||
|
import org.apache.olingo.server.core.ODataWritableContent;
|
||||||
import org.apache.olingo.server.core.serializer.SerializerResultImpl;
|
import org.apache.olingo.server.core.serializer.SerializerResultImpl;
|
||||||
import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
|
import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
|
||||||
import org.apache.olingo.server.core.serializer.utils.ContentTypeHelper;
|
import org.apache.olingo.server.core.serializer.utils.ContentTypeHelper;
|
||||||
|
@ -136,7 +139,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SerializerResult entityCollection(final ServiceMetadata metadata,
|
public SerializerResult entityCollection(final ServiceMetadata metadata,
|
||||||
final EdmEntityType entityType, final EntityCollection entitySet,
|
final EdmEntityType entityType, final AbstractEntityCollection entitySet,
|
||||||
final EntityCollectionSerializerOptions options) throws SerializerException {
|
final EntityCollectionSerializerOptions options) throws SerializerException {
|
||||||
OutputStream outputStream = null;
|
OutputStream outputStream = null;
|
||||||
SerializerException cachedException = null;
|
SerializerException cachedException = null;
|
||||||
|
@ -175,6 +178,50 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SerializerStreamResult entityCollectionStreamed(ServiceMetadata metadata, EdmEntityType entityType,
|
||||||
|
EntityIterator entities, EntityCollectionSerializerOptions options) throws SerializerException {
|
||||||
|
|
||||||
|
return ODataWritableContent.with(entities, entityType, this, metadata, options).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void entityCollectionIntoStream(final ServiceMetadata metadata,
|
||||||
|
final EdmEntityType entityType, final EntityIterator entitySet,
|
||||||
|
final EntityCollectionSerializerOptions options, final OutputStream outputStream)
|
||||||
|
throws SerializerException {
|
||||||
|
|
||||||
|
SerializerException cachedException;
|
||||||
|
try {
|
||||||
|
JsonGenerator json = new JsonFactory().createGenerator(outputStream);
|
||||||
|
json.writeStartObject();
|
||||||
|
|
||||||
|
final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
|
||||||
|
writeContextURL(contextURL, json);
|
||||||
|
|
||||||
|
writeMetadataETag(metadata, json);
|
||||||
|
|
||||||
|
if (options != null && options.getCount() != null && options.getCount().getValue()) {
|
||||||
|
writeCount(entitySet, json);
|
||||||
|
}
|
||||||
|
json.writeFieldName(Constants.VALUE);
|
||||||
|
if (options == null) {
|
||||||
|
writeEntitySet(metadata, entityType, entitySet, null, null, false, json);
|
||||||
|
} else {
|
||||||
|
writeEntitySet(metadata, entityType, entitySet,
|
||||||
|
options.getExpand(), options.getSelect(), options.getWriteOnlyReferences(), json);
|
||||||
|
}
|
||||||
|
// next link not supported by default for streaming results
|
||||||
|
// writeNextLink(entitySet, json);
|
||||||
|
|
||||||
|
json.close();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
cachedException =
|
||||||
|
new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION);
|
||||||
|
throw cachedException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SerializerResult entity(final ServiceMetadata metadata, final EdmEntityType entityType,
|
public SerializerResult entity(final ServiceMetadata metadata, final EdmEntityType entityType,
|
||||||
final Entity entity, final EntitySerializerOptions options) throws SerializerException {
|
final Entity entity, final EntitySerializerOptions options) throws SerializerException {
|
||||||
|
@ -203,7 +250,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContextURL checkContextURL(final ContextURL contextURL) throws SerializerException {
|
ContextURL checkContextURL(final ContextURL contextURL) throws SerializerException {
|
||||||
if (isODataMetadataNone) {
|
if (isODataMetadataNone) {
|
||||||
return null;
|
return null;
|
||||||
} else if (contextURL == null) {
|
} else if (contextURL == null) {
|
||||||
|
@ -213,11 +260,11 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType,
|
protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType,
|
||||||
final EntityCollection entitySet, final ExpandOption expand, final SelectOption select,
|
final AbstractEntityCollection entitySet, final ExpandOption expand, final SelectOption select,
|
||||||
final boolean onlyReference, final JsonGenerator json) throws IOException,
|
final boolean onlyReference, final JsonGenerator json) throws IOException,
|
||||||
SerializerException {
|
SerializerException {
|
||||||
json.writeStartArray();
|
json.writeStartArray();
|
||||||
for (final Entity entity : entitySet.getEntities()) {
|
for (final Entity entity : entitySet) {
|
||||||
if (onlyReference) {
|
if (onlyReference) {
|
||||||
json.writeStartObject();
|
json.writeStartObject();
|
||||||
json.writeStringField(Constants.JSON_ID, entity.getId().toASCIIString());
|
json.writeStringField(Constants.JSON_ID, entity.getId().toASCIIString());
|
||||||
|
@ -229,9 +276,9 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
json.writeEndArray();
|
json.writeEndArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType,
|
public void writeEntity(final ServiceMetadata metadata, final EdmEntityType entityType, final Entity entity,
|
||||||
final Entity entity, final ContextURL contextURL, final ExpandOption expand,
|
final ContextURL contextURL, final ExpandOption expand, final SelectOption select, final boolean onlyReference,
|
||||||
final SelectOption select, final boolean onlyReference, final JsonGenerator json)
|
final JsonGenerator json)
|
||||||
throws IOException, SerializerException {
|
throws IOException, SerializerException {
|
||||||
json.writeStartObject();
|
json.writeStartObject();
|
||||||
if (!isODataMetadataNone) {
|
if (!isODataMetadataNone) {
|
||||||
|
@ -736,7 +783,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SerializerResult referenceCollection(final ServiceMetadata metadata, final EdmEntitySet edmEntitySet,
|
public SerializerResult referenceCollection(final ServiceMetadata metadata, final EdmEntitySet edmEntitySet,
|
||||||
final EntityCollection entityCollection, final ReferenceCollectionSerializerOptions options)
|
final AbstractEntityCollection entityCollection, final ReferenceCollectionSerializerOptions options)
|
||||||
throws SerializerException {
|
throws SerializerException {
|
||||||
OutputStream outputStream = null;
|
OutputStream outputStream = null;
|
||||||
SerializerException cachedException = null;
|
SerializerException cachedException = null;
|
||||||
|
@ -755,7 +802,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
json.writeArrayFieldStart(Constants.VALUE);
|
json.writeArrayFieldStart(Constants.VALUE);
|
||||||
for (final Entity entity : entityCollection.getEntities()) {
|
for (final Entity entity : entityCollection) {
|
||||||
json.writeStartObject();
|
json.writeStartObject();
|
||||||
json.writeStringField(Constants.JSON_ID, uriHelper.buildCanonicalURL(edmEntitySet, entity));
|
json.writeStringField(Constants.JSON_ID, uriHelper.buildCanonicalURL(edmEntitySet, entity));
|
||||||
json.writeEndObject();
|
json.writeEndObject();
|
||||||
|
@ -779,13 +826,13 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeContextURL(final ContextURL contextURL, final JsonGenerator json) throws IOException {
|
void writeContextURL(final ContextURL contextURL, final JsonGenerator json) throws IOException {
|
||||||
if (!isODataMetadataNone && contextURL != null) {
|
if (!isODataMetadataNone && contextURL != null) {
|
||||||
json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString());
|
json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeMetadataETag(final ServiceMetadata metadata, final JsonGenerator json) throws IOException {
|
void writeMetadataETag(final ServiceMetadata metadata, final JsonGenerator json) throws IOException {
|
||||||
if (!isODataMetadataNone
|
if (!isODataMetadataNone
|
||||||
&& metadata != null
|
&& metadata != null
|
||||||
&& metadata.getServiceMetadataETagSupport() != null
|
&& metadata.getServiceMetadataETagSupport() != null
|
||||||
|
@ -795,7 +842,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeCount(final EntityCollection entityCollection, final JsonGenerator json) throws IOException {
|
void writeCount(final AbstractEntityCollection entityCollection, final JsonGenerator json) throws IOException {
|
||||||
if (entityCollection.getCount() != null) {
|
if (entityCollection.getCount() != null) {
|
||||||
if (isIEEE754Compatible) {
|
if (isIEEE754Compatible) {
|
||||||
json.writeStringField(Constants.JSON_COUNT, entityCollection.getCount().toString());
|
json.writeStringField(Constants.JSON_COUNT, entityCollection.getCount().toString());
|
||||||
|
@ -805,7 +852,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeNextLink(final EntityCollection entitySet, final JsonGenerator json) throws IOException {
|
void writeNextLink(final AbstractEntityCollection entitySet, final JsonGenerator json) throws IOException {
|
||||||
if (entitySet.getNext() != null) {
|
if (entitySet.getNext() != null) {
|
||||||
json.writeStringField(Constants.JSON_NEXT_LINK, entitySet.getNext().toASCIIString());
|
json.writeStringField(Constants.JSON_NEXT_LINK, entitySet.getNext().toASCIIString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,6 +193,25 @@ public class CircleStreamBuffer {
|
||||||
return readBuffer.get();
|
return readBuffer.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ByteBuffer getBuffer() throws IOException {
|
||||||
|
if (readClosed) {
|
||||||
|
throw new IOException("Tried to read from closed stream.");
|
||||||
|
}
|
||||||
|
writeMode = false;
|
||||||
|
|
||||||
|
// FIXME: mibo_160108: This is not efficient and only for test/poc reasons
|
||||||
|
int reqSize = 0;
|
||||||
|
for (ByteBuffer byteBuffer : bufferQueue) {
|
||||||
|
reqSize += byteBuffer.position();
|
||||||
|
}
|
||||||
|
ByteBuffer tmp = ByteBuffer.allocateDirect(reqSize);
|
||||||
|
for (ByteBuffer byteBuffer : bufferQueue) {
|
||||||
|
byteBuffer.flip();
|
||||||
|
tmp.put(byteBuffer);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
// #############################################
|
// #############################################
|
||||||
// #
|
// #
|
||||||
// # Writing parts
|
// # Writing parts
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.olingo.server.core.serializer.utils;
|
||||||
|
|
||||||
|
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.Channel;
|
||||||
|
import java.nio.channels.Channels;
|
||||||
|
import java.nio.channels.ReadableByteChannel;
|
||||||
|
import java.nio.channels.WritableByteChannel;
|
||||||
|
|
||||||
|
public class ResultHelper {
|
||||||
|
|
||||||
|
public static final int COPY_BUFFER_SIZE = 8192;
|
||||||
|
|
||||||
|
public static void copy(InputStream input, OutputStream output) {
|
||||||
|
copy(Channels.newChannel(input), Channels.newChannel(output));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void copy(ReadableByteChannel input, WritableByteChannel output) {
|
||||||
|
try {
|
||||||
|
ByteBuffer inBuffer = ByteBuffer.allocate(COPY_BUFFER_SIZE);
|
||||||
|
while (input.read(inBuffer) > 0) {
|
||||||
|
inBuffer.flip();
|
||||||
|
output.write(inBuffer);
|
||||||
|
inBuffer.clear();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ODataRuntimeException("Error on reading request content", e);
|
||||||
|
} finally {
|
||||||
|
closeStream(input);
|
||||||
|
closeStream(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void closeStream(final Channel closeable) {
|
||||||
|
if (closeable != null) {
|
||||||
|
try {
|
||||||
|
closeable.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,6 +35,8 @@ import org.apache.olingo.commons.api.data.ComplexValue;
|
||||||
import org.apache.olingo.commons.api.data.ContextURL;
|
import org.apache.olingo.commons.api.data.ContextURL;
|
||||||
import org.apache.olingo.commons.api.data.Entity;
|
import org.apache.olingo.commons.api.data.Entity;
|
||||||
import org.apache.olingo.commons.api.data.EntityCollection;
|
import org.apache.olingo.commons.api.data.EntityCollection;
|
||||||
|
import org.apache.olingo.commons.api.data.AbstractEntityCollection;
|
||||||
|
import org.apache.olingo.commons.api.data.EntityIterator;
|
||||||
import org.apache.olingo.commons.api.data.Link;
|
import org.apache.olingo.commons.api.data.Link;
|
||||||
import org.apache.olingo.commons.api.data.Linked;
|
import org.apache.olingo.commons.api.data.Linked;
|
||||||
import org.apache.olingo.commons.api.data.Property;
|
import org.apache.olingo.commons.api.data.Property;
|
||||||
|
@ -51,6 +53,7 @@ import org.apache.olingo.commons.api.edm.EdmType;
|
||||||
import org.apache.olingo.commons.api.edm.FullQualifiedName;
|
import org.apache.olingo.commons.api.edm.FullQualifiedName;
|
||||||
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
|
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
|
||||||
import org.apache.olingo.commons.api.ex.ODataErrorDetail;
|
import org.apache.olingo.commons.api.ex.ODataErrorDetail;
|
||||||
|
import org.apache.olingo.commons.api.ex.ODataRuntimeException;
|
||||||
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
|
import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
|
||||||
import org.apache.olingo.commons.core.edm.primitivetype.EdmString;
|
import org.apache.olingo.commons.core.edm.primitivetype.EdmString;
|
||||||
import org.apache.olingo.server.api.ODataServerError;
|
import org.apache.olingo.server.api.ODataServerError;
|
||||||
|
@ -63,9 +66,11 @@ import org.apache.olingo.server.api.serializer.ReferenceCollectionSerializerOpti
|
||||||
import org.apache.olingo.server.api.serializer.ReferenceSerializerOptions;
|
import org.apache.olingo.server.api.serializer.ReferenceSerializerOptions;
|
||||||
import org.apache.olingo.server.api.serializer.SerializerException;
|
import org.apache.olingo.server.api.serializer.SerializerException;
|
||||||
import org.apache.olingo.server.api.serializer.SerializerResult;
|
import org.apache.olingo.server.api.serializer.SerializerResult;
|
||||||
|
import org.apache.olingo.server.api.serializer.SerializerStreamResult;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
|
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
|
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
|
||||||
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
|
import org.apache.olingo.server.api.uri.queryoption.SelectOption;
|
||||||
|
import org.apache.olingo.server.core.ODataWritableContent;
|
||||||
import org.apache.olingo.server.core.serializer.AbstractODataSerializer;
|
import org.apache.olingo.server.core.serializer.AbstractODataSerializer;
|
||||||
import org.apache.olingo.server.core.serializer.SerializerResultImpl;
|
import org.apache.olingo.server.core.serializer.SerializerResultImpl;
|
||||||
import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
|
import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
|
||||||
|
@ -210,7 +215,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SerializerResult entityCollection(final ServiceMetadata metadata,
|
public SerializerResult entityCollection(final ServiceMetadata metadata,
|
||||||
final EdmEntityType entityType, final EntityCollection entitySet,
|
final EdmEntityType entityType, final AbstractEntityCollection entitySet,
|
||||||
final EntityCollectionSerializerOptions options) throws SerializerException {
|
final EntityCollectionSerializerOptions options) throws SerializerException {
|
||||||
|
|
||||||
final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
|
final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
|
||||||
|
@ -278,6 +283,69 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void entityCollectionIntoStream(ServiceMetadata metadata, EdmEntityType entityType, EntityIterator entitySet,
|
||||||
|
EntityCollectionSerializerOptions options, OutputStream outputStream) throws SerializerException {
|
||||||
|
|
||||||
|
final ContextURL contextURL = checkContextURL(options == null ? null : options.getContextURL());
|
||||||
|
// if (options != null && options.getWriteOnlyReferences()) {
|
||||||
|
// ReferenceCollectionSerializerOptions rso = ReferenceCollectionSerializerOptions.with()
|
||||||
|
// .contextURL(contextURL).build();
|
||||||
|
// return entityReferenceCollection(entitySet, rso);
|
||||||
|
// }
|
||||||
|
|
||||||
|
SerializerException cachedException = null;
|
||||||
|
try {
|
||||||
|
CircleStreamBuffer buffer = new CircleStreamBuffer();
|
||||||
|
outputStream = buffer.getOutputStream();
|
||||||
|
XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(outputStream, DEFAULT_CHARSET);
|
||||||
|
writer.writeStartDocument(DEFAULT_CHARSET, "1.0");
|
||||||
|
writer.writeStartElement(ATOM, Constants.ATOM_ELEM_FEED, NS_ATOM);
|
||||||
|
writer.writeNamespace(ATOM, NS_ATOM);
|
||||||
|
writer.writeNamespace(METADATA, NS_METADATA);
|
||||||
|
writer.writeNamespace(DATA, NS_DATA);
|
||||||
|
|
||||||
|
writer.writeAttribute(METADATA, NS_METADATA, Constants.CONTEXT,
|
||||||
|
ContextURLBuilder.create(contextURL).toASCIIString());
|
||||||
|
writeMetadataETag(metadata, writer);
|
||||||
|
|
||||||
|
if (options != null && options.getId() != null) {
|
||||||
|
writer.writeStartElement(ATOM, Constants.ATOM_ELEM_ID, NS_ATOM);
|
||||||
|
writer.writeCharacters(options.getId());
|
||||||
|
writer.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options != null && options.getCount() != null && options.getCount().getValue()
|
||||||
|
&& entitySet.getCount() != null) {
|
||||||
|
writeCount(entitySet, writer);
|
||||||
|
}
|
||||||
|
if (entitySet.getNext() != null) {
|
||||||
|
writeNextLink(entitySet, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options == null) {
|
||||||
|
writeEntitySet(metadata, entityType, entitySet, null, null, null, writer);
|
||||||
|
} else {
|
||||||
|
writeEntitySet(metadata, entityType, entitySet,
|
||||||
|
options.getExpand(), options.getSelect(), options.xml10InvalidCharReplacement(), writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeEndElement();
|
||||||
|
writer.writeEndDocument();
|
||||||
|
|
||||||
|
writer.flush();
|
||||||
|
} catch (final XMLStreamException e) {
|
||||||
|
cachedException =
|
||||||
|
new SerializerException(IO_EXCEPTION_TEXT, e, SerializerException.MessageKeys.IO_EXCEPTION);
|
||||||
|
throw cachedException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SerializerStreamResult entityCollectionStreamed(ServiceMetadata metadata, EdmEntityType entityType,
|
||||||
|
EntityIterator entities, EntityCollectionSerializerOptions options) throws SerializerException {
|
||||||
|
return ODataWritableContent.with(entities, entityType, this, metadata, options).build();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SerializerResult entity(final ServiceMetadata metadata, final EdmEntityType entityType,
|
public SerializerResult entity(final ServiceMetadata metadata, final EdmEntityType entityType,
|
||||||
final Entity entity, final EntitySerializerOptions options) throws SerializerException {
|
final Entity entity, final EntitySerializerOptions options) throws SerializerException {
|
||||||
|
@ -338,10 +406,10 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType,
|
protected void writeEntitySet(final ServiceMetadata metadata, final EdmEntityType entityType,
|
||||||
final EntityCollection entitySet, final ExpandOption expand, final SelectOption select,
|
final AbstractEntityCollection entitySet, final ExpandOption expand, final SelectOption select,
|
||||||
final String xml10InvalidCharReplacement,final XMLStreamWriter writer)
|
final String xml10InvalidCharReplacement,final XMLStreamWriter writer)
|
||||||
throws XMLStreamException, SerializerException {
|
throws XMLStreamException, SerializerException {
|
||||||
for (final Entity entity : entitySet.getEntities()) {
|
for (final Entity entity : entitySet) {
|
||||||
writeEntity(metadata, entityType, entity, null, expand, select, xml10InvalidCharReplacement, writer, false);
|
writeEntity(metadata, entityType, entity, null, expand, select, xml10InvalidCharReplacement, writer, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1063,12 +1131,12 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SerializerResult referenceCollection(final ServiceMetadata metadata, final EdmEntitySet edmEntitySet,
|
public SerializerResult referenceCollection(final ServiceMetadata metadata, final EdmEntitySet edmEntitySet,
|
||||||
final EntityCollection entityCollection, final ReferenceCollectionSerializerOptions options)
|
final AbstractEntityCollection entityCollection, final ReferenceCollectionSerializerOptions options)
|
||||||
throws SerializerException {
|
throws SerializerException {
|
||||||
return entityReferenceCollection(entityCollection, options);
|
return entityReferenceCollection(entityCollection, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SerializerResult entityReferenceCollection(final EntityCollection entitySet,
|
protected SerializerResult entityReferenceCollection(final AbstractEntityCollection entitySet,
|
||||||
final ReferenceCollectionSerializerOptions options) throws SerializerException {
|
final ReferenceCollectionSerializerOptions options) throws SerializerException {
|
||||||
OutputStream outputStream = null;
|
OutputStream outputStream = null;
|
||||||
SerializerException cachedException = null;
|
SerializerException cachedException = null;
|
||||||
|
@ -1091,7 +1159,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
if (entitySet.getNext() != null) {
|
if (entitySet.getNext() != null) {
|
||||||
writeNextLink(entitySet, writer);
|
writeNextLink(entitySet, writer);
|
||||||
}
|
}
|
||||||
for (final Entity entity : entitySet.getEntities()) {
|
for (final Entity entity : entitySet) {
|
||||||
writeReference(entity, options == null ? null : options.getContextURL(), writer, false);
|
writeReference(entity, options == null ? null : options.getContextURL(), writer, false);
|
||||||
}
|
}
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
|
@ -1114,14 +1182,14 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeCount(final EntityCollection entitySet, final XMLStreamWriter writer)
|
private void writeCount(final AbstractEntityCollection entitySet, final XMLStreamWriter writer)
|
||||||
throws XMLStreamException {
|
throws XMLStreamException {
|
||||||
writer.writeStartElement(METADATA, Constants.ATOM_ELEM_COUNT, NS_METADATA);
|
writer.writeStartElement(METADATA, Constants.ATOM_ELEM_COUNT, NS_METADATA);
|
||||||
writer.writeCharacters(String.valueOf(entitySet.getCount()));
|
writer.writeCharacters(String.valueOf(entitySet.getCount()));
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeNextLink(final EntityCollection entitySet, final XMLStreamWriter writer)
|
private void writeNextLink(final AbstractEntityCollection entitySet, final XMLStreamWriter writer)
|
||||||
throws XMLStreamException {
|
throws XMLStreamException {
|
||||||
writer.writeStartElement(ATOM, Constants.ATOM_ELEM_LINK, NS_ATOM);
|
writer.writeStartElement(ATOM, Constants.ATOM_ELEM_LINK, NS_ATOM);
|
||||||
writer.writeAttribute(Constants.ATTR_REL, Constants.NEXT_LINK_REL);
|
writer.writeAttribute(Constants.ATTR_REL, Constants.NEXT_LINK_REL);
|
||||||
|
|
|
@ -18,6 +18,13 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.olingo.server.core.uri.parser.search;
|
package org.apache.olingo.server.core.uri.parser.search;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.apache.olingo.server.core.uri.parser.search.SearchQueryToken.Token.AND;
|
import static org.apache.olingo.server.core.uri.parser.search.SearchQueryToken.Token.AND;
|
||||||
import static org.apache.olingo.server.core.uri.parser.search.SearchQueryToken.Token.CLOSE;
|
import static org.apache.olingo.server.core.uri.parser.search.SearchQueryToken.Token.CLOSE;
|
||||||
import static org.apache.olingo.server.core.uri.parser.search.SearchQueryToken.Token.NOT;
|
import static org.apache.olingo.server.core.uri.parser.search.SearchQueryToken.Token.NOT;
|
||||||
|
@ -26,13 +33,6 @@ import static org.apache.olingo.server.core.uri.parser.search.SearchQueryToken.T
|
||||||
import static org.apache.olingo.server.core.uri.parser.search.SearchQueryToken.Token.PHRASE;
|
import static org.apache.olingo.server.core.uri.parser.search.SearchQueryToken.Token.PHRASE;
|
||||||
import static org.apache.olingo.server.core.uri.parser.search.SearchQueryToken.Token.WORD;
|
import static org.apache.olingo.server.core.uri.parser.search.SearchQueryToken.Token.WORD;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class SearchTokenizerTest {
|
public class SearchTokenizerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.olingo.server.tecsvc.processor;
|
package org.apache.olingo.server.tecsvc.processor;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.apache.olingo.commons.api.data.ContextURL;
|
import org.apache.olingo.commons.api.data.ContextURL;
|
||||||
|
@ -25,6 +27,9 @@ import org.apache.olingo.commons.api.data.ContextURL.Builder;
|
||||||
import org.apache.olingo.commons.api.data.ContextURL.Suffix;
|
import org.apache.olingo.commons.api.data.ContextURL.Suffix;
|
||||||
import org.apache.olingo.commons.api.data.Entity;
|
import org.apache.olingo.commons.api.data.Entity;
|
||||||
import org.apache.olingo.commons.api.data.EntityCollection;
|
import org.apache.olingo.commons.api.data.EntityCollection;
|
||||||
|
import org.apache.olingo.commons.api.data.EntityIterator;
|
||||||
|
import org.apache.olingo.commons.api.data.Property;
|
||||||
|
import org.apache.olingo.commons.api.data.ValueType;
|
||||||
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
import org.apache.olingo.commons.api.edm.EdmEntitySet;
|
||||||
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
import org.apache.olingo.commons.api.edm.EdmEntityType;
|
||||||
import org.apache.olingo.commons.api.format.ContentType;
|
import org.apache.olingo.commons.api.format.ContentType;
|
||||||
|
@ -51,6 +56,7 @@ import org.apache.olingo.server.api.serializer.EntitySerializerOptions;
|
||||||
import org.apache.olingo.server.api.serializer.ReferenceCollectionSerializerOptions;
|
import org.apache.olingo.server.api.serializer.ReferenceCollectionSerializerOptions;
|
||||||
import org.apache.olingo.server.api.serializer.ReferenceSerializerOptions;
|
import org.apache.olingo.server.api.serializer.ReferenceSerializerOptions;
|
||||||
import org.apache.olingo.server.api.serializer.SerializerResult;
|
import org.apache.olingo.server.api.serializer.SerializerResult;
|
||||||
|
import org.apache.olingo.server.api.serializer.SerializerStreamResult;
|
||||||
import org.apache.olingo.server.api.uri.UriInfo;
|
import org.apache.olingo.server.api.uri.UriInfo;
|
||||||
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
|
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
|
||||||
import org.apache.olingo.server.api.uri.UriResourceNavigation;
|
import org.apache.olingo.server.api.uri.UriResourceNavigation;
|
||||||
|
@ -519,12 +525,26 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
|
||||||
id = request.getRawBaseUri() + edmEntitySet.getName();
|
id = request.getRawBaseUri() + edmEntitySet.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize
|
if(isReference) {
|
||||||
final SerializerResult serializerResult = (isReference) ?
|
final SerializerResult serializerResult =
|
||||||
serializeReferenceCollection(entitySetSerialization, edmEntitySet, requestedContentType, countOption) :
|
serializeReferenceCollection(entitySetSerialization, edmEntitySet, requestedContentType, countOption);
|
||||||
serializeEntityCollection(request, entitySetSerialization, edmEntitySet, edmEntityType, requestedContentType,
|
response.setContent(serializerResult.getContent());
|
||||||
expand, select, countOption, id);
|
} else if(isOdataStreaming(request)) {
|
||||||
response.setContent(serializerResult.getContent());
|
final SerializerStreamResult serializerResult =
|
||||||
|
serializeEntityCollectionStreamed(request,
|
||||||
|
entitySetSerialization, edmEntitySet, edmEntityType, requestedContentType,
|
||||||
|
expand, select, countOption, id);
|
||||||
|
|
||||||
|
response.setODataContent(serializerResult.getODataContent());
|
||||||
|
} else {
|
||||||
|
final SerializerResult serializerResult =
|
||||||
|
serializeEntityCollection(request,
|
||||||
|
entitySetSerialization, edmEntitySet, edmEntityType, requestedContentType,
|
||||||
|
expand, select, countOption, id);
|
||||||
|
response.setContent(serializerResult.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
|
response.setStatusCode(HttpStatusCode.OK.getStatusCode());
|
||||||
response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
|
response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
|
||||||
if (pageSize != null) {
|
if (pageSize != null) {
|
||||||
|
@ -533,6 +553,11 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isOdataStreaming(ODataRequest request) {
|
||||||
|
String odataStreaming = request.getHeader("odata.streaming");
|
||||||
|
return Boolean.parseBoolean(odataStreaming);
|
||||||
|
}
|
||||||
|
|
||||||
private SerializerResult serializeEntityCollection(final ODataRequest request, final EntityCollection
|
private SerializerResult serializeEntityCollection(final ODataRequest request, final EntityCollection
|
||||||
entityCollection, final EdmEntitySet edmEntitySet, final EdmEntityType edmEntityType,
|
entityCollection, final EdmEntitySet edmEntitySet, final EdmEntityType edmEntityType,
|
||||||
final ContentType requestedFormat, final ExpandOption expand, final SelectOption select,
|
final ContentType requestedFormat, final ExpandOption expand, final SelectOption select,
|
||||||
|
@ -551,6 +576,56 @@ public class TechnicalEntityProcessor extends TechnicalProcessor
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// serialise as streamed collection
|
||||||
|
private SerializerStreamResult serializeEntityCollectionStreamed(final ODataRequest request,
|
||||||
|
final EntityCollection entityCollection, final EdmEntitySet edmEntitySet,
|
||||||
|
final EdmEntityType edmEntityType,
|
||||||
|
final ContentType requestedFormat, final ExpandOption expand, final SelectOption select,
|
||||||
|
final CountOption countOption, final String id) throws ODataLibraryException {
|
||||||
|
|
||||||
|
EntityIterator streamCollection = new EntityIterator() {
|
||||||
|
Iterator<Entity> entityIterator = entityCollection.iterator();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return entityIterator.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entity next() {
|
||||||
|
return addToPrimitiveProperty(entityIterator.next(), "PropertyString", "->streamed");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Entity addToPrimitiveProperty(Entity entity, String name, Object data) {
|
||||||
|
List<Property> properties = entity.getProperties();
|
||||||
|
int pos = 0;
|
||||||
|
for (Property property : properties) {
|
||||||
|
if(name.equals(property.getName())) {
|
||||||
|
properties.remove(pos);
|
||||||
|
final String old = property.getValue().toString();
|
||||||
|
String newValue = (old == null ? "": old) + data.toString();
|
||||||
|
entity.addProperty(new Property(null, name, ValueType.PRIMITIVE, newValue));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return odata.createSerializer(requestedFormat).entityCollectionStreamed(
|
||||||
|
serviceMetadata,
|
||||||
|
edmEntityType,
|
||||||
|
streamCollection,
|
||||||
|
EntityCollectionSerializerOptions.with()
|
||||||
|
.contextURL(isODataMetadataNone(requestedFormat) ? null :
|
||||||
|
getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, false, expand, select))
|
||||||
|
.count(countOption)
|
||||||
|
.expand(expand).select(select)
|
||||||
|
.id(id)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
private SerializerResult serializeReferenceCollection(final EntityCollection entityCollection,
|
private SerializerResult serializeReferenceCollection(final EntityCollection entityCollection,
|
||||||
final EdmEntitySet edmEntitySet, final ContentType requestedFormat, final CountOption countOption)
|
final EdmEntitySet edmEntitySet, final ContentType requestedFormat, final CountOption countOption)
|
||||||
throws ODataLibraryException {
|
throws ODataLibraryException {
|
||||||
|
|
|
@ -18,18 +18,25 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.olingo.server.core.serializer.json;
|
package org.apache.olingo.server.core.serializer.json;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.WritableByteChannel;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.commons.io.output.ByteArrayOutputStream;
|
||||||
import org.apache.olingo.commons.api.data.ComplexValue;
|
import org.apache.olingo.commons.api.data.ComplexValue;
|
||||||
import org.apache.olingo.commons.api.data.ContextURL;
|
import org.apache.olingo.commons.api.data.ContextURL;
|
||||||
import org.apache.olingo.commons.api.data.ContextURL.Suffix;
|
import org.apache.olingo.commons.api.data.ContextURL.Suffix;
|
||||||
import org.apache.olingo.commons.api.data.Entity;
|
import org.apache.olingo.commons.api.data.Entity;
|
||||||
import org.apache.olingo.commons.api.data.EntityCollection;
|
import org.apache.olingo.commons.api.data.EntityCollection;
|
||||||
|
import org.apache.olingo.commons.api.data.EntityIterator;
|
||||||
import org.apache.olingo.commons.api.data.Property;
|
import org.apache.olingo.commons.api.data.Property;
|
||||||
import org.apache.olingo.commons.api.data.ValueType;
|
import org.apache.olingo.commons.api.data.ValueType;
|
||||||
import org.apache.olingo.commons.api.edm.EdmComplexType;
|
import org.apache.olingo.commons.api.edm.EdmComplexType;
|
||||||
|
@ -40,7 +47,10 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
|
||||||
import org.apache.olingo.commons.api.edm.EdmProperty;
|
import org.apache.olingo.commons.api.edm.EdmProperty;
|
||||||
import org.apache.olingo.commons.api.format.ContentType;
|
import org.apache.olingo.commons.api.format.ContentType;
|
||||||
import org.apache.olingo.server.api.OData;
|
import org.apache.olingo.server.api.OData;
|
||||||
|
import org.apache.olingo.server.api.ODataContent;
|
||||||
import org.apache.olingo.server.api.ServiceMetadata;
|
import org.apache.olingo.server.api.ServiceMetadata;
|
||||||
|
import org.apache.olingo.server.api.WriteContentErrorCallback;
|
||||||
|
import org.apache.olingo.server.api.WriteContentErrorContext;
|
||||||
import org.apache.olingo.server.api.edmx.EdmxReference;
|
import org.apache.olingo.server.api.edmx.EdmxReference;
|
||||||
import org.apache.olingo.server.api.serializer.ComplexSerializerOptions;
|
import org.apache.olingo.server.api.serializer.ComplexSerializerOptions;
|
||||||
import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
|
import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
|
||||||
|
@ -207,6 +217,90 @@ public class ODataJsonSerializerTest {
|
||||||
Assert.assertEquals(8, count);
|
Assert.assertEquals(8, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void entityCollectionStreamed() throws Exception {
|
||||||
|
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
|
||||||
|
final EntityIterator entityIterator = new EntityIterator() {
|
||||||
|
Iterator<Entity> innerIterator = data.readAll(edmEntitySet).iterator();
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return innerIterator.hasNext();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Entity next() {
|
||||||
|
return innerIterator.next();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
CountOption countOption = Mockito.mock(CountOption.class);
|
||||||
|
Mockito.when(countOption.getValue()).thenReturn(true);
|
||||||
|
|
||||||
|
ODataContent result = serializer.entityCollectionStreamed(
|
||||||
|
metadata, edmEntitySet.getEntityType(), entityIterator,
|
||||||
|
EntityCollectionSerializerOptions.with()
|
||||||
|
.contextURL(ContextURL.with().entitySet(edmEntitySet).build())
|
||||||
|
.build()).getODataContent();
|
||||||
|
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||||
|
result.write(bout);
|
||||||
|
final String resultString = new String(bout.toByteArray(), "UTF-8");
|
||||||
|
|
||||||
|
Assert.assertThat(resultString, CoreMatchers.startsWith("{"
|
||||||
|
+ "\"@odata.context\":\"$metadata#ESAllPrim\","
|
||||||
|
+ "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\","
|
||||||
|
+ "\"value\":[{\"PropertyInt16\":32767,\"PropertyString\""));
|
||||||
|
Assert.assertThat(resultString, CoreMatchers.endsWith(
|
||||||
|
"\"PropertyTimeOfDay\":\"00:01:01\"}]}"));
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
int index = -1;
|
||||||
|
while ((index = resultString.indexOf("PropertyInt16\":", ++index)) > 0) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
Assert.assertEquals(3, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void entityCollectionStreamedWithError() throws Exception {
|
||||||
|
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
|
||||||
|
final EntityIterator entityIterator = new EntityIterator() {
|
||||||
|
Iterator<Entity> innerIterator = data.readAll(edmEntitySet).iterator();
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return innerIterator.hasNext();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Entity next() {
|
||||||
|
return new Entity();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
CountOption countOption = Mockito.mock(CountOption.class);
|
||||||
|
Mockito.when(countOption.getValue()).thenReturn(true);
|
||||||
|
|
||||||
|
WriteContentErrorCallback errorCallback = new WriteContentErrorCallback() {
|
||||||
|
@Override
|
||||||
|
public void handleError(WriteContentErrorContext context, WritableByteChannel channel) {
|
||||||
|
try {
|
||||||
|
String msgKey = context.getODataLibraryException().getMessageKey().getKey();
|
||||||
|
String toChannel = "ERROR: " + msgKey;
|
||||||
|
channel.write(ByteBuffer.wrap(toChannel.getBytes("UTF-8")));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Error in error.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ODataContent result = serializer.entityCollectionStreamed(
|
||||||
|
metadata, edmEntitySet.getEntityType(), entityIterator,
|
||||||
|
EntityCollectionSerializerOptions.with()
|
||||||
|
.writeContentErrorCallback(errorCallback)
|
||||||
|
.contextURL(ContextURL.with().entitySet(edmEntitySet).build())
|
||||||
|
.build()).getODataContent();
|
||||||
|
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||||
|
result.write(bout);
|
||||||
|
final String resultString = new String(bout.toByteArray(), "UTF-8");
|
||||||
|
Assert.assertEquals(resultString, "ERROR: MISSING_PROPERTY");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void entityCollAllPrim() throws Exception {
|
public void entityCollAllPrim() throws Exception {
|
||||||
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim");
|
final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim");
|
||||||
|
|
Loading…
Reference in New Issue