Headers.java :  » Scripting » java2script » org » eclipse » osgi » framework » util » Java Open Source

Java Open Source » Scripting » java2script 
java2script » org » eclipse » osgi » framework » util » Headers.java
/*******************************************************************************
 * Copyright (c) 2003, 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.osgi.framework.util;

import java.io.*;
import java.util.Dictionary;
import java.util.Enumeration;
import org.eclipse.osgi.framework.internal.core.Msg;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleException;

/**
 * Headers classes. This class implements a Dictionary that has
 * the following behaviour:
 * <ul>
 * <li>put and remove clear throw UnsupportedOperationException.
 * The Dictionary is thus read-only to others.
 * <li>The String keys in the Dictionary are case-preserved,
 * but the get operation is case-insensitive.
 * </ul>
 * @since 3.1
 */
public class Headers extends Dictionary {
  Object[] headers;
  Object[] values;
  int size = 0;

  /**
   * Create an empty Headers dictionary.
   *
   * @param initialCapacity The initial capacity of this Headers object.
   */
  public Headers(int initialCapacity) {
    super();
    headers = new Object[initialCapacity];
    values = new Object[initialCapacity];
  }

  /**
   * Create a Headers dictionary from a Dictionary.
   *
   * @param values The initial dictionary for this Headers object.
   * @exception IllegalArgumentException If a case-variant of the key is
   * in the dictionary parameter.
   */
  public Headers(Dictionary values) {
    this(values.size());
    /* initialize the headers and values */
    Enumeration keys = values.keys();
    while (keys.hasMoreElements()) {
      Object key = keys.nextElement();
      set(key, values.get(key));
    }
  }

  /**
   * Case-preserved keys.
   */
  public synchronized Enumeration keys() {
    return new ArrayEnumeration(headers, size);
  }

  /**
   * Values.
   */
  public synchronized Enumeration elements() {
    return new ArrayEnumeration(values, size);
  }

  private int getIndex(Object key) {
    boolean stringKey = key instanceof String;
    for (int i = 0; i < size; i++) {
      if (headers[i].equals(key))
        return i;
      if (stringKey && (headers[i] instanceof String) && ((String) headers[i]).equalsIgnoreCase((String) key))
        return i;
    }
    return -1;
  }

  private Object remove(int remove) {
    Object removed = values[remove];
    for (int i = remove; i < size; i++) {
      if (i == headers.length - 1) {
        headers[i] = null;
        values[i] = null;
      }
      else {
        headers[i] = headers[i + 1];
        values[i] = values[i + 1];
      }
    }
    if (remove < size)
      size--;
    return removed;
  }

  private void add(Object header, Object value) {
    if (size == headers.length) {
      // grow the arrays
      Object[] newHeaders = new Object[headers.length + 10];
      Object[] newValues = new Object[values.length + 10];
      System.arraycopy(headers, 0, newHeaders, 0, headers.length);
      System.arraycopy(values, 0, newValues, 0, values.length);
      headers = newHeaders;
      values = newValues;
    }
    headers[size] = header;
    values[size] = value;
    size++;
  }

  /**
   * Support case-insensitivity for keys.
   *
   * @param key name.
   */
  public synchronized Object get(Object key) {
    int i = -1;
    if ((i = getIndex(key)) != -1)
      return values[i];
    return null;
  }

  /**
   * Set a header value.
   *
   * @param key Key name.
   * @param value Value of the key or null to remove key.
   * @return the previous value to which the key was mapped,
   * or null if the key did not have a previous mapping.
   *
   * @exception IllegalArgumentException If a case-variant of the key is
   * already present.
   */
  public synchronized Object set(Object key, Object value) {
    if (key instanceof String)
      key = ((String)key).intern();
    int i = getIndex(key);
    if (value == null) /* remove */
    {
      if (i != -1)
        return remove(i);
    } else /* put */
    {
      if (i != -1) /* duplicate key */
        throw new IllegalArgumentException(NLS.bind(Msg.HEADER_DUPLICATE_KEY_EXCEPTION, key));
      add(key, value);
    }
    return null;
  }

  /**
   * Returns the number of entries (distinct keys) in this dictionary.
   *
   * @return  the number of keys in this dictionary.
   */
  public synchronized int size() {
    return size;
  }

  /**
   * Tests if this dictionary maps no keys to value. The general contract
   * for the <tt>isEmpty</tt> method is that the result is true if and only
   * if this dictionary contains no entries.
   *
   * @return  <code>true</code> if this dictionary maps no keys to values;
   *          <code>false</code> otherwise.
   */
  public synchronized boolean isEmpty() {
    return size == 0;
  }

  /**
   * Always throws UnsupportedOperationException.
   *
   * @param key header name.
   * @param value header value.
   * @throws UnsupportedOperationException
   */
  public Object put(Object key, Object value) {
    throw new UnsupportedOperationException();
  }

  /**
   * Always throws UnsupportedOperationException.
   *
   * @param key header name.
   * @throws UnsupportedOperationException
   */
  public Object remove(Object key) {
    throw new UnsupportedOperationException();
  }

  public String toString() {
    return (values.toString());
  }

  public static Headers parseManifest(InputStream in) throws BundleException {
    try {
      Headers headers = new Headers(10);
      BufferedReader br;
      try {
        br = new BufferedReader(new InputStreamReader(in, "UTF8")); //$NON-NLS-1$
      } catch (UnsupportedEncodingException e) {
        br = new BufferedReader(new InputStreamReader(in));
      }

      String header = null;
      StringBuffer value = new StringBuffer(256);
      boolean firstLine = true;

      while (true) {
        String line = br.readLine();
        /* The java.util.jar classes in JDK 1.3 use the value of the last
         * encountered manifest header. So we do the same to emulate
         * this behavior. We no longer throw a BundleException
         * for duplicate manifest headers.
         */

        if ((line == null) || (line.length() == 0)) /* EOF or empty line */
        {
          if (!firstLine) /* flush last line */
          {
            headers.set(header, null); /* remove old attribute,if present */
            headers.set(header, value.toString().trim());
          }
          break; /* done processing main attributes */
        }

        if (line.charAt(0) == ' ') /* continuation */
        {
          if (firstLine) /* if no previous line */
          {
            throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_SPACE, line));
          }
          value.append(line.substring(1));
          continue;
        }

        if (!firstLine) {
          headers.set(header, null); /* remove old attribute,if present */
          headers.set(header, value.toString().trim());
          value.setLength(0); /* clear StringBuffer */
        }

        int colon = line.indexOf(':');
        if (colon == -1) /* no colon */
        {
          throw new BundleException(NLS.bind(Msg.MANIFEST_INVALID_LINE_NOCOLON, line));
        }
        header = line.substring(0, colon).trim();
        value.append(line.substring(colon + 1));
        firstLine = false;
      }
      return headers;
    } catch (IOException e) {
      throw new BundleException(Msg.MANIFEST_IOEXCEPTION, e);
    } finally {
      try {
        in.close();
      } catch (IOException ee) {
      }
    }
  }

  class ArrayEnumeration implements Enumeration {
    private Object[] array;
    int cur = 0;

    public ArrayEnumeration(Object[] array, int size) {
      this.array = new Object[size];
      System.arraycopy(array, 0, this.array, 0, this.array.length);
    }

    public boolean hasMoreElements() {
      return cur < array.length;
    }

    public Object nextElement() {
      return array[cur++];
    }
    
  }
}
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.