Add model group implementation for client server setup
This commit is contained in:
parent
c49a7db192
commit
ba21dd2aeb
|
@ -1,6 +1,8 @@
|
||||||
package ctbrec.ui.action;
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -49,7 +51,7 @@ public class AddToGroupAction {
|
||||||
if (StringUtil.isBlank(text)) {
|
if (StringUtil.isBlank(text)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Set<ModelGroup> modelGroups = Config.getInstance().getSettings().modelGroups;
|
Set<ModelGroup> modelGroups = recorder.getModelGroups();
|
||||||
Optional<ModelGroup> existingGroup = modelGroups.stream().filter(mg -> mg.getName().equalsIgnoreCase(text)).findFirst();
|
Optional<ModelGroup> existingGroup = modelGroups.stream().filter(mg -> mg.getName().equalsIgnoreCase(text)).findFirst();
|
||||||
if (existingGroup.isPresent()) {
|
if (existingGroup.isPresent()) {
|
||||||
existingGroup.get().add(model);
|
existingGroup.get().add(model);
|
||||||
|
@ -63,7 +65,7 @@ public class AddToGroupAction {
|
||||||
recorder.saveModelGroup(group);
|
recorder.saveModelGroup(group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException e) {
|
||||||
Dialogs.showError(source.getScene(), "Add model to group", "Saving model group failed", e);
|
Dialogs.showError(source.getScene(), "Add model to group", "Saving model group failed", e);
|
||||||
} finally {
|
} finally {
|
||||||
source.setCursor(Cursor.DEFAULT);
|
source.setCursor(Cursor.DEFAULT);
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package ctbrec.ui.action;
|
package ctbrec.ui.action;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import ctbrec.Config;
|
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.ModelGroup;
|
import ctbrec.ModelGroup;
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
|
@ -47,6 +49,12 @@ public class EditGroupAction {
|
||||||
group.getModelUrls().clear();
|
group.getModelUrls().clear();
|
||||||
group.getModelUrls().addAll(dialog.getUrls());
|
group.getModelUrls().addAll(dialog.getUrls());
|
||||||
recorder.saveModelGroup(group);
|
recorder.saveModelGroup(group);
|
||||||
|
if (dialog.getUrls().isEmpty()) {
|
||||||
|
boolean delete = Dialogs.showConfirmDialog(DIALOG_TITLE, "Do you want to delete the group?", "Group is empty", source.getScene());
|
||||||
|
if (delete) {
|
||||||
|
recorder.deleteModelGroup(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Dialogs.showError(source.getScene(), DIALOG_TITLE, "Editing model group failed", e);
|
Dialogs.showError(source.getScene(), DIALOG_TITLE, "Editing model group failed", e);
|
||||||
|
@ -55,7 +63,7 @@ public class EditGroupAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class EditModelGroupDialog extends GridPane {
|
private class EditModelGroupDialog extends GridPane {
|
||||||
private TextField groupName;
|
private TextField groupName;
|
||||||
private ListView<String> urlListView;
|
private ListView<String> urlListView;
|
||||||
private ObservableList<String> urlList;
|
private ObservableList<String> urlList;
|
||||||
|
@ -63,13 +71,18 @@ public class EditGroupAction {
|
||||||
private List<String> urls;
|
private List<String> urls;
|
||||||
|
|
||||||
public EditModelGroupDialog(Model model) {
|
public EditModelGroupDialog(Model model) {
|
||||||
Optional<ModelGroup> optionalModelGroup = Config.getInstance().getModelGroup(model);
|
Optional<ModelGroup> optionalModelGroup;
|
||||||
if (optionalModelGroup.isPresent()) {
|
try {
|
||||||
modelGroup = optionalModelGroup.get();
|
optionalModelGroup = recorder.getModelGroup(model);
|
||||||
urls = new ArrayList<>(modelGroup.getModelUrls());
|
if (optionalModelGroup.isPresent()) {
|
||||||
createGui(modelGroup);
|
modelGroup = optionalModelGroup.get();
|
||||||
} else {
|
urls = new ArrayList<>(modelGroup.getModelUrls());
|
||||||
Dialogs.showError(getScene(), DIALOG_TITLE, "No group found for model", null);
|
createGui(modelGroup);
|
||||||
|
} else {
|
||||||
|
Dialogs.showError(getScene(), DIALOG_TITLE, "No group found for model", null);
|
||||||
|
}
|
||||||
|
} catch (InvalidKeyException | NoSuchAlgorithmException | IOException e) {
|
||||||
|
Dialogs.showError(getScene(), DIALOG_TITLE, "Couldn't edit model group", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ import static ctbrec.ui.controls.Dialogs.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -46,6 +48,7 @@ import ctbrec.ui.action.IgnoreModelsAction;
|
||||||
import ctbrec.ui.action.OpenRecordingsDir;
|
import ctbrec.ui.action.OpenRecordingsDir;
|
||||||
import ctbrec.ui.action.SetStopDateAction;
|
import ctbrec.ui.action.SetStopDateAction;
|
||||||
import ctbrec.ui.controls.CustomMouseBehaviorContextMenu;
|
import ctbrec.ui.controls.CustomMouseBehaviorContextMenu;
|
||||||
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import ctbrec.ui.controls.FasterVerticalScrollPaneSkin;
|
import ctbrec.ui.controls.FasterVerticalScrollPaneSkin;
|
||||||
import ctbrec.ui.controls.SearchBox;
|
import ctbrec.ui.controls.SearchBox;
|
||||||
import ctbrec.ui.controls.SearchPopover;
|
import ctbrec.ui.controls.SearchPopover;
|
||||||
|
@ -543,7 +546,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
if (site.supportsTips()) {
|
if (site.supportsTips()) {
|
||||||
contextMenu.getItems().add(sendTip);
|
contextMenu.getItems().add(sendTip);
|
||||||
}
|
}
|
||||||
Optional<ModelGroup> modelGroup = Config.getInstance().getModelGroup(model);
|
Optional<ModelGroup> modelGroup = getModelGroup(model);
|
||||||
contextMenu.getItems().add(modelGroup.isEmpty() ? addToGroup : editGroup);
|
contextMenu.getItems().add(modelGroup.isEmpty() ? addToGroup : editGroup);
|
||||||
contextMenu.getItems().addAll(copyUrl, openInBrowser, ignore, refresh, openRecDir);
|
contextMenu.getItems().addAll(copyUrl, openInBrowser, ignore, refresh, openRecDir);
|
||||||
if (model instanceof MyFreeCamsModel && Objects.equals(System.getenv("CTBREC_DEV"), "1")) {
|
if (model instanceof MyFreeCamsModel && Objects.equals(System.getenv("CTBREC_DEV"), "1")) {
|
||||||
|
@ -555,6 +558,15 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
|
||||||
return contextMenu;
|
return contextMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Optional<ModelGroup> getModelGroup(Model model) {
|
||||||
|
try {
|
||||||
|
return recorder.getModelGroup(model);
|
||||||
|
} catch (InvalidKeyException | NoSuchAlgorithmException | IOException e) {
|
||||||
|
Dialogs.showError(grid.getScene(), "Error", "Couldn't get model group for model " + model, e);
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void editGroup(Model model) {
|
private void editGroup(Model model) {
|
||||||
new EditGroupAction(this.getContent(), recorder, model).execute();
|
new EditGroupAction(this.getContent(), recorder, model).execute();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
package ctbrec.ui.tabs;
|
package ctbrec.ui.tabs;
|
||||||
|
|
||||||
|
import static ctbrec.ui.controls.Dialogs.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.sites.Site;
|
import ctbrec.sites.Site;
|
||||||
import ctbrec.ui.SiteUiFactory;
|
import ctbrec.ui.SiteUiFactory;
|
||||||
|
@ -7,13 +15,6 @@ import ctbrec.ui.controls.SearchPopover;
|
||||||
import ctbrec.ui.controls.SearchPopoverTreeList;
|
import ctbrec.ui.controls.SearchPopoverTreeList;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static ctbrec.ui.controls.Dialogs.showError;
|
|
||||||
|
|
||||||
public class ThumbOverviewTabSearchTask extends Task<List<Model>> {
|
public class ThumbOverviewTabSearchTask extends Task<List<Model>> {
|
||||||
|
|
||||||
|
|
|
@ -2,19 +2,26 @@ package ctbrec.ui.tabs.recorded;
|
||||||
|
|
||||||
import static ctbrec.ui.Icon.*;
|
import static ctbrec.ui.Icon.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import ctbrec.Config;
|
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.ModelGroup;
|
import ctbrec.ModelGroup;
|
||||||
|
import ctbrec.recorder.Recorder;
|
||||||
|
import ctbrec.ui.controls.Dialogs;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
|
|
||||||
public class ModelNameTableCell extends IconTableCell<String> {
|
public class ModelNameTableCell extends IconTableCell<String> {
|
||||||
|
|
||||||
public ModelNameTableCell() {
|
private Recorder recorder;
|
||||||
|
|
||||||
|
public ModelNameTableCell(Recorder recorder) {
|
||||||
super(Map.of(GROUP_16, new ImageView(GROUP_16.url())));
|
super(Map.of(GROUP_16, new ImageView(GROUP_16.url())));
|
||||||
|
this.recorder = recorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,7 +33,7 @@ public class ModelNameTableCell extends IconTableCell<String> {
|
||||||
if (item != null && !empty) {
|
if (item != null && !empty) {
|
||||||
setText(item);
|
setText(item);
|
||||||
Model m = getTableView().getItems().get(getTableRow().getIndex());
|
Model m = getTableView().getItems().get(getTableRow().getIndex());
|
||||||
Optional<ModelGroup> optionalGroup = Config.getInstance().getModelGroup(m);
|
Optional<ModelGroup> optionalGroup = getModelGroup(m);
|
||||||
if (optionalGroup.isPresent()) {
|
if (optionalGroup.isPresent()) {
|
||||||
ModelGroup group = optionalGroup.get();
|
ModelGroup group = optionalGroup.get();
|
||||||
setText(group.getName() + " (aka " + item + ')');
|
setText(group.getName() + " (aka " + item + ')');
|
||||||
|
@ -37,4 +44,13 @@ public class ModelNameTableCell extends IconTableCell<String> {
|
||||||
}
|
}
|
||||||
super.updateItem(item, empty);
|
super.updateItem(item, empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Optional<ModelGroup> getModelGroup(Model model) {
|
||||||
|
try {
|
||||||
|
return recorder.getModelGroup(model);
|
||||||
|
} catch (InvalidKeyException | NoSuchAlgorithmException | IOException e) {
|
||||||
|
Dialogs.showError(getScene(), "Error", "Couldn't get model group for model " + model, e);
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,7 +173,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
TableColumn<JavaFxModel, String> name = new TableColumn<>("Model");
|
TableColumn<JavaFxModel, String> name = new TableColumn<>("Model");
|
||||||
name.setPrefWidth(200);
|
name.setPrefWidth(200);
|
||||||
name.setCellValueFactory(new PropertyValueFactory<>("displayName"));
|
name.setCellValueFactory(new PropertyValueFactory<>("displayName"));
|
||||||
name.setCellFactory(param -> new ModelNameTableCell());
|
name.setCellFactory(param -> new ModelNameTableCell(recorder));
|
||||||
name.setEditable(false);
|
name.setEditable(false);
|
||||||
name.setId("name");
|
name.setId("name");
|
||||||
TableColumn<JavaFxModel, String> url = new TableColumn<>("URL");
|
TableColumn<JavaFxModel, String> url = new TableColumn<>("URL");
|
||||||
|
@ -694,7 +694,7 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
} else {
|
} else {
|
||||||
menu.getItems().addAll(resumeRecording, pauseRecording);
|
menu.getItems().addAll(resumeRecording, pauseRecording);
|
||||||
}
|
}
|
||||||
Optional<ModelGroup> modelGroup = Config.getInstance().getModelGroup(selectedModels.get(0));
|
Optional<ModelGroup> modelGroup = getModelGroup(selectedModels.get(0));
|
||||||
menu.getItems().add(modelGroup.isEmpty() ? addToGroup : editGroup);
|
menu.getItems().add(modelGroup.isEmpty() ? addToGroup : editGroup);
|
||||||
menu.getItems().addAll(copyUrl, openInPlayer, openInBrowser, openRecDir, switchStreamSource, follow, notes, ignore);
|
menu.getItems().addAll(copyUrl, openInPlayer, openInBrowser, openRecDir, switchStreamSource, follow, notes, ignore);
|
||||||
|
|
||||||
|
@ -709,6 +709,15 @@ public class RecordedModelsTab extends Tab implements TabSelectionListener {
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Optional<ModelGroup> getModelGroup(Model model) {
|
||||||
|
try {
|
||||||
|
return recorder.getModelGroup(model);
|
||||||
|
} catch (InvalidKeyException | NoSuchAlgorithmException | IOException e) {
|
||||||
|
Dialogs.showError(grid.getScene(), "Error", "Couldn't get model group for model " + model, e);
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void addToGroup(Model model) {
|
private void addToGroup(Model model) {
|
||||||
new AddToGroupAction(this.getContent(), recorder, model).execute();
|
new AddToGroupAction(this.getContent(), recorder, model).execute();
|
||||||
table.refresh();
|
table.refresh();
|
||||||
|
|
|
@ -311,10 +311,4 @@ public class Config {
|
||||||
public void enableSaving() {
|
public void enableSaving() {
|
||||||
savingDisabled = false;
|
savingDisabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ModelGroup> getModelGroup(Model model) {
|
|
||||||
return getSettings().modelGroups.stream()
|
|
||||||
.filter(mg -> mg.getModelUrls().contains(model.getUrl()))
|
|
||||||
.findFirst();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -783,16 +783,6 @@ public class NextGenLocalRecorder implements Recorder {
|
||||||
return config.getSettings().modelGroups;
|
return config.getSettings().modelGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<ModelGroup> getModelGroup(UUID id) {
|
|
||||||
for (ModelGroup group : getModelGroups()) {
|
|
||||||
if (Objects.equals(group.getId(), id)) {
|
|
||||||
return Optional.of(group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveModelGroup(ModelGroup group) throws IOException {
|
public void saveModelGroup(ModelGroup group) throws IOException {
|
||||||
Set<ModelGroup> modelGroups = config.getSettings().modelGroups;
|
Set<ModelGroup> modelGroups = config.getSettings().modelGroups;
|
||||||
|
|
|
@ -6,7 +6,6 @@ import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
|
@ -153,17 +152,23 @@ public interface Recorder {
|
||||||
*/
|
*/
|
||||||
public int getModelCount();
|
public int getModelCount();
|
||||||
|
|
||||||
public Set<ModelGroup> getModelGroups();
|
public Set<ModelGroup> getModelGroups() throws InvalidKeyException, NoSuchAlgorithmException, IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves a model group. If the group already exists, it will be overwritten. Otherwise it will
|
* Saves a model group. If the group already exists, it will be overwritten. Otherwise it will
|
||||||
* be saved as a new group.
|
* be saved as a new group.
|
||||||
* @param group
|
* @param group
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
|
* @throws NoSuchAlgorithmException
|
||||||
|
* @throws InvalidKeyException
|
||||||
*/
|
*/
|
||||||
public void saveModelGroup(ModelGroup group) throws IOException;
|
public void saveModelGroup(ModelGroup group) throws IOException, InvalidKeyException, NoSuchAlgorithmException;
|
||||||
|
|
||||||
public Optional<ModelGroup> getModelGroup(UUID uuid);
|
public void deleteModelGroup(ModelGroup group) throws IOException, InvalidKeyException, NoSuchAlgorithmException;
|
||||||
|
|
||||||
public void deleteModelGroup(ModelGroup group) throws IOException;
|
default Optional<ModelGroup> getModelGroup(Model model) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
|
return getModelGroups().stream()
|
||||||
|
.filter(mg -> mg.getModelUrls().contains(model.getUrl()))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@ public class RecordingPreconditions {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureNoOtherFromModelGroupIsRecording(Model model) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
private void ensureNoOtherFromModelGroupIsRecording(Model model) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
Optional<ModelGroup> modelGroup = Config.getInstance().getModelGroup(model);
|
Optional<ModelGroup> modelGroup = recorder.getModelGroup(model);
|
||||||
if (modelGroup.isPresent()) {
|
if (modelGroup.isPresent()) {
|
||||||
for (String modelUrl : modelGroup.get().getModelUrls()) {
|
for (String modelUrl : modelGroup.get().getModelUrls()) {
|
||||||
if (modelUrl.equals(model.getUrl())) {
|
if (modelUrl.equals(model.getUrl())) {
|
||||||
|
|
|
@ -9,9 +9,9 @@ import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -37,6 +37,7 @@ import ctbrec.io.HttpClient;
|
||||||
import ctbrec.io.HttpException;
|
import ctbrec.io.HttpException;
|
||||||
import ctbrec.io.InstantJsonAdapter;
|
import ctbrec.io.InstantJsonAdapter;
|
||||||
import ctbrec.io.ModelJsonAdapter;
|
import ctbrec.io.ModelJsonAdapter;
|
||||||
|
import ctbrec.io.UuidJSonAdapter;
|
||||||
import ctbrec.sites.Site;
|
import ctbrec.sites.Site;
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
|
@ -56,16 +57,20 @@ public class RemoteRecorder implements Recorder {
|
||||||
.add(Instant.class, new InstantJsonAdapter())
|
.add(Instant.class, new InstantJsonAdapter())
|
||||||
.add(Model.class, new ModelJsonAdapter())
|
.add(Model.class, new ModelJsonAdapter())
|
||||||
.add(File.class, new FileJsonAdapter())
|
.add(File.class, new FileJsonAdapter())
|
||||||
|
.add(UUID.class, new UuidJSonAdapter())
|
||||||
.build();
|
.build();
|
||||||
private JsonAdapter<ModelListResponse> modelListResponseAdapter = moshi.adapter(ModelListResponse.class);
|
private JsonAdapter<ModelListResponse> modelListResponseAdapter = moshi.adapter(ModelListResponse.class);
|
||||||
private JsonAdapter<RecordingListResponse> recordingListResponseAdapter = moshi.adapter(RecordingListResponse.class);
|
private JsonAdapter<RecordingListResponse> recordingListResponseAdapter = moshi.adapter(RecordingListResponse.class);
|
||||||
private JsonAdapter<ModelRequest> modelRequestAdapter = moshi.adapter(ModelRequest.class);
|
private JsonAdapter<ModelRequest> modelRequestAdapter = moshi.adapter(ModelRequest.class);
|
||||||
|
private JsonAdapter<ModelGroupRequest> modelGroupRequestAdapter = moshi.adapter(ModelGroupRequest.class);
|
||||||
|
private JsonAdapter<ModelGroupListResponse> modelGroupListResponseAdapter = moshi.adapter(ModelGroupListResponse.class);
|
||||||
private JsonAdapter<RecordingRequest> recordingRequestAdapter = moshi.adapter(RecordingRequest.class);
|
private JsonAdapter<RecordingRequest> recordingRequestAdapter = moshi.adapter(RecordingRequest.class);
|
||||||
private JsonAdapter<SimpleResponse> simpleResponseAdapter = moshi.adapter(SimpleResponse.class);
|
private JsonAdapter<SimpleResponse> simpleResponseAdapter = moshi.adapter(SimpleResponse.class);
|
||||||
|
|
||||||
private List<Model> models = Collections.emptyList();
|
private List<Model> models = Collections.emptyList();
|
||||||
private List<Model> onlineModels = Collections.emptyList();
|
private List<Model> onlineModels = Collections.emptyList();
|
||||||
private List<Recording> recordings = Collections.emptyList();
|
private List<Recording> recordings = Collections.emptyList();
|
||||||
|
private Set<ModelGroup> modelGroups = new HashSet<>();
|
||||||
private List<Site> sites;
|
private List<Site> sites;
|
||||||
private long spaceTotal = -1;
|
private long spaceTotal = -1;
|
||||||
private long spaceFree = -1;
|
private long spaceFree = -1;
|
||||||
|
@ -106,7 +111,7 @@ public class RemoteRecorder implements Recorder {
|
||||||
|
|
||||||
private Optional<String> sendRequest(String action) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
private Optional<String> sendRequest(String action) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||||
String msg = "{\"action\": \"" + action + "\"}";
|
String msg = "{\"action\": \"" + action + "\"}";
|
||||||
LOG.debug("Sending request to recording server: {}", msg);
|
LOG.trace("Sending request to recording server: {}", msg);
|
||||||
RequestBody requestBody = RequestBody.Companion.create(msg, JSON);
|
RequestBody requestBody = RequestBody.Companion.create(msg, JSON);
|
||||||
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(requestBody);
|
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(requestBody);
|
||||||
addHmacIfNeeded(msg, builder);
|
addHmacIfNeeded(msg, builder);
|
||||||
|
@ -124,7 +129,7 @@ public class RemoteRecorder implements Recorder {
|
||||||
|
|
||||||
private void sendRequest(String action, Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
private void sendRequest(String action, Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||||
String payload = modelRequestAdapter.toJson(new ModelRequest(action, model));
|
String payload = modelRequestAdapter.toJson(new ModelRequest(action, model));
|
||||||
LOG.debug("Sending request to recording server: {}", payload);
|
LOG.trace("Sending request to recording server: {}", payload);
|
||||||
RequestBody body = RequestBody.Companion.create(payload, JSON);
|
RequestBody body = RequestBody.Companion.create(payload, JSON);
|
||||||
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
||||||
addHmacIfNeeded(payload, builder);
|
addHmacIfNeeded(payload, builder);
|
||||||
|
@ -154,6 +159,7 @@ public class RemoteRecorder implements Recorder {
|
||||||
String msg = recordingRequestAdapter.toJson(recReq);
|
String msg = recordingRequestAdapter.toJson(recReq);
|
||||||
RequestBody body = RequestBody.Companion.create(msg, JSON);
|
RequestBody body = RequestBody.Companion.create(msg, JSON);
|
||||||
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
||||||
|
LOG.trace("Sending request to recording server: {}", msg);
|
||||||
addHmacIfNeeded(msg, builder);
|
addHmacIfNeeded(msg, builder);
|
||||||
Request request = builder.build();
|
Request request = builder.build();
|
||||||
try (Response response = client.execute(request)) {
|
try (Response response = client.execute(request)) {
|
||||||
|
@ -173,6 +179,33 @@ public class RemoteRecorder implements Recorder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendRequest(String action, ModelGroup model) throws IOException, InvalidKeyException, NoSuchAlgorithmException {
|
||||||
|
String payload = modelGroupRequestAdapter.toJson(new ModelGroupRequest(action, model));
|
||||||
|
LOG.trace("Sending request to recording server: {}", payload);
|
||||||
|
RequestBody body = RequestBody.Companion.create(payload, JSON);
|
||||||
|
Request.Builder builder = new Request.Builder().url(getRecordingEndpoint()).post(body);
|
||||||
|
addHmacIfNeeded(payload, builder);
|
||||||
|
Request request = builder.build();
|
||||||
|
try (Response response = client.execute(request)) {
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
String json = response.body().string();
|
||||||
|
updateModelGroups(json);
|
||||||
|
} else {
|
||||||
|
throw new HttpException(response.code(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateModelGroups(String responseBody) throws IOException {
|
||||||
|
ModelGroupListResponse resp = modelGroupListResponseAdapter.fromJson(responseBody);
|
||||||
|
if (!resp.status.equals(SUCCESS)) {
|
||||||
|
throw new IOException("Server returned error " + resp.status + " " + resp.msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
modelGroups.clear();
|
||||||
|
modelGroups.addAll(resp.groups);
|
||||||
|
}
|
||||||
|
|
||||||
private void addHmacIfNeeded(String msg, Builder builder) throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {
|
private void addHmacIfNeeded(String msg, Builder builder) throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {
|
||||||
if (Config.getInstance().getSettings().requireAuthentication) {
|
if (Config.getInstance().getSettings().requireAuthentication) {
|
||||||
byte[] key = Config.getInstance().getSettings().key;
|
byte[] key = Config.getInstance().getSettings().key;
|
||||||
|
@ -240,10 +273,25 @@ public class RemoteRecorder implements Recorder {
|
||||||
syncOnlineModels();
|
syncOnlineModels();
|
||||||
syncSpace();
|
syncSpace();
|
||||||
syncRecordings();
|
syncRecordings();
|
||||||
|
syncModelGroups();
|
||||||
sleep();
|
sleep();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void syncModelGroups() {
|
||||||
|
try {
|
||||||
|
sendRequest("listModelGroups").ifPresent(body -> {
|
||||||
|
try {
|
||||||
|
updateModelGroups(body);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("Error while loading model groups from server", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException | InvalidKeyException | NoSuchAlgorithmException e) {
|
||||||
|
LOG.error("Error while loading model groups from server", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void syncSpace() {
|
private void syncSpace() {
|
||||||
try {
|
try {
|
||||||
String msg = "{\"action\": \"space\"}";
|
String msg = "{\"action\": \"space\"}";
|
||||||
|
@ -427,6 +475,12 @@ public class RemoteRecorder implements Recorder {
|
||||||
public List<Model> models;
|
public List<Model> models;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ModelGroupListResponse {
|
||||||
|
public String status;
|
||||||
|
public String msg;
|
||||||
|
public List<ModelGroup> groups;
|
||||||
|
}
|
||||||
|
|
||||||
private static class SimpleResponse {
|
private static class SimpleResponse {
|
||||||
public String status;
|
public String status;
|
||||||
public String msg;
|
public String msg;
|
||||||
|
@ -475,6 +529,33 @@ public class RemoteRecorder implements Recorder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ModelGroupRequest {
|
||||||
|
private String action;
|
||||||
|
private ModelGroup modelGroup;
|
||||||
|
|
||||||
|
public ModelGroupRequest(String action, ModelGroup modelGroup) {
|
||||||
|
super();
|
||||||
|
this.action = action;
|
||||||
|
this.modelGroup = modelGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAction(String action) {
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelGroup getModelGroup() {
|
||||||
|
return modelGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModelGroup(ModelGroup model) {
|
||||||
|
this.modelGroup = model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class RecordingRequest {
|
public static class RecordingRequest {
|
||||||
private String action;
|
private String action;
|
||||||
private Recording recording;
|
private Recording recording;
|
||||||
|
@ -609,28 +690,17 @@ public class RemoteRecorder implements Recorder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ModelGroup> getModelGroups() {
|
public Set<ModelGroup> getModelGroups() throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
// TODO Auto-generated method stub
|
return modelGroups;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveModelGroup(ModelGroup group) {
|
public void saveModelGroup(ModelGroup group) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
// TODO Auto-generated method stub
|
sendRequest("saveModelGroup", group);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteModelGroup(ModelGroup group) {
|
public void deleteModelGroup(ModelGroup group) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
// TODO Auto-generated method stub
|
sendRequest("deleteModelGroup", group);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<ModelGroup> getModelGroup(UUID id) {
|
|
||||||
for (ModelGroup group : getModelGroups()) {
|
|
||||||
if (Objects.equals(group.getId(), id)) {
|
|
||||||
return Optional.of(group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,9 @@ package ctbrec.recorder.postprocessing;
|
||||||
import static ctbrec.StringUtil.*;
|
import static ctbrec.StringUtil.*;
|
||||||
import static java.util.Optional.*;
|
import static java.util.Optional.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
@ -15,6 +18,9 @@ import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
import ctbrec.ModelGroup;
|
import ctbrec.ModelGroup;
|
||||||
|
@ -24,10 +30,18 @@ import ctbrec.sites.Site;
|
||||||
|
|
||||||
public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPostProcessor {
|
public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPostProcessor {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(AbstractPlaceholderAwarePostProcessor.class);
|
||||||
|
|
||||||
public String fillInPlaceHolders(String input, PostProcessingContext ctx) {
|
public String fillInPlaceHolders(String input, PostProcessingContext ctx) {
|
||||||
Recording rec = ctx.getRecording();
|
Recording rec = ctx.getRecording();
|
||||||
Config config = ctx.getConfig();
|
Config config = ctx.getConfig();
|
||||||
Optional<ModelGroup> modelGroup = config.getModelGroup(rec.getModel());
|
Optional<ModelGroup> modelGroup;
|
||||||
|
try {
|
||||||
|
modelGroup = ctx.getRecorder().getModelGroup(rec.getModel());
|
||||||
|
} catch (InvalidKeyException | NoSuchAlgorithmException | IOException e) {
|
||||||
|
LOG.error("Couldn't get model group for {}", rec.getModel(), e);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, Function<String, Optional<String>>> placeholderValueSuppliers = new HashMap<>();
|
Map<String, Function<String, Optional<String>>> placeholderValueSuppliers = new HashMap<>();
|
||||||
placeholderValueSuppliers.put("modelName", r -> ofNullable(rec.getModel().getName()));
|
placeholderValueSuppliers.put("modelName", r -> ofNullable(rec.getModel().getName()));
|
||||||
|
|
|
@ -10,6 +10,8 @@ import java.time.Instant;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -25,11 +27,13 @@ import com.squareup.moshi.Moshi;
|
||||||
import ctbrec.Config;
|
import ctbrec.Config;
|
||||||
import ctbrec.GlobalThreadPool;
|
import ctbrec.GlobalThreadPool;
|
||||||
import ctbrec.Model;
|
import ctbrec.Model;
|
||||||
|
import ctbrec.ModelGroup;
|
||||||
import ctbrec.Recording;
|
import ctbrec.Recording;
|
||||||
import ctbrec.io.BandwidthMeter;
|
import ctbrec.io.BandwidthMeter;
|
||||||
import ctbrec.io.FileJsonAdapter;
|
import ctbrec.io.FileJsonAdapter;
|
||||||
import ctbrec.io.InstantJsonAdapter;
|
import ctbrec.io.InstantJsonAdapter;
|
||||||
import ctbrec.io.ModelJsonAdapter;
|
import ctbrec.io.ModelJsonAdapter;
|
||||||
|
import ctbrec.io.UuidJSonAdapter;
|
||||||
import ctbrec.recorder.Recorder;
|
import ctbrec.recorder.Recorder;
|
||||||
import ctbrec.sites.Site;
|
import ctbrec.sites.Site;
|
||||||
|
|
||||||
|
@ -67,6 +71,7 @@ public class RecorderServlet extends AbstractCtbrecServlet {
|
||||||
.add(Instant.class, new InstantJsonAdapter())
|
.add(Instant.class, new InstantJsonAdapter())
|
||||||
.add(Model.class, new ModelJsonAdapter(sites))
|
.add(Model.class, new ModelJsonAdapter(sites))
|
||||||
.add(File.class, new FileJsonAdapter())
|
.add(File.class, new FileJsonAdapter())
|
||||||
|
.add(UUID.class, new UuidJSonAdapter())
|
||||||
.build();
|
.build();
|
||||||
JsonAdapter<Request> requestAdapter = moshi.adapter(Request.class);
|
JsonAdapter<Request> requestAdapter = moshi.adapter(Request.class);
|
||||||
Request request = requestAdapter.fromJson(json);
|
Request request = requestAdapter.fromJson(json);
|
||||||
|
@ -234,6 +239,17 @@ public class RecorderServlet extends AbstractCtbrecServlet {
|
||||||
response = "{\"status\": \"success\"}";
|
response = "{\"status\": \"success\"}";
|
||||||
resp.getWriter().write(response);
|
resp.getWriter().write(response);
|
||||||
break;
|
break;
|
||||||
|
case "saveModelGroup":
|
||||||
|
recorder.saveModelGroup(request.modelGroup);
|
||||||
|
sendModelGroups(resp, recorder.getModelGroups());
|
||||||
|
break;
|
||||||
|
case "deleteModelGroup":
|
||||||
|
recorder.deleteModelGroup(request.modelGroup);
|
||||||
|
sendModelGroups(resp, recorder.getModelGroups());
|
||||||
|
break;
|
||||||
|
case "listModelGroups":
|
||||||
|
sendModelGroups(resp, recorder.getModelGroups());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
resp.setStatus(SC_BAD_REQUEST);
|
resp.setStatus(SC_BAD_REQUEST);
|
||||||
response = "{\"status\": \"error\", \"msg\": \"Unknown action ["+request.action+"]\"}";
|
response = "{\"status\": \"error\", \"msg\": \"Unknown action ["+request.action+"]\"}";
|
||||||
|
@ -258,6 +274,13 @@ public class RecorderServlet extends AbstractCtbrecServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendModelGroups(HttpServletResponse resp, Set<ModelGroup> modelGroups) throws IOException {
|
||||||
|
JSONObject jsonResponse = new JSONObject();
|
||||||
|
jsonResponse.put("status", "success");
|
||||||
|
jsonResponse.put("groups", modelGroups);
|
||||||
|
resp.getWriter().write(jsonResponse.toString());
|
||||||
|
}
|
||||||
|
|
||||||
private void startByUrl(Request request) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
private void startByUrl(Request request) throws InvalidKeyException, NoSuchAlgorithmException, IOException {
|
||||||
String url = request.model.getUrl();
|
String url = request.model.getUrl();
|
||||||
for (Site site : sites) {
|
for (Site site : sites) {
|
||||||
|
@ -291,5 +314,6 @@ public class RecorderServlet extends AbstractCtbrecServlet {
|
||||||
public String action;
|
public String action;
|
||||||
public Model model;
|
public Model model;
|
||||||
public Recording recording;
|
public Recording recording;
|
||||||
|
public ModelGroup modelGroup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue