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:
parent
8081dbdc02
commit
58a14cc020
|
@ -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>
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue