google drive integration part 1

added a google drive integration, not very clean and working yet!
This commit is contained in:
Seil0 2017-04-17 00:58:49 +02:00
parent a10840db73
commit ed5eef8a49
44 changed files with 496 additions and 8 deletions

View File

@ -6,5 +6,16 @@
<classpathentry kind="lib" path="src/libraries/sqlite-jdbc-3.16.1.jar"/>
<classpathentry kind="lib" path="src/libraries/commons-io-2.5.jar"/>
<classpathentry kind="lib" path="src/libraries/jfoenix-1.3.0.jar"/>
<classpathentry kind="lib" path="src/libraries/google_apis/google-api-client-1.22.0.jar"/>
<classpathentry kind="lib" path="src/libraries/google_apis/google-api-services-drive-v3-rev68-1.22.0.jar"/>
<classpathentry kind="lib" path="src/libraries/google_apis/google-http-client-1.22.0.jar"/>
<classpathentry kind="lib" path="src/libraries/google_apis/google-http-client-jackson2-1.22.0.jar"/>
<classpathentry kind="lib" path="src/libraries/google_apis/google-oauth-client-1.22.0.jar"/>
<classpathentry kind="lib" path="src/libraries/google_apis/google-oauth-client-java6-1.22.0.jar"/>
<classpathentry kind="lib" path="src/libraries/google_apis/google-oauth-client-jetty-1.22.0.jar"/>
<classpathentry kind="lib" path="src/libraries/google_apis/javax.servlet-api-3.1.0.jar"/>
<classpathentry kind="lib" path="src/libraries/google_apis/jetty-6.1.25.jar"/>
<classpathentry kind="lib" path="src/libraries/google_apis/jetty-util-6.1.25.jar"/>
<classpathentry kind="lib" path="src/libraries/google_apis/jackson-core-2.8.8.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

51
.gitignore vendored Normal file
View File

@ -0,0 +1,51 @@
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
config.xml
client_secret.json
.directory

Binary file not shown.

Binary file not shown.

View File

@ -61,10 +61,10 @@
<JFXButton fx:id="romTFBtn" layoutX="337.0" layoutY="159.0" onAction="#romTFBtnAction" prefHeight="32.0" prefWidth="108.0" text="choose directory" AnchorPane.leftAnchor="333.0" AnchorPane.topAnchor="151.0" />
<JFXButton fx:id="cemuTFBtn" layoutX="333.0" layoutY="79.0" onAction="#cemuTFBtnAction" prefHeight="32.0" prefWidth="108.0" text="choose directory" AnchorPane.leftAnchor="333.0" AnchorPane.topAnchor="79.0" />
<JFXColorPicker fx:id="colorPicker" layoutX="22.0" layoutY="235.0" onAction="#colorPickerAction" AnchorPane.leftAnchor="16.0" AnchorPane.topAnchor="227.0" />
<JFXToggleButton fx:id="fullscreenToggleBtn" layoutX="18.0" layoutY="316.0" onAction="#fullscreenToggleBtnAction" text="start game in fullscreen" AnchorPane.leftAnchor="18.0" AnchorPane.topAnchor="314.0" />
<JFXToggleButton fx:id="fullscreenToggleBtn" layoutX="14.0" layoutY="391.0" onAction="#fullscreenToggleBtnAction" text="start game in fullscreen" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="390.0" />
<Label layoutX="22.0" layoutY="135.0" text="Rom Directory" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="131.0" />
<Label layoutX="22.0" layoutY="211.0" text="main Color" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="203.0" />
<Label layoutX="18.0" layoutY="281.0" text="Cemu Settings" AnchorPane.leftAnchor="18.0" AnchorPane.topAnchor="287.0">
<Label layoutX="14.0" layoutY="371.0" text="Cemu Settings" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="350.0">
<font>
<Font name="System Bold" size="14.0" />
</font>
@ -74,6 +74,7 @@
<Font name="System Bold" size="14.0" />
</font>
</Label>
<JFXToggleButton fx:id="cloudSyncToggleBtn" layoutX="14.0" layoutY="264.0" onAction="#cloudSyncToggleBtnAction" text="cloud savegames (Google Drive)" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="267.0" />
</children>
</AnchorPane>
<JFXButton fx:id="playBtn" buttonType="RAISED" maxHeight="38.0" maxWidth="100.0" onAction="#playBtnAction" ripplerFill="#c92a2a" text="play" visible="false" AnchorPane.bottomAnchor="7.0" AnchorPane.leftAnchor="396.0" AnchorPane.rightAnchor="396.0" AnchorPane.topAnchor="555.0">

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,85 @@
/**
* TODO own thread
*/
package application;
import java.io.File;
import java.io.IOException;
import cloudControllerInstances.GoogleDriveController;
public class CloudController {
public CloudController(Main ma) {
main = ma;
}
@SuppressWarnings("unused")//TODO
private Main main;
private GoogleDriveController googleDriveController = new GoogleDriveController();
void initializeConnection(String cloudService, String cemuDirectory) {
System.out.println("sartting initialisation... ");
if(cloudService == "GoogleDrive") {
try {
googleDriveController.main(cemuDirectory);
} catch (IOException e) {
e.printStackTrace();
}
}
if(cloudService == "Dropbox") {
}
System.out.println("done!");
}
void sync(String cloudService, String cemuDirectory) {
if(cloudService == "GoogleDrive") {
try {
googleDriveController.sync(cemuDirectory);
} catch (IOException e) {
e.printStackTrace();
}
}
if(cloudService == "Dropbox") {
}
}
void uploadFile(String cloudService, File file) {
if(cloudService == "GoogleDrive") {
try {
googleDriveController.uploadFile(file);
} catch (IOException e) {
e.printStackTrace();
}
}
if(cloudService == "Dropbox") {
}
}
void download(String cloudService) {
}
public String getFolderID(String cloudService) {
String folderID = "";
if(cloudService == "GoogleDrive") {
folderID = googleDriveController.getFolderID();
}
if(cloudService == "Dropbox") {
}
return folderID;
}
public void setFolderID(String folderID, String cloudService) {
if(cloudService == "GoogleDrive") {
googleDriveController.setFolderID(folderID);
}
if(cloudService == "Dropbox") {
}
}
}

