private function deserializeClass(Clazz $instanceClass, $instance) { /** * A map from field names to corresponding setter methods. The reference * will be null for classes that do not require special handling for * server-only fields. */ $setters = null; /** * A list of fields of this class known to the client. If null, assume the class is not * enhanced and don't attempt to deal with server-only fields. */ $clientFieldNames = $this->serializationPolicy->getClientFieldNamesForEnhancedClass($instanceClass); if (!is_null($clientFieldNames)) { // Read and set server-only instance fields encoded in RPC data try { $encodedData = $this->readString(); if (!is_null($encodedData)) { $serializedData = Base64Utils::fromBase6($encodedData); $ois = new ObjectInputStream($serializedData); $count = $ois->readInt(); for ($i = 0; $i < $count; $i++) { $fieldName = $ois->readString(); $fieldValue = $ois->readObject(); $field = $instanceClass->getField($fieldName); $field->setAccessible(true); $field->setValue($instance, $fieldValue); } } } catch (Exception $e) { throw new SerializationException($e); } $setters = $this->getSetters($instanceClass); } $serializableFields = SerializabilityUtilEx::applyFieldSerializationPolicy($instanceClass); foreach ($serializableFields as $declField) { assert(!is_null($declField)); if (!is_null($clientFieldNames) && !$clientFieldNames->contains($declField->getName())) { continue; } assert($declField->hasType()); $value = $this->deserializeValue($declField->getType()); $fieldName = $declField->getName(); $setter = null; /* * If setters is non-null and there is a setter method for the given * field, call the setter. Otherwise, set the field value directly. For * persistence APIs such as JDO, the setter methods have been enhanced to * manipulate additional object state, causing direct field writes to fail * to update the object state properly. */ if (!is_null($setters) && !is_null($setters = $setters->get($fieldName))) { $setter->invoke($instance, $value); } else { $isAccessible = $declField->isAccessible(); $needsAccessOverride = !$isAccessible && !$declField->isPublic(); if ($needsAccessOverride) { // Override access restrictions $declField->setAccessible(true); } $declField->setValue($instance, $value); } } $superClass = $instanceClass->getSuperClass(); if ($this->serializationPolicy->shouldDeserializeFields($superClass)) { $this->deserializeImpl(SerializabilityUtilEx::hasCustomFieldSerializer($superClass), $superClass, $instance); } }
private function serializeClass($instance, Clazz $instanceClass) { assert(!is_null($instance)); $serializableFields = SerializabilityUtilEx::applyFieldSerializationPolicy($instanceClass); /* * If clientFieldNames is non-null, identify any additional server-only fields and serialize * them separately. Java serialization is used to construct a byte array, which is encoded * as a String and written prior to the rest of the field data. */ $clientFieldNames = $this->serializationPolicy->getClientFieldNamesForEnhancedClass($instanceClass); if (!is_null($clientFieldNames)) { $serverFields = array(); foreach ($serializableFields as $declField) { assert(!is_null($declField)); // Identity server-only fields if (!$clientFieldNames->contains($declField->getName())) { $serverFields[] = $declField; continue; } } // Serialize the server-only fields into a byte array and encode as a String $oos = new ObjectOutputStream(); $oos->writeInt(count($serverFields)); foreach ($serverFields as $f) { $oos->writeObject($f->getName()); $f->setAccessible(true); $fieldData = $f->get($instance); $oos->writeObject($fieldData); } $oos->close(); $encodedData = Base64Utils::toBase64((string) $oos); $this->writeString($encodedData); } // Write the client-visible field data foreach ($serializableFields as $declField) { if (!is_null($clientFieldNames) && !$clientFieldNames->contains($decl->getName())) { // Skip server-only fields continue; } $isAccessible = $declField->isAccessible(); $needsAccessOverride = !$isAccessible && !$declField->isPublic(); if ($needsAccessOverride) { // Override the access restrictions $declField->setAccessible(true); } $value = $declField->getValue($instance); $this->serializeValue($value, $declField->getType()); } $superClass = $instanceClass->getSuperClass(); if ($this->serializationPolicy->shouldSerializeFields($superClass)) { $this->serializeImpl($instance, $superClass); } }