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