1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.prometheus.data;
18
19 import io.github.tonywasher.joceanus.gordianknot.api.factory.GordianFactory;
20 import io.github.tonywasher.joceanus.gordianknot.api.factory.GordianFactory.GordianFactoryLock;
21 import io.github.tonywasher.joceanus.gordianknot.util.GordianUtilities;
22 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataList;
23 import io.github.tonywasher.joceanus.metis.data.MetisDataResource;
24 import io.github.tonywasher.joceanus.metis.field.MetisFieldItem;
25 import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
26 import io.github.tonywasher.joceanus.metis.field.MetisFieldVersionedSet;
27 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
28 import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
29 import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
30 import io.github.tonywasher.joceanus.prometheus.data.PrometheusControlKeySet.PrometheusControlKeySetList;
31 import io.github.tonywasher.joceanus.prometheus.data.PrometheusCryptographyData.PrometheusControlKeyCtl;
32 import io.github.tonywasher.joceanus.prometheus.data.PrometheusCryptographyData.PrometheusControlKeySetCtl;
33 import io.github.tonywasher.joceanus.prometheus.data.PrometheusCryptographyData.PrometheusCryptographicDataSet;
34 import io.github.tonywasher.joceanus.prometheus.data.PrometheusData.PrometheusDataSetCtl;
35 import io.github.tonywasher.joceanus.prometheus.exc.PrometheusDataException;
36 import io.github.tonywasher.joceanus.prometheus.security.PrometheusSecurityPasswordManager;
37
38 import java.util.ArrayList;
39 import java.util.Iterator;
40 import java.util.List;
41
42
43
44
45
46
47
48 public final class PrometheusControlKey
49 extends PrometheusDataItem
50 implements PrometheusControlKeyCtl {
51
52
53
54 public static final String OBJECT_NAME = PrometheusCryptographyDataType.CONTROLKEY.getItemName();
55
56
57
58
59 public static final String LIST_NAME = PrometheusCryptographyDataType.CONTROLKEY.getListName();
60
61
62
63
64 public static final int LOCKLEN = GordianUtilities.getFactoryLockLen();
65
66
67
68
69 private static final MetisFieldVersionedSet<PrometheusControlKey> FIELD_DEFS = MetisFieldVersionedSet.newVersionedFieldSet(PrometheusControlKey.class);
70
71
72
73
74 static {
75 FIELD_DEFS.declareByteArrayField(PrometheusDataResource.CONTROLKEY_LOCKBYTES, LOCKLEN);
76 FIELD_DEFS.declareDateField(PrometheusDataResource.CONTROLKEY_CREATION);
77 FIELD_DEFS.declareDerivedVersionedField(PrometheusDataResource.CONTROLKEY_LOCK);
78 FIELD_DEFS.declareLocalField(PrometheusDataResource.CONTROLKEYSET_LIST, PrometheusControlKey::getControlKeySets);
79 }
80
81
82
83
84 public static final String NAME_DATABASE = PrometheusDataResource.CONTROLKEY_DATABASE.getValue();
85
86
87
88
89 private ControlKeySetCache theKeySetCache = new ControlKeySetCache();
90
91
92
93
94
95
96
97 private PrometheusControlKey(final PrometheusControlKeyList pList,
98 final PrometheusControlKey pSource) {
99
100 super(pList, pSource);
101 }
102
103
104
105
106
107
108
109
110 private PrometheusControlKey(final PrometheusControlKeyList pList,
111 final PrometheusDataValues pValues) throws OceanusException {
112
113 super(pList, pValues);
114
115
116 try {
117
118 Object myValue = pValues.getValue(PrometheusDataResource.CONTROLKEY_LOCKBYTES);
119 if (myValue instanceof byte[] ba) {
120 setValueFactoryLockBytes(ba);
121 }
122
123
124 myValue = pValues.getValue(PrometheusDataResource.CONTROLKEY_LOCK);
125 if (myValue instanceof GordianFactoryLock l) {
126 setValueFactoryLock(l);
127 } else if (getLockBytes() != null) {
128
129 final PrometheusDataSetCtl myData = getDataSet();
130 final PrometheusSecurityPasswordManager myPasswordMgr = myData.getPasswordMgr();
131
132
133 final GordianFactoryLock myLock = myPasswordMgr.resolveFactoryLock(getLockBytes(), NAME_DATABASE);
134
135
136 setValueFactoryLock(myLock);
137 }
138
139
140 myValue = pValues.getValue(PrometheusDataResource.CONTROLKEY_CREATION);
141 if (!(myValue instanceof OceanusDate)) {
142 myValue = new OceanusDate();
143 }
144 setValueCreationDate((OceanusDate) myValue);
145
146
147 } catch (OceanusException e) {
148
149 throw new PrometheusDataException(this, ERROR_CREATEITEM, e);
150 }
151 }
152
153
154
155
156
157
158
159
160
161 private PrometheusControlKey(final PrometheusControlKeyList pList) throws OceanusException {
162
163 super(pList, 0);
164
165
166 try {
167
168 final PrometheusDataSetCtl myData = getDataSet();
169 final PrometheusSecurityPasswordManager myPasswordMgr = myData.getPasswordMgr();
170
171
172 final GordianFactoryLock myLock = myPasswordMgr.newFactoryLock(NAME_DATABASE);
173
174
175 setValueFactoryLockBytes(myLock.getLockBytes());
176 setValueFactoryLock(myLock);
177
178
179 allocateControlKeySets(myData);
180
181
182 setValueCreationDate(new OceanusDate());
183
184
185 } catch (OceanusException e) {
186
187 throw new PrometheusDataException(this, ERROR_CREATEITEM, e);
188 }
189 }
190
191
192
193
194
195
196
197
198
199 private PrometheusControlKey(final PrometheusControlKey pKey) throws OceanusException {
200
201 super(pKey.getList(), 0);
202
203
204 try {
205
206 final PrometheusDataSetCtl myData = getDataSet();
207 final PrometheusSecurityPasswordManager myPasswordMgr = myData.getPasswordMgr();
208
209
210 final GordianFactory myFactory = myPasswordMgr.getSecurityFactory();
211 myFactory.reSeedRandom();
212
213
214 final GordianFactoryLock myLock = myPasswordMgr.similarFactoryLock(pKey.getFactoryLock());
215
216
217 setValueFactoryLockBytes(myLock.getLockBytes());
218 setValueFactoryLock(myLock);
219
220
221 allocateControlKeySets(myData);
222
223
224 } catch (OceanusException e) {
225
226 throw new PrometheusDataException(this, ERROR_CREATEITEM, e);
227 }
228 }
229
230 @Override
231 public MetisFieldSetDef getDataFieldSet() {
232 return FIELD_DEFS;
233 }
234
235
236
237
238
239
240 private ControlKeySetCache getControlKeySets() {
241 return theKeySetCache;
242 }
243
244
245
246
247
248
249 public byte[] getLockBytes() {
250 return getValues().getValue(PrometheusDataResource.CONTROLKEY_LOCKBYTES, byte[].class);
251 }
252
253
254
255
256
257
258 public GordianFactoryLock getFactoryLock() {
259 return getValues().getValue(PrometheusDataResource.CONTROLKEY_LOCK, GordianFactoryLock.class);
260 }
261
262 @Override
263 public GordianFactory getSecurityFactory() {
264 final GordianFactoryLock myLock = getFactoryLock();
265 return myLock == null ? null : myLock.getFactory();
266 }
267
268
269
270
271
272
273 public OceanusDate getCreationDate() {
274 return getValues().getValue(PrometheusDataResource.CONTROLKEY_CREATION, OceanusDate.class);
275 }
276
277
278
279
280
281
282
283 private void setValueFactoryLockBytes(final byte[] pValue) throws OceanusException {
284 getValues().setValue(PrometheusDataResource.CONTROLKEY_LOCKBYTES, pValue);
285 }
286
287
288
289
290
291
292
293 private void setValueFactoryLock(final GordianFactoryLock pValue) throws OceanusException {
294 getValues().setValue(PrometheusDataResource.CONTROLKEY_LOCK, pValue);
295 }
296
297
298
299
300
301
302
303 private void setValueCreationDate(final OceanusDate pValue) throws OceanusException {
304 getValues().setValue(PrometheusDataResource.CONTROLKEY_CREATION, pValue);
305 }
306
307 @Override
308 public PrometheusControlKey getBase() {
309 return (PrometheusControlKey) super.getBase();
310 }
311
312 @Override
313 public PrometheusControlKeyList getList() {
314 return (PrometheusControlKeyList) super.getList();
315 }
316
317
318
319
320
321
322 PrometheusDataKeySet getNextDataKeySet() {
323 return theKeySetCache.getNextDataKeySet();
324 }
325
326 @Override
327 public int compareValues(final PrometheusDataItem pThat) {
328
329 return 0;
330 }
331
332
333
334
335
336
337
338 private void allocateControlKeySets(final PrometheusDataSetCtl pData) throws OceanusException {
339
340 final PrometheusControlKeySetList mySets = pData.getDataList(PrometheusCryptographyDataType.CONTROLKEYSET, PrometheusControlKeySetList.class);
341 setNewVersion();
342
343
344 final int myNumKeySets = pData.getNumActiveKeySets();
345 for (int i = 0; i < myNumKeySets; i++) {
346
347 final PrometheusControlKeySet mySet = new PrometheusControlKeySet(mySets, this);
348 mySet.setNewVersion();
349 mySets.add(mySet);
350
351
352 theKeySetCache.registerControlKeySet(mySet);
353 }
354 }
355
356
357
358
359 void deleteControlSet() {
360
361 theKeySetCache.deleteControlKeySets();
362
363
364 setDeleted(true);
365 }
366
367
368
369
370
371
372
373 void updateFactoryLock(final String pSource) throws OceanusException {
374
375 final PrometheusDataSetCtl myData = getDataSet();
376 final PrometheusSecurityPasswordManager myPasswordMgr = myData.getPasswordMgr();
377
378
379 final GordianFactoryLock myLock = myPasswordMgr.newFactoryLock(getSecurityFactory(), pSource);
380
381
382 pushHistory();
383
384
385 setValueFactoryLock(myLock);
386 setValueFactoryLockBytes(myLock.getLockBytes());
387 myData.setVersion(myData.getVersion() + 1);
388
389
390 checkForHistory();
391 }
392
393 @Override
394 public void registerControlKeySet(final PrometheusControlKeySetCtl pKeySet) {
395
396 theKeySetCache.registerControlKeySet((PrometheusControlKeySet) pKeySet);
397 }
398
399
400
401
402 public static class PrometheusControlKeyList
403 extends PrometheusDataList<PrometheusControlKey> {
404
405
406
407 private static final MetisFieldSet<PrometheusControlKeyList> FIELD_DEFS = MetisFieldSet.newFieldSet(PrometheusControlKeyList.class);
408
409
410
411
412
413
414 protected PrometheusControlKeyList(final PrometheusDataSetCtl pData) {
415 this(pData, PrometheusListStyle.CORE);
416 }
417
418
419
420
421
422
423
424 protected PrometheusControlKeyList(final PrometheusDataSetCtl pData,
425 final PrometheusListStyle pStyle) {
426 super(PrometheusControlKey.class, pData, PrometheusCryptographyDataType.CONTROLKEY, pStyle);
427 }
428
429
430
431
432
433
434 private PrometheusControlKeyList(final PrometheusControlKeyList pSource) {
435 super(pSource);
436 }
437
438 @Override
439 public MetisFieldSet<PrometheusControlKeyList> getDataFieldSet() {
440 return FIELD_DEFS;
441 }
442
443 @Override
444 public String listName() {
445 return LIST_NAME;
446 }
447
448 @Override
449 public MetisFieldSet<PrometheusControlKey> getItemFields() {
450 return PrometheusControlKey.FIELD_DEFS;
451 }
452
453 @Override
454 public boolean includeDataXML() {
455 return false;
456 }
457
458 @Override
459 public PrometheusCryptographicDataSet getDataSet() {
460 return (PrometheusCryptographicDataSet) super.getDataSet();
461 }
462
463 @Override
464 protected PrometheusControlKeyList getEmptyList(final PrometheusListStyle pStyle) {
465 final PrometheusControlKeyList myList = new PrometheusControlKeyList(this);
466 myList.setStyle(pStyle);
467 return myList;
468 }
469
470 @Override
471 public PrometheusControlKeyList deriveList(final PrometheusListStyle pStyle) throws OceanusException {
472 return (PrometheusControlKeyList) super.deriveList(pStyle);
473 }
474
475 @Override
476 public PrometheusControlKeyList deriveDifferences(final PrometheusDataSetCtl pDataSet,
477 final PrometheusDataList<?> pOld) {
478 return (PrometheusControlKeyList) super.deriveDifferences(pDataSet, pOld);
479 }
480
481 @Override
482 public PrometheusControlKey addCopyItem(final PrometheusDataItem pItem) {
483
484 if (!(pItem instanceof PrometheusControlKey)) {
485 return null;
486 }
487
488
489 final PrometheusControlKey myKey = new PrometheusControlKey(this, (PrometheusControlKey) pItem);
490 add(myKey);
491 return myKey;
492 }
493
494 @Override
495 public PrometheusControlKey addNewItem() {
496 throw new UnsupportedOperationException();
497 }
498
499 @Override
500 public PrometheusControlKey addValuesItem(final PrometheusDataValues pValues) throws OceanusException {
501
502 final PrometheusControlKey myKey = new PrometheusControlKey(this, pValues);
503
504
505 if (!isIdUnique(myKey.getIndexedId())) {
506 myKey.addError(ERROR_DUPLICATE, MetisDataResource.DATA_ID);
507 throw new PrometheusDataException(myKey, ERROR_VALIDATION);
508 }
509
510
511 add(myKey);
512
513
514 return myKey;
515 }
516
517
518
519
520
521
522
523 public PrometheusControlKey createNewKeySet() throws OceanusException {
524
525 final PrometheusControlKey myKey = new PrometheusControlKey(this);
526
527
528 add(myKey);
529 return myKey;
530 }
531
532
533
534
535
536
537
538
539 public PrometheusControlKey cloneItem(final PrometheusControlKey pSource) throws OceanusException {
540
541 final PrometheusControlKey myKey = new PrometheusControlKey(pSource);
542
543
544 add(myKey);
545 return myKey;
546 }
547
548
549
550
551
552
553
554 protected void initialiseSecurity(final PrometheusCryptographicDataSet pDatabase) throws OceanusException {
555
556 final PrometheusCryptographicDataSet myData = getDataSet();
557 final PrometheusControlKey myDatabaseKey = (PrometheusControlKey) pDatabase.getControlKey();
558 final PrometheusControlKey myKey;
559
560
561 if (myDatabaseKey != null) {
562
563 myKey = cloneControlKey(myDatabaseKey);
564
565
566 } else {
567
568 myKey = createNewKeySet();
569 }
570
571
572 myData.getControl().setControlKey(myKey);
573 }
574
575
576
577
578 protected void purgeOldControlKeys() {
579
580 final PrometheusCryptographicDataSet myData = getDataSet();
581 final PrometheusControlKeyCtl myKey = myData.getControl().getControlKey();
582
583
584 final Iterator<PrometheusControlKey> myIterator = iterator();
585 while (myIterator.hasNext()) {
586 final PrometheusControlKey myCurr = myIterator.next();
587
588
589 if (!myKey.equals(myCurr)) {
590 myCurr.deleteControlSet();
591 }
592 }
593 }
594
595
596
597
598
599
600
601
602 private PrometheusControlKey cloneControlKey(final PrometheusControlKey pControlKey) throws OceanusException {
603
604 final PrometheusDataValues myValues = new PrometheusDataValues(OBJECT_NAME);
605 myValues.addValue(MetisDataResource.DATA_ID, pControlKey.getIndexedId());
606 myValues.addValue(PrometheusDataResource.CONTROLKEY_LOCKBYTES, pControlKey.getLockBytes());
607 myValues.addValue(PrometheusDataResource.CONTROLKEY_CREATION, pControlKey.getCreationDate());
608 myValues.addValue(PrometheusDataResource.CONTROLKEY_LOCK, pControlKey.getFactoryLock());
609
610
611 final PrometheusControlKey myControl = addValuesItem(myValues);
612
613
614 final PrometheusDataSetCtl myData = getDataSet();
615 final PrometheusControlKeySetList myKeySets
616 = myData.getDataList(PrometheusCryptographyDataType.CONTROLKEYSET, PrometheusControlKeySetList.class);
617
618
619 final ControlKeySetCache mySource = pControlKey.getControlKeySets();
620 myControl.theKeySetCache = mySource.cloneControlKeySetCache(myControl, myKeySets);
621
622
623 return myControl;
624 }
625
626 @Override
627 public void postProcessOnLoad() throws OceanusException {
628
629 reSort();
630 }
631
632 @Override
633 protected PrometheusDataMapItem allocateDataMap() {
634
635 throw new UnsupportedOperationException();
636 }
637 }
638
639
640
641
642 private static final class ControlKeySetCache
643 implements MetisFieldItem, MetisDataList<PrometheusControlKeySet> {
644
645
646
647 private static final MetisFieldSet<ControlKeySetCache> FIELD_DEFS = MetisFieldSet.newFieldSet(ControlKeySetCache.class);
648
649
650
651
652 static {
653 FIELD_DEFS.declareLocalField(MetisDataResource.LIST_SIZE, ControlKeySetCache::size);
654 }
655
656
657
658
659 private final List<PrometheusControlKeySet> theList;
660
661
662
663
664 private Iterator<PrometheusControlKeySet> theIterator;
665
666
667
668
669 ControlKeySetCache() {
670 theList = new ArrayList<>();
671 }
672
673 @Override
674 public MetisFieldSet<ControlKeySetCache> getDataFieldSet() {
675 return FIELD_DEFS;
676 }
677
678 @Override
679 public List<PrometheusControlKeySet> getUnderlyingList() {
680 return theList;
681 }
682
683 @Override
684 public String formatObject(final OceanusDataFormatter pFormatter) {
685 return getDataFieldSet().getName();
686 }
687
688
689
690
691
692
693 private void registerControlKeySet(final PrometheusControlKeySet pKeySet) {
694
695 if (!theList.contains(pKeySet)) {
696
697 theList.add(pKeySet);
698
699
700 if (theIterator != null) {
701 theIterator = iterator();
702 }
703 }
704 }
705
706
707
708
709
710
711 private PrometheusDataKeySet getNextDataKeySet() {
712
713 if (isEmpty()) {
714 return null;
715 }
716
717
718 if (theIterator == null
719 || !theIterator.hasNext()) {
720 theIterator = iterator();
721 }
722
723
724 return theIterator.next().getNextDataKeySet();
725 }
726
727
728
729
730 private void deleteControlKeySets() {
731
732 final Iterator<PrometheusControlKeySet> myIterator = iterator();
733 while (myIterator.hasNext()) {
734 final PrometheusControlKeySet mySet = myIterator.next();
735
736
737 mySet.deleteControlKeySet();
738 }
739 }
740
741
742
743
744
745
746
747
748
749 private ControlKeySetCache cloneControlKeySetCache(final PrometheusControlKey pControlKey,
750 final PrometheusControlKeySetList pKeySets) throws OceanusException {
751
752 final ControlKeySetCache myCache = new ControlKeySetCache();
753
754
755 final Iterator<PrometheusControlKeySet> myIterator = iterator();
756 while (myIterator.hasNext()) {
757 final PrometheusControlKeySet mySet = myIterator.next();
758
759
760 final PrometheusControlKeySet myNewSet = pKeySets.cloneControlKeySet(pControlKey, mySet);
761 myCache.registerControlKeySet(myNewSet);
762 }
763
764
765 return myCache;
766 }
767 }
768 }