001 /* 002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org 003 * Copyright (C) 2011 NightLabs Consulting GmbH 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 package org.cumulus4j.store; 019 020 import java.util.Properties; 021 022 import javax.jdo.PersistenceManager; 023 024 import org.cumulus4j.store.Cumulus4jConnectionFactory.Cumulus4jManagedConnection; 025 import org.cumulus4j.store.crypto.CryptoContext; 026 import org.cumulus4j.store.model.Sequence2; 027 import org.cumulus4j.store.model.Sequence2DAO; 028 import org.datanucleus.store.valuegenerator.AbstractDatastoreGenerator; 029 import org.datanucleus.store.valuegenerator.ValueGenerationBlock; 030 import org.datanucleus.store.valuegenerator.ValueGenerator; 031 032 /** 033 * {@link ValueGenerator} implementation generating values by incrementing a counter. 034 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de 035 */ 036 public class Cumulus4jIncrementGenerator extends AbstractDatastoreGenerator 037 { 038 private String sequenceName; 039 040 /** 041 * Create an instance. This is called by DataNucleus. 042 * @param name symbolic name for the generator. 043 * @param props Properties controlling the behaviour of the generator. 044 */ 045 public Cumulus4jIncrementGenerator(String name, Properties props) { 046 super(name, props); 047 allocationSize = 5; 048 049 // TODO Check these names and what we want to use for Cumulus4j (classname or fieldname) 050 if (properties.getProperty("sequence-name") != null) { 051 // Specified sequence-name so use that 052 sequenceName = properties.getProperty("sequence-name"); 053 } 054 else if (properties.getProperty("field-name") != null) { 055 // Use field name as the sequence name so we have one sequence per field on the class 056 sequenceName = properties.getProperty("field-name"); 057 } 058 else { 059 // Use actual class name as the sequence name so we have one sequence per class 060 sequenceName = properties.getProperty("class-name"); 061 } 062 } 063 064 @Override 065 protected ValueGenerationBlock reserveBlock(long size) { 066 if (size > Integer.MAX_VALUE) 067 throw new IllegalStateException("Cannot reserve a block of more than " + Integer.MAX_VALUE + " values!"); 068 069 Long[] values = new Long[(int)size]; 070 Cumulus4jManagedConnection mconn = (Cumulus4jManagedConnection) connectionProvider.retrieveConnection(); 071 try { 072 PersistenceManagerConnection pmConn = (PersistenceManagerConnection)mconn.getConnection(); 073 PersistenceManager pm = pmConn.getDataPM(); 074 Cumulus4jStoreManager storeManager = (Cumulus4jStoreManager) storeMgr; 075 076 CryptoContext cryptoContext = new CryptoContext( 077 storeManager.getEncryptionCoordinateSetManager(), 078 storeManager.getKeyStoreRefManager(), 079 mconn.getExecutionContext(), 080 pmConn 081 ); 082 storeManager.getDatastoreVersionManager().applyOnce(cryptoContext); 083 084 pm.currentTransaction().setSerializeRead(true); 085 try { 086 Sequence2 sequence = new Sequence2DAO(pm, cryptoContext.getKeyStoreRefID()).createSequence2(sequenceName); 087 long nextValue = sequence.getNextValue(); 088 for (int idx = 0; idx < values.length; ++idx) { 089 values[idx] = nextValue++; 090 } 091 sequence.setNextValue(nextValue); 092 } finally { 093 pm.currentTransaction().setSerializeRead(false); 094 } 095 } finally { 096 connectionProvider.releaseConnection(); 097 } 098 return new ValueGenerationBlock(values); 099 } 100 }