-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#4 Implement FirebaseStorageServiceImpl
- Loading branch information
Showing
9 changed files
with
831 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
src/main/java/io/github/ilyalisov/storage/config/StorageFile.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package io.github.ilyalisov.storage.config; | ||
|
||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
||
import java.io.InputStream; | ||
import java.nio.file.Path; | ||
import java.util.Optional; | ||
|
||
/** | ||
* File class. | ||
*/ | ||
@Getter | ||
@Setter | ||
public class StorageFile { | ||
|
||
/** | ||
* Path to store file in. | ||
*/ | ||
private Path path; | ||
|
||
/** | ||
* Name of file. Must ends with extension. | ||
*/ | ||
private String fileName; | ||
|
||
/** | ||
* Content type of file. | ||
*/ | ||
private String contentType; | ||
|
||
/** | ||
* InputStream with file data. | ||
*/ | ||
private InputStream inputStream; | ||
|
||
/** | ||
* Creates an object. | ||
* | ||
* @param fileName name of file | ||
* @param contentType content type | ||
* @param inputStream input stream with file data | ||
*/ | ||
public StorageFile( | ||
final String fileName, | ||
final String contentType, | ||
final InputStream inputStream | ||
) { | ||
this( | ||
fileName, | ||
null, | ||
contentType, | ||
inputStream | ||
); | ||
} | ||
|
||
/** | ||
* Creates an object. | ||
* | ||
* @param path path to file | ||
* @param fileName name of file | ||
* @param contentType content type | ||
* @param inputStream input stream with file data | ||
*/ | ||
public StorageFile( | ||
final String fileName, | ||
final Path path, | ||
final String contentType, | ||
final InputStream inputStream | ||
) { | ||
if (!containsExtension(fileName)) { | ||
throw new IllegalArgumentException( | ||
"Filename must contain extension." | ||
); | ||
} | ||
this.path = path; | ||
this.fileName = fileName; | ||
updatePath(fileName); | ||
this.contentType = contentType; | ||
this.inputStream = inputStream; | ||
} | ||
|
||
/** | ||
* Checks if file name contains extension. | ||
* | ||
* @param fileName name of file | ||
* @return true - if contains, false - otherwise | ||
*/ | ||
private boolean containsExtension( | ||
final String fileName | ||
) { | ||
return Optional.of(fileName) | ||
.filter(f -> f.contains(".")) | ||
.map(f -> f.substring(fileName.lastIndexOf(".") + 1)) | ||
.isPresent(); | ||
} | ||
|
||
private void updatePath( | ||
final String fileName | ||
) { | ||
Path newPath; | ||
if (this.path == null) { | ||
newPath = Path.of("", fileName); | ||
} else { | ||
newPath = Path.of(path.toString(), fileName); | ||
} | ||
this.path = newPath.getParent(); | ||
this.fileName = newPath.getFileName().toString(); | ||
|
||
} | ||
|
||
} |
177 changes: 177 additions & 0 deletions
177
src/main/java/io/github/ilyalisov/storage/service/FirebaseStorageServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
package io.github.ilyalisov.storage.service; | ||
|
||
import com.google.api.gax.paging.Page; | ||
import com.google.auth.oauth2.GoogleCredentials; | ||
import com.google.cloud.storage.Blob; | ||
import com.google.cloud.storage.Bucket; | ||
import com.google.firebase.FirebaseApp; | ||
import com.google.firebase.FirebaseOptions; | ||
import com.google.firebase.cloud.StorageClient; | ||
import io.github.ilyalisov.storage.config.StorageFile; | ||
import lombok.SneakyThrows; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.InputStream; | ||
import java.nio.file.Path; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
/** | ||
* Implementation of StorageService based on Firebase. | ||
*/ | ||
public class FirebaseStorageServiceImpl implements StorageService { | ||
|
||
/** | ||
* Firebase Bucket. | ||
*/ | ||
private final Bucket bucket; | ||
|
||
/** | ||
* Returns bucket. | ||
* | ||
* @return bucket | ||
*/ | ||
public Bucket getBucket() { | ||
return bucket; | ||
} | ||
|
||
/** | ||
* Creates an object. | ||
* | ||
* @param credentials input stream with Firebase credentials from JSON file | ||
* @param bucket Firebase bucket name | ||
*/ | ||
@SneakyThrows | ||
public FirebaseStorageServiceImpl( | ||
final InputStream credentials, | ||
final String bucket | ||
) { | ||
FirebaseOptions options = FirebaseOptions.builder() | ||
.setCredentials( | ||
GoogleCredentials.fromStream( | ||
credentials | ||
) | ||
) | ||
.build(); | ||
FirebaseApp.initializeApp(options); | ||
this.bucket = StorageClient.getInstance() | ||
.bucket(bucket); | ||
} | ||
|
||
@Override | ||
public Optional<StorageFile> find( | ||
final String fileName | ||
) { | ||
Blob result = bucket.get(fileName); | ||
if (result == null) { | ||
return Optional.empty(); | ||
} | ||
StorageFile file = new StorageFile( | ||
fileName, | ||
result.getContentType(), | ||
new ByteArrayInputStream(result.getContent()) | ||
); | ||
return Optional.of(file); | ||
} | ||
|
||
@Override | ||
public Optional<StorageFile> find( | ||
final String fileName, | ||
final Path path | ||
) { | ||
Blob result = bucket.get(path.toString() + "/" + fileName); | ||
if (result == null) { | ||
return Optional.empty(); | ||
} | ||
StorageFile file = new StorageFile( | ||
fileName, | ||
path, | ||
result.getContentType(), | ||
new ByteArrayInputStream(result.getContent()) | ||
); | ||
return Optional.of(file); | ||
} | ||
|
||
@Override | ||
public List<StorageFile> findAll( | ||
final Path path | ||
) { | ||
Page<Blob> results = bucket.list(); | ||
List<StorageFile> files = new ArrayList<>(); | ||
results.streamAll().forEach( | ||
(result) -> { | ||
if (result.getName().startsWith(path + "/")) { | ||
StorageFile file = find(result.getName()) | ||
.get(); | ||
files.add(file); | ||
} | ||
} | ||
); | ||
return files; | ||
} | ||
|
||
@Override | ||
public boolean exists( | ||
final String fileName | ||
) { | ||
return bucket.get(fileName) != null; | ||
} | ||
|
||
@Override | ||
public boolean exists( | ||
final String fileName, | ||
final Path path | ||
) { | ||
return bucket.get(path.toString() + "/" + fileName) != null; | ||
} | ||
|
||
@Override | ||
@SneakyThrows | ||
public Path save( | ||
final StorageFile file | ||
) { | ||
String path = file.getPath() != null ? file.getPath() + "/" : ""; | ||
bucket.create( | ||
path + file.getFileName(), | ||
file.getInputStream().readAllBytes(), | ||
file.getContentType() | ||
); | ||
return Path.of(path, file.getFileName()); | ||
} | ||
|
||
@Override | ||
public void delete( | ||
final String fileName | ||
) { | ||
Blob file = bucket.get(fileName); | ||
if (file != null) { | ||
file.delete(); | ||
} | ||
} | ||
|
||
@Override | ||
public void delete( | ||
final String fileName, | ||
final Path path | ||
) { | ||
Blob file = bucket.get(path.toString() + "/" + fileName); | ||
if (file != null) { | ||
file.delete(); | ||
} | ||
} | ||
|
||
@Override | ||
public void delete( | ||
final Path path | ||
) { | ||
Page<Blob> blobs = bucket.list(); | ||
String pathToString = path.toString(); | ||
blobs.streamAll().forEach(blob -> { | ||
if (blob.getName().startsWith(pathToString)) { | ||
blob.delete(); | ||
} | ||
}); | ||
} | ||
|
||
} |
Oops, something went wrong.