Package org.apache.clerezza.triaxrs.providers

Source Code of org.apache.clerezza.triaxrs.providers.ProvidersImpl

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.apache.clerezza.triaxrs.providers;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Providers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* An implementation of {@link Providers} that allows setting providers
* by instance and by class at construction or afterwards
*
* @author reto
*/
public class ProvidersImpl implements Providers {

  private Set<MessageBodyReader<?>> bodyReaders;
  private SelectableProviders<MessageBodyReader<?>> selectableBodyReaders;
  private Set<MessageBodyWriter<?>> bodyWriters;
  private SelectableProviders<MessageBodyWriter<?>> selectableBodyWriters;
  private Set<ExceptionMapper<?>> exceptionMappers;
  private Set<ContextResolver<?>> contextResolvers;
  private Logger logger = LoggerFactory.getLogger(ProvidersImpl.class);

  public ProvidersImpl() {
    bodyReaders =
        new HashSet<MessageBodyReader<?>>();
    bodyWriters =
        new HashSet<MessageBodyWriter<?>>();
    exceptionMappers = new HashSet<ExceptionMapper<?>>();
    contextResolvers = new HashSet<ContextResolver<?>>();
    this.selectableBodyReaders = selectableBodyReaderFromSet(bodyReaders);
    this.selectableBodyWriters = selectableBodyWritersFromSet(bodyWriters);
  }

  @SuppressWarnings("unchecked")
  public ProvidersImpl(Class<?>[] providerClasses) {
    bodyReaders =
        new HashSet<MessageBodyReader<?>>();
    bodyWriters =
        new HashSet<MessageBodyWriter<?>>();
    exceptionMappers = new HashSet<ExceptionMapper<?>>();
    contextResolvers = new HashSet<ContextResolver<?>>();
    Map<Class<?>, Set> typeSetMap = new HashMap<Class<?>, Set>();
    typeSetMap.put(MessageBodyReader.class, bodyReaders);
    typeSetMap.put(MessageBodyWriter.class, bodyWriters);
    typeSetMap.put(ExceptionMapper.class, exceptionMappers);
    typeSetMap.put(ContextResolver.class, contextResolvers);
    for (Class<?> providerClass : providerClasses) {
      for (Class<?> supportedClass : typeSetMap.keySet()) {
        if (supportedClass.isAssignableFrom(providerClass)) {
          try {
            (typeSetMap.get(supportedClass)).add(providerClass.
                newInstance());
          } catch (InstantiationException ex) {
            logger.error("Exception {}", ex);
          } catch (IllegalAccessException ex) {
            logger.error("Exception {}", ex);
          }
        }
      }

    }
    this.selectableBodyReaders = selectableBodyReaderFromSet(bodyReaders);
    this.selectableBodyWriters = selectableBodyWritersFromSet(bodyWriters);
  }

  public ProvidersImpl(Set<MessageBodyReader<?>> bodyReaders,
      Set<MessageBodyWriter<?>> bodyWriters,
      Set<ContextResolver<?>> contextResolvers,
      Set<ExceptionMapper<?>> exceptionMappers) {
    this.bodyReaders = bodyReaders;
    this.bodyWriters = bodyWriters;
    this.selectableBodyReaders = selectableBodyReaderFromSet(bodyReaders);
    this.selectableBodyWriters = selectableBodyWritersFromSet(bodyWriters);
    this.contextResolvers = contextResolvers;
    this.exceptionMappers = exceptionMappers;
  }

  public void addClass(Class<?> componentClass) {
    try {
      addInstance(componentClass.newInstance());
    } catch (InstantiationException ex) {
      logger.error("Exception {}", ex);
    } catch (IllegalAccessException ex) {
      logger.error("Exception {}", ex);
    }
  }

  public void addInstance(Object component) {
    if (component instanceof MessageBodyWriter) {
      bodyWriters.add((MessageBodyWriter<?>) component);
      selectableBodyWriters = selectableBodyWritersFromSet(bodyWriters);
      return;
    }
    if (component instanceof MessageBodyReader) {
      bodyReaders.add((MessageBodyReader<?>) component);
      selectableBodyReaders = selectableBodyReaderFromSet(bodyReaders);
      return;
    }
    if (component instanceof ExceptionMapper) {
      exceptionMappers.add((ExceptionMapper<?>) component);
      return;
    }
    throw new RuntimeException("unsupported provider component "+component);
  }


  @Override
  public <T> ContextResolver<T> getContextResolver(Class<T> contextType,
      MediaType mediaType) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public Set<ContextResolver<?>> getContextResolvers() {
    return contextResolvers;
  }

  @Override
  public <T extends Throwable> ExceptionMapper<T> getExceptionMapper(final Class<T> clazz) {
    //Get an exception mapping provider for a particular class of exception.
    //Returns the provider whose generic type is the nearest superclass of type.
    if (!Exception.class.isAssignableFrom(clazz)) {
      return null;
    }
    Class<?> checkedClass = clazz;
    while (true) {
      ExceptionMapper exceptionMapper = getExceptionMapperForExactType(
          checkedClass);
      if (exceptionMapper != null) {
        return exceptionMapper;
      }
      if (checkedClass == Throwable.class) {
        return null;
      }
      checkedClass = checkedClass.getSuperclass();
    }
  }

  boolean isEmpty() {
    return (bodyReaders.isEmpty() && bodyWriters.isEmpty() &&
        exceptionMappers.isEmpty() && contextResolvers.isEmpty());
  }

  void removeInstance(Object component) {
    if (component instanceof MessageBodyWriter) {
      bodyWriters.remove((MessageBodyWriter<?>) component);
      selectableBodyWriters = selectableBodyWritersFromSet(bodyWriters);
      return;
    }
    if (component instanceof MessageBodyReader) {
      bodyReaders.remove((MessageBodyReader<?>) component);
      selectableBodyReaders = selectableBodyReaderFromSet(bodyReaders);
      return;
    }
    if (component instanceof ExceptionMapper) {
      exceptionMappers.remove((ExceptionMapper<?>) component);
      return;
    }
    throw new RuntimeException("unsupported provider component "+component);
  }

  private ExceptionMapper getExceptionMapperForExactType(Class<?> clazz) {
    for (ExceptionMapper<?> exceptionMapper : exceptionMappers) {
      for (Type type : exceptionMapper.getClass().getGenericInterfaces()) {
        if (type instanceof ParameterizedType) {
          ParameterizedType parameterizedType =
              (ParameterizedType) type;
          if (parameterizedType.getRawType() == ExceptionMapper.class) {
            if (parameterizedType.getActualTypeArguments()[0].equals(
                clazz)) {
              return exceptionMapper;
            }
          }
        }
      }
    }
    return null;
  }



  @SuppressWarnings("unchecked")
  @Override
  public <T> MessageBodyReader<T> getMessageBodyReader(Class<T> c, Type t,
      Annotation[] as, MediaType mediaType) {
    return (MessageBodyReader<T>) selectableBodyReaders.selectFor(c, t, as,
        mediaType);

  }

  @Override
  @SuppressWarnings("unchecked")
  public <T> MessageBodyWriter<T> getMessageBodyWriter(Class<T> c,
      Type t, Annotation[] as, MediaType mediaType) {
    return (MessageBodyWriter<T>) selectableBodyWriters.selectFor(c, t, as,
        mediaType);
  }

  private SelectableProviders<MessageBodyReader<?>> selectableBodyReaderFromSet(
      Set<MessageBodyReader<?>> bodyReaders) {
    return new SelectableProviders<MessageBodyReader<?>>(
        bodyReaders, new ProviderCriteria<MessageBodyReader<?>>() {

      @Override
      public boolean isAcceptable(MessageBodyReader<?> messageBodyReader,
          Class<?> c, Type t, Annotation[] as, MediaType m) {
        return messageBodyReader.isReadable(c, t, as, m);
      }

      @Override
      public String[] getMediaTypeAnnotationValues(
          MessageBodyReader<?> producer) {
        Consumes consumes = producer.getClass().getAnnotation(
            Consumes.class);
        if (consumes == null) {
          return null;
        } else {
          return consumes.value();
        }
      }
    });
  }

  private SelectableProviders<MessageBodyWriter<?>> selectableBodyWritersFromSet(
      Set<MessageBodyWriter<?>> bodyWriters) {
    return new SelectableProviders<MessageBodyWriter<?>>(
        bodyWriters, new ProviderCriteria<MessageBodyWriter<?>>() {

      @Override
      public boolean isAcceptable(MessageBodyWriter<?> messageBodyWriter,
          Class<?> c, Type t, Annotation[] as, MediaType m) {
        return messageBodyWriter.isWriteable(c, t, as, m);
      }
     
      @Override
      public String[] getMediaTypeAnnotationValues(
          MessageBodyWriter<?> producer) {
        Produces produces = producer.getClass().getAnnotation(
            Produces.class);
        if (produces == null) {
          return null;
        } else {
          return produces.value();
        }
      }
    });
  }
}
TOP

Related Classes of org.apache.clerezza.triaxrs.providers.ProvidersImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.