View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.client.util;
20  
21  import java.io.IOException;
22  import java.nio.ByteBuffer;
23  import java.nio.channels.SeekableByteChannel;
24  import java.nio.file.AccessDeniedException;
25  import java.nio.file.Files;
26  import java.nio.file.NoSuchFileException;
27  import java.nio.file.Path;
28  import java.nio.file.StandardOpenOption;
29  import java.util.Iterator;
30  import java.util.NoSuchElementException;
31  
32  import org.eclipse.jetty.client.api.ContentProvider;
33  
34  /**
35   * A {@link ContentProvider} for files using JDK 7's {@code java.nio.file} APIs.
36   * <p />
37   * It is possible to specify, at the constructor, a buffer size used to read content from the
38   * stream, by default 4096 bytes.
39   */
40  public class PathContentProvider implements ContentProvider
41  {
42      private final Path filePath;
43      private final long fileSize;
44      private final int bufferSize;
45  
46      public PathContentProvider(Path filePath) throws IOException
47      {
48          this(filePath, 4096);
49      }
50  
51      public PathContentProvider(Path filePath, int bufferSize) throws IOException
52      {
53          if (!Files.isRegularFile(filePath))
54              throw new NoSuchFileException(filePath.toString());
55          if (!Files.isReadable(filePath))
56              throw new AccessDeniedException(filePath.toString());
57          this.filePath = filePath;
58          this.fileSize = Files.size(filePath);
59          this.bufferSize = bufferSize;
60      }
61  
62      @Override
63      public long getLength()
64      {
65          return fileSize;
66      }
67  
68      @Override
69      public Iterator<ByteBuffer> iterator()
70      {
71          return new Iterator<ByteBuffer>()
72          {
73              private final ByteBuffer buffer = ByteBuffer.allocateDirect(bufferSize);
74              private SeekableByteChannel channel;
75              private long position;
76  
77              @Override
78              public boolean hasNext()
79              {
80                  return position < getLength();
81              }
82  
83              @Override
84              public ByteBuffer next()
85              {
86                  try
87                  {
88                      if (channel == null)
89                          channel = Files.newByteChannel(filePath, StandardOpenOption.READ);
90  
91                      buffer.clear();
92                      int read = channel.read(buffer);
93                      if (read < 0)
94                          throw new NoSuchElementException();
95  
96                      position += read;
97                      buffer.flip();
98                      return buffer;
99                  }
100                 catch (IOException x)
101                 {
102                     throw (NoSuchElementException)new NoSuchElementException().initCause(x);
103                 }
104             }
105 
106             @Override
107             public void remove()
108             {
109                 throw new UnsupportedOperationException();
110             }
111         };
112     }
113 }