All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.osgi.framework.util.Headers Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2003, 2013 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.IOException;
import java.io.InputStream;
import java.util.*;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleException;

/**
 * Headers classes. This class implements a Dictionary that has
 * the following behavior:
 * 
    *
  • put and remove clear throw UnsupportedOperationException. * The Dictionary is thus read-only to others. *
  • The String keys in the Dictionary are case-preserved, * but the get operation is case-insensitive. *
* @since 3.1 */ public class Headers extends Dictionary implements Map { private boolean readOnly = false; private K[] headers; private V[] values; private int size = 0; /** * Create an empty Headers dictionary. * * @param initialCapacity The initial capacity of this Headers object. */ public Headers(int initialCapacity) { super(); @SuppressWarnings("unchecked") K[] k = (K[]) new Object[initialCapacity]; headers = k; @SuppressWarnings("unchecked") V[] v = (V[]) new Object[initialCapacity]; values = v; } /** * 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()) { K 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 (stringKey && (headers[i] instanceof String)) { if (((String) headers[i]).equalsIgnoreCase((String) key)) return i; } else { if (headers[i].equals(key)) return i; } } return -1; } private V remove(int remove) { V 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(K header, V value) { if (size == headers.length) { // grow the arrays @SuppressWarnings("unchecked") K[] nh = (K[]) new Object[headers.length + 10]; K[] newHeaders = nh; @SuppressWarnings("unchecked") V[] nv = (V[]) new Object[values.length + 10]; V[] newValues = nv; 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 V get(Object key) { int i = -1; if ((i = getIndex(key)) != -1) return values[i]; return null; } /** * Set a header value or optionally replace it if it already exists. * * @param key Key name. * @param value Value of the key or null to remove key. * @param replace A value of true will allow a previous * value of the key to be replaced. A value of false * will cause an IllegalArgumentException to be thrown * if a previous value of the key exists. * @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. * @since 3.2 */ public synchronized V set(K key, V value, boolean replace) { if (readOnly) throw new UnsupportedOperationException(); if (key instanceof String) { @SuppressWarnings("unchecked") K k = (K) ((String) key).intern(); key = k; } int i = getIndex(key); if (value == null) { /* remove */ if (i != -1) return remove(i); } else { /* put */ if (i != -1) { /* duplicate key */ if (!replace) throw new IllegalArgumentException(NLS.bind(Msg.HEADER_DUPLICATE_KEY_EXCEPTION, key)); V oldVal = values[i]; values[i] = value; return oldVal; } add(key, value); } 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 V set(K key, V value) { return set(key, value, false); } public synchronized void setReadOnly() { readOnly = true; } /** * 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 isEmpty method is that the result is true if and only * if this dictionary contains no entries. * * @return true if this dictionary maps no keys to values; * false otherwise. */ public synchronized boolean isEmpty() { return size == 0; } /** * Always throws UnsupportedOperationException. * * @param key header name. * @param value header value. * @throws UnsupportedOperationException */ public synchronized V put(K key, V value) { if (readOnly) throw new UnsupportedOperationException(); return set(key, value, true); } /** * Always throws UnsupportedOperationException. * * @param key header name. * @throws UnsupportedOperationException */ public V remove(Object key) { throw new UnsupportedOperationException(); } public String toString() { StringBuilder sb = new StringBuilder(); sb.append('{'); for (int i = 0; i < size; i++) { if (i != 0) { sb.append(", "); //$NON-NLS-1$ } K header = headers[i]; if (header == this) { sb.append("(this Dictionary)"); //$NON-NLS-1$ } else { sb.append(header); } sb.append('='); V value = values[i]; if (value == this) { sb.append("(this Dictionary)"); //$NON-NLS-1$ } else { sb.append(value); } } sb.append('}'); return sb.toString(); } public static Headers parseManifest(InputStream in) throws BundleException { Headers headers = new Headers(10); try { ManifestElement.parseBundleManifest(in, headers); } catch (IOException e) { throw new BundleException(Msg.MANIFEST_IOEXCEPTION, BundleException.MANIFEST_ERROR, e); } headers.setReadOnly(); return headers; } private static class ArrayEnumeration implements Enumeration { private E[] array; int cur = 0; public ArrayEnumeration(E[] array, int size) { @SuppressWarnings("unchecked") E[] a = (E[]) new Object[size]; this.array = a; System.arraycopy(array, 0, this.array, 0, this.array.length); } public boolean hasMoreElements() { return cur < array.length; } public E nextElement() { return array[cur++]; } } public synchronized void clear() { if (readOnly) throw new UnsupportedOperationException(); } public synchronized boolean containsKey(Object key) { return getIndex(key) >= 0; } public boolean containsValue(Object value) { throw new UnsupportedOperationException(); } public Set> entrySet() { throw new UnsupportedOperationException(); } public Set keySet() { throw new UnsupportedOperationException(); } public void putAll(Map c) { throw new UnsupportedOperationException(); } public Collection values() { throw new UnsupportedOperationException(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy