You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2016/12/19 01:20:30 UTC

cxf git commit: CXF-7180: Implement JAX-RS 2.1 NIO Proposal (Server/Reader)

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 <dr...@gmail.com>
Authored: Sun Dec 18 20:20:06 2016 -0500
Committer: reta <dr...@gmail.com>
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
+