package com.twasyl.slideshowfx.app;
import com.twasyl.slideshowfx.controllers.SlideshowFXController;
import com.twasyl.slideshowfx.engine.presentation.PresentationEngine;
import com.twasyl.slideshowfx.engine.template.TemplateEngine;
import com.twasyl.slideshowfx.global.configuration.GlobalConfiguration;
import com.twasyl.slideshowfx.hosting.connector.IHostingConnector;
import com.twasyl.slideshowfx.osgi.OSGiManager;
import com.twasyl.slideshowfx.server.SlideshowFXServer;
import com.twasyl.slideshowfx.utils.io.DeleteFileVisitor;
import com.twasyl.slideshowfx.utils.time.DateTimeUtils;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* JavaFX application class to launch SlideshowFX.
*
* @author Thierry Wasylczenko
* @version 1.1
* @since SlideshowFX 1.0
*/
public class SlideshowFX extends Application {
private static final Logger LOGGER = Logger.getLogger(SlideshowFX.class.getName());
private static final String PRESENTATION_ARGUMENT_PREFIX = "presentation";
private static final String TEMPLATE_ARGUMENT_PREFIX = "template";
private static final ReadOnlyObjectProperty<Stage> stage = new SimpleObjectProperty<>();
private static final ReadOnlyObjectProperty<Scene> presentationBuilderScene = new SimpleObjectProperty<>();
private final ReadOnlyObjectProperty<SlideshowFXController> mainController = new SimpleObjectProperty<>();
private Set<File> filesToOpen;
@Override
public void init() throws Exception {
// Initialize the configuration
GlobalConfiguration.createApplicationDirectory();
if(GlobalConfiguration.createConfigurationFile()) {
GlobalConfiguration.fillConfigurationWithDefaultValue();
} else {
GlobalConfiguration.fillConfigurationWithDefaultValue();
}
// Start the MarkupManager
LOGGER.info("Starting Felix");
OSGiManager.getInstance().startAndDeploy();
// Retrieve the files to open at startup
final Map<String, String> params = getParameters().getNamed();
if(params != null && !params.isEmpty()) {
this.filesToOpen = new HashSet<>();
// Only files that exist and can be read and opened are added to the list of files to open
params.forEach((paramName, paramValue) -> {
if(paramName != null && (paramName.startsWith(PRESENTATION_ARGUMENT_PREFIX) ||
paramName.startsWith(TEMPLATE_ARGUMENT_PREFIX))) {
final File file = new File(paramValue);
if (file.exists() && file.canRead() && file.canWrite() && !this.filesToOpen.contains(file)) {
this.filesToOpen.add(file);
}
}
});
}
// Try to load parameters that are passed dynamically with just a value
final List<String> unnamedParams = getParameters().getUnnamed();
if(unnamedParams != null && !unnamedParams.isEmpty()) {
unnamedParams.forEach(param -> {
final File file = new File(param);
if((file.getName().endsWith(TemplateEngine.DEFAULT_ARCHIVE_EXTENSION) ||
file.getName().endsWith(PresentationEngine.DEFAULT_ARCHIVE_EXTENSION))
&& file.exists() && file.canRead() && file.canWrite() && !this.filesToOpen.contains(file)) {
this.filesToOpen.add(file);
}
});
}
}
@Override
public void start(Stage stage) throws Exception {
((SimpleObjectProperty<Stage>) SlideshowFX.stage).set(stage);
final FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/twasyl/slideshowfx/fxml/SlideshowFX.fxml"));
final Parent root = loader.load();
((SimpleObjectProperty<SlideshowFXController>) this.mainController).set(loader.getController());
final Scene scene = new Scene(root);
((SimpleObjectProperty<Scene>) presentationBuilderScene).set(scene);
stage.setTitle("SlideshowFX");
stage.setScene(scene);
stage.setMaximized(true);
stage.getIcons().addAll(
new Image(SlideshowFX.class.getResourceAsStream("/com/twasyl/slideshowfx/images/appicons/16.png")),
new Image(SlideshowFX.class.getResourceAsStream("/com/twasyl/slideshowfx/images/appicons/32.png")),
new Image(SlideshowFX.class.getResourceAsStream("/com/twasyl/slideshowfx/images/appicons/64.png")),
new Image(SlideshowFX.class.getResourceAsStream("/com/twasyl/slideshowfx/images/appicons/128.png")),
new Image(SlideshowFX.class.getResourceAsStream("/com/twasyl/slideshowfx/images/appicons/256.png")),
new Image(SlideshowFX.class.getResourceAsStream("/com/twasyl/slideshowfx/images/appicons/512.png")));
stage.show();
if(this.filesToOpen != null && !this.filesToOpen.isEmpty()) {
this.filesToOpen.forEach(file -> {
try {
this.mainController.get().openTemplateOrPresentation(file);
} catch (IllegalAccessException | FileNotFoundException e) {
LOGGER.log(Level.SEVERE, "Can not open file at startup", e);
}
});
}
}
@Override
public void stop() throws Exception {
super.stop();
this.mainController.get().closeAllPresentations(true);
deleteTemporaryFiles();
stopInternalServer();
stopOSGIManager();
}
/**
* Deletes temporary files older than the configuration parameter {@link GlobalConfiguration#TEMPORARY_FILES_MAX_AGE_PARAMETER}.
*/
private void deleteTemporaryFiles() {
if(GlobalConfiguration.canDeleteTemporaryFiles()) {
LOGGER.info("Cleaning temporary files");
final File tempDirectory = new File(System.getProperty("java.io.tmpdir"));
Arrays.stream(tempDirectory.listFiles())
.filter(file -> file.getName().startsWith("sfx-"))
.filter(DateTimeUtils.getFilterForFilesOlderThanGivenDays(GlobalConfiguration.getTemporaryFilesMaxAge()))
.forEach(file -> {
try {
Files.walkFileTree(file.toPath(), new DeleteFileVisitor());
} catch (IOException e) {
LOGGER.log(Level.SEVERE,
String.format("Can not delete temporary file %1$s", file.getAbsolutePath()),
e);
}
});
}
}
/**
* Stop the internal server if it is running.
*/
private void stopInternalServer() {
if(SlideshowFXServer.getSingleton() != null) {
LOGGER.info("Closing the internal server");
SlideshowFXServer.getSingleton().stop();
}
}
/**
* Stops the OSGI manager. If some {@link IHostingConnector} are registered, disconnect from them.
*/
private void stopOSGIManager() {
this.stopHostingConnectors();
LOGGER.info("Stopping the OSGi manager");
OSGiManager.getInstance().stop();
}
/**
* Disconnect all hosting connectors if they are running.
*/
private void stopHostingConnectors() {
final List<IHostingConnector> connectors = OSGiManager.getInstance().getInstalledServices(IHostingConnector.class);
if(!connectors.isEmpty()) {
LOGGER.info("Disconnecting from all hosting connectors");
connectors.forEach(hostingConnector -> hostingConnector.disconnect());
}
}
public static ReadOnlyObjectProperty<Stage> stageProperty() { return stage; }
public static Stage getStage() { return stageProperty().get(); }
public static void main(String[] args) {
SlideshowFX.launch(args);
}
}