]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics/src/org/simantics/BaselineCreatorApplication.java
Added -f SCL/Module/function argument for BaselineCreatorApplication
[simantics/platform.git] / bundles / org.simantics / src / org / simantics / BaselineCreatorApplication.java
1 package org.simantics;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.net.URL;
6 import java.nio.file.Files;
7 import java.nio.file.Path;
8 import java.time.LocalDateTime;
9 import java.time.format.DateTimeFormatter;
10
11 import org.eclipse.core.runtime.CoreException;
12 import org.eclipse.core.runtime.IProgressMonitor;
13 import org.eclipse.core.runtime.IStatus;
14 import org.eclipse.core.runtime.NullProgressMonitor;
15 import org.eclipse.core.runtime.Platform;
16 import org.eclipse.core.runtime.Status;
17 import org.eclipse.equinox.app.IApplication;
18 import org.eclipse.equinox.app.IApplicationContext;
19 import org.eclipse.osgi.service.datalocation.Location;
20 import org.simantics.application.arguments.Arguments;
21 import org.simantics.application.arguments.IArgumentFactory;
22 import org.simantics.application.arguments.IArgumentFactory.NoValueArgumentFactory;
23 import org.simantics.application.arguments.IArgumentFactory.StringArgumentFactory;
24 import org.simantics.application.arguments.IArguments;
25 import org.simantics.application.arguments.SimanticsArguments;
26 import org.simantics.internal.Activator;
27 import org.simantics.scl.runtime.SCLContext;
28 import org.simantics.scl.runtime.reporting.SCLReportingHandler;
29 import org.simantics.scl.runtime.tuple.Tuple0;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * @author Tuukka Lehtonen
35  * @since 1.34.0
36  */
37 public class BaselineCreatorApplication implements IApplication {
38
39         private static final Logger LOGGER = LoggerFactory.getLogger(BaselineCreatorApplication.class);
40
41         private static final IArgumentFactory<String> OUTPUT = new StringArgumentFactory("-o");
42         private static final IArgumentFactory<Boolean> VERBOSE = new NoValueArgumentFactory("-v");
43
44         /**
45          * The -f argument specifies an SCL function that shall be executed after the
46          * platform has been started and before the platform is shutdown.
47          * 
48          * <p>
49          * The function must be:
50          * <ol>
51          * <li>a parameterless function</li>
52          * <li>a function with <code>&lt;Proc&gt;</code> effect only</li>. It must internally invoke
53          * <code>syncWrite</code> etc. to have other effects.
54          * </ol>
55          * 
56          * <p>
57          * This means the function must have the following signature:
58          * <code>func :: <Proc> ()</code>
59          */
60         private static final IArgumentFactory<String> FUNCTION = new StringArgumentFactory("-f");
61
62         IArgumentFactory<?>[] accepted = {
63                         SimanticsArguments.RECOVERY_POLICY_FIX_ERRORS,
64                         SimanticsArguments.ONTOLOGY_RECOVERY_POLICY_REINSTALL,
65                         SimanticsArguments.DISABLE_INDEX,
66                         SimanticsArguments.DATABASE_ID,
67                         OUTPUT,
68                         VERBOSE,
69                         FUNCTION,
70         };
71
72         private static String currentLocalDateTimeStamp() {
73                 return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HHmm"));
74         }
75
76         private static Path constructOutputPath(Path workspace, IArguments parsedArgs) {
77                 if (parsedArgs.contains(OUTPUT)) {
78                         return workspace.resolve(parsedArgs.get(OUTPUT));
79                 } else {
80                         return workspace.resolve(workspace.getFileName().toString() + "-" + currentLocalDateTimeStamp() + ".zip");
81                 }
82         }
83
84         private static Path getInstanceLocation() throws CoreException, IOException {
85                 Location l = Platform.getInstanceLocation();
86                 if (l == null || l.isReadOnly())
87                         throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
88                                         "Workspace not defined. Use -data <path> argument to define where to place the baselining workspace."));
89
90                 URL workspaceUrl = l.getURL();
91                 Path workspacePath = new File(workspaceUrl.getPath()).toPath();
92                 Files.createDirectories(workspacePath);
93                 return workspacePath;
94         }
95
96         @Override
97         public Object start(IApplicationContext context) throws Exception {
98                 try {
99                         Path workspace = getInstanceLocation();
100
101                         String[] args = (String[]) context.getArguments().get("application.args");
102                         IArguments parsedArgs = Arguments.parse(args, accepted);
103
104                         Path output = constructOutputPath(workspace, parsedArgs);
105                         LOGGER.info("Selected output file: {} ", output);
106
107                         // Create database and indexes
108                         IProgressMonitor progress = parsedArgs.contains(VERBOSE)
109                                         ? new TimingProgressMonitor()
110                                         : new NullProgressMonitor();
111                         Simantics.startUpHeadless(parsedArgs, progress);
112
113                         if (parsedArgs.contains(FUNCTION)) {
114                                 String func = parsedArgs.get(FUNCTION);
115                                 String[] moduleAndFunc = splitFunction(func);
116                                 if (moduleAndFunc != null) {
117                                         try {
118                                                 LOGGER.info("Invoking SCL function {}/{}", moduleAndFunc[0], moduleAndFunc[1]);
119                                                 SCLContext.getCurrent().put(SCLReportingHandler.REPORTING_HANDLER, SCLReportingHandler.DEFAULT);
120                                                 Simantics.applySCL(moduleAndFunc[0], moduleAndFunc[1], Tuple0.INSTANCE);
121                                         } catch (Throwable t) {
122                                                 LOGGER.error("Invocation failed", t);
123                                         }
124                                 } else {
125                                         LOGGER.error("SCL function '{}' not invocable for baselining the database", func);
126                                 }
127                         }
128
129                         Simantics.shutdown(progress);
130
131                         // Create the baseline package file
132                         Path actualOutput = DatabaseBaselines.packageBaseline(workspace, output);
133                         System.out.println("OK " + actualOutput.normalize().toAbsolutePath());
134
135                         return IApplication.EXIT_OK;
136                 } catch (Exception e) {
137                         LOGGER.error("Baseline creation failed.", e);
138                         throw (Exception) e;
139                 } finally {
140                         System.exit(0);
141                 }
142         }
143
144         private String[] splitFunction(String func) {
145                 int l = func.lastIndexOf('/');
146                 if (l < 0)
147                         return null;
148                 return new String[] { func.substring(0, l), func.substring(l+1) };
149         }
150
151         @Override
152         public void stop() {
153         }
154
155 }