View File

@ -61,10 +61,10 @@
<JFXButton fx:id="romTFBtn" layoutX="337.0" layoutY="159.0" onAction="#romTFBtnAction" prefHeight="32.0" prefWidth="108.0" text="choose directory" AnchorPane.leftAnchor="333.0" AnchorPane.topAnchor="151.0" />
<JFXButton fx:id="cemuTFBtn" layoutX="333.0" layoutY="79.0" onAction="#cemuTFBtnAction" prefHeight="32.0" prefWidth="108.0" text="choose directory" AnchorPane.leftAnchor="333.0" AnchorPane.topAnchor="79.0" />
<JFXColorPicker fx:id="colorPicker" layoutX="22.0" layoutY="235.0" onAction="#colorPickerAction" AnchorPane.leftAnchor="16.0" AnchorPane.topAnchor="227.0" />
<JFXToggleButton fx:id="fullscreenToggleBtn" layoutX="18.0" layoutY="316.0" onAction="#fullscreenToggleBtnAction" text="start game in fullscreen" AnchorPane.leftAnchor="18.0" AnchorPane.topAnchor="314.0" />
<JFXToggleButton fx:id="fullscreenToggleBtn" layoutX="14.0" layoutY="391.0" onAction="#fullscreenToggleBtnAction" text="start game in fullscreen" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="390.0" />
<Label layoutX="22.0" layoutY="135.0" text="Rom Directory" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="131.0" />
<Label layoutX="22.0" layoutY="211.0" text="main Color" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="203.0" />
<Label layoutX="18.0" layoutY="281.0" text="Cemu Settings" AnchorPane.leftAnchor="18.0" AnchorPane.topAnchor="287.0">
<Label layoutX="14.0" layoutY="371.0" text="Cemu Settings" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="350.0">
<font>
<Font name="System Bold" size="14.0" />
</font>
@ -74,6 +74,7 @@
<Font name="System Bold" size="14.0" />
</font>
</Label>
<JFXToggleButton fx:id="cloudSyncToggleBtn" layoutX="14.0" layoutY="264.0" onAction="#cloudSyncToggleBtnAction" text="cloud savegames (Google Drive)" AnchorPane.leftAnchor="14.0" AnchorPane.topAnchor="267.0" />
</children>
</AnchorPane>
<JFXButton fx:id="playBtn" buttonType="RAISED" maxHeight="38.0" maxWidth="100.0" onAction="#playBtnAction" ripplerFill="#c92a2a" text="play" visible="false" AnchorPane.bottomAnchor="7.0" AnchorPane.leftAnchor="396.0" AnchorPane.rightAnchor="396.0" AnchorPane.topAnchor="555.0">

