Repository: cxf Updated Branches: refs/heads/master 1e89d332a -> 440538282
CXF-7180: Implement JAX-RS 2.1 NIO Proposal (Server/Reader) Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/44053828 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/44053828 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/44053828 Branch: refs/heads/master Commit: 440538282e39c9da528101968cade1e7dcb32e0e Parents: 1e89d33 Author: reta <[email protected]> Authored: Sun Dec 18 20:20:06 2016 -0500 Committer: reta <[email protected]> Committed: Sun Dec 18 20:20:06 2016 -0500 ---------------------------------------------------------------------- .../org/apache/cxf/jaxrs/impl/RequestImpl.java | 29 ++- .../cxf/jaxrs/nio/DelegatingNioInputStream.java | 85 +++++++ .../org/apache/cxf/jaxrs/nio/NioReadEntity.java | 47 ++++ .../cxf/jaxrs/nio/NioReadListenerImpl.java | 60 +++++ .../cxf/systest/jaxrs/nio/NioBookStore.java | 47 ++++ .../cxf/systest/jaxrs/nio/NioBookStoreTest.java | 15 ++ .../jaxrs/src/test/resources/files/books.txt | 245 +++++++++++++++++++ 7 files changed, 520 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/44053828/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestImpl.java ---------------------------------------------------------------------- diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestImpl.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestImpl.java index e57f3e0..9f25400 100644 --- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestImpl.java +++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/RequestImpl.java @@ -19,6 +19,7 @@ package org.apache.cxf.jaxrs.impl; +import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Collections; @@ -28,6 +29,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.HttpMethod; import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.HttpHeaders; @@ -41,10 +43,13 @@ import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Variant; import org.apache.cxf.common.util.StringUtils; +import org.apache.cxf.jaxrs.nio.NioReadEntity; +import org.apache.cxf.jaxrs.nio.NioReadListenerImpl; import org.apache.cxf.jaxrs.utils.HttpUtils; import org.apache.cxf.jaxrs.utils.JAXRSUtils; import org.apache.cxf.message.Message; import org.apache.cxf.phase.PhaseInterceptorChain; +import org.apache.cxf.transport.http.AbstractHTTPDestination; /** * TODO : deal with InvalidStateExceptions @@ -387,22 +392,30 @@ public class RequestImpl implements Request { } @Override - public void entity(NioReaderHandler arg0) { - // TODO: Implementation required (JAX-RS 2.1) + public void entity(NioReaderHandler reader) { + entity(reader, in -> { }, throwable -> { }); } @Override - public void entity(NioReaderHandler arg0, NioCompletionHandler arg1) { - // TODO: Implementation required (JAX-RS 2.1) + public void entity(NioReaderHandler reader, NioCompletionHandler completion) { + entity(reader, completion, throwable -> { }); } @Override - public void entity(NioReaderHandler arg0, NioErrorHandler arg1) { - // TODO: Implementation required (JAX-RS 2.1) + public void entity(NioReaderHandler reader, NioErrorHandler error) { + entity(reader, in -> { }, error); } @Override - public void entity(NioReaderHandler arg0, NioCompletionHandler arg1, NioErrorHandler arg2) { - // TODO: Implementation required (JAX-RS 2.1) + public void entity(NioReaderHandler reader, NioCompletionHandler completion, NioErrorHandler error) { + try { + final HttpServletRequest request = (HttpServletRequest)m.get(AbstractHTTPDestination.HTTP_REQUEST); + if (request != null) { + final NioReadEntity entity = new NioReadEntity(reader, completion, error); + request.getInputStream().setReadListener(new NioReadListenerImpl(entity, request.getInputStream())); + } + } catch (final IOException ex) { + throw new RuntimeException("Unable to initialize NIO entity", ex); + } } } http://git-wip-us.apache.org/repos/asf/cxf/blob/44053828/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/nio/DelegatingNioInputStream.java ---------------------------------------------------------------------- diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/nio/DelegatingNioInputStream.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/nio/DelegatingNioInputStream.java new file mode 100644 index 0000000..f7b64ec --- /dev/null +++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/nio/DelegatingNioInputStream.java @@ -0,0 +1,85 @@ +/** + * 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.cxf.jaxrs.nio; + +import java.io.IOException; + +import javax.servlet.ServletInputStream; +import javax.ws.rs.core.NioInputStream; + +public class DelegatingNioInputStream extends NioInputStream { + private final ServletInputStream in; + + public DelegatingNioInputStream(final ServletInputStream in) { + this.in = in; + } + + @Override + public boolean isFinished() { + return in.isFinished(); + } + + @Override + public int read() throws IOException { + return in.read(); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return in.read(b, off, len); + } + + @Override + public int read(byte[] b) throws IOException { + return in.read(b); + } + + @Override + public synchronized void reset() throws IOException { + in.reset(); + } + + @Override + public void close() throws IOException { + in.close(); + } + + @Override + public long skip(long n) throws IOException { + return in.skip(n); + } + @Override + public int available() throws IOException { + return in.available(); + } + + @Override + public synchronized void mark(int readlimit) { + in.mark(readlimit); + } + + @Override + public boolean markSupported() { + return in.markSupported(); + } + + public boolean isReady() { + return in.isReady(); + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/44053828/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/nio/NioReadEntity.java ---------------------------------------------------------------------- diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/nio/NioReadEntity.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/nio/NioReadEntity.java new file mode 100644 index 0000000..00857f0 --- /dev/null +++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/nio/NioReadEntity.java @@ -0,0 +1,47 @@ +/** + * 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.cxf.jaxrs.nio; + +import javax.ws.rs.core.NioCompletionHandler; +import javax.ws.rs.core.NioErrorHandler; +import javax.ws.rs.core.NioReaderHandler; + +public class NioReadEntity { + private final NioReaderHandler reader; + private final NioCompletionHandler completion; + private final NioErrorHandler error; + + public NioReadEntity(NioReaderHandler reader, NioCompletionHandler completion, NioErrorHandler error) { + this.reader = reader; + this.completion = completion; + this.error = error; + } + + public NioReaderHandler getReader() { + return reader; + } + + public NioCompletionHandler getCompletion() { + return completion; + } + + public NioErrorHandler getError() { + return error; + } +} http://git-wip-us.apache.org/repos/asf/cxf/blob/44053828/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/nio/NioReadListenerImpl.java ---------------------------------------------------------------------- diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/nio/NioReadListenerImpl.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/nio/NioReadListenerImpl.java new file mode 100644 index 0000000..47a4d8d --- /dev/null +++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/nio/NioReadListenerImpl.java @@ -0,0 +1,60 @@ +/** + * 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.cxf.jaxrs.nio; + +import java.io.IOException; +import java.util.logging.Logger; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; + +import org.apache.cxf.common.logging.LogUtils; +import org.apache.cxf.jaxrs.utils.ExceptionUtils; + +public final class NioReadListenerImpl implements ReadListener { + private static final Logger LOG = LogUtils.getL7dLogger(NioReadListenerImpl.class); + private final NioReadEntity entity; + private final DelegatingNioInputStream in; + + public NioReadListenerImpl(NioReadEntity entity, ServletInputStream in) { + this.entity = entity; + this.in = new DelegatingNioInputStream(in); + } + + @Override + public void onError(Throwable t) { + try { + entity.getError().error(t); + } catch (final Throwable ex) { + LOG.warning("NIO NioReadListener error: " + ExceptionUtils.getStackTrace(ex)); + } + } + + @Override + public void onDataAvailable() throws IOException { + while (in.isReady() && !in.isFinished()) { + entity.getReader().read(in); + } + } + + @Override + public void onAllDataRead() throws IOException { + entity.getCompletion().complete(in); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cxf/blob/44053828/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/nio/NioBookStore.java ---------------------------------------------------------------------- diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/nio/NioBookStore.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/nio/NioBookStore.java index e4a0c05..d6c6748 100644 --- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/nio/NioBookStore.java +++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/nio/NioBookStore.java @@ -19,14 +19,22 @@ package org.apache.cxf.systest.jaxrs.nio; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.concurrent.atomic.LongAdder; +import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.container.AsyncResponse; +import javax.ws.rs.container.Suspended; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Request; import javax.ws.rs.core.Response; import org.apache.cxf.annotations.UseNio; @@ -75,4 +83,43 @@ public class NioBookStore { public InputStream readBooksFromInputStream() throws IOException { return getClass().getResourceAsStream("/files/books.txt"); } + + @POST + @Consumes(MediaType.APPLICATION_OCTET_STREAM) + @Produces(MediaType.TEXT_PLAIN) + public void uploadBooks(@Context Request request, @Suspended AsyncResponse response) { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final byte[] buffer = new byte[4096]; + final LongAdder adder = new LongAdder(); + + request.entity( + in -> { + try { + final int n = in.read(buffer); + if (n > 0) { + adder.add(n); + out.write(buffer, 0, n); + } + } catch (IOException e) { + throw new WebApplicationException(e); + } + }, + in -> { + try { + if (!in.isFinished()) { + throw new IllegalStateException("Reader did not finish yet"); + } + + out.close(); + response.resume("Book Store uploaded: " + adder.longValue() + " bytes"); + } catch (IOException e) { + throw new WebApplicationException(e); + } + }, + throwable -> { // error handler + System.out.println("Problem found: " + throwable.getMessage()); + throw throwable; + } + ); + } } http://git-wip-us.apache.org/repos/asf/cxf/blob/44053828/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/nio/NioBookStoreTest.java ---------------------------------------------------------------------- diff --git a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/nio/NioBookStoreTest.java b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/nio/NioBookStoreTest.java index c1743e3..efd9c4d 100644 --- a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/nio/NioBookStoreTest.java +++ b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/nio/NioBookStoreTest.java @@ -19,6 +19,7 @@ package org.apache.cxf.systest.jaxrs.nio; +import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -72,6 +73,20 @@ public class NioBookStoreTest extends AbstractBusClientServerTestBase { } } + @Test + public void testPostBookStore() throws IOException { + final Response response = createWebClient("/bookstore", MediaType.TEXT_PLAIN) + .type(MediaType.APPLICATION_OCTET_STREAM) + .post(IOUtils.readBytesFromStream(getClass().getResourceAsStream("/files/books.txt"))); + + try { + assertEquals(200, response.getStatus()); + assertThat(response.readEntity(String.class), equalTo("Book Store uploaded: 10355 bytes")); + } finally { + response.close(); + } + } + protected WebClient createWebClient(final String url, final String mediaType) { final List< ? > providers = Arrays.asList(new JacksonJsonProvider()); http://git-wip-us.apache.org/repos/asf/cxf/blob/44053828/systests/jaxrs/src/test/resources/files/books.txt ---------------------------------------------------------------------- diff --git a/systests/jaxrs/src/test/resources/files/books.txt b/systests/jaxrs/src/test/resources/files/books.txt index 6f23352..aedd064 100644 --- a/systests/jaxrs/src/test/resources/files/books.txt +++ b/systests/jaxrs/src/test/resources/files/books.txt @@ -2,3 +2,248 @@ Molecular Breeding and Nutritional Aspects of Buckwheat {Progress in Heterocyclic Chemistry, Volume 28} Pharmacology and Therapeutics for Dentistry Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +Molecular Breeding and Nutritional Aspects of Buckwheat +{Progress in Heterocyclic Chemistry, Volume 28} +Pharmacology and Therapeutics for Dentistry +Plotkin's Vaccines +
