com.digitalpetri.opcua.stack.core.serialization.DelegateRegistry.java Source code

Java tutorial

Introduction

Here is the source code for com.digitalpetri.opcua.stack.core.serialization.DelegateRegistry.java

Source

/*
 * Copyright 2015 Kevin Herron
 *
 * 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 com.digitalpetri.opcua.stack.core.serialization;

import java.io.IOException;
import java.util.Arrays;
import java.util.Map;

import com.digitalpetri.opcua.stack.core.Stack;
import com.digitalpetri.opcua.stack.core.StatusCodes;
import com.digitalpetri.opcua.stack.core.UaSerializationException;
import com.digitalpetri.opcua.stack.core.types.builtin.NodeId;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.reflect.ClassPath;
import com.google.common.reflect.ClassPath.ClassInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DelegateRegistry {

    private static final Map<Class<?>, EncoderDelegate<?>> encodersByClass = Maps.newConcurrentMap();

    private static final Map<NodeId, EncoderDelegate<?>> encodersById = Maps.newConcurrentMap();

    private static final Map<Class<?>, DecoderDelegate<?>> decodersByClass = Maps.newConcurrentMap();

    private static final Map<NodeId, DecoderDelegate<?>> decodersById = Maps.newConcurrentMap();

    public static <T> void registerEncoder(EncoderDelegate<T> delegate, Class<T> clazz, NodeId... ids) {
        encodersByClass.put(clazz, delegate);

        if (ids != null) {
            Arrays.stream(ids).forEach(id -> encodersById.put(id, delegate));
        }
    }

    public static <T> void registerDecoder(DecoderDelegate<T> delegate, Class<T> clazz, NodeId... ids) {
        decodersByClass.put(clazz, delegate);

        if (ids != null) {
            Arrays.stream(ids).forEach(id -> decodersById.put(id, delegate));
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> EncoderDelegate<T> getEncoder(Object t) throws UaSerializationException {
        try {
            return (EncoderDelegate<T>) encodersByClass.get(t.getClass());
        } catch (NullPointerException e) {
            throw new UaSerializationException(StatusCodes.Bad_EncodingError,
                    "no encoder registered for class=" + t);
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> EncoderDelegate<T> getEncoder(Class<?> clazz) throws UaSerializationException {
        try {
            return (EncoderDelegate<T>) encodersByClass.get(clazz);
        } catch (NullPointerException e) {
            throw new UaSerializationException(StatusCodes.Bad_EncodingError,
                    "no encoder registered for class=" + clazz);
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> EncoderDelegate<T> getEncoder(NodeId encodingId) throws UaSerializationException {
        try {
            return (EncoderDelegate<T>) encodersById.get(encodingId);
        } catch (NullPointerException e) {
            throw new UaSerializationException(StatusCodes.Bad_EncodingError,
                    "no encoder registered for encodingId=" + encodingId);
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> DecoderDelegate<T> getDecoder(T t) throws UaSerializationException {
        try {
            return (DecoderDelegate<T>) decodersByClass.get(t.getClass());
        } catch (NullPointerException e) {
            throw new UaSerializationException(StatusCodes.Bad_DecodingError,
                    "no decoder registered for class=" + t);
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> DecoderDelegate<T> getDecoder(Class<T> clazz) throws UaSerializationException {
        try {
            return (DecoderDelegate<T>) decodersByClass.get(clazz);
        } catch (NullPointerException e) {
            throw new UaSerializationException(StatusCodes.Bad_DecodingError,
                    "no decoder registered for class=" + clazz);
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> DecoderDelegate<T> getDecoder(NodeId encodingId) {
        DecoderDelegate<T> decoder = (DecoderDelegate<T>) decodersById.get(encodingId);

        if (decoder == null) {
            throw new UaSerializationException(StatusCodes.Bad_DecodingError,
                    "no decoder registered for encodingId=" + encodingId);
        }

        return decoder;
    }

    static {
        /*
         * Reflect-o-magically find all generated structured and enumerated types and force their static initialization
         * blocks to run, registering their encode/decode methods with the delegate registry.
         */
        Logger logger = LoggerFactory.getLogger(DelegateRegistry.class);

        ClassLoader classLoader = Stack.getCustomClassLoader().orElse(DelegateRegistry.class.getClassLoader());

        try {
            loadGeneratedClasses(classLoader);
        } catch (Exception e1) {
            // Temporarily set the thread context ClassLoader to our
            // ClassLoader and try loading the classes one more time.

            Thread thread = Thread.currentThread();
            ClassLoader contextClassLoader = thread.getContextClassLoader();

            thread.setContextClassLoader(classLoader);

            try {
                loadGeneratedClasses(classLoader);
            } catch (Exception e2) {
                logger.error("Error loading generated classes.", e2);
            } finally {
                thread.setContextClassLoader(contextClassLoader);
            }
        }
    }

    private static void loadGeneratedClasses(ClassLoader classLoader) throws IOException, ClassNotFoundException {
        ClassPath classPath = ClassPath.from(classLoader);

        ImmutableSet<ClassInfo> structures = classPath
                .getTopLevelClasses("com.digitalpetri.opcua.stack.core.types.structured");

        ImmutableSet<ClassInfo> enumerations = classPath
                .getTopLevelClasses("com.digitalpetri.opcua.stack.core.types.enumerated");

        for (ClassInfo classInfo : Sets.union(structures, enumerations)) {
            Class<?> clazz = classInfo.load();
            Class.forName(clazz.getName(), true, classLoader);
        }
    }

}