View File

@ -119,6 +119,9 @@ public class MainWindowController {
@FXML
private JFXToggleButton fullscreenToggleBtn;
@FXML
private JFXToggleButton cloudSyncToggleBtn;
@FXML
private AnchorPane settingsAnchorPane;
@ -142,6 +145,8 @@ public class MainWindowController {
private boolean settingsTrue = false;
private boolean playTrue = false;
private boolean fullscreen;
private boolean cloudSync;
private String cloudService = "GoogleDrive"; //set cloud provider (at the moment only GoogleDrive, Dropbox is planed)
private String cemuPath;
private String romPath;
private String gameExecutePath;
@ -519,13 +524,13 @@ public class MainWindowController {
@FXML
void cemuTextFieldAction(ActionEvent event){
setCemuPath(cemuTextField.getText());
saveSettings();
saveSettings();//TODO remove (only save on exit settings)
}
@FXML
void romTextFieldAction(ActionEvent event){
setRomPath(romTextField.getText());
saveSettings();
saveSettings();//TODO remove (only save on exit settings)
}
@FXML
@ -535,7 +540,19 @@ public class MainWindowController {
}else{
fullscreen = true;
}
saveSettings();
saveSettings();//TODO remove (only save on exit settings)
}
@FXML
void cloudSyncToggleBtnAction(ActionEvent event){
if(cloudSync) {
cloudSync = false;
} else {
cloudSync = true;
main.cloudController.initializeConnection(getCloudService(), getCemuPath());
main.cloudController.sync(getCloudService(), getCemuPath());
}
saveSettings();//TODO remove (only save on exit settings)
}
@FXML
@ -733,8 +750,9 @@ public class MainWindowController {
}
}
//TODO xPosHelper based on window with
private void generatePosition(){
// System.out.println(main.primaryStage.getWidth());
if(xPosHelper == 4){
xPos = 17;
yPos = yPos + 345;
@ -805,6 +823,8 @@ public class MainWindowController {
props.setProperty("romPath", getRomPath());
props.setProperty("color", getColor());
props.setProperty("fullscreen", String.valueOf(isFullscreen()));
props.setProperty("cloudSync", String.valueOf(cloudSync));
props.setProperty("folderID", main.cloudController.getFolderID(getCloudService()));
if(System.getProperty("os.name").equals("Linux")){
outputStream = new FileOutputStream(fileLinux);
}else{
@ -832,6 +852,8 @@ public class MainWindowController {
setRomPath(props.getProperty("romPath"));
setColor(props.getProperty("color"));
setFullscreen(Boolean.parseBoolean(props.getProperty("fullscreen")));
setCloudSync(Boolean.parseBoolean(props.getProperty("cloudSync")));
main.cloudController.setFolderID(props.getProperty("folderID"), getCloudService());
inputStream.close();
System.out.println("done!");
} catch (IOException e) {
@ -983,6 +1005,14 @@ public class MainWindowController {
this.fullscreen = fullscreen;
}
public boolean isCloudSync() {
return cloudSync;
}
public void setCloudSync(boolean cloudSync) {
this.cloudSync = cloudSync;
}
public String getGameExecutePath() {
return gameExecutePath;
}
@ -999,4 +1029,12 @@ public class MainWindowController {
this.selectedGameTitleID = selectedGameTitleID;
}
public String getCloudService() {
return cloudService;
}
public void setCloudService(String cloudService) {
this.cloudService = cloudService;
}
}

View File

@ -60,6 +60,13 @@ public class playGame extends Thread{
}
mainWindowController.main.primaryStage.setIconified(false);
});
// System.out.println(mainWindowController.getCemuPath()+"/mlc01/emulatorSave/"+);
//sync savegame with cloud service
if(mainWindowController.isCloudSync()) {
mainWindowController.main.cloudController.sync(mainWindowController.getCloudService(), mainWindowController.getCemuPath());
}
}catch (IOException | InterruptedException e){
e.printStackTrace();
}

View File

@ -0,0 +1,294 @@
package cloudControllerInstances;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.googleapis.media.MediaHttpUploader.UploadState;
import com.google.api.client.http.FileContent;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.util.DateTime;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.*;
import javafx.print.Collation;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.Drive.Files;
import com.google.api.services.drive.Drive.Files.Get;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import javax.servlet.ServletInputStream;
import org.apache.commons.io.FileUtils;
public class GoogleDriveController {
Drive service;
private String uploadFilePath = "C:/Users/Jannik/Documents/cemu_1.7.4/mlc01/emulatorSave/019be15c/userdata.dat";
private String cemuDirectory;
private String folderID;
private java.io.File uploadFile = new java.io.File(uploadFilePath);
private File uploadedFile;
private ArrayList<java.io.File> localSavegames = new ArrayList<>();
private ArrayList<File> cloudSavegames = new ArrayList<>();
private ArrayList<String> localSavegamesName = new ArrayList<>();
private ArrayList<String> cloudSavegamesName = new ArrayList<>();
/** Application name. */
private final String APPLICATION_NAME ="cemu_Ui Drive API Controller";
/** Directory to store user credentials for this application. */
private final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".credentials/cemu_UI_credential");
/** Global instance of the {@link FileDataStoreFactory}. */
private FileDataStoreFactory DATA_STORE_FACTORY;
/** Global instance of the JSON factory. */
private final JsonFactory JSON_FACTORY =JacksonFactory.getDefaultInstance();
/** Global instance of the HTTP transport. */
private HttpTransport HTTP_TRANSPORT;
/** Global instance of the scopes required by this quickstart.
*
* If modifying these scopes, delete your previously saved credentials
* at ~/.credentials/cemu_UI_credential
*/
private final java.util.Collection<String> SCOPES = DriveScopes.all();
public GoogleDriveController() {
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
folderID = "";
} catch (Throwable t) {
t.printStackTrace();
System.exit(1);
}
}
/**
* Creates an authorized Credential object.
* @return an authorized Credential object.
* @throws IOException
*/
public Credential authorize() throws IOException {
// Load client secrets.
InputStream in = getClass().getClassLoader().getResourceAsStream("recources/client_secret.json");
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow =
new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(DATA_STORE_FACTORY)
.setAccessType("offline")
.build();
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
System.out.println("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
return credential;
}
/**
* Build and return an authorized Drive client service.
* @return an authorized Drive client service
* @throws IOException
*/
public Drive getDriveService() throws IOException {
Credential credential = authorize();
return new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
}
public void main(String cemuDirectory) throws IOException {
service = getDriveService();
this.cemuDirectory = cemuDirectory;
// sync();
// upload();
// download();
}
public void sync(String cemuDirectory) throws IOException {
getLocalSavegames();
// upload();
if(!checkFolder()) {
creatFolder();
for(int i = 0; i < localSavegames.size(); i++) {
uploadFile(localSavegames.get(i));
}
} else {
getCloudSavegames();
System.out.println(cloudSavegames.size()+"; "+localSavegames.size()+"; "+localSavegamesName.size());
//download files from cloud which don't exist locally
for(int i = 0; i < cloudSavegames.size(); i++) {
// System.out.println(localSavegamesName.get(i)+"; "+cloudSavegames.get(i).getName());
// System.out.println(localSavegames.get(a).getName()+"; "+cloudSavegames.get(i).getName().substring(9, cloudSavegames.get(i).getName().length()));
// String localSavegameName = localSavegames.get(a).getParentFile().getName()+"_"+localSavegames.get(a).getName();
if(localSavegamesName.contains(cloudSavegames.get(i).getName())) {
int localSavegamesNumber = localSavegamesName.indexOf(cloudSavegames.get(i).getName());
// System.out.println(localSavegamesNumber);
System.out.println(localSavegames.get(localSavegamesNumber).getName()+"; "+cloudSavegames.get(i).getName());
long localModified = new DateTime(localSavegames.get(localSavegamesNumber).lastModified()).getValue();
long cloudModified = cloudSavegames.get(i).getModifiedTime().getValue();
System.out.println(new Date(localModified)+"; "+new Date(cloudModified));
if(localModified == cloudModified) {
System.out.println("both files are the same, nothing to do \n");
} else if(localModified >= cloudModified) {
System.out.println("local is newer, going to upload local file \n");
// updateFile(localSavegames.get(localSavegamesNumber));
} else {
System.out.println("cloud is newer, going to download cloud file \n");
// downloadFile(cloudSavegames.get(i));
}
} else {
System.out.println("download "+cloudSavegames.get(i).getName()+" from the cloud");
// downloadFile(cloudSavegames.get(i));
}
}
//upload file to cloud which don't exist in the cloud
for(int j = 0; j < localSavegames.size(); j++) {
if(!cloudSavegamesName.contains(localSavegamesName.get(j))) {
System.out.println("upload "+localSavegames.get(j).getName()+" to the cloud");
// uploadFile(localSavegames.get(j));
}
}
//check if there are new local files to upload or download, if so upload/download them and [check if there are files in the cloud were last edit is newer than local, and other way round]
}
}
private void creatFolder() throws IOException {
System.out.println("creating new folder");
File fileMetadata = new File();
fileMetadata.setName("cemu_savegames");
fileMetadata.setMimeType("application/vnd.google-apps.folder");
File file = service.files().create(fileMetadata)
.setFields("id")
.execute();
System.out.println("Folder ID: " + file.getId());
folderID = file.getId();
}
private boolean checkFolder() {
try {
Files.List request = service.files().list().setQ("mimeType = 'application/vnd.google-apps.folder' and name = 'cemu_savegames'");
FileList files = request.execute();
if(files.getFiles().size() == 0) {
return false;
} else {
return true;
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
private void getLocalSavegames() throws IOException {
java.io.File dir = new java.io.File(cemuDirectory+"/mlc01/emulatorSave");
String[] extensions = new String[] { "dat" };
System.out.println("Getting all .dat files in " + dir.getCanonicalPath()+" including those in subdirectories \n");
List<java.io.File> files = (List<java.io.File>) FileUtils.listFiles(dir, extensions, true);
for (java.io.File file : files) {
localSavegamesName.add(file.getParentFile().getName()+"_"+file.getName());
localSavegames.add(file);
// System.out.println(file.getAbsolutePath());
// System.out.println(file.getParentFile().getName());
// System.out.println(file.lastModified());
// System.out.println(file.getName()+"\n");
}
}
private void getCloudSavegames() throws IOException {
Files.List request = service.files().list().setQ("fileExtension = 'dat' and '"+folderID+"' in parents").setFields("nextPageToken, files(id, name, size, modifiedTime, createdTime)");
FileList files = request.execute();
for (File file : files.getFiles()) {
cloudSavegamesName.add(file.getName());
cloudSavegames.add(file);
// System.out.println(file.getName());
// System.out.println(file.getModifiedTime()+"\n");
}
}
public void uploadFile(java.io.File uploadFile) throws IOException{
System.out.println("uploading ...");
File fileMetadata = new File();
fileMetadata.setName(uploadFile.getParentFile().getName()+"_"+uploadFile.getName());
fileMetadata.setParents(Collections.singletonList(folderID));
// System.out.println(new DateTime(uploadFile.lastModified())+"; "+ new DateTime(uploadFile.lastModified()).getTimeZoneShift());
fileMetadata.setModifiedTime(new DateTime(uploadFile.lastModified()));
// System.out.println(fileMetadata.getModifiedTime()+"; "+fileMetadata.getModifiedTime().getTimeZoneShift());
FileContent mediaContent = new FileContent("", uploadFile);
File file = service.files().create(fileMetadata, mediaContent).setFields("id, parents").execute();
uploadedFile = file;
System.out.println("File ID: " + file.getId());
}
private void downloadFile(File downloadFile) throws IOException{
System.out.println("downloading "+downloadFile.getName()+" ...");
// String directory = downloadFile.getName().substring(0,8);
java.io.File directoryFile = new java.io.File("/mlc01/emulatorSave/"+ downloadFile.getName().substring(0,8));
String file = downloadFile.getName().substring(9,downloadFile.getName().length());
// System.out.println(cemuDirectory+"/mlc01/emulatorSave/"+ directory +"/"+ file);
// System.out.println(downloadFile.getId());
if(!directoryFile.exists()) {
directoryFile.mkdir();
}
OutputStream outputStream = new FileOutputStream(directoryFile +"/"+ file); //TODO needs to be tested
service.files().get(downloadFile.getId()).executeMediaAndDownloadTo(outputStream);
System.out.println("done");
}
private void updateFile(java.io.File uploadFile) {
}
public String getFolderID() {
return folderID;
}
public void setFolderID(String folderID) {
this.folderID = folderID;
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.