Overriding the ProxyList class

"Robert Giddings" <[email protected]> Thu, 13 Sep 2007 10:16:29 +0100
Newsgroups gmane.comp.jakarta.ojb.user
Message-ID <000001c7f5e6$c4f7dd10$0600a8c0@zaphod>
Hi,

Can anyone please tell me why this code doesn't seem to have an effect?
That is I get a class cast exception because an encrypted object for
example EncryptedCostCentre does not get decrypted to a CostCentre. Both
classes implement an interface called ICostCentre, but this interface
has no method signatures etc as the structure of the two classes is
different. I.e. CostCentre has getter/setters and EncryptedCostCentre
has an encrypt and decrypt methods.
The concept works fine, if I override the java.util.List methods and
encrypt and decrypt there, but this isn't really practical as I can
override methods such as indexOf(Object o) as they rely on equals.
The cypherMachine and encryptedClassType are set in the decrypt method
of the owner object, where a reference to the ICostCentre collection is
passed to the decrypted version of that object.
Also what changes am I likely to need to make to the afterStore method?

Thanks,

Robert Giddings


The code:


package com.netcase.database.ojb.proxy;

import java.lang.reflect.Method;

import java.util.Iterator;

import org.apache.ojb.broker.ManageableCollection;
import org.apache.ojb.broker.PBKey;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.PersistenceBrokerException;
import org.apache.ojb.broker.core.proxy.ListProxyDefaultImpl;
import org.apache.ojb.broker.query.Query;

import com.netcase.encryption.CypherMachine;

public class EncryptableCollectionProxy extends ListProxyDefaultImpl {

	private CypherMachine cypherMachine;
	
	private Class encryptedClassType;
	
	public EncryptableCollectionProxy(PBKey brokerKey,
java.lang.Class collClass, Query query) {
		super(brokerKey, collClass, query);
		cypherMachine = null;
		encryptedClassType = null;
	}
	
	public EncryptableCollectionProxy(PBKey brokerKey, Query query)
{
		super(brokerKey, query);
		cypherMachine = null;
		encryptedClassType = null;
	}

	/**
	 * @return the cypherMachine
	 */
	public CypherMachine getCypherMachine() {
		return cypherMachine;
	}

	/**
	 * @param cypherMachine the cypherMachine to set
	 */
	public void setCypherMachine(CypherMachine cypherMachine) {
		this.cypherMachine = cypherMachine;
	}
	
	/**
	 * @return the encryptedClassType
	 */
	public Class getEncryptedClassType() {
		return encryptedClassType;
	}

	/**
	 * @param encryptedClassType the encryptedClassType to set
	 */
	public void setEncryptedClassType(Class encryptedClassType) {
		this.encryptedClassType = encryptedClassType;
	}

	private Object decryptObject(Object o) {
		try {
			Method decrypt =
encryptedClassType.getMethod("decrypt", CypherMachine.class);
			return decrypt.invoke(o, cypherMachine);
		}
		catch(Exception e) {
			return null;
		}
	}
	
	private Object encryptObject(Object o) {
		try {
			Method encrypt =
encryptedClassType.getMethod("encrypt", CypherMachine.class);
			return encrypt.invoke(o, cypherMachine);
		}
		catch(Exception e) {
			return null;
		}
	}
	
	public void ojbAdd(Object anObject) {
		super.ojbAdd(this.decryptObject(anObject));
	}
	
	public void ojbAddAll(ManageableCollection otherCollection) {
		Iterator i = otherCollection.ojbIterator();
		while(i.hasNext()) {
			this.ojbAdd(i.next());
		}
	}
	
	public Iterator ojbIterator() {
		EncryptableCollectionProxy ecp = 
			new
EncryptableCollectionProxy(this.getBrokerKey(), 
					this.getCollectionClass(),
this.getQuery());
		for(Object o: this) {
			ecp.add(this.encryptObject(o));
		}
		return ecp.ojbIterator();
	}
	
	public void afterStore(PersistenceBroker broker) throws
PersistenceBrokerException {
		super.afterStore(broker);
	}
	
}



An example of the XDoclet code is:



/**
	 * @ojb.collection
element-class-ref="com.netcase.netspat.recordSystem.encryption.encrypted
Objects.EncryptedCostCentre"
	 *                 foreignkey="clientId"
	 *                 proxy="true"
	 *                 auto-retrieve="true"
	 *                 auto-update="none"
	 *                 auto-delete="none"
	 */
	private Collection<ICostCentre> costCentres;




Use of code:


public Client decrypt(CypherMachine cm) throws FailedDecryptionException
{
		Client c = new Client(this.id);
		try {
			...
			
			EncryptableCollectionProxy costCentresProxy =
(EncryptableCollectionProxy)costCentres;
			costCentresProxy.setCypherMachine(cm);
	
costCentresProxy.setEncryptedClassType(EncryptedCostCentre.class);
			c.setCostCentres(costCentresProxy);
			
		...
			
			return c;
		} catch(Exception e) {
			throw new FailedDecryptionException("Unable to
decrypt encrypted client: " + this.toString(), e);
		}
	}