1 package de.spiritscorp.datasync.io;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.io.IOException;
24 import java.io.OutputStream;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.nio.file.Paths;
28 import java.nio.file.StandardOpenOption;
29 import java.nio.file.attribute.FileTime;
30 import java.util.HashMap;
31 import java.util.Map;
32
33 import jakarta.json.Json;
34 import jakarta.json.JsonException;
35 import jakarta.json.JsonObject;
36 import jakarta.json.JsonObjectBuilder;
37 import jakarta.json.JsonReader;
38 import jakarta.json.JsonValue;
39 import jakarta.json.JsonWriter;
40 import jakarta.json.JsonWriterFactory;
41 import jakarta.json.stream.JsonGenerator;
42
43 import de.spiritscorp.datasync.model.FileAttributes;
44
45
46
47
48
49 class IOSyncMap {
50
51
52 private final Path jobSyncMapPath;
53
54
55
56
57 IOSyncMap( final String jobName ) {
58 this.jobSyncMapPath = PreferenceManager.getInstance().getConfigPath().getParent().resolve( "syncMap_" + jobName + ".json" );
59 }
60
61
62
63
64
65
66
67
68
69
70
71 boolean loadSyncMap( final Map<Path, FileAttributes> syncMap ) {
72 if( !syncMap.isEmpty() || !Files.exists( jobSyncMapPath ) ) { return false; }
73 try( JsonReader jsonReader = Json.createReader( Files.newInputStream( jobSyncMapPath, StandardOpenOption.READ ) ) ) {
74 final JsonObject jsonObject = jsonReader.readObject();
75
76 for( final Map.Entry<String, JsonValue> entry : jsonObject.entrySet() ) {
77 final JsonObject objectEntry = entry.getValue().asJsonObject();
78 final FileAttributes fileAttributes = new FileAttributes(
79 Paths.get( objectEntry.getString( "relativeFilePath" ) ),
80 objectEntry.getString( "createTimeString" ),
81 FileTime.fromMillis( Long.parseLong( objectEntry.get( "createTime" ).toString() ) ),
82 objectEntry.getString( "modTimeString" ),
83 FileTime.fromMillis( Long.parseLong( objectEntry.get( "modTime" ).toString() ) ),
84 Long.parseLong( objectEntry.get( "size" ).toString() ),
85 objectEntry.getString( "fileHash" ) );
86 syncMap.put( Paths.get( objectEntry.getString( "relativeFilePath" ) ), fileAttributes );
87 }
88 return true;
89 }catch( final IllegalArgumentException | UnsupportedOperationException | SecurityException | IOException e ) {
90
91 Debug.printDebug( "[IO Sync Map Error] File system or configuration failure while opening stream: %s", e.getMessage() );
92 Debug.printException( this.getClass(), e );
93 return false;
94
95 }catch( final JsonException exception ) {
96
97 Debug.printDebug( "[IO Sync Map Error] JSON processing or syntax error: %s", exception.getMessage() );
98 Debug.printException( this.getClass(), exception );
99 return false;
100
101 }catch( final IllegalStateException exception ) {
102
103 Debug.printDebug( "[IO Sync Map Error] Parser state conflict: %s", exception.getMessage() );
104 Debug.printException( this.getClass(), exception );
105 return false;
106 }
107 }
108
109
110
111
112
113
114
115
116 void writeSyncMap( final Map<Path, FileAttributes> syncMap ) {
117 try( OutputStream outputStream = Files.newOutputStream( jobSyncMapPath, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING ) ) {
118 final HashMap<String, Boolean> config = new HashMap<>();
119 config.put( JsonGenerator.PRETTY_PRINTING, true );
120 final JsonWriterFactory jWriterFactory = Json.createWriterFactory( config );
121
122 final JsonObject jsonObject = createJsonObject( syncMap );
123 final JsonWriter jsonWriter = jWriterFactory.createWriter( outputStream );
124 jsonWriter.write( jsonObject );
125 jsonWriter.close();
126 }catch( final IOException exception ) {
127 Debug.printDebug( "[IO Sync Map Error] File system or configuration failure while writing file: %s", exception.getMessage() );
128 Debug.printException( this.getClass(), exception );
129 }
130 }
131
132
133
134
135
136
137
138
139
140
141 boolean deleteSyncMap() {
142 try {
143 if( Files.deleteIfExists( jobSyncMapPath ) ) {
144 Debug.printDebug( "[IO Sync Map] Successfully deleted sync map file: %s", jobSyncMapPath.getFileName().toString() );
145 }
146 return true;
147 }catch( final IOException exception ) {
148 Debug.printDebug( "[IO Sync Map Error] File system failure while deleting file: %s", exception.getMessage() );
149 Debug.printException( this.getClass(), exception );
150 return false;
151 }
152 }
153
154
155
156
157
158
159
160
161
162 private JsonObject createJsonObject( final Map<Path, FileAttributes> syncMap ) {
163 final JsonObjectBuilder joBuilder = Json.createObjectBuilder();
164 for( final Map.Entry<Path, FileAttributes> entry : syncMap.entrySet() ) {
165 final JsonObject jsonObject = Json.createObjectBuilder()
166 .add( "relativeFilePath", entry.getValue().getRelativeFilePath().toString() )
167 .add( "fileHash", entry.getValue().getFileHash() )
168 .add( "modTimeString", entry.getValue().getModTimeString() )
169 .add( "createTime", entry.getValue().getCreateTime().toMillis() )
170 .add( "modTime", entry.getValue().getModTime().toMillis() )
171 .add( "size", entry.getValue().getSize() )
172 .add( "createTimeString", entry.getValue().getCreateTimeString() )
173 .build();
174 joBuilder.add( entry.getValue().getRelativeFilePath().toString(), jsonObject );
175 }
176 return joBuilder.build();
177 }
178 }