/*******************************************************************************
 * Copyright (c) 2005 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
 *******************************************************************************/

package org.eclipse.wtp.releng.tools.component.ui.internal;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.jar.JarInputStream;
import java.util.zip.ZipEntry;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.wtp.releng.tools.component.IClazz;
import org.eclipse.wtp.releng.tools.component.IClazzVisitor;
import org.eclipse.wtp.releng.tools.component.ILibrary;
import org.osgi.framework.Bundle;

public class BundleLibrary implements ILibrary
{
  private Bundle bundle;
  private ManifestElement manifestElement;
  private Map types;

  public BundleLibrary(Bundle bundle, ManifestElement manifestElement)
  {
    this.bundle = bundle;
    this.manifestElement = manifestElement;
  }
  /**
   * Answers a mapping of (qualified) type names to <code>Type</code> objects
   * which are found in this library.
   * 
   * @return Map a mapping of type names to <code>Type</code> objects.
   */
  public Map getTypes()
  {
    if (types == null)
    {
      types = new HashMap(1);
      URL libURL = Platform.find(bundle, new Path(manifestElement.getValue()));
      if (libURL != null)
      {
        try
        {
          JarInputStream jis = new JarInputStream(libURL.openStream());
          ZipEntry entry = jis.getNextEntry();
          while (entry != null)
          {
            if (!entry.isDirectory() && entry.getName().endsWith(EXT_CLASS))
            {
              ByteArrayOutputStream baos = new ByteArrayOutputStream();
              byte[] b = new byte[2048];
              int read = jis.read(b);
              while (read != -1)
              {
                baos.write(b, 0, read);
                read = jis.read(b);
              }
              BundleClazz clazz = new BundleClazz(baos.toByteArray());
              types.put(clazz.getName(), clazz);
              clazz.resetClazz();
            }
            entry = jis.getNextEntry();
          }
          jis.close();
        }
        catch (IOException e)
        {
          e.printStackTrace();
        }
      }
    }
    return types;
  }

  public void resetTypes()
  {
    types = null;
  }

  public void accept(IClazzVisitor visitor)
  {
    for (Iterator it = getTypes().values().iterator(); it.hasNext();)
    {
      IClazz clazz = (IClazz)it.next();
      visitor.visit(clazz);
      clazz.resetClazz();
    }
  }
}
