CompositeMetadataRepository.java :  » IDE-Eclipse » equinox » org » eclipse » equinox » internal » p2 » metadata » repository » Java Open Source

Java Open Source » IDE Eclipse » equinox 
equinox » org » eclipse » equinox » internal » p2 » metadata » repository » CompositeMetadataRepository.java
/*******************************************************************************
 * Copyright (c) 2008, 2009 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     EclipseSource - ongoing development
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.metadata.repository;

import org.eclipse.equinox.internal.provisional.p2.repository.ICompositeRepository;
import org.eclipse.equinox.internal.provisional.p2.repository.IRepository;

import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.internal.p2.persistence.CompositeRepositoryIO;
import org.eclipse.equinox.internal.p2.persistence.CompositeRepositoryState;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
import org.eclipse.equinox.internal.provisional.p2.query.*;
import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.AbstractMetadataRepository;
import org.eclipse.osgi.util.NLS;

public class CompositeMetadataRepository extends AbstractMetadataRepository implements IMetadataRepository, ICompositeRepository {

  static final public String REPOSITORY_TYPE = CompositeMetadataRepository.class.getName();
  public static final String PI_REPOSITORY_TYPE = "compositeMetadataRepository"; //$NON-NLS-1$
  static final private Integer REPOSITORY_VERSION = new Integer(1);
  static final public String XML_EXTENSION = ".xml"; //$NON-NLS-1$
  static final private String JAR_EXTENSION = ".jar"; //$NON-NLS-1$

  // keep a list of the child URIs. they can be absolute or relative. they may or may not point
  // to a valid reachable repo
  private List childrenURIs = new ArrayList();
  // keep a list of the repositories that we have successfully loaded
  private List loadedRepos = new ArrayList();

  /**
   * Create a Composite repository in memory.
   * @return the repository or null if unable to create one
   */
  public static CompositeMetadataRepository createMemoryComposite() {
    IMetadataRepositoryManager manager = getManager();
    if (manager == null)
      return null;
    try {
      //create a unique opaque URI 
      long time = System.currentTimeMillis();
      URI repositoryURI = new URI("memory:" + String.valueOf(time)); //$NON-NLS-1$
      while (manager.contains(repositoryURI))
        repositoryURI = new URI("memory:" + String.valueOf(++time)); //$NON-NLS-1$

      CompositeMetadataRepository result = (CompositeMetadataRepository) manager.createRepository(repositoryURI, repositoryURI.toString(), IMetadataRepositoryManager.TYPE_COMPOSITE_REPOSITORY, null);
      manager.removeRepository(repositoryURI);
      return result;
    } catch (ProvisionException e) {
      // just return null
      LogHelper.log(e);
    } catch (URISyntaxException e) {
      // just return null
    }
    return null;
  }

  static private IMetadataRepositoryManager getManager() {
    return (IMetadataRepositoryManager) ServiceHelper.getService(Activator.getContext(), IMetadataRepositoryManager.class.getName());
  }

  private boolean isLocal() {
    return "file".equalsIgnoreCase(location.getScheme()); //$NON-NLS-1$
  }

  public boolean isModifiable() {
    return isLocal();
  }

  public CompositeMetadataRepository(URI location, String name, Map properties) {
    super(name == null ? (location != null ? location.toString() : "") : name, REPOSITORY_TYPE, REPOSITORY_VERSION.toString(), location, null, null, properties); //$NON-NLS-1$
    //when creating a repository, we must ensure it exists on disk so a subsequent load will succeed
    save();
  }

  /*
   * This is only called by the parser when loading a repository.
   */
  public CompositeMetadataRepository(CompositeRepositoryState state) {
    super(state.getName(), state.getType(), state.getVersion(), state.getLocation(), state.getDescription(), state.getProvider(), state.getProperties());
    for (int i = 0; i < state.getChildren().length; i++)
      addChild(state.getChildren()[i], false);
  }

  /*
   * Create and return a new repository state object which represents this repository.
   * It will be used while persisting the repository to disk.
   */
  public CompositeRepositoryState toState() {
    CompositeRepositoryState result = new CompositeRepositoryState();
    result.setName(getName());
    result.setType(getType());
    result.setVersion(getVersion());
    result.setLocation(getLocation());
    result.setDescription(getDescription());
    result.setProvider(getProvider());
    result.setProperties(getProperties());
    // it is important to directly access the field so we have the relative URIs
    result.setChildren((URI[]) childrenURIs.toArray(new URI[childrenURIs.size()]));
    return result;
  }

  public Collector query(Query query, Collector collector, IProgressMonitor monitor) {
    if (monitor == null)
      monitor = new NullProgressMonitor();
    try {
      // Query all the all the repositories this composite repo contains
      CompoundQueryable queryable = new CompoundQueryable((IQueryable[]) loadedRepos.toArray(new IQueryable[loadedRepos.size()]));
      collector = queryable.query(query, collector, monitor);
    } finally {
      if (monitor != null)
        monitor.done();
    }
    return collector;
  }

  private void addChild(URI childURI, boolean save) {
    URI absolute = URIUtil.makeAbsolute(childURI, location);
    if (childrenURIs.contains(childURI) || childrenURIs.contains(absolute))
      return;
    // always add the URI to the list of child URIs (even if we can't load it later)
    childrenURIs.add(childURI);
    if (save)
      save();
    try {
      boolean currentLoaded = getManager().contains(absolute);
      IMetadataRepository currentRepo = getManager().loadRepository(absolute, null);
      if (!currentLoaded) {
        //set enabled to false so repositories do not polled twice
        getManager().setEnabled(absolute, false);
        //set repository to system to hide from users
        getManager().setRepositoryProperty(absolute, IRepository.PROP_SYSTEM, String.valueOf(true));
      }
      // we successfully loaded the repo so remember it
      loadedRepos.add(currentRepo);
    } catch (ProvisionException e) {
      //repository failed to load. fall through
      LogHelper.log(e);
    }
  }

  public void addChild(URI childURI) {
    addChild(childURI, true);
  }

  public void removeChild(URI childURI) {
    boolean removed = childrenURIs.remove(childURI);
    // if the child wasn't there make sure and try the other permutation
    // (absolute/relative) to see if it really is in the list.
    URI other = childURI.isAbsolute() ? URIUtil.makeRelative(childURI, location) : URIUtil.makeAbsolute(childURI, location);
    if (!removed)
      removed = childrenURIs.remove(other);

    if (removed) {
      // we removed the child from the list so remove the associated repo object as well
      IMetadataRepository found = null;
      for (Iterator iter = loadedRepos.iterator(); found == null && iter.hasNext();) {
        IMetadataRepository current = (IMetadataRepository) iter.next();
        URI repoLocation = current.getLocation();
        if (URIUtil.sameURI(childURI, repoLocation))
          found = current;
        else if (URIUtil.sameURI(other, repoLocation))
          found = current;
      }
      if (found != null)
        loadedRepos.remove(found);
      save();
    }
  }

  public void removeAllChildren() {
    childrenURIs.clear();
    loadedRepos.clear();
    save();
  }

  public synchronized void addInstallableUnits(IInstallableUnit[] installableUnits) {
    throw new UnsupportedOperationException("Cannot add IUs to a composite repository");
  }

  public synchronized void removeAll() {
    throw new UnsupportedOperationException("Cannot remove IUs to a composite repository");
  }

  public synchronized boolean removeInstallableUnits(Query query, IProgressMonitor monitor) {
    throw new UnsupportedOperationException("Cannot remove IUs to a composite repository");
  }

  private static File getActualLocation(URI location, String extension) {
    File spec = URIUtil.toFile(location);
    String path = spec.getAbsolutePath();
    if (path.endsWith(CompositeMetadataRepositoryFactory.CONTENT_FILENAME + extension)) {
      //todo this is the old code that doesn't look right
      //      return new File(spec + extension);
      return spec;
    }
    if (path.endsWith("/")) //$NON-NLS-1$
      path += CompositeMetadataRepositoryFactory.CONTENT_FILENAME;
    else
      path += "/" + CompositeMetadataRepositoryFactory.CONTENT_FILENAME; //$NON-NLS-1$
    return new File(path + extension);
  }

  public static File getActualLocation(URI location) {
    return getActualLocation(location, XML_EXTENSION);
  }

  public synchronized void addReference(URI repositoryLocation, int repositoryType, int options) {
    throw new UnsupportedOperationException("Cannot add References to a composite repository");
  }

  // caller should be synchronized
  private void save() {
    if (!isModifiable())
      return;
    File file = getActualLocation(location);
    File jarFile = getActualLocation(location, JAR_EXTENSION);
    boolean compress = "true".equalsIgnoreCase((String) properties.get(PROP_COMPRESSED)); //$NON-NLS-1$
    try {
      OutputStream output = null;
      if (!compress) {
        if (jarFile.exists()) {
          jarFile.delete();
        }
        if (!file.exists()) {
          if (!file.getParentFile().exists())
            file.getParentFile().mkdirs();
          file.createNewFile();
        }
        output = new FileOutputStream(file);
      } else {
        if (file.exists()) {
          file.delete();
        }
        if (!jarFile.exists()) {
          if (!jarFile.getParentFile().exists())
            jarFile.getParentFile().mkdirs();
          jarFile.createNewFile();
        }
        JarEntry jarEntry = new JarEntry(file.getName());
        JarOutputStream jOutput = new JarOutputStream(new FileOutputStream(jarFile));
        jOutput.putNextEntry(jarEntry);
        output = jOutput;
      }
      super.setProperty(IRepository.PROP_TIMESTAMP, Long.toString(System.currentTimeMillis()));
      new CompositeRepositoryIO().write(toState(), output, PI_REPOSITORY_TYPE);
    } catch (IOException e) {
      LogHelper.log(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_FAILED_WRITE, NLS.bind(Messages.io_failedWrite, location), e));
    }
  }

  public List getChildren() {
    List result = new ArrayList();
    for (Iterator iter = childrenURIs.iterator(); iter.hasNext();)
      result.add(URIUtil.makeAbsolute((URI) iter.next(), location));
    return result;
  }

  public static URI getActualLocationURI(URI base, String extension) {
    if (extension == null)
      extension = XML_EXTENSION;
    return URIUtil.append(base, CompositeMetadataRepositoryFactory.CONTENT_FILENAME + extension);
  }

  //TODO this should never be called. What do we do?
  public void initialize(RepositoryState state) {
    this.name = state.Name;
    this.type = state.Type;
    this.version = state.Version.toString();
    this.provider = state.Provider;
    this.description = state.Description;
    this.location = state.Location;
    this.properties = state.Properties;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.