/******************************************************************************* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. *******************************************************************************/ package at.gv.egovernment.moa.id.storage; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.PersistenceException; import javax.persistence.Query; import org.apache.commons.lang.SerializationUtils; import org.hibernate.HibernateException; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; import at.gv.egovernment.moa.id.auth.exception.BuildException; import at.gv.egovernment.moa.id.commons.db.dao.session.AssertionStore; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.data.EncryptedData; import at.gv.egovernment.moa.id.util.SessionEncrytionUtil; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; @Repository @Transactional("sessionTransactionManager") public class DBTransactionStorage implements ITransactionStorage { @PersistenceContext(unitName="session") private EntityManager entityManager; public boolean containsKey(String key) { try { searchInDatabase(key); return true; } catch (MOADatabaseException e) { return false; } } /* (non-Javadoc) * @see at.gv.egovernment.moa.id.storage.ITransactionStorage#changeKey(java.lang.String, java.lang.String, java.lang.Object) */ @Override public void changeKey(String oldKey, String newKey, Object value) throws MOADatabaseException { //search if key already exists AssertionStore element = searchInDatabase(oldKey); if (element == null) { Logger.info("No transaction-data with oldKey:" + oldKey + " found. Process gets stopped."); throw new MOADatabaseException("No transaction-data with oldKey:" + oldKey + " found. Process gets stopped."); } put(element, newKey, value); } public void put(String key, Object value, int timeout_ms) throws MOADatabaseException { //search if key already exists AssertionStore element = searchInDatabase(key); //create a new entry if key does not exists already if (element == null) { element = new AssertionStore(); } put(element, key, value); } public T get(String key, final Class clazz) throws MOADatabaseException { try { return get(key, clazz, -1); } catch (AuthenticationException e) { //this execption only occurs if an additional timeOut is used Logger.error("This exeption should not occur!!!!", e); return null; } } public Object get(String key) throws MOADatabaseException { AssertionStore element = searchInDatabase(key); if (element == null) return null; Object data = SerializationUtils.deserialize(element.getAssertion()); //decrypt data if required Object resultData = null; if (data instanceof EncryptedData) { Logger.trace("Find encrypted data. --> Starting decryption process ..."); try { byte[] decData = decryptData((EncryptedData)data); resultData = SerializationUtils.deserialize(decData); } catch (BuildException e) { Logger.warn("Transaction information decryption FAILED.", e); throw new MOADatabaseException("Transaction information decryption FAILED.", e); } } else { Logger.trace("Find unencrypted data. --> Use it as is"); resultData = data; } return resultData; } public T get(String key, final Class clazz, long dataTimeOut) throws MOADatabaseException, AuthenticationException { AssertionStore element = searchInDatabase(key); if (element == null) return null; if (dataTimeOut > -1) { //check timeout long now = new Date().getTime(); if (now - element.getDatatime().getTime() > dataTimeOut) { Logger.info("Transaction-Data with key: " + key + " is out of time."); throw new AuthenticationException("1207", new Object[] { key }); } } //Deserialize Assertion Object data = SerializationUtils.deserialize(element.getAssertion()); //decrypt data if required Object resultData = null; if (data instanceof EncryptedData) { Logger.trace("Find encrypted data. --> Starting decryption process ..."); try { byte[] decData = decryptData((EncryptedData)data); resultData = SerializationUtils.deserialize(decData); } catch (BuildException e) { Logger.warn("Transaction information decryption FAILED.", e); throw new MOADatabaseException("Transaction information decryption FAILED.", e); } } else { Logger.trace("Find unencrypted data. --> Use it as is"); resultData = data; } //check if assertion has the correct class type try { @SuppressWarnings("unchecked") T test = (T) Class.forName(element.getType()).cast(resultData); return test; } catch (Exception e) { Logger.warn("Sessioninformation Cast-Exception by using Artifact=" + key); throw new MOADatabaseException("Sessioninformation Cast-Exception"); } } public List clean(Date now, long dataTimeOut) { Date expioredate = new Date(now.getTime() - dataTimeOut); List results; List returnValues = new ArrayList();; Query query = entityManager.createNamedQuery("getAssertionWithTimeOut"); query.setParameter("timeout", expioredate); results = query.getResultList(); if (results != null) { for (AssertionStore el : results) returnValues.add(el.getArtifact()); } return returnValues; } public void remove(String key) { try { AssertionStore element = searchInDatabase(key); if (element == null) { Logger.debug("Sessioninformation not removed! (Sessioninformation with ID=" + key + "not found)"); return; } cleanDelete(element); Logger.debug("Remove stored information with ID: " + key); } catch (MOADatabaseException e) { Logger.info("Sessioninformation not removed! (Message:"+ e.getMessage() + ")"); } catch (HibernateException e) { Logger.warn("Sessioninformation not removed! (Erreor during Database communication)", e); } } @Override public Object getRaw(String key) throws MOADatabaseException { return searchInDatabase(key); } @Override public void putRaw(String key, Object element) throws MOADatabaseException { if (element instanceof AssertionStore) entityManager.merge(element); else { Logger.error("Can not persist Object of type: " + element.getClass().getName()); throw new RuntimeException("Can not persist Object of type: " + element.getClass().getName()); } } private void cleanDelete(AssertionStore element) { try{ element.setAssertion("blank".getBytes()); entityManager.merge(element); entityManager.remove(element); }catch(PersistenceException e){ Logger.error("ShortTime session with artifact=" + element.getArtifact() + " not removed! (Error during Database communication)"); } } @SuppressWarnings("rawtypes") private AssertionStore searchInDatabase(String artifact) throws MOADatabaseException { MiscUtil.assertNotNull(artifact, "artifact"); Logger.trace("Getting sessioninformation with ID " + artifact + " from database."); List results; Query query = entityManager.createNamedQuery("getAssertionWithArtifact"); query.setParameter("artifact", artifact); results = query.getResultList(); Logger.trace("Found entries: " + results.size()); //Assertion requires an unique artifact if (results.size() != 1) { Logger.debug("No transaction information with ID:" + artifact + " found."); return null; } return results.get(0); } private void put(AssertionStore element, String key, Object value) throws MOADatabaseException { element.setArtifact(key); element.setType(value.getClass().getName()); element.setDatatime(new Date()); if (!Serializable.class.isInstance(value)) { Logger.warn("Transaction-Storage can only store objects which implements the 'Seralizable' interface"); throw new MOADatabaseException("Transaction-Storage can only store objects which implements the 'Seralizable' interface", null); } try { //serialize the Assertion for Database storage byte[] data = SerializationUtils.serialize((Serializable) value); element.setAssertion(encryptData(data)); //store AssertionStore element to Database entityManager.persist(element); Logger.debug(value.getClass().getName() + " with ID: " + key + " is stored in Database"); } catch (BuildException e) { Logger.warn("Sessioninformation could not be stored."); throw new MOADatabaseException("Can not store data into transaction-storage", e); } } private static byte[] encryptData(byte[] data) throws BuildException { EncryptedData encdata = SessionEncrytionUtil.getInstance().encrypt(data); return SerializationUtils.serialize(encdata); } private static byte[] decryptData(EncryptedData encdata) throws BuildException { return SessionEncrytionUtil.getInstance().decrypt(encdata); } }