Package org.sonatype.nexus.client.rest.jersey

Source Code of org.sonatype.nexus.client.rest.jersey.JerseyNexusClient

/*
* Sonatype Nexus (TM) Open Source Version
* Copyright (c) 2007-2014 Sonatype, Inc.
* All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
*
* This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
* which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
* of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
* Eclipse Foundation. All other trademarks are the property of their respective owners.
*/
package org.sonatype.nexus.client.rest.jersey;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;

import org.sonatype.nexus.client.core.Condition;
import org.sonatype.nexus.client.core.NexusClient;
import org.sonatype.nexus.client.core.NexusStatus;
import org.sonatype.nexus.client.core.exception.NexusClientAccessForbiddenException;
import org.sonatype.nexus.client.core.exception.NexusClientBadRequestException;
import org.sonatype.nexus.client.core.exception.NexusClientErrorResponseException;
import org.sonatype.nexus.client.core.exception.NexusClientException;
import org.sonatype.nexus.client.core.exception.NexusClientNotFoundException;
import org.sonatype.nexus.client.core.exception.NexusClientResponseException;
import org.sonatype.nexus.client.core.spi.SubsystemProvider;
import org.sonatype.nexus.client.internal.msg.ErrorMessage;
import org.sonatype.nexus.client.internal.msg.ErrorResponse;
import org.sonatype.nexus.client.internal.rest.AbstractXStreamNexusClient;
import org.sonatype.nexus.client.internal.util.Check;
import org.sonatype.nexus.client.rest.ConnectionInfo;
import org.sonatype.nexus.rest.model.StatusResource;
import org.sonatype.nexus.rest.model.StatusResourceResponse;
import org.sonatype.sisu.siesta.client.ClientBuilder;
import org.sonatype.sisu.siesta.client.ClientBuilder.Target.Factory;

import com.google.common.collect.Maps;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.thoughtworks.xstream.XStream;
import org.apache.commons.io.IOUtils;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

