Package org.sonatype.nexus.content.internal

Source Code of org.sonatype.nexus.content.internal.VelocityContentRenderer$CollectionEntry

/*
* 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.content.internal;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.sonatype.nexus.SystemStatus;
import org.sonatype.nexus.proxy.ItemNotFoundException;
import org.sonatype.nexus.proxy.ItemNotFoundException.ItemNotFoundInRepositoryReason;
import org.sonatype.nexus.proxy.ItemNotFoundException.ItemNotFoundReason;
import org.sonatype.nexus.proxy.RequestContext;
import org.sonatype.nexus.proxy.ResourceStoreRequest;
import org.sonatype.nexus.proxy.attributes.Attributes;
import org.sonatype.nexus.proxy.item.StorageCollectionItem;
import org.sonatype.nexus.proxy.item.StorageCompositeItem;
import org.sonatype.nexus.proxy.item.StorageFileItem;
import org.sonatype.nexus.proxy.item.StorageItem;
import org.sonatype.nexus.proxy.item.uid.IsHiddenAttribute;
import org.sonatype.nexus.proxy.repository.GroupItemNotFoundException;
import org.sonatype.nexus.proxy.repository.Repository;
import org.sonatype.nexus.web.BaseUrlHolder;
import org.sonatype.nexus.web.TemplateRenderer;
import org.sonatype.sisu.goodies.common.ComponentSupport;
import org.sonatype.sisu.goodies.common.Iso8601Date;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

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

/**
* Implementation of {@link ContentRenderer} using Apache Velocity.
*
* @since 2.8
*/
@Singleton
@Named
public class VelocityContentRenderer
    extends ComponentSupport
    implements ContentRenderer
{
  private final TemplateRenderer templateRenderer;

  private final String applicationVersion;

  @Inject
  public VelocityContentRenderer(final TemplateRenderer templateRenderer,
                                 final Provider<SystemStatus> systemStatusProvider)
  {
    this.templateRenderer = checkNotNull(templateRenderer);
    this.applicationVersion = checkNotNull(systemStatusProvider).get().getVersion();
  }

  @Override
  public void renderCollection(final HttpServletRequest request,
                               final HttpServletResponse response,
                               final StorageCollectionItem coll,
                               final Collection<StorageItem> children)
      throws IOException
  {
    final Set<String> uniqueNames = Sets.newHashSetWithExpectedSize(children.size());
    final List<CollectionEntry> entries = Lists.newArrayListWithCapacity(children.size());
   
    // use request URL (it does not contain any parameters) as the base URL of collection entries
    final String collUrl = BaseUrlHolder.get() + request.getServletPath() + request.getPathInfo();
    for (StorageItem child : children) {
      if (child.isVirtual() || !child.getRepositoryItemUid().getBooleanAttributeValue(IsHiddenAttribute.class)) {
        if (!uniqueNames.contains(child.getName())) {
          final boolean isCollection = child instanceof StorageCollectionItem;
          final String name = isCollection ? child.getName() + "/" : child.getName();
          final CollectionEntry entry = new CollectionEntry(name, isCollection, collUrl + name,
              new Date(child.getModified()), StorageFileItem.class.isAssignableFrom(child
              .getClass()) ? ((StorageFileItem) child).getLength() : -1, "");
          entries.add(entry);
          uniqueNames.add(child.getName());
        }
      }
    }

    Collections.sort(entries, new CollectionEntryComparator());

    final Map<String, Object> dataModel = createBaseModel();
    dataModel.put("requestPath", coll.getPath());
    dataModel.put("listItems", entries);
    templateRenderer.render(templateRenderer.template("/org/sonatype/nexus/content/internal/repositoryContentHtml.vm",
        getClass().getClassLoader()), dataModel, response);
  }

  @Override
  public void renderRequestDescription(final HttpServletRequest request,
                                       final HttpServletResponse response,
                                       final ResourceStoreRequest resourceStoreRequest,
                                       final StorageItem item,
                                       final Exception exception)
      throws IOException
  {
    final Map<String, Object> dataModel = createBaseModel();
    dataModel.put("req", resourceStoreRequest);
    if (item != null) {
      dataModel.put("item", item);
      dataModel.put("itemContext", filterItemContext(item.getItemContext()).flatten());
      dataModel.put("itemAttributes", filterItemAttributes(item.getRepositoryItemAttributes()));
      if (item instanceof StorageCompositeItem) {
        final StorageCompositeItem compositeItem = (StorageCompositeItem) item;
        final List<String> sources = Lists.newArrayList();
        for (StorageItem source : compositeItem.getSources()) {
          if (!source.isVirtual()) {
            sources.add(source.getRepositoryItemUid().toString());
          }
          else {
            sources.add(source.getPath());
          }
        }
        dataModel.put("compositeSources", sources);
      }
    }
    dataModel.put("exception", exception);
    final Reasoning reasoning = buildReasoning(exception);
    if (reasoning != null) {
      dataModel.put("reasoning", reasoning);
    }
    templateRenderer.render(templateRenderer.template("/org/sonatype/nexus/content/internal/requestDescriptionHtml.vm",
        getClass().getClassLoader()), dataModel, response);
  }

  // ==

  private RequestContext filterItemContext(final RequestContext itemContext) {
    final RequestContext filtered = new RequestContext();
    filtered.setParentContext(itemContext);
    return filtered;
  }

  private Map<String, String> filterItemAttributes(final Attributes itemAttributes) {
    final Map<String, String> filtered = Maps.newHashMap();
    filtered.putAll(itemAttributes.asMap());
    final String remoteUrl = filtered.get("storageItem-remoteUrl");
   
    // strip params from secure central remote urls
    if (remoteUrl != null && remoteUrl.startsWith("https://secure.central.sonatype.com/")) {
      int qpIdx = remoteUrl.indexOf("?");
      if (qpIdx > -1) {
        filtered.put("storageItem-remoteUrl", remoteUrl.substring(0, qpIdx) + "?truncated");
      }
    }
    return filtered;
  }

  private Reasoning buildReasoning(final Throwable ex) {
    if (ex instanceof ItemNotFoundException) {
      final ItemNotFoundReason reason = ((ItemNotFoundException) ex).getReason();
      if (reason instanceof ItemNotFoundInRepositoryReason) {
        return buildReasoning(((ItemNotFoundInRepositoryReason) reason).getRepository().getId(), ex);
      }
    }
    return null;
  }

  private Reasoning buildReasoning(final String repositoryId, final Throwable ex) {
    final Reasoning result = new Reasoning(repositoryId, ex.getMessage());
    if (ex instanceof GroupItemNotFoundException) {
      final GroupItemNotFoundException ginfex = (GroupItemNotFoundException) ex;
      for (Entry<Repository, Throwable> memberReason : ginfex.getMemberReasons().entrySet()) {
        result.getMembers().add(buildReasoning(memberReason.getKey().getId(), memberReason.getValue()));
      }
    }
    return result;
  }

  /**
   * This class is public only for Velocity access only, as it's used in "describe" page template to render
   * "reasoning", see methods above {@link #buildReasoning(Throwable)} and {@link #buildReasoning(String, Throwable)}.
   */
  public static class Reasoning
  {
    private final String repositoryId;

    private final String reason;

    private final List<Reasoning> members;

    public Reasoning(final String repositoryId, final String reason) {
      this.repositoryId = checkNotNull(repositoryId);
      this.reason = checkNotNull(reason);
      this.members = Lists.newArrayList();
    }

    public String getRepositoryId() {
      return repositoryId;
    }

    public String getReason() {
      return reason;
    }

    public List<Reasoning> getMembers() {
      return members;
    }
  }

  // ==

  private Map<String, Object> createBaseModel() {
    final Map<String, Object> dataModel = Maps.newHashMap();
    dataModel.put("nexusRoot", BaseUrlHolder.get());
    dataModel.put("nexusVersion", applicationVersion);
    return dataModel;
  }

  // =

  private static class CollectionEntryComparator
      implements Comparator<CollectionEntry>
  {
    @Override
    public int compare(final CollectionEntry o1, final CollectionEntry o2) {
      if (o1.isCollection()) {
        if (o2.isCollection()) {
          // 2 directories, do a path compare
          return o1.getName().compareTo(o2.getName());
        }
        else {
          // first item is a dir, second is a file, dirs always win
          return -1;
        }
      }
      else if (o2.isCollection()) {
        // first item is a file, second is a dir, dirs always win
        return 1;
      }
      else {
        // 2 files, do a path compare
        return o1.getName().compareTo(o2.getName());
      }
    }
  }

  /**
   * Entry exposed to template for rendering.
   */
  //@TemplateAccessible
  public static class CollectionEntry
  {
    private final String name;

    private final boolean collection;

    private final String resourceUri;

    private final Date lastModified;

    private final long size;

    private final String description;

    public CollectionEntry(final String name,
                           final boolean collection,
                           final String resourceUri,
                           final Date lastModified,
                           final long size,
                           final String description)
    {
      this.name = checkNotNull(name);
      this.collection = collection;
      this.resourceUri = checkNotNull(resourceUri);
      this.lastModified = checkNotNull(lastModified);
      this.size = size;
      this.description = description;
    }

    public String getName() {
      return name;
    }

    public boolean isCollection() {
      return collection;
    }

    public String getResourceUri() {
      return resourceUri;
    }

    public Date getLastModified() {
      return lastModified;
    }

    public String getLastModifiedIso8601() {
      return Iso8601Date.format(getLastModified());
    }

    public long getSize() {
      return size;
    }

    public String getDescription() {
      return description;
    }
  }
}
TOP

Related Classes of org.sonatype.nexus.content.internal.VelocityContentRenderer$CollectionEntry

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.
ga('create', 'UA-20639858-1', 'auto'); ga('send', 'pageview');