Refactoring serialization flow:

- New class CommonSerializeUtils: helper class dedicated to serialization, to contain common code to all the OlmXXX classes that require to be serialized
- make OlmXXX classes extending CommonSerializeUtils
This commit is contained in:
pedroGitt 2016-10-31 12:09:06 +01:00
parent 7a0d7cc36d
commit 8041a7e0ef
5 changed files with 150 additions and 152 deletions

View file

@ -0,0 +1,90 @@
/*
* Copyright 2016 OpenMarket Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.olm;
import android.text.TextUtils;
import android.util.Log;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* Helper class dedicated to serialization mechanism (template method pattern).
*/
abstract class CommonSerializeUtils {
private static final String LOG_TAG = "CommonSerializeUtils";
/**
* Kick off the serialization mechanism.
* @param aOutStream output stream for serializing
* @throws IOException exception
*/
protected void serializeObject(ObjectOutputStream aOutStream) throws IOException {
aOutStream.defaultWriteObject();
// generate serialization key
String key = OlmUtility.getRandomKey();
// compute pickle string
StringBuffer errorMsg = new StringBuffer();
String pickledData = serializeDataWithKey(key, errorMsg);
if(null == pickledData) {
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SERIALIZATION, String.valueOf(errorMsg));
} else {
aOutStream.writeObject(key);
aOutStream.writeObject(pickledData);
}
}
/**
* Kick off the deserialization mechanism.
* @param aInStream input stream
* @throws IOException exception
* @throws ClassNotFoundException exception
*/
protected void deserializeObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException {
aInStream.defaultReadObject();
StringBuffer errorMsg = new StringBuffer();
String key = (String) aInStream.readObject();
String pickledData = (String) aInStream.readObject();
if(TextUtils.isEmpty(key)) {
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key");
} else if(TextUtils.isEmpty(pickledData)) {
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle");
} else if(!createNewObjectFromSerialization()) {
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION);
} else if(!initWithSerializedData(pickledData, key, errorMsg)) {
releaseObjectFromSerialization(); // prevent memory leak
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg));
} else {
Log.d(LOG_TAG,"## readObject(): success");
}
}
protected abstract String serializeDataWithKey(String aKey, StringBuffer aErrorMsg);
protected abstract boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg);
protected abstract boolean createNewObjectFromSerialization();
protected abstract void releaseObjectFromSerialization();
}

View file

@ -32,7 +32,7 @@ import java.io.Serializable;
* OlmAccount provides APIs to retrieve the Olm keys. * OlmAccount provides APIs to retrieve the Olm keys.
*<br><br>Detailed implementation guide is available at <a href="http://matrix.org/docs/guides/e2e_implementation.html">Implementing End-to-End Encryption in Matrix clients</a>. *<br><br>Detailed implementation guide is available at <a href="http://matrix.org/docs/guides/e2e_implementation.html">Implementing End-to-End Encryption in Matrix clients</a>.
*/ */
public class OlmAccount implements Serializable { public class OlmAccount extends CommonSerializeUtils implements Serializable {
private static final long serialVersionUID = 3497486121598434824L; private static final long serialVersionUID = 3497486121598434824L;
private static final String LOG_TAG = "OlmAccount"; private static final String LOG_TAG = "OlmAccount";
@ -71,21 +71,7 @@ public class OlmAccount implements Serializable {
* @throws IOException exception * @throws IOException exception
*/ */
private void writeObject(ObjectOutputStream aOutStream) throws IOException { private void writeObject(ObjectOutputStream aOutStream) throws IOException {
aOutStream.defaultWriteObject(); serializeObject(aOutStream);
// generate serialization key
String key = OlmUtility.getRandomKey();
// compute pickle string
StringBuffer errorMsg = new StringBuffer();
String pickledData = serializeDataWithKey(key, errorMsg);
if(null == pickledData) {
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SERIALIZATION, String.valueOf(errorMsg));
} else {
aOutStream.writeObject(key);
aOutStream.writeObject(pickledData);
}
} }
/** /**
@ -95,28 +81,17 @@ public class OlmAccount implements Serializable {
* @throws ClassNotFoundException exception * @throws ClassNotFoundException exception
*/ */
private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException {
aInStream.defaultReadObject(); deserializeObject(aInStream);
StringBuffer errorMsg = new StringBuffer(); }
String key = (String) aInStream.readObject(); @Override
String pickledData = (String) aInStream.readObject(); protected boolean createNewObjectFromSerialization() {
return createNewAccount();
}
if(TextUtils.isEmpty(key)) { @Override
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); protected void releaseObjectFromSerialization() {
releaseAccount();
} else if(TextUtils.isEmpty(pickledData)) {
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle");
} else if(!createNewAccount()) {
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION);
} else if(!initWithSerializedData(pickledData, key, errorMsg)) {
releaseAccount(); // prevent memory leak
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg));
} else {
Log.d(LOG_TAG,"## readObject(): success");
}
} }
/** /**
@ -128,7 +103,8 @@ public class OlmAccount implements Serializable {
* @param aErrorMsg error message description * @param aErrorMsg error message description
* @return pickled base64 string if operation succeed, null otherwise * @return pickled base64 string if operation succeed, null otherwise
*/ */
private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { @Override
protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) {
String pickleRetValue = null; String pickleRetValue = null;
// sanity check // sanity check
@ -154,7 +130,8 @@ public class OlmAccount implements Serializable {
* @param aErrorMsg error message description * @param aErrorMsg error message description
* @return true if operation succeed, false otherwise * @return true if operation succeed, false otherwise
*/ */
private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { @Override
protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) {
boolean retCode = false; boolean retCode = false;
String jniError; String jniError;

View file

@ -34,7 +34,7 @@ import java.io.Serializable;
* *
* <br><br>Detailed implementation guide is available at <a href="http://matrix.org/docs/guides/e2e_implementation.html">Implementing End-to-End Encryption in Matrix clients</a>. * <br><br>Detailed implementation guide is available at <a href="http://matrix.org/docs/guides/e2e_implementation.html">Implementing End-to-End Encryption in Matrix clients</a>.
*/ */
public class OlmInboundGroupSession implements Serializable { public class OlmInboundGroupSession extends CommonSerializeUtils implements Serializable {
private static final long serialVersionUID = -772028491251653253L; private static final long serialVersionUID = -772028491251653253L;
private static final String LOG_TAG = "OlmInboundGroupSession"; private static final String LOG_TAG = "OlmInboundGroupSession";
@ -139,21 +139,7 @@ public class OlmInboundGroupSession implements Serializable {
* @throws IOException exception * @throws IOException exception
*/ */
private void writeObject(ObjectOutputStream aOutStream) throws IOException { private void writeObject(ObjectOutputStream aOutStream) throws IOException {
aOutStream.defaultWriteObject(); serializeObject(aOutStream);
// generate serialization key
String key = OlmUtility.getRandomKey();
// compute pickle string
StringBuffer errorMsg = new StringBuffer();
String pickledData = serializeDataWithKey(key, errorMsg);
if(null == pickledData) {
throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_SERIALIZATION, String.valueOf(errorMsg));
} else {
aOutStream.writeObject(key);
aOutStream.writeObject(pickledData);
}
} }
/** /**
@ -163,28 +149,17 @@ public class OlmInboundGroupSession implements Serializable {
* @throws ClassNotFoundException exception * @throws ClassNotFoundException exception
*/ */
private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException {
aInStream.defaultReadObject(); deserializeObject(aInStream);
StringBuffer errorMsg = new StringBuffer(); }
String key = (String) aInStream.readObject(); @Override
String pickledData = (String) aInStream.readObject(); protected boolean createNewObjectFromSerialization() {
return createNewSession();
}
if(TextUtils.isEmpty(key)) { @Override
throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); protected void releaseObjectFromSerialization() {
releaseSession();
} else if(TextUtils.isEmpty(pickledData)) {
throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle");
} else if(!createNewSession()) {
throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION);
} else if(!initWithSerializedData(pickledData, key, errorMsg)) {
releaseSession(); // prevent memory leak
throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, String.valueOf(errorMsg));
} else {
Log.d(LOG_TAG,"## readObject(): success");
}
} }
/** /**
@ -196,7 +171,8 @@ public class OlmInboundGroupSession implements Serializable {
* @param aErrorMsg error message description * @param aErrorMsg error message description
* @return pickled base64 string if operation succeed, null otherwise * @return pickled base64 string if operation succeed, null otherwise
*/ */
private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { @Override
protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) {
String pickleRetValue = null; String pickleRetValue = null;
// sanity check // sanity check
@ -228,7 +204,8 @@ public class OlmInboundGroupSession implements Serializable {
* @param aErrorMsg error message description * @param aErrorMsg error message description
* @return true if operation succeed, false otherwise * @return true if operation succeed, false otherwise
*/ */
private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { @Override
protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) {
boolean retCode = false; boolean retCode = false;
String jniError; String jniError;

View file

@ -32,7 +32,7 @@ import java.io.Serializable;
* *
* <br><br>Detailed implementation guide is available at <a href="http://matrix.org/docs/guides/e2e_implementation.html">Implementing End-to-End Encryption in Matrix clients</a>. * <br><br>Detailed implementation guide is available at <a href="http://matrix.org/docs/guides/e2e_implementation.html">Implementing End-to-End Encryption in Matrix clients</a>.
*/ */
public class OlmOutboundGroupSession implements Serializable { public class OlmOutboundGroupSession extends CommonSerializeUtils implements Serializable {
private static final long serialVersionUID = -3133097431283604416L; private static final long serialVersionUID = -3133097431283604416L;
private static final String LOG_TAG = "OlmOutboundGroupSession"; private static final String LOG_TAG = "OlmOutboundGroupSession";
@ -65,21 +65,7 @@ public class OlmOutboundGroupSession implements Serializable {
* @throws IOException exception * @throws IOException exception
*/ */
private void writeObject(ObjectOutputStream aOutStream) throws IOException { private void writeObject(ObjectOutputStream aOutStream) throws IOException {
aOutStream.defaultWriteObject(); serializeObject(aOutStream);
// generate serialization key
String key = OlmUtility.getRandomKey();
// compute pickle string
StringBuffer errorMsg = new StringBuffer();
String pickledData = serializeDataWithKey(key, errorMsg);
if(null == pickledData) {
throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_SERIALIZATION, String.valueOf(errorMsg));
} else {
aOutStream.writeObject(key);
aOutStream.writeObject(pickledData);
}
} }
/** /**
@ -89,28 +75,17 @@ public class OlmOutboundGroupSession implements Serializable {
* @throws ClassNotFoundException exception * @throws ClassNotFoundException exception
*/ */
private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException {
aInStream.defaultReadObject(); deserializeObject(aInStream);
StringBuffer errorMsg = new StringBuffer(); }
String key = (String) aInStream.readObject(); @Override
String pickledData = (String) aInStream.readObject(); protected boolean createNewObjectFromSerialization() {
return createNewSession();
}
if(TextUtils.isEmpty(key)) { @Override
throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); protected void releaseObjectFromSerialization() {
releaseSession();
} else if(TextUtils.isEmpty(pickledData)) {
throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle");
} else if(!createNewSession()) {
throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION);
} else if(!initWithSerializedData(pickledData, key, errorMsg)) {
releaseSession(); // prevent memory leak
throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, String.valueOf(errorMsg));
} else {
Log.d(LOG_TAG,"## readObject(): success");
}
} }
/** /**
@ -122,7 +97,8 @@ public class OlmOutboundGroupSession implements Serializable {
* @param aErrorMsg error message description * @param aErrorMsg error message description
* @return pickled base64 string if operation succeed, null otherwise * @return pickled base64 string if operation succeed, null otherwise
*/ */
private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { @Override
protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) {
String pickleRetValue = null; String pickleRetValue = null;
// sanity check // sanity check
@ -148,7 +124,8 @@ public class OlmOutboundGroupSession implements Serializable {
* @param aErrorMsg error message description * @param aErrorMsg error message description
* @return true if operation succeed, false otherwise * @return true if operation succeed, false otherwise
*/ */
private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { @Override
protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) {
boolean retCode = false; boolean retCode = false;
String jniError; String jniError;

View file

@ -32,7 +32,7 @@ import java.io.Serializable;
* From this step on, messages can be exchanged by using {@link #encryptMessage(String)} and {@link #decryptMessage(OlmMessage)}. * From this step on, messages can be exchanged by using {@link #encryptMessage(String)} and {@link #decryptMessage(OlmMessage)}.
* <br><br>Detailed implementation guide is available at <a href="http://matrix.org/docs/guides/e2e_implementation.html">Implementing End-to-End Encryption in Matrix clients</a>. * <br><br>Detailed implementation guide is available at <a href="http://matrix.org/docs/guides/e2e_implementation.html">Implementing End-to-End Encryption in Matrix clients</a>.
*/ */
public class OlmSession implements Serializable { public class OlmSession extends CommonSerializeUtils implements Serializable {
private static final long serialVersionUID = -8975488639186976419L; private static final long serialVersionUID = -8975488639186976419L;
private static final String LOG_TAG = "OlmSession"; private static final String LOG_TAG = "OlmSession";
@ -54,21 +54,7 @@ public class OlmSession implements Serializable {
* @throws IOException exception * @throws IOException exception
*/ */
private void writeObject(ObjectOutputStream aOutStream) throws IOException { private void writeObject(ObjectOutputStream aOutStream) throws IOException {
aOutStream.defaultWriteObject(); serializeObject(aOutStream);
// generate serialization key
String key = OlmUtility.getRandomKey();
// compute pickle string
StringBuffer errorMsg = new StringBuffer();
String pickledData = serializeDataWithKey(key, errorMsg);
if(null == pickledData) {
throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_SERIALIZATION, String.valueOf(errorMsg));
} else {
aOutStream.writeObject(key);
aOutStream.writeObject(pickledData);
}
} }
/** /**
@ -78,28 +64,17 @@ public class OlmSession implements Serializable {
* @throws ClassNotFoundException exception * @throws ClassNotFoundException exception
*/ */
private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException {
aInStream.defaultReadObject(); deserializeObject(aInStream);
StringBuffer errorMsg = new StringBuffer(); }
String key = (String) aInStream.readObject(); @Override
String pickledData = (String) aInStream.readObject(); protected boolean createNewObjectFromSerialization() {
return createNewSession();
}
if(TextUtils.isEmpty(key)) { @Override
throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); protected void releaseObjectFromSerialization() {
releaseSession();
} else if(TextUtils.isEmpty(pickledData)) {
throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle");
} else if(!createNewSession()) {
throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION);
} else if(!initWithSerializedData(pickledData, key, errorMsg)) {
releaseSession(); // prevent memory leak
throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, String.valueOf(errorMsg));
} else {
Log.d(LOG_TAG,"## readObject(): success");
}
} }
/** /**
@ -111,7 +86,8 @@ public class OlmSession implements Serializable {
* @param aErrorMsg error message description * @param aErrorMsg error message description
* @return pickled base64 string if operation succeed, null otherwise * @return pickled base64 string if operation succeed, null otherwise
*/ */
private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { @Override
protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) {
String pickleRetValue = null; String pickleRetValue = null;
// sanity check // sanity check
@ -137,7 +113,8 @@ public class OlmSession implements Serializable {
* @param aErrorMsg error message description * @param aErrorMsg error message description
* @return true if operation succeed, false otherwise * @return true if operation succeed, false otherwise
*/ */
private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { @Override
protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) {
boolean retCode = false; boolean retCode = false;
String jniError; String jniError;