]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.fileimport/src/org/simantics/fileimport/FileImportService.java
Sync git svn branch with SVN repository r33249.
[simantics/platform.git] / bundles / org.simantics.fileimport / src / org / simantics / fileimport / FileImportService.java
1 package org.simantics.fileimport;\r
2 \r
3 import java.io.IOException;\r
4 import java.io.InputStream;\r
5 import java.io.OutputStream;\r
6 import java.nio.file.Files;\r
7 import java.nio.file.Path;\r
8 import java.nio.file.Paths;\r
9 import java.util.ArrayList;\r
10 import java.util.Collections;\r
11 import java.util.HashMap;\r
12 import java.util.List;\r
13 import java.util.Map;\r
14 import java.util.Optional;\r
15 import java.util.Properties;\r
16 import java.util.function.Consumer;\r
17 \r
18 import org.osgi.framework.InvalidSyntaxException;\r
19 import org.osgi.framework.ServiceReference;\r
20 import org.simantics.fileimport.dropins.FileImportDropins;\r
21 \r
22 /**\r
23  * Utility class for Simantics File import functions\r
24  * \r
25  * @author Jani Simomaa\r
26  *\r
27  */\r
28 public class FileImportService {\r
29 \r
30     private FileImportService() {}\r
31     \r
32     public static final String DB_FILE = ".simanticsdb";\r
33 \r
34     private static List<IGenericFileImport> getFileImportServices() {\r
35         ServiceReference<?>[] serviceReferences = new ServiceReference<?>[0];\r
36         try {\r
37             serviceReferences = Activator.getContext().getAllServiceReferences(IGenericFileImport.class.getName(),\r
38                     null);\r
39         } catch (InvalidSyntaxException e) {\r
40             e.printStackTrace();\r
41         }\r
42         if (serviceReferences.length == 0)\r
43             return Collections.emptyList();\r
44 \r
45         List<IGenericFileImport> services = new ArrayList<>(serviceReferences.length);\r
46         for (ServiceReference<?> reference : serviceReferences) {\r
47             IGenericFileImport service = (IGenericFileImport) Activator.getContext().getService(reference);\r
48             services.add(service);\r
49         }\r
50         return services;\r
51     }\r
52 \r
53     /**\r
54      * Lists all supported file extensions which have a registered service for handling the import\r
55      * \r
56      * @return Map containing the extension and the description of the extension in that order\r
57      */\r
58     public static Map<String, String> supportedExtensionsWithFilters() {\r
59         List<IGenericFileImport> services = getFileImportServices();\r
60         Map<String, String> extensionsWithFilters = new HashMap<>();\r
61         for (IGenericFileImport service : services)\r
62             extensionsWithFilters.putAll(service.allowedExtensionsWithFilters());\r
63 \r
64         return extensionsWithFilters;\r
65     }\r
66 \r
67     /**\r
68      * Method that performs the import of the given file. This method is called when e.g. {@link FileImportDropins} watcher detects {@link java.nio.file.StandardWatchEventKinds.ENTRY_CREATE} operation\r
69      * \r
70      * @param file Path file to be imported\r
71      * @param callback Optional callback which can be used to catch Throwables thrown in the import process\r
72      */\r
73     public static void performFileImport(Path file, Optional<Consumer<Throwable>> callback) {\r
74         if (file.getFileName().toString().equals(DB_FILE))\r
75             return;\r
76         Optional<IGenericFileImport> serviceOp = findServiceForFileExtension(file);\r
77         serviceOp.ifPresent(service -> {\r
78             try {\r
79                 Optional<String> resource = service.perform(file);\r
80                 saveResourceForPath(file, resource);\r
81             } catch (Throwable t) {\r
82                 if (callback.isPresent()) {\r
83                     callback.get().accept(t);\r
84                 } else {\r
85                     t.printStackTrace();\r
86                 }\r
87             }\r
88         });\r
89     }\r
90 \r
91     \r
92     /**\r
93      * Remove the entity that matches the file. This method is called when e.g. the {@link FileImportDropins} watcher detects {@link java.nio.file.StandardWatchEventKinds.ENTRY_DELETE} operation\r
94      * \r
95      * @param file Path file that was deleted\r
96      * @param callback Optional callback to catch Throwables thrown during the deletion process\r
97      */\r
98     public static void removeResourceForFile(Path file, Optional<Consumer<Throwable>> callback) {\r
99         Optional<IGenericFileImport> serviceOp = findServiceForFileExtension(file);\r
100         serviceOp.ifPresent(service -> {\r
101             try {\r
102                 Optional<String> resource = getResourceForPath(file);\r
103                 if (!resource.isPresent())\r
104                     return;\r
105                 service.remove(resource.get());\r
106                 removeResourceForPath(file);\r
107             } catch (Throwable t) {\r
108                 if (callback.isPresent()) {\r
109                     callback.get().accept(t);\r
110                 } else {\r
111                     t.printStackTrace();\r
112                 }\r
113             }\r
114         });\r
115     }\r
116     \r
117     public static void removeFileForResource(long id, Optional<Consumer<Throwable>> callback) {\r
118         Optional<Path> fileOp;\r
119         try {\r
120             fileOp = findPathForId(id);\r
121         } catch (IOException e) {\r
122             e.printStackTrace();\r
123             return;\r
124         }\r
125         if (!fileOp.isPresent())\r
126             return;\r
127         Path file = fileOp.get();\r
128         Optional<IGenericFileImport> serviceOp = findServiceForFileExtension(file);\r
129         serviceOp.ifPresent(service -> {\r
130             try {\r
131                 Optional<String> resource = getResourceForPath(file);\r
132                 if (!resource.isPresent())\r
133                     return;\r
134                 service.remove(resource.get());\r
135                 removeResourceForPath(file);\r
136                 try {\r
137                     Files.delete(file);\r
138                 } catch (IOException e) {\r
139                     Files.delete(file);\r
140                 }\r
141             } catch (Throwable t) {\r
142                 if (callback.isPresent()) {\r
143                     callback.get().accept(t);\r
144                 } else {\r
145                     t.printStackTrace();\r
146                 }\r
147             }\r
148         });\r
149     }\r
150 \r
151     private static Optional<Path> findPathForId(long id) throws IOException {\r
152         Path db = Activator.getDropinsFolder().resolve(DB_FILE);\r
153         if (!Files.exists(db))\r
154             Files.createFile(db);\r
155         Properties props = new Properties();\r
156         try (InputStream stream = Files.newInputStream(db)) {\r
157             props.load(stream);\r
158         }\r
159         for (Map.Entry<Object, Object> entry : props.entrySet()) {\r
160             Long value = Long.valueOf(entry.getValue().toString());\r
161             if (value.longValue() == id) {\r
162                 String key = (String) entry.getKey();\r
163                 return Optional.of(Paths.get(key));\r
164             }\r
165         }\r
166         return Optional.empty();\r
167     }\r
168 \r
169     static final String FOLDER = "_folder_";\r
170     \r
171     /**\r
172      * Method for finding a File Import service for the given file based on the file extension\r
173      * \r
174      * @param file Path file for which the import service is looked for\r
175      * @return Optiona IGenerigFileImport service which is able to handle the import of this type of file\r
176      */\r
177     public static Optional<IGenericFileImport> findServiceForFileExtension(Path file) {\r
178         String extension = "";\r
179 \r
180         int i = file.getFileName().toString().lastIndexOf('.');\r
181         if (i > 0) {\r
182             extension = file.getFileName().toString().substring(i);\r
183         } else {\r
184             // Handle case that file is actually a directory\r
185             if (Files.isDirectory(file) || !Files.isRegularFile(file)) {\r
186                 extension = FOLDER;\r
187             }\r
188         }\r
189 \r
190         List<IGenericFileImport> services = getFileImportServices();\r
191         for (IGenericFileImport service : services) {\r
192             for (Map.Entry<String, String> entry : service.allowedExtensionsWithFilters().entrySet()) {\r
193                 String possibleExtensions = entry.getKey();\r
194                 if (possibleExtensions.startsWith("*"))\r
195                     possibleExtensions = possibleExtensions.substring(1);\r
196                 if (possibleExtensions.equals(extension) || possibleExtensions.isEmpty()) {\r
197                     if (extension.equals(FOLDER) && possibleExtensions.equals(FOLDER)) {\r
198                         return Optional.of(service);\r
199                     } else if (!extension.isEmpty() && !extension.equals(FOLDER)){\r
200                         return Optional.of(service);\r
201                     }\r
202                 }\r
203             }\r
204         }\r
205         return Optional.empty();\r
206     }\r
207     \r
208     /**\r
209      * Method for listing all current paths and their corresponding identifiers in Simantics database\r
210      * \r
211      * @return Map containing \r
212      */\r
213     public static Map<String, String> getPathsAndResources() {\r
214         try {\r
215             Path db = Activator.getDropinsFolder().resolve(DB_FILE);\r
216             if (!Files.exists(db))\r
217                 Files.createFile(db);\r
218             Properties props = new Properties();\r
219             try (InputStream stream = Files.newInputStream(db)) {\r
220                 props.load(stream);\r
221             }\r
222             Map<String, String> map = new HashMap<>();\r
223             for (Map.Entry<Object, Object> entry : props.entrySet()) {\r
224                 String value = (String) entry.getValue();\r
225                 String key = (String) entry.getKey();\r
226                 map.put(key, value);\r
227             }\r
228             return map;\r
229         } catch (IOException e) {\r
230             e.printStackTrace();\r
231             return Collections.emptyMap();\r
232         }\r
233     }\r
234 \r
235     private static void saveResourceForPath(Path file, Optional<String> resource) {\r
236         resource.ifPresent(res -> {\r
237             try {\r
238                 Path db = Activator.getDropinsFolder().resolve(DB_FILE);\r
239                 if (!Files.exists(db))\r
240                     Files.createFile(db);\r
241                 Properties props = new Properties();\r
242                 try (InputStream stream = Files.newInputStream(db)) {\r
243                     props.load(stream);\r
244                 }\r
245                 props.put(file.getFileName().toString(), resource.get());\r
246                 try (OutputStream stream = Files.newOutputStream(db)) {\r
247                     props.store(stream, null);\r
248                 }\r
249             } catch (IOException e) {\r
250                 e.printStackTrace();\r
251             }\r
252         });\r
253     }\r
254 \r
255     private static void removeResourceForPath(Path file) throws IOException {\r
256         Path db = Activator.getDropinsFolder().resolve(DB_FILE);\r
257         if (!Files.exists(db))\r
258             Files.createFile(db);\r
259         Properties props = new Properties();\r
260         try (InputStream stream = Files.newInputStream(db)) {\r
261             props.load(stream);\r
262         }\r
263         props.remove(file.getFileName().toString());\r
264         try (OutputStream stream = Files.newOutputStream(db)) {\r
265             props.store(stream, null);\r
266         }\r
267     }\r
268     \r
269     private static Optional<String> getResourceForPath(Path file) throws IOException {\r
270         Path db = Activator.getDropinsFolder().resolve(DB_FILE);\r
271         if (!Files.exists(db))\r
272             Files.createFile(db);\r
273         Properties props = new Properties();\r
274         try (InputStream stream = Files.newInputStream(db)) {\r
275             props.load(stream);\r
276         }\r
277         String value = props.getProperty(file.getFileName().toString());\r
278         if (value == null)\r
279             return Optional.empty();\r
280         return Optional.of(value);\r
281     }\r
282 }\r