/**
* Jersey client with some extra fluff: it maintains reference to XStream used by Provider it uses, to make it able to
* pass XStream around (toward subsystems) to apply needed XStream configuration. As Nexus currently is married to
* XStream, this will probably change, hence, this class, as one of the implementations keeps the fact of XStream use
* encapsulated, I did not want to proliferate it through all of Nexus Client. This class should not be instantiated
* manually, use {@link JerseyNexusClientFactory} for it.
*
* @since 2.1
*/
public class JerseyNexusClient
    extends AbstractXStreamNexusClient
{

  private Client client;

  private final MediaType mediaType;

  private final List<SubsystemProvider> subsystemProviders;

  private final Map<Object, Object> context;

  public JerseyNexusClient(final Condition connectionCondition,
                           final List<SubsystemProvider> subsystemProviders,
                           final ConnectionInfo connectionInfo,
                           final XStream xstream,
                           final Client client,
                           final MediaType mediaType)
  {
    super(connectionInfo, xstream);
    this.client = Check.notNull(client, Client.class);
    this.mediaType = Check.notNull(mediaType, MediaType.class);
    this.subsystemProviders = subsystemProviders;
    getLogger().debug("Client created for media-type {} and connection {}", mediaType, connectionInfo);

    initializeConnection(connectionCondition);

    context = Maps.newHashMap();
    context.put(NexusClient.class, this);
    context.put(Factory.class, ClientBuilder.using(client).toAccess(connectionInfo.getBaseUrl().toUrl()));
  }

  public Client getClient() {
    return client;
  }

  public MediaType getMediaType() {
    return mediaType;
  }

  public String resolvePath(final String path) {
    // we need more logic here, but for now will do it ;)
    return getConnectionInfo().getBaseUrl() + path;
  }

  public String resolveServicePath(final String path) {
    // we need more logic here, but for now will do it ;)
    return resolvePath("service/local/" + path);
  }

  public WebResource.Builder serviceResource(final String uri) {
    return getClient()
        .resource(resolveServicePath(uri))
        .type(getMediaType())
        .accept(getMediaType());
  }

  public WebResource.Builder serviceResource(final String uri, final MultivaluedMap<String, String> queryParameters) {
    return getClient()
        .resource(resolveServicePath(uri))
        .queryParams(queryParameters)
        .type(getMediaType())
        .accept(getMediaType());
  }

  public WebResource.Builder uri(final String uri) {
    return getClient()
        .resource(resolvePath(uri))
        .getRequestBuilder();
  }

  public WebResource.Builder uri(final String uri, final MultivaluedMap<String, String> queryParameters) {
    return getClient()
        .resource(resolvePath(uri))
        .queryParams(queryParameters)
        .getRequestBuilder();
  }

  @Override
  public NexusStatus getStatus() {
    try {
      final StatusResource response = serviceResource("status")
          .get(StatusResourceResponse.class)
          .getData();
      return new NexusStatus(response.getAppName(), response.getFormattedAppName(), response.getVersion(),
          response.getApiVersion(), response.getEditionLong(), response.getEditionShort(), response.getState(),
          response.getInitializedAt(), response.getStartedAt(), response.getLastConfigChange(), -1,
          response.isFirstStart(), response.isInstanceUpgraded(), response.isConfigurationUpgraded(),
          response.getBaseUrl());
    }
    catch (UniformInterfaceException e) {
      throw convert(e);
    }
    catch (ClientHandlerException e) {
      throw convert(e);
    }
  }

  @Override
  public synchronized void close() {
    try {
      if (client != null) {
        client.destroy();
        client = null;
      }
    }
    finally {
      super.close();
    }
  }

  // ==

  @Override
  protected <S> S createSubsystem(final Class<S> subsystemType)
      throws IllegalArgumentException
  {
    checkNotNull(subsystemType, "subsystemType cannot be null");
    for (final SubsystemProvider subsystemProvider : subsystemProviders) {
      final Object subsystem = subsystemProvider.get(subsystemType, context);
      if (subsystem != null) {
        checkState(
            subsystemType.isAssignableFrom(subsystem.getClass()),
            "Subsystem '%s' created by '%s' is not an instance of '%s'",
            subsystem, subsystemProvider, subsystemType.getSimpleName()
        );
        return subsystemType.cast(subsystem);
      }
    }
    throw new IllegalArgumentException(
        "No " + SubsystemProvider.class.getName() + " was able to create a subsystem of type"
            + subsystemType.getName()
    );
  }

  public NexusClientNotFoundException convertIf404(final UniformInterfaceException e) {
    final ClientResponse response = e.getResponse();
    if (ClientResponse.Status.NOT_FOUND.equals(response.getClientResponseStatus())) {
      return new NexusClientNotFoundException(
          getMessageIfPresent(ClientResponse.Status.NOT_FOUND.getStatusCode(), e),
          response.getClientResponseStatus().getReasonPhrase(),
          getResponseBody(response)
      );
    }
    return null;
  }

  public NexusClientBadRequestException convertIf400(final UniformInterfaceException e) {
    final ClientResponse response = e.getResponse();
    if (ClientResponse.Status.BAD_REQUEST.equals(response.getClientResponseStatus())) {
      return new NexusClientBadRequestException(
          getMessageIfPresent(ClientResponse.Status.BAD_REQUEST.getStatusCode(), e),
          response.getClientResponseStatus().getReasonPhrase(),
          getResponseBody(response)
      );
    }
    return null;
  }

  public NexusClientAccessForbiddenException convertIf403(final UniformInterfaceException e) {
    final ClientResponse response = e.getResponse();
    if (ClientResponse.Status.FORBIDDEN.equals(response.getClientResponseStatus())) {
      return new NexusClientAccessForbiddenException(
          getMessageIfPresent(ClientResponse.Status.FORBIDDEN.getStatusCode(), e),
          response.getClientResponseStatus().getReasonPhrase(),
          getResponseBody(response)
      );
    }
    return null;
  }

  public NexusClientErrorResponseException convertIf400WithErrorMessage(final UniformInterfaceException e) {
    final ClientResponse response = e.getResponse();
    if (ClientResponse.Status.BAD_REQUEST.equals(response.getClientResponseStatus())) {
      final String body = getResponseBody(response);
      ErrorResponse errorResponse = null;
      try {
        errorResponse = (ErrorResponse) getXStream().fromXML(body, new ErrorResponse());
      }
      catch (Exception e1) {
        // ignore
        // XStreamException if body is not ErrorResponse
      }
      if (errorResponse != null) {
        // convert them to hide stupid "old" REST model, and not have it leak out
        final ArrayList<NexusClientErrorResponseException.ErrorMessage> errors =
            new ArrayList<NexusClientErrorResponseException.ErrorMessage>(errorResponse.getErrors().size());
        for (ErrorMessage message : errorResponse.getErrors()) {
          errors.add(
              new NexusClientErrorResponseException.ErrorMessage(message.getId(), message.getMsg()));
        }
        return new NexusClientErrorResponseException(
            response.getClientResponseStatus().getReasonPhrase(),
            body,
            errors
        );
      }
    }
    return null;
  }

  public NexusClientException convert(final UniformInterfaceException e) {
    NexusClientException exception = convertIfKnown(e);
    if (exception != null) {
      return exception;
    }

    return new NexusClientResponseException(
        getMessageIfPresent(e.getResponse().getClientResponseStatus().getStatusCode(), e),
        e.getResponse().getClientResponseStatus().getStatusCode(),
        e.getResponse().getClientResponseStatus().getReasonPhrase(),
        getResponseBody(e.getResponse())
    );
  }

  public NexusClientException convertIfKnown(final UniformInterfaceException e) {
    NexusClientException exception = convertIf404(e);
    if (exception != null) {
      return exception;
    }

    exception = convertIf403(e);
    if (exception != null) {
      return exception;
    }

    exception = convertIf400WithErrorMessage(e);
    if (exception != null) {
      return exception;
    }

    exception = convertIf400(e);
    if (exception != null) {
      return exception;
    }

    return null;
  }

  public NexusClientException convert(final ClientHandlerException e) {
    throw new NexusClientHandlerException(e);
  }

  public String getResponseBody(final ClientResponse response) {
    try {
      final byte[] body = IOUtils.toByteArray(response.getEntityInputStream());
      response.setEntityInputStream(new ByteArrayInputStream(body));
      return IOUtils.toString(body, "UTF-8");
    }
    catch (IOException e) {
      throw new IllegalStateException("Jersey unexpectedly refused to rewind buffered entity.");
    }
  }

  private String getMessageIfPresent(final int status, final UniformInterfaceException e) {
    if (e instanceof ContextAwareUniformInterfaceException) {
      return ((ContextAwareUniformInterfaceException) e).getMessage(status);
    }
    return null;
  }

}
TOP

Related Classes of org.sonatype.nexus.client.rest.jersey.JerseyNexusClient

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.