Package aQute.library.bnd

Source Code of aQute.library.bnd.Index$Repo

package aQute.library.bnd;

import java.io.*;
import java.net.*;
import java.util.*;

import aQute.bnd.version.*;
import aQute.lib.converter.*;
import aQute.lib.io.*;
import aQute.lib.json.*;
import aQute.libg.reporter.*;
import aQute.service.library.*;
import aQute.service.library.Library.RevisionRef;
import aQute.service.reporter.*;
import aQute.struct.*;

public class Index {
  Reporter  reporter  = new ReporterAdapter(System.out);

  static public class Repo extends struct {
    public List<Library.RevisionRef>  revisionRefs  = list();
    public boolean            learning    = true;
    public boolean            recurse      = true;

    byte[]                synced;

    // Manually print this so that we
    // have 1 line per resource, making it easier on git
    // to compare.
    void write(Formatter format) throws Exception {
      codec.enc().indent(" ").to(format.out()).put(this);
      format.flush();
    }
  }

  private static final SortedSet<Version>            EMPTY_VERSIONS  = Collections
                                            .unmodifiableSortedSet(new TreeSet<Version>());

  private File                        indexFile;

  private Map<String,SortedMap<Version,Library.RevisionRef>>  cache;

  private Repo                        repo;

  public Index(File file) {
    this.indexFile = file;
  }

  static final JSONCodec  codec  = new JSONCodec();

  private boolean      dirty;

  private void init() throws Exception {
    if (repo == null) {
      cache = new TreeMap<String,SortedMap<Version,Library.RevisionRef>>();

      if (indexFile.isFile() && indexFile.length() > 100) {
        Decoder dec = codec.dec();
        try {
          repo = dec.from(indexFile).get(new TypeReference<Repo>() {});
          for (Library.RevisionRef r : repo.revisionRefs) {
            SortedMap<Version,Library.RevisionRef> map = cache.get(r.bsn);
            if (map == null) {
              map = new TreeMap<Version,Library.RevisionRef>(Collections.reverseOrder());
              cache.put(r.bsn, map);
            }
            Version v = toVersion(r.baseline, r.qualifier);
            map.put(v, r);
          }
        }
        finally {
          dec.close();
        }
      } else {
        repo = new Repo();
      }
    }
  }

  public Set<String> getBsns() throws Exception {
    init();
    return cache.keySet();
  }

  public SortedSet<Version> getVersions(String bsn) throws Exception {
    init();

    Map<Version,Library.RevisionRef> map = cache.get(bsn);
    if (map == null)
      return EMPTY_VERSIONS;

    return (SortedSet<Version>) map.keySet();
  }

  public boolean addRevision(Library.RevisionRef ref) throws Exception {
    init();
    Version v = toVersion(ref.baseline, ref.qualifier);
    SortedMap<Version,Library.RevisionRef> map = cache.get(ref.bsn);
    if (map == null) {
      map = new TreeMap<Version,Library.RevisionRef>();
      cache.put(ref.bsn, map);
    }

    map.put(v, ref);
    dirty = true;
    repo.revisionRefs.add(ref);
    return true;
  }

  @SuppressWarnings("deprecation")
  public Library.RevisionRef getRevisionRef(String bsn, Version version) throws Exception {
    init();
    Map<Version,Library.RevisionRef> map = cache.get(bsn);
    if (map == null)
      return null;

    // Fixup the change from ref.url to ref.urls ...
    boolean save = false;

    RevisionRef ref = map.get(version);
    if (ref == null) {
      return null;
    }

    if (ref.urls.isEmpty() && ref.url != null) {
      ref.urls.add(ref.url);
      ref.url = null;
      save = true;
    }
    // Another fixup, have file urls in the refs :-(
    for (Iterator<URI> i = ref.urls.iterator(); i.hasNext();) {
      URI uri = i.next();
      if (uri.getScheme().equalsIgnoreCase("file")) {
        i.remove();
        save = true;
      }
    }
    if (save)
      save();

    return ref;
  }

  public boolean delete(String bsn, Version v) throws Exception {
    init();
    Map<Version,Library.RevisionRef> map = cache.get(bsn);
    if (map != null) {
      try {
        Library.RevisionRef removed = map.remove(v);
        if (removed != null) {
          for (Iterator<RevisionRef> i = repo.revisionRefs.iterator(); i.hasNext();) {
            RevisionRef other = i.next();
            if (Arrays.equals(other.revision, removed.revision)) {
              i.remove();
            }
          }
          repo.revisionRefs.remove(removed);
          dirty = true;
          return true;
        }
      }
      finally {
        if (map.isEmpty())
          cache.remove(bsn);
      }
    }

    return false;
  }

  public void save(Writer out) throws Exception {
    init();
    repo.revisionRefs = getRevisionRefs();
    Formatter f = new Formatter(out);
    repo.write(f);
  }

  public void save(OutputStream out) throws Exception {
    save(new OutputStreamWriter(out));
  }

  public void save(File out) throws Exception {
    File tmp = IO.createTempFile(out.getParentFile(), out.getName(), ".tmp");
    FileWriter fout = new FileWriter(tmp);
    try {
      save(fout);
    }
    finally {
      fout.close();
    }
    IO.rename(tmp, out);
  }

  public void save() throws Exception {
    if (dirty)
      save(indexFile);
    dirty = false;
  }

  static Version toVersion(String baseline, String qualifier) {
    if (qualifier == null || qualifier.isEmpty())
      return new Version(baseline);
    else
      return new Version(baseline + "." + qualifier);
  }

  public static Version toVersion(Library.RevisionRef ref) {
    return toVersion(ref.baseline, ref.qualifier);
  }

  public Library.RevisionRef getRevisionRef(byte[] sha) throws Exception {
    init();
    for (SortedMap<Version, ? extends RevisionRef> list : cache.values()) {
      for (RevisionRef r : list.values()) {
        if (Arrays.equals(sha, r.revision))
          return r;
      }
    }
    return null;
  }

  public List<RevisionRef> getRevisionRefs() {
    List<RevisionRef> refs = new ArrayList<Library.RevisionRef>();
    for (SortedMap<Version, ? extends RevisionRef> list : cache.values()) {
      refs.addAll(list.values());
    }
    return refs;
  }

  public void setReporter(Reporter reporter) {
    this.reporter = reporter;
  }

  public boolean isLearning() throws Exception {
    init();
    return repo.learning;
  }

  public void setLearning(boolean learning) {
    dirty |= repo.learning != learning;
    repo.learning = learning;

  }

  public boolean isRecurse() {
    return repo.recurse;
  }

  public void setRecurse(boolean learning) {
    dirty |= repo.recurse != learning;
    repo.recurse = learning;

  }

  public boolean isDirty() {
    return dirty;
  }

  public Revisions getRevisions() throws Exception {
    init();
    Revisions revisions = new Revisions();
    for (RevisionRef ref : repo.revisionRefs)
      revisions.content.add(ref.revision);
    revisions._id = Revisions.checksum(revisions);
    return revisions;
  }

  public boolean isSynced() throws Exception {
    init();
    return repo.synced != null && Arrays.equals(repo.synced, getRevisions()._id);
  }

  public byte[] getSynced() {
    return repo.synced;
  }

  public void setSynced(byte[] revisions) throws Exception {
    repo.synced = revisions;
    save();
  }
}
TOP

Related Classes of aQute.library.bnd.Index$Repo

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.