All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.reactivex.netty.contexts.ContextHolder Maven / Gradle / Ivy

There is a newer version: 0.5.1
Show newest version
/*
 * Copyright 2014 Netflix, Inc.
 *
 * 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 io.reactivex.netty.contexts;

import com.netflix.server.context.BiDirectional;
import com.netflix.server.context.ContextSerializationException;
import com.netflix.server.context.ContextSerializer;
import com.netflix.server.context.DirectionAwareContextSerializer;

/**
 * A holder of an contexts containing augmenting information about the context.
 *
 * @author Nitesh Kant ([email protected])
 */
class ContextHolder {

    private T context;
    private final String contextName;
    private DirectionAwareContextSerializer serializer;
    private String serialized;
    private String serializerClassName;
    private int serializedVersion;
    private String rawSerializedForm;
    private boolean updatedExternally;
    private final boolean receivedFromParent;
    private boolean biDirectional;

    private boolean isRaw;

    ContextHolder(T context, String contextName, ContextSerializer serializer) {
        this.context = context;
        this.contextName = contextName;
        this.serializer = unifySerializerTypes(serializer);
        serializerClassName = serializer.getClass().getName();
        biDirectional = context.getClass().getAnnotation(BiDirectional.class) != null;
        receivedFromParent = false;
    }

    ContextHolder(String contextName, String rawSerializedForm, boolean biDirectional) {
        this.contextName = contextName;
        this.rawSerializedForm = rawSerializedForm;
        this.biDirectional = biDirectional;
        receivedFromParent = true;
        isRaw = true;
    }

    String getRawSerializedForm() {
        return rawSerializedForm;
    }

    boolean hasRawSerializedForm() {
        return null != rawSerializedForm;
    }

    /**
     * Asserts whether this context is a raw context i.e. it just has raw serialized context and nothing else.
     *
     * @return {@code true} if this context is a raw context.
     */
    boolean isRaw() {
        return isRaw;
    }

    String getContextName() {
        return contextName;
    }

    /**
     * Returns whether there is a serialized representation of the context already present.
     *
     * @return {@code true}  if there is a serialized representation of the context already present.
     * {@code false} otherwise.
     */
    boolean hasSerialized() {
        return null != serialized;
    }

    /**
     * Returns whether there is a context instance already present.
     *
     * @return {@code true}  if there is a context instance already present. {@code false} otherwise.
     */
    boolean hasContext() {
        return null != context;
    }

    /**
     * Returns the serialized string, if present ({@link ContextHolder#hasSerialized()} returns
     * {@code true} ).
     *
     * @return The serialized string. {@code null}  if none exists.
     */
    String getSerialized() {
        return serialized;
    }

    /**
     * Returns the version of the serialized string, if present ({@link ContextHolder#hasSerialized()} returns
     * {@code true} ).
     *
     * @return The version of the serialized string, if present. -1 if the serialized string is not present.
     */
    int getSerializedVersion() {
        return serializedVersion;
    }

    /**
     * Returns the context, if present ({@link ContextHolder#hasContext()} returns {@code true} )
     *
     * @return The context or {@code null}  if none present.
     */
    T getContext() {
        return context;
    }

    /**
     * Returns if this context was updated externally as defined by
     * {@link ContextsContainer#addContext(String, Object, ContextSerializer)}
     *
     * @return {@code true} if this context was updated externally.
     */
    boolean isUpdatedExternally() {
        return updatedExternally;
    }

    /**
     * Returns whether this context was received from the caller of this service or it was created inside this service.
     *
     * @return {@code true} if received from the caller of this service. {@code false} otherwise.
     */
    public boolean isReceivedFromParent() {
        return receivedFromParent;
    }

    /**
     * Asserts whether this context should flow back from this service in response. 
* This will be true if & only if, *
  • The context is bidirectional i.e. {@link #isBiDirectional()} returns {@code true}
  • The context is updated externally i.e. {@link #isUpdatedExternally()} returns {@code true} OR the context is added for the first time in this service i.e. {@link #isReceivedFromParent()} returns {@code false}
* * @return {@code true} if the context should flow back, {@code false} otherwise. */ public boolean shouldFlowBackInResponse() { return isBiDirectional() && (isUpdatedExternally() || !isReceivedFromParent()); } /** * Sets that this context was updated externally i.e. by calling * {@link ContextsContainer#addContext(String, Object, ContextSerializer)} with a different value than what is * existing. */ void markAsUpdatedExternally() { updatedExternally = true; } boolean isBiDirectional() { return biDirectional; } /** * Returns the serializer associated with this context. This method will instantiate a serializer instance if it is * not already present via reflection for class name provided.

* In case, the serializer is {@link StringSerializer}, then {@link StringSerializer#INSTANCE} will be returned. * * @return The serializer for this context. * * @throws ContextSerializationException If the serializer is not found, not of required type or could not be * instantiated. */ @SuppressWarnings("unchecked") DirectionAwareContextSerializer getSerializer() throws ContextSerializationException { if(null != serializer) { return serializer; } if(null != serializerClassName) { if(serializerClassName.equals(StringSerializer.class.getName())) { return (DirectionAwareContextSerializer) StringSerializer.INSTANCE; } try { @SuppressWarnings("rawtypes") Class aClass = (Class) Class.forName(serializerClassName); serializer = unifySerializerTypes(aClass.newInstance()); return serializer; } catch (InstantiationException e) { throw new ContextSerializationException("Can not instantiate the serializer for class:" + serializerClassName, e); } catch (IllegalAccessException e) { throw new ContextSerializationException("Can not instantiate the serializer for class:" + serializerClassName, e); } catch (ClassNotFoundException e) { throw new ContextSerializationException("Can not instantiate the serializer for class:" + serializerClassName, e); } catch (ClassCastException e) { throw new ContextSerializationException("Serializer:" + serializerClassName + " is not of the required type.", e); } } throw new ContextSerializationException("No serializer found."); } @SuppressWarnings({"unchecked", "rawtypes"}) /* package private only for testing*/ContextSerializer getRawSerializer() throws ContextSerializationException { DirectionAwareContextSerializer serializer = getSerializer(); if (DirectionalSerializerAdapter.class.isAssignableFrom(serializer.getClass())) { return ((DirectionalSerializerAdapter) serializer).actualSerializer; } else { return serializer; } } static DirectionAwareContextSerializer unifySerializerTypes(ContextSerializer serializer) { return DirectionAwareContextSerializer.class.isAssignableFrom(serializer.getClass()) ? (DirectionAwareContextSerializer)serializer : new DirectionalSerializerAdapter(serializer); } @SuppressWarnings({"unchecked", "rawtypes"}) String getSerializerClassName() { if (null == serializerClassName && null != serializer && serializer.getClass().equals(DirectionalSerializerAdapter.class)) { return ((DirectionalSerializerAdapter)serializer).actualSerializer.getClass().getName(); } return serializerClassName; } void update(String serialized, int serializedVersion, String serializerClassName) { this.serialized = serialized; this.serializedVersion = serializedVersion; this.serializerClassName = serializerClassName; isRaw = false; } void update(T context) { this.context = context; biDirectional = context.getClass().getAnnotation(BiDirectional.class) != null; } private static class DirectionalSerializerAdapter implements DirectionAwareContextSerializer { private final ContextSerializer actualSerializer; private DirectionalSerializerAdapter(ContextSerializer actualSerializer) { this.actualSerializer = actualSerializer; } @Override public String serialize(T toSerialize, Direction direction) throws ContextSerializationException { return actualSerializer.serialize(toSerialize); } @Override public T deserialize(String serialized, Direction direction, int version) throws ContextSerializationException { return actualSerializer.deserialize(serialized, version); } @Override public int getVersion() { return actualSerializer.getVersion(); } @Override public String serialize(T toSerialize) throws ContextSerializationException { return actualSerializer.serialize(toSerialize); } @Override public T deserialize(String serialized, int version) throws ContextSerializationException { return actualSerializer.deserialize(serialized, version); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy