FileLfsRepository.java

  1. /*
  2.  * Copyright (C) 2015, Matthias Sohn <matthias.sohn@sap.com> and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */
  10. package org.eclipse.jgit.lfs.server.fs;

  11. import static org.eclipse.jgit.util.HttpSupport.HDR_AUTHORIZATION;

  12. import java.io.IOException;
  13. import java.nio.channels.FileChannel;
  14. import java.nio.channels.ReadableByteChannel;
  15. import java.nio.file.Files;
  16. import java.nio.file.Path;
  17. import java.nio.file.StandardOpenOption;
  18. import java.util.Collections;

  19. import org.eclipse.jgit.annotations.Nullable;
  20. import org.eclipse.jgit.lfs.internal.AtomicObjectOutputStream;
  21. import org.eclipse.jgit.lfs.lib.AnyLongObjectId;
  22. import org.eclipse.jgit.lfs.lib.Constants;
  23. import org.eclipse.jgit.lfs.server.LargeFileRepository;
  24. import org.eclipse.jgit.lfs.server.Response;
  25. import org.eclipse.jgit.lfs.server.Response.Action;

  26. /**
  27.  * Repository storing large objects in the file system
  28.  *
  29.  * @since 4.3
  30.  */
  31. public class FileLfsRepository implements LargeFileRepository {

  32.     private String url;
  33.     private final Path dir;

  34.     /**
  35.      * <p>Constructor for FileLfsRepository.</p>
  36.      *
  37.      * @param url
  38.      *            external URL of this repository
  39.      * @param dir
  40.      *            storage directory
  41.      * @throws java.io.IOException
  42.      */
  43.     public FileLfsRepository(String url, Path dir) throws IOException {
  44.         this.url = url;
  45.         this.dir = dir;
  46.         Files.createDirectories(dir);
  47.     }

  48.     /** {@inheritDoc} */
  49.     @Override
  50.     public Response.Action getDownloadAction(AnyLongObjectId id) {
  51.         return getAction(id);
  52.     }

  53.     /** {@inheritDoc} */
  54.     @Override
  55.     public Action getUploadAction(AnyLongObjectId id, long size) {
  56.         return getAction(id);
  57.     }

  58.     /** {@inheritDoc} */
  59.     @Override
  60.     @Nullable
  61.     public Action getVerifyAction(AnyLongObjectId id) {
  62.         return null;
  63.     }

  64.     /** {@inheritDoc} */
  65.     @Override
  66.     public long getSize(AnyLongObjectId id) throws IOException {
  67.         Path p = getPath(id);
  68.         if (Files.exists(p)) {
  69.             return Files.size(p);
  70.         }
  71.         return -1;
  72.     }

  73.     /**
  74.      * Get the storage directory
  75.      *
  76.      * @return the path of the storage directory
  77.      */
  78.     public Path getDir() {
  79.         return dir;
  80.     }

  81.     /**
  82.      * Get the path where the given object is stored
  83.      *
  84.      * @param id
  85.      *            id of a large object
  86.      * @return path the object's storage path
  87.      */
  88.     protected Path getPath(AnyLongObjectId id) {
  89.         StringBuilder s = new StringBuilder(
  90.                 Constants.LONG_OBJECT_ID_STRING_LENGTH + 6);
  91.         s.append(toHexCharArray(id.getFirstByte())).append('/');
  92.         s.append(toHexCharArray(id.getSecondByte())).append('/');
  93.         s.append(id.name());
  94.         return dir.resolve(s.toString());
  95.     }

  96.     private Response.Action getAction(AnyLongObjectId id) {
  97.         Response.Action a = new Response.Action();
  98.         a.href = url + id.getName();
  99.         a.header = Collections.singletonMap(HDR_AUTHORIZATION, "not:required"); //$NON-NLS-1$
  100.         return a;
  101.     }

  102.     ReadableByteChannel getReadChannel(AnyLongObjectId id)
  103.             throws IOException {
  104.         return FileChannel.open(getPath(id), StandardOpenOption.READ);
  105.     }

  106.     AtomicObjectOutputStream getOutputStream(AnyLongObjectId id)
  107.             throws IOException {
  108.         Path path = getPath(id);
  109.         Path parent = path.getParent();
  110.         if (parent != null) {
  111.             Files.createDirectories(parent);
  112.         }
  113.         return new AtomicObjectOutputStream(path, id);
  114.     }

  115.     private static char[] toHexCharArray(int b) {
  116.         final char[] dst = new char[2];
  117.         formatHexChar(dst, 0, b);
  118.         return dst;
  119.     }

  120.     private static final char[] hexchar = { '0', '1', '2', '3', '4', '5', '6',
  121.             '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

  122.     private static void formatHexChar(char[] dst, int p, int b) {
  123.         int o = p + 1;
  124.         while (o >= p && b != 0) {
  125.             dst[o--] = hexchar[b & 0xf];
  126.             b >>>= 4;
  127.         }
  128.         while (o >= p)
  129.             dst[o--] = '0';
  130.     }

  131.     /**
  132.      * @return the url of the content server
  133.      * @since 4.11
  134.      */
  135.     public String getUrl() {
  136.         return url;
  137.     }

  138.     /**
  139.      * @param url
  140.      *            the url of the content server
  141.      * @since 4.11
  142.      */
  143.     public void setUrl(String url) {
  144.         this.url = url;
  145.     }
  146. }