HTTPCLIENT-1749: OSGi client builder to use weak references to track HttpClient instances

Contributed by Justin Edelson <justin at justinedelson.com>

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1747905 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2016-06-11 15:55:15 +00:00
parent 8081dbdc02
commit 58a14cc020
5 changed files with 194 additions and 11 deletions

View File

@ -215,13 +215,6 @@
<_removeheaders>JAVA_1_3_HOME,JAVA_1_4_HOME</_removeheaders>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>clirr-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -31,7 +31,6 @@ import java.io.IOException;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -62,7 +61,11 @@ public final class HttpProxyConfigurationActivator implements BundleActivator, M
private final Map<String, ServiceRegistration> registeredConfigurations = new LinkedHashMap<>();
private final List<CloseableHttpClient> trackedHttpClients = new LinkedList<>();
private final List<CloseableHttpClient> trackedHttpClients;
public HttpProxyConfigurationActivator() {
trackedHttpClients = new WeakList<CloseableHttpClient>();
}
/**
* {@inheritDoc}

View File

@ -26,6 +26,7 @@
*/
package org.apache.hc.client5.http.osgi.impl;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -39,7 +40,7 @@ import org.osgi.framework.ServiceRegistration;
*/
final class OSGiHttpClientBuilder extends HttpClientBuilder {
private final List<CloseableHttpClient> trackedHttpClients;
private final Collection<CloseableHttpClient> trackedHttpClients;
public OSGiHttpClientBuilder(
final BundleContext bundleContext,
@ -55,7 +56,9 @@ final class OSGiHttpClientBuilder extends HttpClientBuilder {
@Override
public CloseableHttpClient build() {
final CloseableHttpClient httpClient = super.build();
trackedHttpClients.add(httpClient);
synchronized (trackedHttpClients) {
trackedHttpClients.add(httpClient);
}
return httpClient;
}

View File

@ -0,0 +1,122 @@
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.hc.client5.http.osgi.impl;
import java.lang.ref.WeakReference;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
/**
* Implementation of a list backed by WeakReference objects.
* This is not a general purpose list and is only meant to be used by this package. It cannot correctly manage null entries by design.
*/
class WeakList<T> extends AbstractList<T> {
private final List<WeakReference<T>> innerList;
public WeakList() {
this.innerList = new ArrayList<WeakReference<T>>();
}
@Override
public T get(final int index) {
return innerList.get(index).get();
}
@Override
public int size() {
checkReferences();
return innerList.size();
}
@Override
public boolean add(final T t) {
return innerList.add(new WeakReference<T>(t));
}
private void checkReferences() {
final ListIterator<WeakReference<T>> references = innerList.listIterator();
while (references.hasNext()) {
final WeakReference<T> reference = references.next();
if (reference.get() == null) {
references.remove();
}
}
}
@Override
public Iterator<T> iterator() {
return new WeakIterator<T>(innerList.iterator());
}
private class WeakIterator<T> implements Iterator<T> {
private final Iterator<WeakReference<T>> innerIterator;
private WeakReference<T> next;
public WeakIterator(final Iterator<WeakReference<T>> innerIterator) {
this.innerIterator = innerIterator;
fetchNext();
}
public boolean hasNext() {
return next != null;
}
public T next() {
if (next != null) {
final T result = next.get();
fetchNext();
return result;
} else {
throw new NoSuchElementException();
}
}
private void fetchNext() {
while (innerIterator.hasNext()) {
final WeakReference<T> ref = innerIterator.next();
final T obj = ref.get();
if (obj != null) {
next = ref;
return;
}
}
next = null;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}

View File

@ -0,0 +1,62 @@
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.hc.client5.http.osgi.impl;
import org.junit.Test;
import java.util.Iterator;
import java.util.NoSuchElementException;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertEquals;
public class WeakListTest {
@Test
public void testWeakList() {
final WeakList<Object> list = new WeakList<Object>();
list.add("hello");
list.add(null);
// null objects are seen as GC'd, so we only expect a size of 1
assertEquals(1, list.size());
final Iterator<Object> it = list.iterator();
assertTrue(it.hasNext());
assertEquals("hello", it.next());
assertFalse(it.hasNext());
boolean thrown = false;
try {
it.next();
} catch (NoSuchElementException e) {
thrown = true;
}
assertTrue(thrown);
}
}