]> 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 r33216.
[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             } catch (Throwable t) {\r
137                 if (callback.isPresent()) {\r
138                     callback.get().accept(t);\r
139                 } else {\r
140                     t.printStackTrace();\r
141                 }\r
142             }\r
143         });\r
144     }\r
145 \r
146     private static Optional<Path> findPathForId(long id) throws IOException {\r
147         Path db = Activator.getDropinsFolder().resolve(DB_FILE);\r
148         if (!Files.exists(db))\r
149             Files.createFile(db);\r
150         Properties props = new Properties();\r
151         try (InputStream stream = Files.newInputStream(db)) {\r
152             props.load(stream);\r
153         }\r
154         for (Map.Entry<Object, Object> entry : props.entrySet()) {\r
155             Long value = Long.valueOf(entry.getValue().toString());\r
156             if (value.longValue() == id) {\r
157                 String key = (String) entry.getKey();\r
158                 return Optional.of(Paths.get(key));\r
159             }\r
160         }\r
161         return Optional.empty();\r
162     }\r
163 \r
164     static final String FOLDER = "_folder_";\r
165     \r
166     /**\r
167      * Method for finding a File Import service for the given file based on the file extension\r
168      * \r
169      * @param file Path file for which the import service is looked for\r
170      * @return Optiona IGenerigFileImport service which is able to handle the import of this type of file\r
171      */\r
172     public static Optional<IGenericFileImport> findServiceForFileExtension(Path file) {\r
173         String extension = "";\r
174 \r
175         int i = file.getFileName().toString().lastIndexOf('.');\r
176         if (i > 0) {\r
177             extension = file.getFileName().toString().substring(i);\r
178         } else {\r
179             // Handle case that file is actually a directory\r
180             if (Files.isDirectory(file) || !Files.isRegularFile(file)) {\r
181                 extension = FOLDER;\r
182             }\r
183         }\r
184 \r
185         List<IGenericFileImport> services = getFileImportServices();\r
186         for (IGenericFileImport service : services) {\r
187             for (Map.Entry<String, String> entry : service.allowedExtensionsWithFilters().entrySet()) {\r
188                 String possibleExtensions = entry.getKey();\r
189                 if (possibleExtensions.startsWith("*"))\r
190                     possibleExtensions = possibleExtensions.substring(1);\r
191                 if (possibleExtensions.equals(extension) || possibleExtensions.isEmpty()) {\r
192                     if (extension.equals(FOLDER) && possibleExtensions.equals(FOLDER)) {\r
193                         return Optional.of(service);\r
194                     } else if (!extension.isEmpty() && !extension.equals(FOLDER)){\r
195                         return Optional.of(service);\r
196                     }\r
197                 }\r
198             }\r
199         }\r
200         return Optional.empty();\r
201     }\r
202     \r
203     /**\r
204      * Method for listing all current paths and their corresponding identifiers in Simantics database\r
205      * \r
206      * @return Map containing \r
207      */\r
208     public static Map<String, String> getPathsAndResources() {\r
209         try {\r
210             Path db = Activator.getDropinsFolder().resolve(DB_FILE);\r
211             if (!Files.exists(db))\r
212                 Files.createFile(db);\r
213             Properties props = new Properties();\r
214             try (InputStream stream = Files.newInputStream(db)) {\r
215                 props.load(stream);\r
216             }\r
217             Map<String, String> map = new HashMap<>();\r
218             for (Map.Entry<Object, Object> entry : props.entrySet()) {\r
219                 String value = (String) entry.getValue();\r
220                 String key = (String) entry.getKey();\r
221                 map.put(key, value);\r
222             }\r
223             return map;\r
224         } catch (IOException e) {\r
225             e.printStackTrace();\r
226             return Collections.emptyMap();\r
227         }\r
228     }\r
229 \r
230     private static void saveResourceForPath(Path file, Optional<String> resource) {\r
231         resource.ifPresent(res -> {\r
232             try {\r
233                 Path db = Activator.getDropinsFolder().resolve(DB_FILE);\r
234                 if (!Files.exists(db))\r
235                     Files.createFile(db);\r
236                 Properties props = new Properties();\r
237                 try (InputStream stream = Files.newInputStream(db)) {\r
238                     props.load(stream);\r
239                 }\r
240                 props.put(file.getFileName().toString(), resource.get());\r
241                 try (OutputStream stream = Files.newOutputStream(db)) {\r
242                     props.store(stream, null);\r
243                 }\r
244             } catch (IOException e) {\r
245                 e.printStackTrace();\r
246             }\r
247         });\r
248     }\r
249 \r
250     private static void removeResourceForPath(Path file) throws IOException {\r
251         Path db = Activator.getDropinsFolder().resolve(DB_FILE);\r
252         if (!Files.exists(db))\r
253             Files.createFile(db);\r
254         Properties props = new Properties();\r
255         try (InputStream stream = Files.newInputStream(db)) {\r
256             props.load(stream);\r
257         }\r
258         props.remove(file.getFileName().toString());\r
259         try (OutputStream stream = Files.newOutputStream(db)) {\r
260             props.store(stream, null);\r
261         }\r
262     }\r
263     \r
264     private static Optional<String> getResourceForPath(Path file) throws IOException {\r
265         Path db = Activator.getDropinsFolder().resolve(DB_FILE);\r
266         if (!Files.exists(db))\r
267             Files.createFile(db);\r
268         Properties props = new Properties();\r
269         try (InputStream stream = Files.newInputStream(db)) {\r
270             props.load(stream);\r
271         }\r
272         String value = props.getProperty(file.getFileName().toString());\r
273         if (value == null)\r
274             return Optional.empty();\r
275         return Optional.of(value);\r
276     }\r
277 }\r