001    package org.cumulus4j.store.crypto;
002    
003    import javax.jdo.PersistenceManager;
004    
005    import org.cumulus4j.store.EncryptionCoordinateSetManager;
006    import org.cumulus4j.store.KeyStoreRefManager;
007    import org.cumulus4j.store.PersistenceManagerConnection;
008    import org.cumulus4j.store.model.KeyStoreRef;
009    import org.datanucleus.store.ExecutionContext;
010    
011    /**
012     * Context for encryption and decryption.
013     * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
014     */
015    public class CryptoContext
016    {
017            /**
018             * Create a new context.
019             * @param encryptionCoordinateSetManager the <code>EncryptionCoordinateSetManager</code> to be used in this context; must not be <code>null</code>.
020             * @param keyStoreRefManager the <code>KeyStoreRefManager</code> to be used in this context; must not be <code>null</code>.
021             * @param executionContext the <code>ExecutionContext</code> to be used in this context; must not be <code>null</code>.
022             * @param persistenceManagerConnection the <code>PersistenceManagerConnection</code> to be used in this context; must not be <code>null</code>.
023             */
024            public CryptoContext(EncryptionCoordinateSetManager encryptionCoordinateSetManager, KeyStoreRefManager keyStoreRefManager, ExecutionContext executionContext, PersistenceManagerConnection persistenceManagerConnection)
025            {
026                    if (encryptionCoordinateSetManager == null)
027                            throw new IllegalArgumentException("encryptionCoordinateSetManager == null");
028    
029                    if (keyStoreRefManager == null)
030                            throw new IllegalArgumentException("keyStoreRefManager == null");
031    
032                    if (executionContext == null)
033                            throw new IllegalArgumentException("executionContext == null");
034    
035                    if (persistenceManagerConnection == null)
036                            throw new IllegalArgumentException("persistenceManagerConnection == null");
037    
038                    this.encryptionCoordinateSetManager = encryptionCoordinateSetManager;
039                    this.keyStoreRefManager = keyStoreRefManager;
040                    this.executionContext = executionContext;
041                    this.persistenceManagerConnection = persistenceManagerConnection;
042                    this.persistenceManagerForData = persistenceManagerConnection.getDataPM();
043                    this.persistenceManagerForIndex = persistenceManagerConnection.getIndexPM();
044            }
045    
046            private EncryptionCoordinateSetManager encryptionCoordinateSetManager;
047    
048            public KeyStoreRefManager getKeyStoreRefManager() {
049                    return keyStoreRefManager;
050            }
051    
052            private KeyStoreRefManager keyStoreRefManager;
053    
054            /**
055             * Get the <code>EncryptionCoordinateSetManager</code> to be used in this context; never <code>null</code>.
056             * @return the <code>EncryptionCoordinateSetManager</code> to be used in this context; never <code>null</code>.
057             */
058            public EncryptionCoordinateSetManager getEncryptionCoordinateSetManager() {
059                    return encryptionCoordinateSetManager;
060            }
061    
062            private ExecutionContext executionContext;
063    
064            /**
065             * Get the <code>ExecutionContext</code> to be used in this context; never <code>null</code>.
066             * @return the <code>ExecutionContext</code> to be used in this context; never <code>null</code>.
067             */
068            public ExecutionContext getExecutionContext() {
069                    return executionContext;
070            }
071    
072            private PersistenceManagerConnection persistenceManagerConnection;
073    
074            /**
075             * Get the <code>PersistenceManagerConnection</code> to be used in this context; never <code>null</code>.
076             * @return the <code>PersistenceManagerConnection</code> to be used in this context; never <code>null</code>.
077             */
078            public PersistenceManagerConnection getPersistenceManagerConnection() {
079                    return persistenceManagerConnection;
080            }
081    
082            private PersistenceManager persistenceManagerForData;
083    
084            /**
085             * Convenience method synonymous to {@link PersistenceManagerConnection#getDataPM()}.
086             * @return the PM used for the actual data.
087             */
088            public PersistenceManager getPersistenceManagerForData() {
089                    return persistenceManagerForData;
090            }
091    
092            private PersistenceManager persistenceManagerForIndex;
093    
094            /**
095             * Convenience method synonymous to {@link PersistenceManagerConnection#getIndexPM()}.
096             * @return the PM used for index data. If there is no separate index-datastore, this
097             * is the same as {@link #getPersistenceManagerForData()}.
098             */
099            public PersistenceManager getPersistenceManagerForIndex() {
100                    return persistenceManagerForIndex;
101            }
102    
103            public CryptoSession getCryptoSession()
104            {
105                    ExecutionContext ec = executionContext;
106                    Object cryptoManagerID = ec.getProperty(CryptoManager.PROPERTY_CRYPTO_MANAGER_ID);
107                    if (cryptoManagerID == null)
108                            throw new IllegalStateException("Property \"" + CryptoManager.PROPERTY_CRYPTO_MANAGER_ID + "\" is not set!");
109    
110                    if (!(cryptoManagerID instanceof String))
111                            throw new IllegalStateException("Property \"" + CryptoManager.PROPERTY_CRYPTO_MANAGER_ID + "\" is set, but it is an instance of " + cryptoManagerID.getClass().getName() + " instead of java.lang.String!");
112    
113                    CryptoManager cryptoManager = CryptoManagerRegistry.sharedInstance(ec.getNucleusContext()).getCryptoManager((String) cryptoManagerID);
114    
115                    Object cryptoSessionID = ec.getProperty(CryptoSession.PROPERTY_CRYPTO_SESSION_ID);
116                    if (cryptoSessionID == null)
117                            throw new IllegalStateException("Property \"" + CryptoSession.PROPERTY_CRYPTO_SESSION_ID + "\" is not set!");
118    
119                    if (!(cryptoSessionID instanceof String))
120                            throw new IllegalStateException("Property \"" + CryptoSession.PROPERTY_CRYPTO_SESSION_ID + "\" is set, but it is an instance of " + cryptoSessionID.getClass().getName() + " instead of java.lang.String!");
121    
122                    CryptoSession cryptoSession = cryptoManager.getCryptoSession((String) cryptoSessionID);
123                    return cryptoSession;
124            }
125    
126            private Integer keyStoreRefID;
127    
128            public int getKeyStoreRefID() {
129                    Integer keyStoreRefID = this.keyStoreRefID;
130                    if (keyStoreRefID == null) {
131                            String keyStoreID = getCryptoSession().getKeyStoreID();
132                            KeyStoreRef keyStoreRef = getKeyStoreRefManager().createKeyStoreRef(getPersistenceManagerConnection(), keyStoreID);
133                            keyStoreRefID = keyStoreRef.getKeyStoreRefID();
134                            this.keyStoreRefID = keyStoreRefID;
135                    }
136                    return keyStoreRefID;
137            }
138    }