Source:
<code>public static FileObject buildFileObject(final URI uri, final RestS3Service s3Client) throws ServiceException { final S3Coords coords = new S3Coords(checkURI(uri)); final StorageObject s3Obj = s3Client.getObjectDetails(coords.bucket, coords.path); final String path = uri.getPath(); return new FileObject() { final Object inputStreamOpener = new Object(); volatile boolean streamAcquired = false; volatile StorageObject storageObject = s3Obj; @Override public URI toUri() { return uri; } @Override public String getName() { final String ext = Files.getFileExtension(path); return Files.getNameWithoutExtension(path) + (Strings.isNullOrEmpty(ext) ? "" : ("." + ext)); } @Override public InputStream openInputStream() throws IOException { try { synchronized (inputStreamOpener) { if (streamAcquired) { return storageObject.getDataInputStream(); } <START> streamAcquired = true; <END> storageObject = s3Client.getObject(s3Obj.getBucketName(), s3Obj.getKey()); return storageObject.getDataInputStream(); } } catch (ServiceException e) { throw new IOException(StringUtils.safeFormat("Could not load S3 URI [%s]", uri), e); } } @Override public OutputStream openOutputStream() throws IOException { throw new UOE("Cannot stream S3 output"); } @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException { throw new UOE("Cannot open reader"); } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { throw new UOE("Cannot open character sequence"); } @Override public Writer openWriter() throws IOException { throw new UOE("Cannot open writer"); } @Override public long getLastModified() { return s3Obj.getLastModifiedDate().getTime(); } @Override public boolean delete() { throw new UOE("Cannot delete S3 items anonymously. jetS3t doesn't support authenticated deletes easily."); } @Override public void finalize() throws Throwable { try { if (!streamAcquired) { storageObject.closeDataInputStream(); } } finally { super.finalize(); } } }; }</code><technical_language>behavior if getObject fails? Right this throw exception time, return null subsequent calls. put streamAcquired = true getObject succeeds</technical_language>

Target:
public static FileObject buildFileObject(final URI uri, final RestS3Service s3Client) throws ServiceException { final S3Coords coords = new S3Coords(checkURI(uri)); final StorageObject s3Obj = s3Client.getObjectDetails(coords.bucket, coords.path); final String path = uri.getPath(); return new FileObject() { final Object inputStreamOpener = new Object(); volatile boolean streamAcquired = false; volatile StorageObject storageObject = s3Obj; @Override public URI toUri() { return uri; } @Override public String getName() { final String ext = Files.getFileExtension(path); return Files.getNameWithoutExtension(path) + (Strings.isNullOrEmpty(ext) ? "" : ("." + ext)); } @Override public InputStream openInputStream() throws IOException { try { synchronized (inputStreamOpener) { if (streamAcquired) { return storageObject.getDataInputStream(); } storageObject = s3Client.getObject(s3Obj.getBucketName(), s3Obj.getKey()); final InputStream stream = storageObject.getDataInputStream(); streamAcquired = true; return stream; } } catch (ServiceException e) { throw new IOException(StringUtils.safeFormat("Could not load S3 URI [%s]", uri), e); } } @Override public OutputStream openOutputStream() throws IOException { throw new UOE("Cannot stream S3 output"); } @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException { throw new UOE("Cannot open reader"); } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { throw new UOE("Cannot open character sequence"); } @Override public Writer openWriter() throws IOException { throw new UOE("Cannot open writer"); } @Override public long getLastModified() { return s3Obj.getLastModifiedDate().getTime(); } @Override public boolean delete() { throw new UOE("Cannot delete S3 items anonymously. jetS3t doesn't support authenticated deletes easily."); } }; }