/*******************************************************************************
* Copyright 2012 Geoscience Australia
*
* Licensed 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.
******************************************************************************/
package au.gov.ga.earthsci.worldwind.common.downloader;
import gov.nasa.worldwind.retrieve.RetrievalPostProcessor;
import gov.nasa.worldwind.retrieve.Retriever;
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
/**
* Implementation of {@link RetrievalPostProcessor} which notifies at least one
* {@link RetrievalHandler} passing it the {@link RetrievalResult}. Multiple
* {@link RetrievalHandler}s can be added, and each one will be notified when
* the result is downloaded.
*
* @author Michael de Hoog (michael.dehoog@ga.gov.au)
*/
public class HandlerPostProcessor implements RetrievalPostProcessor
{
private URL sourceURL;
private Object lock = new Object();
private final List<RetrievalHandler> handlers = new ArrayList<RetrievalHandler>();
private RetrievalResult result = null;
/**
* @param sourceURL
* Download URL
* @param handler
* Default {@link RetrievalHandler} to notify when this is run
*/
public HandlerPostProcessor(URL sourceURL, RetrievalHandler handler)
{
this.sourceURL = sourceURL;
handlers.add(handler);
}
/**
* Add a {@link RetrievalHandler} to call when this is run. If this has
* already been run (ie already has a result), handler will be notified
* immediately in the caller's thread.
*
* @param handler
* {@link RetrievalHandler} to add
*/
public void addHandler(RetrievalHandler handler)
{
synchronized (lock)
{
if (result == null)
//result has not been calculated yet, so wait for run() to be called
handlers.add(handler);
else
handler.handle(result);
}
}
@Override
public ByteBuffer run(Retriever retriever)
{
Exception error = null;
boolean notModified = false;
if (retriever instanceof ExtendedRetriever)
{
ExtendedRetriever er = (ExtendedRetriever) retriever;
error = er.getError();
notModified = er.isNotModified();
}
ByteBuffer buffer = retriever.getBuffer();
int size;
synchronized (lock)
{
//synchronized with the addHandler method to ensure thread safety
result =
new ByteBufferRetrievalResult(sourceURL, buffer, false, notModified, error,
retriever.getContentType());
size = handlers.size();
}
//iterate through handlers, ending at size (which was calculated in the synchronzied
//block), so that any added in addHandler() in the meantime will not be notified (they
//will instead be notified immediately by addHandler())
for (int i = 0; i < size; i++)
handlers.get(i).handle(result);
return buffer;
}
}