Package aQute.lib.deployer.obr

Source Code of aQute.lib.deployer.obr.LocalOBR

package aQute.lib.deployer.obr;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.transform.stream.StreamResult;

import org.osgi.service.bindex.BundleIndexer;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import aQute.bnd.service.Refreshable;
import aQute.lib.deployer.FileRepo;
import aQute.lib.io.IO;
import aQute.lib.osgi.Jar;
import aQute.libg.reporter.Reporter;
import aQute.libg.sax.SAXUtil;
import aQute.libg.sax.filters.MergeContentFilter;
import aQute.libg.version.Version;

public class LocalOBR extends OBR implements Refreshable {
 
  public static final String PROP_LOCAL_DIR = "local";
  public static final String PROP_READONLY = "readonly";

  private final FileRepo storageRepo = new FileRepo();
 
  private File storageDir;
  private File localIndex;
 
  private List<URL> indexUrls;
 
  @Override
  public void setReporter(Reporter reporter) {
    super.setReporter(reporter);
    storageRepo.setReporter(reporter);
  }

  @Override
  public void setProperties(Map<String, String> map) {
    super.setProperties(map);
   
    // Load essential properties
    String localDirPath = map.get(PROP_LOCAL_DIR);
    if (localDirPath == null)
      throw new IllegalArgumentException(String.format("Attribute '%s' must be set on LocalOBR plugin.", PROP_LOCAL_DIR));
    storageDir = new File(localDirPath);
    if (!storageDir.isDirectory())
      throw new IllegalArgumentException(String.format("Local path '%s' does not exist or is not a directory.", localDirPath));
   
    // Configure the storage repository
    Map<String, String> storageRepoConfig = new HashMap<String, String>(2);
    storageRepoConfig.put(FileRepo.LOCATION, localDirPath);
    storageRepoConfig.put(FileRepo.READONLY, map.get(PROP_READONLY));
    storageRepo.setProperties(storageRepoConfig);
   
    // Set the local index and cache directory locations
    localIndex = new File(storageDir, REPOSITORY_FILE_NAME);
    if (localIndex.exists() && !localIndex.isFile())
      throw new IllegalArgumentException(String.format("Cannot build local repository index: '%s' already exists but is not a plain file.", localIndex.getAbsolutePath()));
    cacheDir = new File(storageDir, ".obrcache");
    if (cacheDir.exists() && !cacheDir.isDirectory())
      throw new IllegalArgumentException(String.format("Cannot create repository cache: '%s' already exists but is not directory.", cacheDir.getAbsolutePath()));
  }
 
  @Override
  protected void initialiseIndexes() throws Exception {
    if (!localIndex.exists()) {
      regenerateIndex();
    }
    try {
      Collection<URL> remotes = super.getOBRIndexes();
      indexUrls = new ArrayList<URL>(remotes.size() + 1);
      indexUrls.add(localIndex.toURI().toURL());
      indexUrls.addAll(remotes);
    } catch (IOException e) {
      throw new IllegalArgumentException("Error initialising local index URL", e);
    }
  }
 
  private void regenerateIndex() throws Exception {
    BundleIndexer indexer = registry.getPlugin(BundleIndexer.class);
    if (indexer == null)
      throw new IllegalStateException("Cannot index repository: no Bundle Indexer service or plugin found.");
   
    Set<File> allFiles = new HashSet<File>();
    gatherFiles(allFiles);
   
    FileOutputStream out = null;
    try {
      out = new FileOutputStream(localIndex);
      if (!allFiles.isEmpty()) {
        Map<String, String> config = new HashMap<String, String>();
        config.put(BundleIndexer.REPOSITORY_NAME, this.getName());
        config.put(BundleIndexer.ROOT_URL, localIndex.getCanonicalFile().toURI().toURL().toString());
        indexer.index(allFiles, out, config);
      } else {
        ByteArrayInputStream emptyRepo = new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>\n<repository lastmodified='0'/>".getBytes());
        IO.copy(emptyRepo, out);
      }
    } finally {
      out.close();
    }
  }

  private void gatherFiles(Set<File> allFiles) throws Exception {
    List<String> bsns = storageRepo.list(null);
    if (bsns != null) for (String bsn : bsns) {
      List<Version> versions = storageRepo.versions(bsn);
      if (versions != null) for (Version version : versions) {
        File file = storageRepo.get(bsn, version.toString(), Strategy.HIGHEST, null);
        if (file != null)
          allFiles.add(file.getCanonicalFile());
      }
    }
  }

  @Override
  public List<URL> getOBRIndexes() {
    return indexUrls;
  }
 
  @Override
  public boolean canWrite() {
    return storageRepo.canWrite();
  }
 
  @Override
  public synchronized File put(Jar jar) throws Exception {
    File newFile = storageRepo.put(jar);
   
    // Index the new file
    BundleIndexer indexer = registry.getPlugin(BundleIndexer.class);
    if (indexer == null)
      throw new IllegalStateException("Cannot index repository: no Bundle Indexer service or plugin found.");
    ByteArrayOutputStream newIndexBuffer = new ByteArrayOutputStream();

    Map<String, String> config = new HashMap<String, String>();
    config.put(BundleIndexer.REPOSITORY_NAME, this.getName());
    config.put(BundleIndexer.ROOT_URL, localIndex.getCanonicalFile().toURI().toURL().toString());
    indexer.index(Collections.singleton(newFile.getCanonicalFile()), newIndexBuffer, null);
   
    // Merge into main index
    File tempIndex = File.createTempFile("repository", ".xml");
    FileOutputStream tempIndexOutput = new FileOutputStream(tempIndex);
    MergeContentFilter merger = new MergeContentFilter();
    XMLReader reader = SAXUtil.buildPipeline(new StreamResult(tempIndexOutput), new UniqueResourceFilter(), merger);
   
    try {
      // Parse the newly generated index
      reader.parse(new InputSource(new ByteArrayInputStream(newIndexBuffer.toByteArray())));
     
      // Parse the existing index (which may be empty/missing)
      try {
        reader.parse(new InputSource(new FileInputStream(localIndex)));
      } catch (Exception e) {
        reporter.warning("Existing local index is invalid or missing, overwriting (%s).", localIndex.getAbsolutePath());
      }
     
      merger.closeRootAndDocument();
    } finally {
      tempIndexOutput.flush();
      tempIndexOutput.close();
    }
    IO.copy(tempIndex, localIndex);
   
    // Re-read the index
    reset();
    init();
   
    return newFile;
  }

  public boolean refresh() {
    reset();
    return true;
  }

  public File getRoot() {
    return storageDir;
  }
}
TOP

Related Classes of aQute.lib.deployer.obr.LocalOBR

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.