All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gerrit.server.tools.ToolsCatalog Maven / Gradle / Ivy

There is a newer version: 3.11.0-rc3
Show newest version
// Copyright (C) 2010 The Android Open Source Project
//
// 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.google.gerrit.server.tools;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.Strings;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.Version;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.util.RawParseUtils;

/**
 * Listing of all client side tools stored on this server.
 *
 * 

Clients may download these tools through our file server, as they are packaged with our own * software releases. */ @Singleton public class ToolsCatalog { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); private final SortedMap toc; @Inject ToolsCatalog() throws IOException { this.toc = readToc(); } /** * Lookup an entry in the tools catalog. * * @param name path of the item, relative to the root of the catalog. * @return the entry; null if the item is not part of the catalog. */ @Nullable public Entry get(@Nullable String name) { if (Strings.isNullOrEmpty(name)) { return null; } if (name.startsWith("/")) { name = name.substring(1); } if (name.endsWith("/")) { name = name.substring(0, name.length() - 1); } return toc.get(name); } private static SortedMap readToc() throws IOException { SortedMap toc = new TreeMap<>(); final BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(read("TOC")), UTF_8)); String line; while ((line = br.readLine()) != null) { if (line.length() > 0 && !line.startsWith("#")) { final Entry e = new Entry(Entry.Type.FILE, line); toc.put(e.getPath(), e); } } final List all = new ArrayList<>(toc.values()); for (Entry e : all) { String path = dirOf(e.getPath()); while (path != null) { Entry d = toc.get(path); if (d == null) { d = new Entry(Entry.Type.DIR, 0755, path); toc.put(d.getPath(), d); } d.children.add(e); path = dirOf(path); e = d; } } final Entry top = new Entry(Entry.Type.DIR, 0755, ""); for (Entry e : toc.values()) { if (dirOf(e.getPath()) == null) { top.children.add(e); } } toc.put(top.getPath(), top); return Collections.unmodifiableSortedMap(toc); } @Nullable private static byte[] read(String path) { String name = "root/" + path; try (InputStream in = ToolsCatalog.class.getResourceAsStream(name)) { if (in == null) { return null; } final ByteArrayOutputStream out = new ByteArrayOutputStream(); final byte[] buf = new byte[8192]; int n; while ((n = in.read(buf, 0, buf.length)) > 0) { out.write(buf, 0, n); } return out.toByteArray(); } catch (Exception e) { logger.atFine().withCause(e).log("Cannot read %s", path); return null; } } @Nullable private static String dirOf(String path) { final int s = path.lastIndexOf('/'); return s < 0 ? null : path.substring(0, s); } /** A file served out of the tools root directory. */ public static class Entry { public enum Type { DIR, FILE } private final Type type; private final int mode; private final String path; private final List children; Entry(Type type, String line) { int s = line.indexOf(' '); String mode = line.substring(0, s); String path = line.substring(s + 1); this.type = type; this.mode = Integer.parseInt(mode, 8); this.path = path; if (type == Type.FILE) { this.children = Collections.emptyList(); } else { this.children = new ArrayList<>(); } } Entry(Type type, int mode, String path) { this.type = type; this.mode = mode; this.path = path; this.children = new ArrayList<>(); } public Type getType() { return type; } /** @return the preferred UNIX file mode, e.g. {@code 0755}. */ public int getMode() { return mode; } /** @return path of the entry, relative to the catalog root. */ public String getPath() { return path; } /** @return name of the entry, within its parent directory. */ public String getName() { final int s = path.lastIndexOf('/'); return s < 0 ? path : path.substring(s + 1); } /** @return collection of entries below this one, if this is a directory. */ public List getChildren() { return Collections.unmodifiableList(children); } /** @return a copy of the file's contents. */ public byte[] getBytes() { byte[] data = read(getPath()); if (isScript(data)) { // Embed Gerrit's version number into the top of the script. // final String version = Version.getVersion(); final int lf = RawParseUtils.nextLF(data, 0); if (version != null && lf < data.length) { byte[] versionHeader = Constants.encode("# From Gerrit Code Review " + version + "\n"); ByteArrayOutputStream buf = new ByteArrayOutputStream(); buf.write(data, 0, lf); buf.write(versionHeader, 0, versionHeader.length); buf.write(data, lf, data.length - lf); data = buf.toByteArray(); } } return data; } private boolean isScript(byte[] data) { return data != null && data.length > 3 // && data[0] == '#' // && data[1] == '!' // && data[2] == '/'; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy