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.base.GordianException;
20 import io.github.tonywasher.joceanus.gordianknot.api.keyset.GordianKeySet;
21 import io.github.tonywasher.joceanus.metis.data.MetisDataDifference;
22 import io.github.tonywasher.joceanus.metis.data.MetisDataType;
23 import io.github.tonywasher.joceanus.metis.field.MetisFieldItem.MetisFieldDef;
24 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
25 import io.github.tonywasher.joceanus.oceanus.convert.OceanusDataConverter;
26 import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
27 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusDecimal;
28 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
29 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusPrice;
30 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRate;
31 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRatio;
32 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusUnits;
33 import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
34 import io.github.tonywasher.joceanus.prometheus.exc.PrometheusDataException;
35 import io.github.tonywasher.joceanus.prometheus.exc.PrometheusLogicException;
36 import io.github.tonywasher.joceanus.prometheus.exc.PrometheusSecurityException;
37
38 import java.util.EnumMap;
39 import java.util.Map;
40
41
42
43
44 public class PrometheusEncryptor {
45
46
47
48 private static final String ERROR_BYTES_CONVERT = "Failed to convert value from bytes";
49
50
51
52
53 private static final String ERROR_CLASS = "Invalid Object Class for Encryption ";
54
55
56
57
58 private static final String ERROR_DATATYPE = "Unsupported Data Type";
59
60
61
62
63 private static final Map<MetisDataType, PrometheusDataEncryptor> ENCRYPTORS = buildEncryptorMap();
64
65
66
67
68 private final GordianKeySet theKeySet;
69
70
71
72
73 private final OceanusDataFormatter theFormatter;
74
75
76
77
78
79
80
81 public PrometheusEncryptor(final OceanusDataFormatter pFormatter,
82 final GordianKeySet pKeySet) {
83 theFormatter = pFormatter;
84 theKeySet = pKeySet;
85 }
86
87
88
89
90
91
92 public GordianKeySet getKeySet() {
93 return theKeySet;
94 }
95
96
97
98
99
100
101
102
103 public byte[] encryptValue(final Object pValue) throws OceanusException {
104
105 try {
106
107 final MetisDataType myDataType = getDataTypeForValue(pValue);
108 final PrometheusDataEncryptor myEncryptor = ENCRYPTORS.get(myDataType);
109
110 final byte[] myBytes = myEncryptor.convertValue(theFormatter, pValue);
111 return theKeySet == null ? null : theKeySet.encryptBytes(myBytes);
112 } catch (GordianException e) {
113 throw new PrometheusSecurityException(e);
114 }
115 }
116
117
118
119
120
121
122
123
124
125 public PrometheusEncryptedPair encryptValue(final PrometheusEncryptedPair pCurrent,
126 final Object pValue) throws OceanusException {
127
128 if (pValue == null) {
129 return null;
130 }
131
132
133 PrometheusEncryptedPair myCurrent = pCurrent;
134 if (myCurrent != null
135 && (theKeySet == null || !theKeySet.equals(myCurrent.getKeySet()))) {
136 myCurrent = null;
137 }
138
139
140 if (myCurrent != null
141 && MetisDataDifference.isEqual(myCurrent.getValue(), pValue)) {
142 return pCurrent;
143 }
144
145
146 final byte[] myEncrypted = encryptValue(pValue);
147 return new PrometheusEncryptedPair(theKeySet, pValue, myEncrypted);
148 }
149
150
151
152
153
154
155
156
157
158 public PrometheusEncryptedPair encryptValue(final Object pValue,
159 final MetisFieldDef pField) throws OceanusException {
160
161 try {
162
163 if (pValue == null) {
164 return null;
165 }
166
167
168 MetisDataType myDataType = pField.getDataType();
169 if (myDataType == MetisDataType.CONTEXT) {
170 myDataType = getDataTypeForValue(pValue);
171 }
172
173
174 final PrometheusDataEncryptor myEncryptor = ENCRYPTORS.get(myDataType);
175 if (myEncryptor == null) {
176 throw new PrometheusLogicException(ERROR_DATATYPE);
177 }
178
179
180 final byte[] myBytes = myEncryptor.convertValue(theFormatter, pValue);
181 final byte[] myEncrypted = theKeySet.encryptBytes(myBytes);
182 return new PrometheusEncryptedPair(theKeySet, pValue, myEncrypted);
183 } catch (GordianException e) {
184 throw new PrometheusSecurityException(e);
185 }
186 }
187
188
189
190
191
192
193
194
195
196 PrometheusEncryptedPair decryptValue(final byte[] pBytes,
197 final MetisFieldDef pField) throws OceanusException {
198
199 try {
200
201 final PrometheusDataEncryptor myEncryptor = ENCRYPTORS.get(pField.getDataType());
202 if (myEncryptor == null) {
203 throw new PrometheusLogicException(ERROR_DATATYPE);
204 }
205
206
207 final byte[] myDecrypted = theKeySet.decryptBytes(pBytes);
208 final Object myValue = myEncryptor.parseValue(theFormatter, myDecrypted);
209 return new PrometheusEncryptedPair(theKeySet, myValue, pBytes);
210 } catch (GordianException e) {
211 throw new PrometheusSecurityException(e);
212 }
213 }
214
215
216
217
218
219
220
221
222
223 PrometheusEncryptedPair decryptValue(final byte[] pBytes,
224 final Class<?> pClazz) throws OceanusException {
225
226 try {
227
228 final MetisDataType myDataType = getDataTypeForClass(pClazz);
229 final PrometheusDataEncryptor myEncryptor = ENCRYPTORS.get(myDataType);
230 if (myEncryptor == null) {
231 throw new PrometheusLogicException(ERROR_DATATYPE);
232 }
233
234
235 final byte[] myDecrypted = theKeySet.decryptBytes(pBytes);
236 final Object myValue = myEncryptor.parseValue(theFormatter, myDecrypted);
237 return new PrometheusEncryptedPair(theKeySet, myValue, pBytes);
238 } catch (GordianException e) {
239 throw new PrometheusSecurityException(e);
240 }
241 }
242
243
244
245
246
247
248
249
250 public static MetisDataType getDataTypeForValue(final Object pValue) throws OceanusException {
251 if (pValue instanceof String) {
252 return MetisDataType.STRING;
253 }
254 if (pValue instanceof Short) {
255 return MetisDataType.SHORT;
256 }
257 if (pValue instanceof Integer) {
258 return MetisDataType.INTEGER;
259 }
260 if (pValue instanceof Long) {
261 return MetisDataType.LONG;
262 }
263 if (pValue instanceof Boolean) {
264 return MetisDataType.BOOLEAN;
265 }
266 if (pValue instanceof char[]) {
267 return MetisDataType.CHARARRAY;
268 }
269
270
271 if (pValue instanceof OceanusDate) {
272 return MetisDataType.DATE;
273 }
274 if (pValue instanceof OceanusUnits) {
275 return MetisDataType.UNITS;
276 }
277 if (pValue instanceof OceanusRate) {
278 return MetisDataType.RATE;
279 }
280 if (pValue instanceof OceanusPrice) {
281 return MetisDataType.PRICE;
282 }
283 if (pValue instanceof OceanusMoney) {
284 return MetisDataType.MONEY;
285 }
286 if (pValue instanceof OceanusRatio) {
287 return MetisDataType.RATIO;
288 }
289
290
291 throw new PrometheusLogicException(ERROR_CLASS
292 + pValue.getClass().getCanonicalName());
293 }
294
295
296
297
298
299
300
301
302 static MetisDataType getDataTypeForClass(final Class<?> pClazz) throws OceanusException {
303 if (String.class.equals(pClazz)) {
304 return MetisDataType.STRING;
305 }
306 if (Short.class.equals(pClazz)) {
307 return MetisDataType.SHORT;
308 }
309 if (Integer.class.equals(pClazz)) {
310 return MetisDataType.INTEGER;
311 }
312 if (Long.class.equals(pClazz)) {
313 return MetisDataType.LONG;
314 }
315 if (Boolean.class.equals(pClazz)) {
316 return MetisDataType.BOOLEAN;
317 }
318 if (char[].class.equals(pClazz)) {
319 return MetisDataType.CHARARRAY;
320 }
321
322
323 if (OceanusDate.class.equals(pClazz)) {
324 return MetisDataType.DATE;
325 }
326 if (OceanusUnits.class.equals(pClazz)) {
327 return MetisDataType.UNITS;
328 }
329 if (OceanusRate.class.equals(pClazz)) {
330 return MetisDataType.RATE;
331 }
332 if (OceanusPrice.class.equals(pClazz)) {
333 return MetisDataType.PRICE;
334 }
335 if (OceanusMoney.class.equals(pClazz)) {
336 return MetisDataType.MONEY;
337 }
338 if (OceanusRatio.class.equals(pClazz)) {
339 return MetisDataType.RATIO;
340 }
341
342
343 throw new PrometheusLogicException(ERROR_CLASS
344 + pClazz.getCanonicalName());
345 }
346
347
348
349
350
351
352 private static Map<MetisDataType, PrometheusDataEncryptor> buildEncryptorMap() {
353 final Map<MetisDataType, PrometheusDataEncryptor> myMap = new EnumMap<>(MetisDataType.class);
354 myMap.put(MetisDataType.DATE, new PrometheusDateEncryptor());
355 myMap.put(MetisDataType.SHORT, new PrometheusShortEncryptor());
356 myMap.put(MetisDataType.INTEGER, new PrometheusIntegerEncryptor());
357 myMap.put(MetisDataType.LONG, new PrometheusLongEncryptor());
358 myMap.put(MetisDataType.STRING, new PrometheusStringEncryptor());
359 myMap.put(MetisDataType.CHARARRAY, new PrometheusCharArrayEncryptor());
360 myMap.put(MetisDataType.BOOLEAN, new PrometheusBooleanEncryptor());
361 myMap.put(MetisDataType.MONEY, new PrometheusMoneyEncryptor());
362 myMap.put(MetisDataType.PRICE, new PrometheusPriceEncryptor());
363 myMap.put(MetisDataType.RATE, new PrometheusRateEncryptor());
364 myMap.put(MetisDataType.UNITS, new PrometheusUnitsEncryptor());
365 myMap.put(MetisDataType.RATIO, new PrometheusRatioEncryptor());
366 return myMap;
367 }
368
369
370
371
372
373
374
375
376 public void adoptEncryption(final PrometheusEncryptedPair pTarget,
377 final PrometheusEncryptedPair pSource) throws OceanusException {
378
379 pTarget.adoptEncryption(this, pSource);
380 }
381
382
383
384
385 private interface PrometheusDataEncryptor {
386
387
388
389
390
391
392
393
394 byte[] convertValue(OceanusDataFormatter pFormatter,
395 Object pValue) throws OceanusException;
396
397
398
399
400
401
402
403
404
405 Object parseValue(OceanusDataFormatter pFormatter,
406 byte[] pBytes) throws OceanusException;
407 }
408
409
410
411
412 private static final class PrometheusDateEncryptor
413 implements PrometheusDataEncryptor {
414 @Override
415 public byte[] convertValue(final OceanusDataFormatter pFormatter,
416 final Object pValue) {
417 return pFormatter.getDateFormatter().toBytes((OceanusDate) pValue);
418 }
419
420 @Override
421 public Object parseValue(final OceanusDataFormatter pFormatter,
422 final byte[] pBytes) throws OceanusException {
423 try {
424 return pFormatter.getDateFormatter().fromBytes(pBytes);
425 } catch (IllegalArgumentException e) {
426 throw new PrometheusDataException(ERROR_BYTES_CONVERT, e);
427 }
428 }
429 }
430
431
432
433
434 private static final class PrometheusShortEncryptor
435 implements PrometheusDataEncryptor {
436 @Override
437 public byte[] convertValue(final OceanusDataFormatter pFormatter,
438 final Object pValue) {
439 return OceanusDataConverter.shortToByteArray((short) pValue);
440 }
441
442 @Override
443 public Object parseValue(final OceanusDataFormatter pFormatter,
444 final byte[] pBytes) throws OceanusException {
445 return OceanusDataConverter.byteArrayToShort(pBytes);
446 }
447 }
448
449
450
451
452 private static final class PrometheusIntegerEncryptor
453 implements PrometheusDataEncryptor {
454 @Override
455 public byte[] convertValue(final OceanusDataFormatter pFormatter,
456 final Object pValue) {
457 return OceanusDataConverter.integerToByteArray((int) pValue);
458 }
459
460 @Override
461 public Object parseValue(final OceanusDataFormatter pFormatter,
462 final byte[] pBytes) throws OceanusException {
463 return OceanusDataConverter.byteArrayToInteger(pBytes);
464 }
465 }
466
467
468
469
470 private static final class PrometheusLongEncryptor
471 implements PrometheusDataEncryptor {
472 @Override
473 public byte[] convertValue(final OceanusDataFormatter pFormatter,
474 final Object pValue) {
475 return OceanusDataConverter.longToByteArray((long) pValue);
476 }
477
478 @Override
479 public Object parseValue(final OceanusDataFormatter pFormatter,
480 final byte[] pBytes) throws OceanusException {
481 return OceanusDataConverter.byteArrayToLong(pBytes);
482 }
483 }
484
485
486
487
488 private static final class PrometheusBooleanEncryptor
489 implements PrometheusDataEncryptor {
490 @Override
491 public byte[] convertValue(final OceanusDataFormatter pFormatter,
492 final Object pValue) {
493 return OceanusDataConverter.stringToByteArray(pValue.toString());
494 }
495
496 @Override
497 public Object parseValue(final OceanusDataFormatter pFormatter,
498 final byte[] pBytes) {
499 final String myBoolString = OceanusDataConverter.byteArrayToString(pBytes);
500 return Boolean.parseBoolean(myBoolString);
501 }
502 }
503
504
505
506
507 private static final class PrometheusStringEncryptor
508 implements PrometheusDataEncryptor {
509 @Override
510 public byte[] convertValue(final OceanusDataFormatter pFormatter,
511 final Object pValue) {
512 return OceanusDataConverter.stringToByteArray((String) pValue);
513 }
514
515 @Override
516 public Object parseValue(final OceanusDataFormatter pFormatter,
517 final byte[] pBytes) {
518 return OceanusDataConverter.byteArrayToString(pBytes);
519 }
520 }
521
522
523
524
525 private static final class PrometheusCharArrayEncryptor
526 implements PrometheusDataEncryptor {
527 @Override
528 public byte[] convertValue(final OceanusDataFormatter pFormatter,
529 final Object pValue) throws OceanusException {
530 return OceanusDataConverter.charsToByteArray((char[]) pValue);
531 }
532
533 @Override
534 public Object parseValue(final OceanusDataFormatter pFormatter,
535 final byte[] pBytes) throws OceanusException {
536 return OceanusDataConverter.bytesToCharArray(pBytes);
537 }
538 }
539
540
541
542
543 private abstract static class PrometheusDecimalEncryptor
544 implements PrometheusDataEncryptor {
545 @Override
546 public byte[] convertValue(final OceanusDataFormatter pFormatter,
547 final Object pValue) {
548 return ((OceanusDecimal) pValue).toBytes();
549 }
550 }
551
552
553
554
555 private static final class PrometheusMoneyEncryptor
556 extends PrometheusDecimalEncryptor {
557 @Override
558 public Object parseValue(final OceanusDataFormatter pFormatter,
559 final byte[] pBytes) throws OceanusException {
560 return new OceanusMoney(pBytes);
561 }
562 }
563
564
565
566
567 private static final class PrometheusPriceEncryptor
568 extends PrometheusDecimalEncryptor {
569 @Override
570 public Object parseValue(final OceanusDataFormatter pFormatter,
571 final byte[] pBytes) throws OceanusException {
572 return new OceanusPrice(pBytes);
573 }
574 }
575
576
577
578
579 private static final class PrometheusRatioEncryptor
580 extends PrometheusDecimalEncryptor {
581 @Override
582 public Object parseValue(final OceanusDataFormatter pFormatter,
583 final byte[] pBytes) throws OceanusException {
584 return new OceanusRatio(pBytes);
585 }
586 }
587
588
589
590
591 private static final class PrometheusUnitsEncryptor
592 extends PrometheusDecimalEncryptor {
593 @Override
594 public Object parseValue(final OceanusDataFormatter pFormatter,
595 final byte[] pBytes) throws OceanusException {
596 return new OceanusUnits(pBytes);
597 }
598 }
599
600
601
602
603 private static final class PrometheusRateEncryptor
604 extends PrometheusDecimalEncryptor {
605 @Override
606 public Object parseValue(final OceanusDataFormatter pFormatter,
607 final byte[] pBytes) throws OceanusException {
608 return new OceanusRate(pBytes);
609 }
610 }
611 }